|
|
|
@ -581,128 +581,6 @@ public:
@@ -581,128 +581,6 @@ public:
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CBlock : public CBlockHeader |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
// network and disk
|
|
|
|
|
std::vector<CTransaction> vtx; |
|
|
|
|
|
|
|
|
|
// memory only
|
|
|
|
|
mutable std::vector<uint256> vMerkleTree; |
|
|
|
|
|
|
|
|
|
CBlock() |
|
|
|
|
{ |
|
|
|
|
SetNull(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CBlock(const CBlockHeader &header) |
|
|
|
|
{ |
|
|
|
|
SetNull(); |
|
|
|
|
*((CBlockHeader*)this) = header; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IMPLEMENT_SERIALIZE |
|
|
|
|
( |
|
|
|
|
READWRITE(*(CBlockHeader*)this); |
|
|
|
|
READWRITE(vtx); |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
void SetNull() |
|
|
|
|
{ |
|
|
|
|
CBlockHeader::SetNull(); |
|
|
|
|
vtx.clear(); |
|
|
|
|
vMerkleTree.clear(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CBlockHeader GetBlockHeader() const |
|
|
|
|
{ |
|
|
|
|
CBlockHeader block; |
|
|
|
|
block.nVersion = nVersion; |
|
|
|
|
block.hashPrevBlock = hashPrevBlock; |
|
|
|
|
block.hashMerkleRoot = hashMerkleRoot; |
|
|
|
|
block.nTime = nTime; |
|
|
|
|
block.nBits = nBits; |
|
|
|
|
block.nNonce = nNonce; |
|
|
|
|
return block; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint256 BuildMerkleTree() const |
|
|
|
|
{ |
|
|
|
|
vMerkleTree.clear(); |
|
|
|
|
BOOST_FOREACH(const CTransaction& tx, vtx) |
|
|
|
|
vMerkleTree.push_back(tx.GetHash()); |
|
|
|
|
int j = 0; |
|
|
|
|
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) |
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < nSize; i += 2) |
|
|
|
|
{ |
|
|
|
|
int i2 = std::min(i+1, nSize-1); |
|
|
|
|
vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), |
|
|
|
|
BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); |
|
|
|
|
} |
|
|
|
|
j += nSize; |
|
|
|
|
} |
|
|
|
|
return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const uint256 &GetTxHash(unsigned int nIndex) const { |
|
|
|
|
assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
|
|
|
|
|
assert(nIndex < vtx.size()); |
|
|
|
|
return vMerkleTree[nIndex]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<uint256> GetMerkleBranch(int nIndex) const |
|
|
|
|
{ |
|
|
|
|
if (vMerkleTree.empty()) |
|
|
|
|
BuildMerkleTree(); |
|
|
|
|
std::vector<uint256> vMerkleBranch; |
|
|
|
|
int j = 0; |
|
|
|
|
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) |
|
|
|
|
{ |
|
|
|
|
int i = std::min(nIndex^1, nSize-1); |
|
|
|
|
vMerkleBranch.push_back(vMerkleTree[j+i]); |
|
|
|
|
nIndex >>= 1; |
|
|
|
|
j += nSize; |
|
|
|
|
} |
|
|
|
|
return vMerkleBranch; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex) |
|
|
|
|
{ |
|
|
|
|
if (nIndex == -1) |
|
|
|
|
return 0; |
|
|
|
|
BOOST_FOREACH(const uint256& otherside, vMerkleBranch) |
|
|
|
|
{ |
|
|
|
|
if (nIndex & 1) |
|
|
|
|
hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash)); |
|
|
|
|
else |
|
|
|
|
hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside)); |
|
|
|
|
nIndex >>= 1; |
|
|
|
|
} |
|
|
|
|
return hash; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void print() const |
|
|
|
|
{ |
|
|
|
|
printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n", |
|
|
|
|
GetHash().ToString().c_str(), |
|
|
|
|
nVersion, |
|
|
|
|
hashPrevBlock.ToString().c_str(), |
|
|
|
|
hashMerkleRoot.ToString().c_str(), |
|
|
|
|
nTime, nBits, nNonce, |
|
|
|
|
vtx.size()); |
|
|
|
|
for (unsigned int i = 0; i < vtx.size(); i++) |
|
|
|
|
{ |
|
|
|
|
printf(" "); |
|
|
|
|
vtx[i].print(); |
|
|
|
|
} |
|
|
|
|
printf(" vMerkleTree: "); |
|
|
|
|
for (unsigned int i = 0; i < vMerkleTree.size(); i++) |
|
|
|
|
printf("%s ", vMerkleTree[i].ToString().c_str()); |
|
|
|
|
printf("\n"); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Functions for disk access for blocks */ |
|
|
|
|
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos); |
|
|
|
|