@@ -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 \ |
@@ -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> |
@@ -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); |
@@ -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) {}; |
@@ -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; | |||
} |
@@ -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 |
@@ -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 |
@@ -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> | |||
@@ -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> | |||