Split off CBlockHeader from CBlock

Cleaner and removes the need for the application-specific flags in
serialize.h.
This commit is contained in:
Pieter Wuille 2012-11-14 22:18:10 +01:00
parent 6caffb5358
commit e754cf4133
5 changed files with 55 additions and 46 deletions

View file

@ -998,21 +998,16 @@ CBlockIndex* FindBlockByHeight(int nHeight)
return pblockindex; return pblockindex;
} }
bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions) bool CBlock::ReadFromDisk(const CBlockIndex* pindex)
{ {
if (!fReadTransactions) if (!ReadFromDisk(pindex->GetBlockPos()))
{
*this = pindex->GetBlockHeader();
return true;
}
if (!ReadFromDisk(pindex->GetBlockPos(), fReadTransactions))
return false; return false;
if (GetHash() != pindex->GetBlockHash()) if (GetHash() != pindex->GetBlockHash())
return error("CBlock::ReadFromDisk() : GetHash() doesn't match index"); return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");
return true; return true;
} }
uint256 static GetOrphanRoot(const CBlock* pblock) uint256 static GetOrphanRoot(const CBlockHeader* pblock)
{ {
// Work back to the first block in the orphan chain // Work back to the first block in the orphan chain
while (mapOrphanBlocks.count(pblock->hashPrevBlock)) while (mapOrphanBlocks.count(pblock->hashPrevBlock))
@ -1059,7 +1054,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime)
return bnResult.GetCompact(); return bnResult.GetCompact();
} }
unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlock *pblock) unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
{ {
unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact(); unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact();
@ -1233,7 +1228,7 @@ bool ConnectBestBlock() {
} while(true); } while(true);
} }
void CBlock::UpdateTime(const CBlockIndex* pindexPrev) void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev)
{ {
nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
@ -3072,6 +3067,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pindex = pindex->pnext; pindex = pindex->pnext;
} }
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
vector<CBlock> vHeaders; vector<CBlock> vHeaders;
int nLimit = 2000; int nLimit = 2000;
printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str()); printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str());

View file

@ -1068,7 +1068,7 @@ public:
* in the block is a special one that creates a new coin owned by the creator * in the block is a special one that creates a new coin owned by the creator
* of the block. * of the block.
*/ */
class CBlock class CBlockHeader
{ {
public: public:
// header // header
@ -1080,17 +1080,7 @@ public:
unsigned int nBits; unsigned int nBits;
unsigned int nNonce; unsigned int nNonce;
// network and disk CBlockHeader()
std::vector<CTransaction> vtx;
// memory only
mutable std::vector<uint256> vMerkleTree;
// Denial-of-service detection:
mutable int nDoS;
bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
CBlock()
{ {
SetNull(); SetNull();
} }
@ -1104,25 +1094,16 @@ public:
READWRITE(nTime); READWRITE(nTime);
READWRITE(nBits); READWRITE(nBits);
READWRITE(nNonce); READWRITE(nNonce);
// ConnectBlock depends on vtx being last so it can calculate offset
if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
READWRITE(vtx);
else if (fRead)
const_cast<CBlock*>(this)->vtx.clear();
) )
void SetNull() void SetNull()
{ {
nVersion = CBlock::CURRENT_VERSION; nVersion = CBlockHeader::CURRENT_VERSION;
hashPrevBlock = 0; hashPrevBlock = 0;
hashMerkleRoot = 0; hashMerkleRoot = 0;
nTime = 0; nTime = 0;
nBits = 0; nBits = 0;
nNonce = 0; nNonce = 0;
vtx.clear();
vMerkleTree.clear();
nDoS = 0;
} }
bool IsNull() const bool IsNull() const
@ -1141,7 +1122,45 @@ public:
} }
void UpdateTime(const CBlockIndex* pindexPrev); void UpdateTime(const CBlockIndex* pindexPrev);
};
class CBlock : public CBlockHeader
{
public:
// network and disk
std::vector<CTransaction> vtx;
// memory only
mutable std::vector<uint256> vMerkleTree;
// Denial-of-service detection:
mutable int nDoS;
bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
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();
nDoS = 0;
}
uint256 BuildMerkleTree() const uint256 BuildMerkleTree() const
{ {
@ -1226,7 +1245,7 @@ public:
return true; return true;
} }
bool ReadFromDisk(const CDiskBlockPos &pos, bool fReadTransactions = true) bool ReadFromDisk(const CDiskBlockPos &pos)
{ {
SetNull(); SetNull();
@ -1234,8 +1253,6 @@ public:
CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION); CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
if (!filein) if (!filein)
return error("CBlock::ReadFromDisk() : OpenBlockFile failed"); return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
if (!fReadTransactions)
filein.nType |= SER_BLOCKHEADERONLY;
// Read block // Read block
try { try {
@ -1282,7 +1299,7 @@ public:
bool ConnectBlock(CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false); bool ConnectBlock(CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false);
// Read a block from disk // Read a block from disk
bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true); bool ReadFromDisk(const CBlockIndex* pindex);
// Add this block to the block index, and if necessary, switch the active block chain to this // Add this block to the block index, and if necessary, switch the active block chain to this
bool AddToBlockIndex(const CDiskBlockPos &pos); bool AddToBlockIndex(const CDiskBlockPos &pos);
@ -1447,7 +1464,7 @@ public:
nNonce = 0; nNonce = 0;
} }
CBlockIndex(CBlock& block) CBlockIndex(CBlockHeader& block)
{ {
phashBlock = NULL; phashBlock = NULL;
pprev = NULL; pprev = NULL;
@ -1488,9 +1505,9 @@ public:
return ret; return ret;
} }
CBlock GetBlockHeader() const CBlockHeader GetBlockHeader() const
{ {
CBlock block; CBlockHeader block;
block.nVersion = nVersion; block.nVersion = nVersion;
if (pprev) if (pprev)
block.hashPrevBlock = pprev->GetBlockHash(); block.hashPrevBlock = pprev->GetBlockHash();
@ -1634,7 +1651,7 @@ public:
uint256 GetBlockHash() const uint256 GetBlockHash() const
{ {
CBlock block; CBlockHeader block;
block.nVersion = nVersion; block.nVersion = nVersion;
block.hashPrevBlock = hashPrev; block.hashPrevBlock = hashPrev;
block.hashMerkleRoot = hashMerkleRoot; block.hashMerkleRoot = hashMerkleRoot;

View file

@ -154,7 +154,7 @@ Value getblock(const Array& params, bool fHelp)
CBlock block; CBlock block;
CBlockIndex* pblockindex = mapBlockIndex[hash]; CBlockIndex* pblockindex = mapBlockIndex[hash];
block.ReadFromDisk(pblockindex, true); block.ReadFromDisk(pblockindex);
return blockToJSON(block, pblockindex); return blockToJSON(block, pblockindex);
} }

View file

@ -50,10 +50,6 @@ enum
SER_NETWORK = (1 << 0), SER_NETWORK = (1 << 0),
SER_DISK = (1 << 1), SER_DISK = (1 << 1),
SER_GETHASH = (1 << 2), SER_GETHASH = (1 << 2),
// modifiers
SER_SKIPSIG = (1 << 16),
SER_BLOCKHEADERONLY = (1 << 17),
}; };
#define IMPLEMENT_SERIALIZE(statements) \ #define IMPLEMENT_SERIALIZE(statements) \

View file

@ -752,7 +752,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
while (pindex) while (pindex)
{ {
CBlock block; CBlock block;
block.ReadFromDisk(pindex, true); block.ReadFromDisk(pindex);
BOOST_FOREACH(CTransaction& tx, block.vtx) BOOST_FOREACH(CTransaction& tx, block.vtx)
{ {
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate)) if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))