Skip to content

Commit afd4b94

Browse files
committed
Move CMerkleBlock and CPartialMerkleTree to their own file
1 parent a0417b8 commit afd4b94

File tree

9 files changed

+318
-294
lines changed

9 files changed

+318
-294
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ BITCOIN_CORE_H = \
101101
leveldbwrapper.h \
102102
limitedmap.h \
103103
main.h \
104+
merkleblock.h \
104105
miner.h \
105106
mruset.h \
106107
netbase.h \
@@ -168,6 +169,7 @@ libbitcoin_server_a_SOURCES = \
168169
init.cpp \
169170
leveldbwrapper.cpp \
170171
main.cpp \
172+
merkleblock.cpp \
171173
miner.cpp \
172174
net.cpp \
173175
noui.cpp \

src/bitcoin-tx.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@
44

55
#include "base58.h"
66
#include "clientversion.h"
7+
#include "primitives/block.h" // for MAX_BLOCK_SIZE
78
#include "primitives/transaction.h"
89
#include "core_io.h"
10+
#include "coins.h"
911
#include "keystore.h"
10-
#include "main.h" // for MAX_BLOCK_SIZE
1112
#include "script/script.h"
1213
#include "script/sign.h"
1314
#include "ui_interface.h" // for _(...)
1415
#include "univalue/univalue.h"
1516
#include "util.h"
17+
#include "utilstrencodings.h"
1618
#include "utilmoneystr.h"
1719

1820
#include <stdio.h>

src/main.cpp

Lines changed: 1 addition & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "checkpoints.h"
1212
#include "checkqueue.h"
1313
#include "init.h"
14+
#include "merkleblock.h"
1415
#include "net.h"
1516
#include "pow.h"
1617
#include "txdb.h"
@@ -2720,159 +2721,6 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
27202721

27212722

27222723

2723-
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
2724-
{
2725-
header = block.GetBlockHeader();
2726-
2727-
vector<bool> vMatch;
2728-
vector<uint256> vHashes;
2729-
2730-
vMatch.reserve(block.vtx.size());
2731-
vHashes.reserve(block.vtx.size());
2732-
2733-
for (unsigned int i = 0; i < block.vtx.size(); i++)
2734-
{
2735-
const uint256& hash = block.vtx[i].GetHash();
2736-
if (filter.IsRelevantAndUpdate(block.vtx[i]))
2737-
{
2738-
vMatch.push_back(true);
2739-
vMatchedTxn.push_back(make_pair(i, hash));
2740-
}
2741-
else
2742-
vMatch.push_back(false);
2743-
vHashes.push_back(hash);
2744-
}
2745-
2746-
txn = CPartialMerkleTree(vHashes, vMatch);
2747-
}
2748-
2749-
2750-
2751-
2752-
2753-
2754-
2755-
2756-
uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid) {
2757-
if (height == 0) {
2758-
// hash at height 0 is the txids themself
2759-
return vTxid[pos];
2760-
} else {
2761-
// calculate left hash
2762-
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
2763-
// calculate right hash if not beyond the end of the array - copy left hash otherwise1
2764-
if (pos*2+1 < CalcTreeWidth(height-1))
2765-
right = CalcHash(height-1, pos*2+1, vTxid);
2766-
else
2767-
right = left;
2768-
// combine subhashes
2769-
return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
2770-
}
2771-
}
2772-
2773-
void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) {
2774-
// determine whether this node is the parent of at least one matched txid
2775-
bool fParentOfMatch = false;
2776-
for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++)
2777-
fParentOfMatch |= vMatch[p];
2778-
// store as flag bit
2779-
vBits.push_back(fParentOfMatch);
2780-
if (height==0 || !fParentOfMatch) {
2781-
// if at height 0, or nothing interesting below, store hash and stop
2782-
vHash.push_back(CalcHash(height, pos, vTxid));
2783-
} else {
2784-
// otherwise, don't store any hash, but descend into the subtrees
2785-
TraverseAndBuild(height-1, pos*2, vTxid, vMatch);
2786-
if (pos*2+1 < CalcTreeWidth(height-1))
2787-
TraverseAndBuild(height-1, pos*2+1, vTxid, vMatch);
2788-
}
2789-
}
2790-
2791-
uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch) {
2792-
if (nBitsUsed >= vBits.size()) {
2793-
// overflowed the bits array - failure
2794-
fBad = true;
2795-
return 0;
2796-
}
2797-
bool fParentOfMatch = vBits[nBitsUsed++];
2798-
if (height==0 || !fParentOfMatch) {
2799-
// if at height 0, or nothing interesting below, use stored hash and do not descend
2800-
if (nHashUsed >= vHash.size()) {
2801-
// overflowed the hash array - failure
2802-
fBad = true;
2803-
return 0;
2804-
}
2805-
const uint256 &hash = vHash[nHashUsed++];
2806-
if (height==0 && fParentOfMatch) // in case of height 0, we have a matched txid
2807-
vMatch.push_back(hash);
2808-
return hash;
2809-
} else {
2810-
// otherwise, descend into the subtrees to extract matched txids and hashes
2811-
uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right;
2812-
if (pos*2+1 < CalcTreeWidth(height-1))
2813-
right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
2814-
else
2815-
right = left;
2816-
// and combine them before returning
2817-
return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
2818-
}
2819-
}
2820-
2821-
CPartialMerkleTree::CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) : nTransactions(vTxid.size()), fBad(false) {
2822-
// reset state
2823-
vBits.clear();
2824-
vHash.clear();
2825-
2826-
// calculate height of tree
2827-
int nHeight = 0;
2828-
while (CalcTreeWidth(nHeight) > 1)
2829-
nHeight++;
2830-
2831-
// traverse the partial tree
2832-
TraverseAndBuild(nHeight, 0, vTxid, vMatch);
2833-
}
2834-
2835-
CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
2836-
2837-
uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
2838-
vMatch.clear();
2839-
// An empty set will not work
2840-
if (nTransactions == 0)
2841-
return 0;
2842-
// check for excessively high numbers of transactions
2843-
if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
2844-
return 0;
2845-
// there can never be more hashes provided than one for every txid
2846-
if (vHash.size() > nTransactions)
2847-
return 0;
2848-
// there must be at least one bit per node in the partial tree, and at least one node per hash
2849-
if (vBits.size() < vHash.size())
2850-
return 0;
2851-
// calculate height of tree
2852-
int nHeight = 0;
2853-
while (CalcTreeWidth(nHeight) > 1)
2854-
nHeight++;
2855-
// traverse the partial tree
2856-
unsigned int nBitsUsed = 0, nHashUsed = 0;
2857-
uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch);
2858-
// verify that no problems occured during the tree traversal
2859-
if (fBad)
2860-
return 0;
2861-
// verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
2862-
if ((nBitsUsed+7)/8 != (vBits.size()+7)/8)
2863-
return 0;
2864-
// verify that all hashes were consumed
2865-
if (nHashUsed != vHash.size())
2866-
return 0;
2867-
return hashMerkleRoot;
2868-
}
2869-
2870-
2871-
2872-
2873-
2874-
2875-
28762724
bool AbortNode(const std::string &strMessage, const std::string &userMessage) {
28772725
strMiscWarning = strMessage;
28782726
LogPrintf("*** %s\n", strMessage);

src/main.h

Lines changed: 0 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ class CValidationState;
4949
struct CBlockTemplate;
5050
struct CNodeStateStats;
5151

52-
/** The maximum allowed size for a serialized block, in bytes (network rule) */
53-
static const unsigned int MAX_BLOCK_SIZE = 1000000;
5452
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
5553
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
5654
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
@@ -352,110 +350,6 @@ class CScriptCheck
352350
}
353351
};
354352

355-
/** Data structure that represents a partial merkle tree.
356-
*
357-
* It represents a subset of the txid's of a known block, in a way that
358-
* allows recovery of the list of txid's and the merkle root, in an
359-
* authenticated way.
360-
*
361-
* The encoding works as follows: we traverse the tree in depth-first order,
362-
* storing a bit for each traversed node, signifying whether the node is the
363-
* parent of at least one matched leaf txid (or a matched txid itself). In
364-
* case we are at the leaf level, or this bit is 0, its merkle node hash is
365-
* stored, and its children are not explorer further. Otherwise, no hash is
366-
* stored, but we recurse into both (or the only) child branch. During
367-
* decoding, the same depth-first traversal is performed, consuming bits and
368-
* hashes as they written during encoding.
369-
*
370-
* The serialization is fixed and provides a hard guarantee about the
371-
* encoded size:
372-
*
373-
* SIZE <= 10 + ceil(32.25*N)
374-
*
375-
* Where N represents the number of leaf nodes of the partial tree. N itself
376-
* is bounded by:
377-
*
378-
* N <= total_transactions
379-
* N <= 1 + matched_transactions*tree_height
380-
*
381-
* The serialization format:
382-
* - uint32 total_transactions (4 bytes)
383-
* - varint number of hashes (1-3 bytes)
384-
* - uint256[] hashes in depth-first order (<= 32*N bytes)
385-
* - varint number of bytes of flag bits (1-3 bytes)
386-
* - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
387-
* The size constraints follow from this.
388-
*/
389-
class CPartialMerkleTree
390-
{
391-
protected:
392-
/** the total number of transactions in the block */
393-
unsigned int nTransactions;
394-
395-
/** node-is-parent-of-matched-txid bits */
396-
std::vector<bool> vBits;
397-
398-
/** txids and internal hashes */
399-
std::vector<uint256> vHash;
400-
401-
/** flag set when encountering invalid data */
402-
bool fBad;
403-
404-
/** helper function to efficiently calculate the number of nodes at given height in the merkle tree */
405-
unsigned int CalcTreeWidth(int height) {
406-
return (nTransactions+(1 << height)-1) >> height;
407-
}
408-
409-
/** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */
410-
uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
411-
412-
/** recursive function that traverses tree nodes, storing the data as bits and hashes */
413-
void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
414-
415-
/**
416-
* recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
417-
* it returns the hash of the respective node.
418-
*/
419-
uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
420-
421-
public:
422-
423-
/** serialization implementation */
424-
ADD_SERIALIZE_METHODS;
425-
426-
template <typename Stream, typename Operation>
427-
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
428-
READWRITE(nTransactions);
429-
READWRITE(vHash);
430-
std::vector<unsigned char> vBytes;
431-
if (ser_action.ForRead()) {
432-
READWRITE(vBytes);
433-
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
434-
us.vBits.resize(vBytes.size() * 8);
435-
for (unsigned int p = 0; p < us.vBits.size(); p++)
436-
us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
437-
us.fBad = false;
438-
} else {
439-
vBytes.resize((vBits.size()+7)/8);
440-
for (unsigned int p = 0; p < vBits.size(); p++)
441-
vBytes[p / 8] |= vBits[p] << (p % 8);
442-
READWRITE(vBytes);
443-
}
444-
}
445-
446-
/** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */
447-
CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
448-
449-
CPartialMerkleTree();
450-
451-
/**
452-
* extract the matching txid's represented by this partial merkle tree.
453-
* returns the merkle root, or 0 in case of failure
454-
*/
455-
uint256 ExtractMatches(std::vector<uint256> &vMatch);
456-
};
457-
458-
459353

460354
/** Functions for disk access for blocks */
461355
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
@@ -646,38 +540,6 @@ struct CBlockTemplate
646540

647541

648542

649-
/**
650-
* Used to relay blocks as header + vector<merkle branch>
651-
* to filtered nodes.
652-
*/
653-
class CMerkleBlock
654-
{
655-
public:
656-
/** Public only for unit testing */
657-
CBlockHeader header;
658-
CPartialMerkleTree txn;
659-
660-
public:
661-
/** Public only for unit testing and relay testing (not relayed) */
662-
std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
663-
664-
/**
665-
* Create from a CBlock, filtering transactions according to filter
666-
* Note that this will call IsRelevantAndUpdate on the filter for each transaction,
667-
* thus the filter will likely be modified.
668-
*/
669-
CMerkleBlock(const CBlock& block, CBloomFilter& filter);
670-
671-
ADD_SERIALIZE_METHODS;
672-
673-
template <typename Stream, typename Operation>
674-
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
675-
READWRITE(header);
676-
READWRITE(txn);
677-
}
678-
};
679-
680-
681543
class CValidationInterface {
682544
protected:
683545
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {};

0 commit comments

Comments
 (0)