Add checksums to undo data
This should be compatible with older code that didn't write checksums.
This commit is contained in:
parent
2cbd71da06
commit
8539361e66
2 changed files with 52 additions and 16 deletions
22
src/main.cpp
22
src/main.cpp
|
@ -1474,19 +1474,11 @@ bool CBlock::DisconnectBlock(CBlockIndex *pindex, CCoinsViewCache &view, bool *p
|
||||||
bool fClean = true;
|
bool fClean = true;
|
||||||
|
|
||||||
CBlockUndo blockUndo;
|
CBlockUndo blockUndo;
|
||||||
{
|
CDiskBlockPos pos = pindex->GetUndoPos();
|
||||||
CDiskBlockPos pos = pindex->GetUndoPos();
|
if (pos.IsNull())
|
||||||
if (pos.IsNull())
|
return error("DisconnectBlock() : no undo data available");
|
||||||
return error("DisconnectBlock() : no undo data available");
|
if (!blockUndo.ReadFromDisk(pos, pindex->pprev->GetBlockHash()))
|
||||||
CAutoFile fileUndo(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
|
return error("DisconnectBlock() : failure reading undo data");
|
||||||
if (!fileUndo)
|
|
||||||
return error("DisconnectBlock() : cannot open undo file");
|
|
||||||
try {
|
|
||||||
fileUndo >> blockUndo;
|
|
||||||
} catch(std::exception &e) {
|
|
||||||
return error("DisconnectBlock() : deserialize or I/O error reading udno data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockUndo.vtxundo.size() + 1 != vtx.size())
|
if (blockUndo.vtxundo.size() + 1 != vtx.size())
|
||||||
return error("DisconnectBlock() : block and undo data inconsistent");
|
return error("DisconnectBlock() : block and undo data inconsistent");
|
||||||
|
@ -1670,9 +1662,9 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
|
||||||
{
|
{
|
||||||
if (pindex->GetUndoPos().IsNull()) {
|
if (pindex->GetUndoPos().IsNull()) {
|
||||||
CDiskBlockPos pos;
|
CDiskBlockPos pos;
|
||||||
if (!FindUndoPos(pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 8))
|
if (!FindUndoPos(pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
|
||||||
return error("ConnectBlock() : FindUndoPos failed");
|
return error("ConnectBlock() : FindUndoPos failed");
|
||||||
if (!blockundo.WriteToDisk(pos))
|
if (!blockundo.WriteToDisk(pos, pindex->pprev->GetBlockHash()))
|
||||||
return error("ConnectBlock() : CBlockUndo::WriteToDisk failed");
|
return error("ConnectBlock() : CBlockUndo::WriteToDisk failed");
|
||||||
|
|
||||||
// update nUndoPos in block index
|
// update nUndoPos in block index
|
||||||
|
|
46
src/main.h
46
src/main.h
|
@ -746,7 +746,7 @@ public:
|
||||||
READWRITE(vtxundo);
|
READWRITE(vtxundo);
|
||||||
)
|
)
|
||||||
|
|
||||||
bool WriteToDisk(CDiskBlockPos &pos)
|
bool WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock)
|
||||||
{
|
{
|
||||||
// Open history file to append
|
// Open history file to append
|
||||||
CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
|
CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
|
||||||
|
@ -764,6 +764,12 @@ public:
|
||||||
pos.nPos = (unsigned int)fileOutPos;
|
pos.nPos = (unsigned int)fileOutPos;
|
||||||
fileout << *this;
|
fileout << *this;
|
||||||
|
|
||||||
|
// calculate & write checksum
|
||||||
|
CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
|
||||||
|
hasher << hashBlock;
|
||||||
|
hasher << *this;
|
||||||
|
fileout << hasher.GetHash();
|
||||||
|
|
||||||
// Flush stdio buffers and commit to disk before returning
|
// Flush stdio buffers and commit to disk before returning
|
||||||
fflush(fileout);
|
fflush(fileout);
|
||||||
if (!IsInitialBlockDownload())
|
if (!IsInitialBlockDownload())
|
||||||
|
@ -771,6 +777,44 @@ public:
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock)
|
||||||
|
{
|
||||||
|
// Open history file to read
|
||||||
|
CAutoFile filein = CAutoFile(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
|
||||||
|
if (!filein)
|
||||||
|
return error("CBlockUndo::ReadFromDisk() : OpenBlockFile failed");
|
||||||
|
|
||||||
|
// Read block
|
||||||
|
uint256 hashChecksum;
|
||||||
|
try {
|
||||||
|
filein >> *this;
|
||||||
|
}
|
||||||
|
catch (std::exception &e) {
|
||||||
|
return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for compatibility with pre-release code that didn't write checksums to undo data
|
||||||
|
// TODO: replace by a simply 'filein >> hashChecksum' in the above try block
|
||||||
|
try {
|
||||||
|
filein >> hashChecksum;
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
hashChecksum = 0;
|
||||||
|
}
|
||||||
|
uint32_t hashInit = hashChecksum.Get64(0) & 0xFFFFFFFFUL;
|
||||||
|
if (hashChecksum == 0 || memcmp(&hashInit, pchMessageStart, 4) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Verify checksum
|
||||||
|
CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
|
||||||
|
hasher << hashBlock;
|
||||||
|
hasher << *this;
|
||||||
|
if (hashChecksum != hasher.GetHash())
|
||||||
|
return error("CBlockUndo::ReadFromDisk() : checksum mismatch");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
|
/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
|
||||||
|
|
Loading…
Reference in a new issue