aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bitcoin-tx.cpp4
-rw-r--r--src/main.cpp154
-rw-r--r--src/main.h138
-rw-r--r--src/merkleblock.cpp152
-rw-r--r--src/merkleblock.h151
-rw-r--r--src/primitives/block.h3
-rw-r--r--src/test/bloom_tests.cpp4
-rw-r--r--src/test/pmt_tests.cpp4
9 files changed, 318 insertions, 294 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 69b3a6d4f1..d6ac6e1277 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -101,6 +101,7 @@ BITCOIN_CORE_H = \
leveldbwrapper.h \
limitedmap.h \
main.h \
+ merkleblock.h \
miner.h \
mruset.h \
netbase.h \
@@ -168,6 +169,7 @@ libbitcoin_server_a_SOURCES = \
init.cpp \
leveldbwrapper.cpp \
main.cpp \
+ merkleblock.cpp \
miner.cpp \
net.cpp \
noui.cpp \
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 1cceab3188..ce66dfbe96 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -4,15 +4,17 @@
#include "base58.h"
#include "clientversion.h"
+#include "primitives/block.h" // for MAX_BLOCK_SIZE
#include "primitives/transaction.h"
#include "core_io.h"
+#include "coins.h"
#include "keystore.h"
-#include "main.h" // for MAX_BLOCK_SIZE
#include "script/script.h"
#include "script/sign.h"
#include "ui_interface.h" // for _(...)
#include "univalue/univalue.h"
#include "util.h"
+#include "utilstrencodings.h"
#include "utilmoneystr.h"
#include <stdio.h>
diff --git a/src/main.cpp b/src/main.cpp
index 451d6c8cd9..cea2925fe2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,6 +11,7 @@
#include "checkpoints.h"
#include "checkqueue.h"
#include "init.h"
+#include "merkleblock.h"
#include "net.h"
#include "pow.h"
#include "txdb.h"
@@ -2720,159 +2721,6 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
-CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
-{
- header = block.GetBlockHeader();
-
- vector<bool> vMatch;
- vector<uint256> vHashes;
-
- vMatch.reserve(block.vtx.size());
- vHashes.reserve(block.vtx.size());
-
- for (unsigned int i = 0; i < block.vtx.size(); i++)
- {
- const uint256& hash = block.vtx[i].GetHash();
- if (filter.IsRelevantAndUpdate(block.vtx[i]))
- {
- vMatch.push_back(true);
- vMatchedTxn.push_back(make_pair(i, hash));
- }
- else
- vMatch.push_back(false);
- vHashes.push_back(hash);
- }
-
- txn = CPartialMerkleTree(vHashes, vMatch);
-}
-
-
-
-
-
-
-
-
-uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid) {
- if (height == 0) {
- // hash at height 0 is the txids themself
- return vTxid[pos];
- } else {
- // calculate left hash
- uint256 left = CalcHash(height-1, pos*2, vTxid), right;
- // calculate right hash if not beyond the end of the array - copy left hash otherwise1
- if (pos*2+1 < CalcTreeWidth(height-1))
- right = CalcHash(height-1, pos*2+1, vTxid);
- else
- right = left;
- // combine subhashes
- return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
- }
-}
-
-void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) {
- // determine whether this node is the parent of at least one matched txid
- bool fParentOfMatch = false;
- for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++)
- fParentOfMatch |= vMatch[p];
- // store as flag bit
- vBits.push_back(fParentOfMatch);
- if (height==0 || !fParentOfMatch) {
- // if at height 0, or nothing interesting below, store hash and stop
- vHash.push_back(CalcHash(height, pos, vTxid));
- } else {
- // otherwise, don't store any hash, but descend into the subtrees
- TraverseAndBuild(height-1, pos*2, vTxid, vMatch);
- if (pos*2+1 < CalcTreeWidth(height-1))
- TraverseAndBuild(height-1, pos*2+1, vTxid, vMatch);
- }
-}
-
-uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch) {
- if (nBitsUsed >= vBits.size()) {
- // overflowed the bits array - failure
- fBad = true;
- return 0;
- }
- bool fParentOfMatch = vBits[nBitsUsed++];
- if (height==0 || !fParentOfMatch) {
- // if at height 0, or nothing interesting below, use stored hash and do not descend
- if (nHashUsed >= vHash.size()) {
- // overflowed the hash array - failure
- fBad = true;
- return 0;
- }
- const uint256 &hash = vHash[nHashUsed++];
- if (height==0 && fParentOfMatch) // in case of height 0, we have a matched txid
- vMatch.push_back(hash);
- return hash;
- } else {
- // otherwise, descend into the subtrees to extract matched txids and hashes
- uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right;
- if (pos*2+1 < CalcTreeWidth(height-1))
- right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
- else
- right = left;
- // and combine them before returning
- return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
- }
-}
-
-CPartialMerkleTree::CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) : nTransactions(vTxid.size()), fBad(false) {
- // reset state
- vBits.clear();
- vHash.clear();
-
- // calculate height of tree
- int nHeight = 0;
- while (CalcTreeWidth(nHeight) > 1)
- nHeight++;
-
- // traverse the partial tree
- TraverseAndBuild(nHeight, 0, vTxid, vMatch);
-}
-
-CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
-
-uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
- vMatch.clear();
- // An empty set will not work
- if (nTransactions == 0)
- return 0;
- // check for excessively high numbers of transactions
- if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
- return 0;
- // there can never be more hashes provided than one for every txid
- if (vHash.size() > nTransactions)
- return 0;
- // there must be at least one bit per node in the partial tree, and at least one node per hash
- if (vBits.size() < vHash.size())
- return 0;
- // calculate height of tree
- int nHeight = 0;
- while (CalcTreeWidth(nHeight) > 1)
- nHeight++;
- // traverse the partial tree
- unsigned int nBitsUsed = 0, nHashUsed = 0;
- uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch);
- // verify that no problems occured during the tree traversal
- if (fBad)
- return 0;
- // verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
- if ((nBitsUsed+7)/8 != (vBits.size()+7)/8)
- return 0;
- // verify that all hashes were consumed
- if (nHashUsed != vHash.size())
- return 0;
- return hashMerkleRoot;
-}
-
-
-
-
-
-
-
bool AbortNode(const std::string &strMessage, const std::string &userMessage) {
strMiscWarning = strMessage;
LogPrintf("*** %s\n", strMessage);
diff --git a/src/main.h b/src/main.h
index fc9913b7c6..dc833673ae 100644
--- a/src/main.h
+++ b/src/main.h
@@ -49,8 +49,6 @@ class CValidationState;
struct CBlockTemplate;
struct CNodeStateStats;
-/** The maximum allowed size for a serialized block, in bytes (network rule) */
-static const unsigned int MAX_BLOCK_SIZE = 1000000;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
@@ -352,110 +350,6 @@ public:
}
};
-/** Data structure that represents a partial merkle tree.
- *
- * It represents a subset of the txid's of a known block, in a way that
- * allows recovery of the list of txid's and the merkle root, in an
- * authenticated way.
- *
- * The encoding works as follows: we traverse the tree in depth-first order,
- * storing a bit for each traversed node, signifying whether the node is the
- * parent of at least one matched leaf txid (or a matched txid itself). In
- * case we are at the leaf level, or this bit is 0, its merkle node hash is
- * stored, and its children are not explorer further. Otherwise, no hash is
- * stored, but we recurse into both (or the only) child branch. During
- * decoding, the same depth-first traversal is performed, consuming bits and
- * hashes as they written during encoding.
- *
- * The serialization is fixed and provides a hard guarantee about the
- * encoded size:
- *
- * SIZE <= 10 + ceil(32.25*N)
- *
- * Where N represents the number of leaf nodes of the partial tree. N itself
- * is bounded by:
- *
- * N <= total_transactions
- * N <= 1 + matched_transactions*tree_height
- *
- * The serialization format:
- * - uint32 total_transactions (4 bytes)
- * - varint number of hashes (1-3 bytes)
- * - uint256[] hashes in depth-first order (<= 32*N bytes)
- * - varint number of bytes of flag bits (1-3 bytes)
- * - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
- * The size constraints follow from this.
- */
-class CPartialMerkleTree
-{
-protected:
- /** the total number of transactions in the block */
- unsigned int nTransactions;
-
- /** node-is-parent-of-matched-txid bits */
- std::vector<bool> vBits;
-
- /** txids and internal hashes */
- std::vector<uint256> vHash;
-
- /** flag set when encountering invalid data */
- bool fBad;
-
- /** helper function to efficiently calculate the number of nodes at given height in the merkle tree */
- unsigned int CalcTreeWidth(int height) {
- return (nTransactions+(1 << height)-1) >> height;
- }
-
- /** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */
- uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
-
- /** recursive function that traverses tree nodes, storing the data as bits and hashes */
- void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
-
- /**
- * recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
- * it returns the hash of the respective node.
- */
- uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
-
-public:
-
- /** serialization implementation */
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(nTransactions);
- READWRITE(vHash);
- std::vector<unsigned char> vBytes;
- if (ser_action.ForRead()) {
- READWRITE(vBytes);
- CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
- us.vBits.resize(vBytes.size() * 8);
- for (unsigned int p = 0; p < us.vBits.size(); p++)
- us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
- us.fBad = false;
- } else {
- vBytes.resize((vBits.size()+7)/8);
- for (unsigned int p = 0; p < vBits.size(); p++)
- vBytes[p / 8] |= vBits[p] << (p % 8);
- READWRITE(vBytes);
- }
- }
-
- /** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */
- CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
-
- CPartialMerkleTree();
-
- /**
- * extract the matching txid's represented by this partial merkle tree.
- * returns the merkle root, or 0 in case of failure
- */
- uint256 ExtractMatches(std::vector<uint256> &vMatch);
-};
-
-
/** Functions for disk access for blocks */
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
@@ -646,38 +540,6 @@ struct CBlockTemplate
-/**
- * Used to relay blocks as header + vector<merkle branch>
- * to filtered nodes.
- */
-class CMerkleBlock
-{
-public:
- /** Public only for unit testing */
- CBlockHeader header;
- CPartialMerkleTree txn;
-
-public:
- /** Public only for unit testing and relay testing (not relayed) */
- std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
-
- /**
- * Create from a CBlock, filtering transactions according to filter
- * Note that this will call IsRelevantAndUpdate on the filter for each transaction,
- * thus the filter will likely be modified.
- */
- CMerkleBlock(const CBlock& block, CBloomFilter& filter);
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(header);
- READWRITE(txn);
- }
-};
-
-
class CValidationInterface {
protected:
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {};
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
new file mode 100644
index 0000000000..8618e355d7
--- /dev/null
+++ b/src/merkleblock.cpp
@@ -0,0 +1,152 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "merkleblock.h"
+
+#include "hash.h"
+#include "primitives/block.h" // for MAX_BLOCK_SIZE
+#include "utilstrencodings.h"
+
+using namespace std;
+
+CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
+{
+ header = block.GetBlockHeader();
+
+ vector<bool> vMatch;
+ vector<uint256> vHashes;
+
+ vMatch.reserve(block.vtx.size());
+ vHashes.reserve(block.vtx.size());
+
+ for (unsigned int i = 0; i < block.vtx.size(); i++)
+ {
+ const uint256& hash = block.vtx[i].GetHash();
+ if (filter.IsRelevantAndUpdate(block.vtx[i]))
+ {
+ vMatch.push_back(true);
+ vMatchedTxn.push_back(make_pair(i, hash));
+ }
+ else
+ vMatch.push_back(false);
+ vHashes.push_back(hash);
+ }
+
+ txn = CPartialMerkleTree(vHashes, vMatch);
+}
+
+uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid) {
+ if (height == 0) {
+ // hash at height 0 is the txids themself
+ return vTxid[pos];
+ } else {
+ // calculate left hash
+ uint256 left = CalcHash(height-1, pos*2, vTxid), right;
+ // calculate right hash if not beyond the end of the array - copy left hash otherwise1
+ if (pos*2+1 < CalcTreeWidth(height-1))
+ right = CalcHash(height-1, pos*2+1, vTxid);
+ else
+ right = left;
+ // combine subhashes
+ return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
+ }
+}
+
+void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) {
+ // determine whether this node is the parent of at least one matched txid
+ bool fParentOfMatch = false;
+ for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++)
+ fParentOfMatch |= vMatch[p];
+ // store as flag bit
+ vBits.push_back(fParentOfMatch);
+ if (height==0 || !fParentOfMatch) {
+ // if at height 0, or nothing interesting below, store hash and stop
+ vHash.push_back(CalcHash(height, pos, vTxid));
+ } else {
+ // otherwise, don't store any hash, but descend into the subtrees
+ TraverseAndBuild(height-1, pos*2, vTxid, vMatch);
+ if (pos*2+1 < CalcTreeWidth(height-1))
+ TraverseAndBuild(height-1, pos*2+1, vTxid, vMatch);
+ }
+}
+
+uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch) {
+ if (nBitsUsed >= vBits.size()) {
+ // overflowed the bits array - failure
+ fBad = true;
+ return 0;
+ }
+ bool fParentOfMatch = vBits[nBitsUsed++];
+ if (height==0 || !fParentOfMatch) {
+ // if at height 0, or nothing interesting below, use stored hash and do not descend
+ if (nHashUsed >= vHash.size()) {
+ // overflowed the hash array - failure
+ fBad = true;
+ return 0;
+ }
+ const uint256 &hash = vHash[nHashUsed++];
+ if (height==0 && fParentOfMatch) // in case of height 0, we have a matched txid
+ vMatch.push_back(hash);
+ return hash;
+ } else {
+ // otherwise, descend into the subtrees to extract matched txids and hashes
+ uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right;
+ if (pos*2+1 < CalcTreeWidth(height-1))
+ right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
+ else
+ right = left;
+ // and combine them before returning
+ return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
+ }
+}
+
+CPartialMerkleTree::CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) : nTransactions(vTxid.size()), fBad(false) {
+ // reset state
+ vBits.clear();
+ vHash.clear();
+
+ // calculate height of tree
+ int nHeight = 0;
+ while (CalcTreeWidth(nHeight) > 1)
+ nHeight++;
+
+ // traverse the partial tree
+ TraverseAndBuild(nHeight, 0, vTxid, vMatch);
+}
+
+CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
+
+uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
+ vMatch.clear();
+ // An empty set will not work
+ if (nTransactions == 0)
+ return 0;
+ // check for excessively high numbers of transactions
+ if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
+ return 0;
+ // there can never be more hashes provided than one for every txid
+ if (vHash.size() > nTransactions)
+ return 0;
+ // there must be at least one bit per node in the partial tree, and at least one node per hash
+ if (vBits.size() < vHash.size())
+ return 0;
+ // calculate height of tree
+ int nHeight = 0;
+ while (CalcTreeWidth(nHeight) > 1)
+ nHeight++;
+ // traverse the partial tree
+ unsigned int nBitsUsed = 0, nHashUsed = 0;
+ uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch);
+ // verify that no problems occured during the tree traversal
+ if (fBad)
+ return 0;
+ // verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
+ if ((nBitsUsed+7)/8 != (vBits.size()+7)/8)
+ return 0;
+ // verify that all hashes were consumed
+ if (nHashUsed != vHash.size())
+ return 0;
+ return hashMerkleRoot;
+}
diff --git a/src/merkleblock.h b/src/merkleblock.h
new file mode 100644
index 0000000000..c549e3cdba
--- /dev/null
+++ b/src/merkleblock.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_MERKLEBLOCK_H
+#define BITCOIN_MERKLEBLOCK_H
+
+#include "serialize.h"
+#include "uint256.h"
+#include "primitives/block.h"
+#include "bloom.h"
+
+#include <vector>
+
+/** Data structure that represents a partial merkle tree.
+ *
+ * It represents a subset of the txid's of a known block, in a way that
+ * allows recovery of the list of txid's and the merkle root, in an
+ * authenticated way.
+ *
+ * The encoding works as follows: we traverse the tree in depth-first order,
+ * storing a bit for each traversed node, signifying whether the node is the
+ * parent of at least one matched leaf txid (or a matched txid itself). In
+ * case we are at the leaf level, or this bit is 0, its merkle node hash is
+ * stored, and its children are not explorer further. Otherwise, no hash is
+ * stored, but we recurse into both (or the only) child branch. During
+ * decoding, the same depth-first traversal is performed, consuming bits and
+ * hashes as they written during encoding.
+ *
+ * The serialization is fixed and provides a hard guarantee about the
+ * encoded size:
+ *
+ * SIZE <= 10 + ceil(32.25*N)
+ *
+ * Where N represents the number of leaf nodes of the partial tree. N itself
+ * is bounded by:
+ *
+ * N <= total_transactions
+ * N <= 1 + matched_transactions*tree_height
+ *
+ * The serialization format:
+ * - uint32 total_transactions (4 bytes)
+ * - varint number of hashes (1-3 bytes)
+ * - uint256[] hashes in depth-first order (<= 32*N bytes)
+ * - varint number of bytes of flag bits (1-3 bytes)
+ * - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
+ * The size constraints follow from this.
+ */
+class CPartialMerkleTree
+{
+protected:
+ /** the total number of transactions in the block */
+ unsigned int nTransactions;
+
+ /** node-is-parent-of-matched-txid bits */
+ std::vector<bool> vBits;
+
+ /** txids and internal hashes */
+ std::vector<uint256> vHash;
+
+ /** flag set when encountering invalid data */
+ bool fBad;
+
+ /** helper function to efficiently calculate the number of nodes at given height in the merkle tree */
+ unsigned int CalcTreeWidth(int height) {
+ return (nTransactions+(1 << height)-1) >> height;
+ }
+
+ /** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */
+ uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
+
+ /** recursive function that traverses tree nodes, storing the data as bits and hashes */
+ void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
+
+ /**
+ * recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
+ * it returns the hash of the respective node.
+ */
+ uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
+
+public:
+
+ /** serialization implementation */
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(nTransactions);
+ READWRITE(vHash);
+ std::vector<unsigned char> vBytes;
+ if (ser_action.ForRead()) {
+ READWRITE(vBytes);
+ CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
+ us.vBits.resize(vBytes.size() * 8);
+ for (unsigned int p = 0; p < us.vBits.size(); p++)
+ us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
+ us.fBad = false;
+ } else {
+ vBytes.resize((vBits.size()+7)/8);
+ for (unsigned int p = 0; p < vBits.size(); p++)
+ vBytes[p / 8] |= vBits[p] << (p % 8);
+ READWRITE(vBytes);
+ }
+ }
+
+ /** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */
+ CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
+
+ CPartialMerkleTree();
+
+ /**
+ * extract the matching txid's represented by this partial merkle tree.
+ * returns the merkle root, or 0 in case of failure
+ */
+ uint256 ExtractMatches(std::vector<uint256> &vMatch);
+};
+
+
+/**
+ * Used to relay blocks as header + vector<merkle branch>
+ * to filtered nodes.
+ */
+class CMerkleBlock
+{
+public:
+ /** Public only for unit testing */
+ CBlockHeader header;
+ CPartialMerkleTree txn;
+
+public:
+ /** Public only for unit testing and relay testing (not relayed) */
+ std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
+
+ /**
+ * Create from a CBlock, filtering transactions according to filter
+ * Note that this will call IsRelevantAndUpdate on the filter for each transaction,
+ * thus the filter will likely be modified.
+ */
+ CMerkleBlock(const CBlock& block, CBloomFilter& filter);
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(header);
+ READWRITE(txn);
+ }
+};
+
+#endif // BITCOIN_MERKLEBLOCK_H
diff --git a/src/primitives/block.h b/src/primitives/block.h
index e663c91e84..a189592539 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -10,6 +10,9 @@
#include "serialize.h"
#include "uint256.h"
+/** The maximum allowed size for a serialized block, in bytes (network rule) */
+static const unsigned int MAX_BLOCK_SIZE = 1000000;
+
/** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work
* requirements. When they solve the proof-of-work, they broadcast the block
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 783e284af5..2de226fdd6 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -7,10 +7,12 @@
#include "base58.h"
#include "clientversion.h"
#include "key.h"
-#include "main.h"
+#include "merkleblock.h"
#include "serialize.h"
+#include "streams.h"
#include "uint256.h"
#include "util.h"
+#include "utilstrencodings.h"
#include <vector>
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index 9dce4daac6..3b535a84fd 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -2,9 +2,11 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "main.h"
+#include "merkleblock.h"
#include "serialize.h"
+#include "streams.h"
#include "uint256.h"
+#include "version.h"
#include <vector>