Improve dealing with abort conditions

This commit is contained in:
Pieter Wuille 2013-01-27 01:24:06 +01:00 committed by Pieter Wuille
parent 18379c8087
commit 7851033dd6
2 changed files with 42 additions and 37 deletions

View file

@ -1687,7 +1687,7 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
return error("ConnectBlock() : FindUndoPos failed"); return error("ConnectBlock() : FindUndoPos failed");
if (!blockundo.WriteToDisk(pos, pindex->pprev->GetBlockHash())) if (!blockundo.WriteToDisk(pos, pindex->pprev->GetBlockHash()))
return state.Error(error("ConnectBlock() : CBlockUndo::WriteToDisk failed")); return state.Abort(_("Error: failed to write undo data"));
// update nUndoPos in block index // update nUndoPos in block index
pindex->nUndoPos = pos.nPos; pindex->nUndoPos = pos.nPos;
@ -1698,16 +1698,15 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
CDiskBlockIndex blockindex(pindex); CDiskBlockIndex blockindex(pindex);
if (!pblocktree->WriteBlockIndex(blockindex)) if (!pblocktree->WriteBlockIndex(blockindex))
return state.Error(error("ConnectBlock() : WriteBlockIndex failed")); return state.Abort(_("Error: failed to write block index"));
} }
if (fTxIndex) if (fTxIndex)
if (!pblocktree->WriteTxIndex(vPos)) if (!pblocktree->WriteTxIndex(vPos))
return state.Error(error("ConnectBlock() : WriteTxIndex failed")); return state.Abort(_("Error: failed to write transaction index"));
// add this block to the view's block chain // add this block to the view's block chain
if (!view.SetBestBlock(pindex)) assert(view.SetBestBlock(pindex));
return state.Error();
// Watch for transactions paying to me // Watch for transactions paying to me
for (unsigned int i=0; i<vtx.size(); i++) for (unsigned int i=0; i<vtx.size(); i++)
@ -1727,13 +1726,14 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
CBlockIndex* plonger = pindexNew; CBlockIndex* plonger = pindexNew;
while (pfork && pfork != plonger) while (pfork && pfork != plonger)
{ {
while (plonger->nHeight > pfork->nHeight) while (plonger->nHeight > pfork->nHeight) {
if (!(plonger = plonger->pprev)) plonger = plonger->pprev;
return state.Error(error("SetBestChain() : plonger->pprev is null")); assert(plonger != NULL);
}
if (pfork == plonger) if (pfork == plonger)
break; break;
if (!(pfork = pfork->pprev)) pfork = pfork->pprev;
return state.Error(error("SetBestChain() : pfork->pprev is null")); assert(pfork != NULL);
} }
// List of what to disconnect (typically nothing) // List of what to disconnect (typically nothing)
@ -1757,7 +1757,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) { BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
CBlock block; CBlock block;
if (!block.ReadFromDisk(pindex)) if (!block.ReadFromDisk(pindex))
return state.Error(error("SetBestBlock() : ReadFromDisk for disconnect failed")); return state.Abort(_("Error: failed to read block"));
int64 nStart = GetTimeMicros(); int64 nStart = GetTimeMicros();
if (!block.DisconnectBlock(state, pindex, view)) if (!block.DisconnectBlock(state, pindex, view))
return error("SetBestBlock() : DisconnectBlock %s failed", BlockHashStr(pindex->GetBlockHash()).c_str()); return error("SetBestBlock() : DisconnectBlock %s failed", BlockHashStr(pindex->GetBlockHash()).c_str());
@ -1777,7 +1777,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
BOOST_FOREACH(CBlockIndex *pindex, vConnect) { BOOST_FOREACH(CBlockIndex *pindex, vConnect) {
CBlock block; CBlock block;
if (!block.ReadFromDisk(pindex)) if (!block.ReadFromDisk(pindex))
return state.Error(error("SetBestBlock() : ReadFromDisk for connect failed")); return state.Abort(_("Error: failed to read block"));
int64 nStart = GetTimeMicros(); int64 nStart = GetTimeMicros();
if (!block.ConnectBlock(state, pindex, view)) { if (!block.ConnectBlock(state, pindex, view)) {
if (state.IsInvalid()) { if (state.IsInvalid()) {
@ -1797,8 +1797,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Flush changes to global coin state // Flush changes to global coin state
int64 nStart = GetTimeMicros(); int64 nStart = GetTimeMicros();
int nModified = view.GetCacheSize(); int nModified = view.GetCacheSize();
if (!view.Flush()) assert(view.Flush());
return state.Error(error("SetBestBlock() : unable to modify coin state"));
int64 nTime = GetTimeMicros() - nStart; int64 nTime = GetTimeMicros() - nStart;
if (fBenchmark) if (fBenchmark)
printf("- Flush %i transactions: %.2fms (%.4fms/tx)\n", nModified, 0.001 * nTime, 0.001 * nTime / nModified); printf("- Flush %i transactions: %.2fms (%.4fms/tx)\n", nModified, 0.001 * nTime, 0.001 * nTime / nModified);
@ -1816,7 +1815,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
FlushBlockFile(); FlushBlockFile();
pblocktree->Sync(); pblocktree->Sync();
if (!pcoinsTip->Flush()) if (!pcoinsTip->Flush())
return state.Error(); return state.Abort(_("Error: failed to write to coin database"));
} }
// At this point, all changes have been done to the database. // At this point, all changes have been done to the database.
@ -1903,8 +1902,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
// Construct new block index object // Construct new block index object
CBlockIndex* pindexNew = new CBlockIndex(*this); CBlockIndex* pindexNew = new CBlockIndex(*this);
if (!pindexNew) assert(pindexNew);
return state.Error(error("AddToBlockIndex() : new CBlockIndex failed"));
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first); pindexNew->phashBlock = &((*mi).first);
map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock); map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
@ -1923,7 +1921,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
setBlockIndexValid.insert(pindexNew); setBlockIndexValid.insert(pindexNew);
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew))) if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
return state.Error(error("AddToBlockIndex() : writing block index failed")); return state.Abort(_("Error: failed to write block index"));
// New best? // New best?
if (!ConnectBestBlock(state)) if (!ConnectBestBlock(state))
@ -1938,7 +1936,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
} }
if (!pblocktree->Flush()) if (!pblocktree->Flush())
return state.Error("AddToBlockIndex() : failed to sync block tree"); return state.Abort(_("Error: failed to sync block index"));
uiInterface.NotifyBlocksChanged(); uiInterface.NotifyBlocksChanged();
return true; return true;
@ -1987,12 +1985,12 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
} }
} }
else else
return state.Error(error("FindBlockPos() : out of disk space")); return state.Error();
} }
} }
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
return state.Error(error("FindBlockPos() : cannot write updated block info")); return state.Abort(_("Error: failed to write file info"));
if (fUpdatedLast) if (fUpdatedLast)
pblocktree->WriteLastBlockFile(nLastBlockFile); pblocktree->WriteLastBlockFile(nLastBlockFile);
@ -2010,15 +2008,15 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
pos.nPos = infoLastBlockFile.nUndoSize; pos.nPos = infoLastBlockFile.nUndoSize;
nNewSize = (infoLastBlockFile.nUndoSize += nAddSize); nNewSize = (infoLastBlockFile.nUndoSize += nAddSize);
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
return state.Error(error("FindUndoPos() : cannot write updated block info")); return state.Abort(_("Error: failed to write block info"));
} else { } else {
CBlockFileInfo info; CBlockFileInfo info;
if (!pblocktree->ReadBlockFileInfo(nFile, info)) if (!pblocktree->ReadBlockFileInfo(nFile, info))
return state.Error(error("FindUndoPos() : cannot read block info")); return state.Abort(_("Error: failed to read block info"));
pos.nPos = info.nUndoSize; pos.nPos = info.nUndoSize;
nNewSize = (info.nUndoSize += nAddSize); nNewSize = (info.nUndoSize += nAddSize);
if (!pblocktree->WriteBlockFileInfo(nFile, info)) if (!pblocktree->WriteBlockFileInfo(nFile, info))
return state.Error(error("FindUndoPos() : cannot write updated block info")); return state.Abort(_("Error: failed to write block info"));
} }
unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
@ -2033,7 +2031,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
} }
} }
else else
return state.Error(error("FindUndoPos() : out of disk space")); return state.Error();
} }
return true; return true;
@ -2164,7 +2162,7 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
return error("AcceptBlock() : FindBlockPos failed"); return error("AcceptBlock() : FindBlockPos failed");
if (dbp == NULL) if (dbp == NULL)
if (!WriteToDisk(blockPos)) if (!WriteToDisk(blockPos))
return state.Error(error("AcceptBlock() : WriteToDisk failed")); return state.Abort(_("Error: failed to write block"));
if (!AddToBlockIndex(state, blockPos)) if (!AddToBlockIndex(state, blockPos))
return error("AcceptBlock() : AddToBlockIndex failed"); return error("AcceptBlock() : AddToBlockIndex failed");
@ -2430,6 +2428,14 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
bool AbortNode(const std::string &strMessage) {
fRequestShutdown = true;
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR);
StartShutdown();
return false;
}
bool CheckDiskSpace(uint64 nAdditionalBytes) bool CheckDiskSpace(uint64 nAdditionalBytes)
{ {
@ -2437,15 +2443,8 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
// Check for nMinDiskSpace bytes (currently 50MB) // Check for nMinDiskSpace bytes (currently 50MB)
if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)
{ return AbortNode(_("Error: Disk space is low!"));
fShutdown = true;
string strMessage = _("Error: Disk space is low!");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR);
StartShutdown();
return false;
}
return true; return true;
} }

View file

@ -181,6 +181,8 @@ bool ConnectBestBlock(CValidationState &state);
CBlockIndex * InsertBlockIndex(uint256 hash); CBlockIndex * InsertBlockIndex(uint256 hash);
/** Verify a signature */ /** Verify a signature */
bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType); bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
/** Abort with a message */
bool AbortNode(const std::string &msg);
@ -1886,9 +1888,13 @@ public:
bool Invalid(bool ret = false) { bool Invalid(bool ret = false) {
return DoS(0, ret); return DoS(0, ret);
} }
bool Error(bool ret = false) { bool Error() {
mode = MODE_ERROR; mode = MODE_ERROR;
return ret; return false;
}
bool Abort(const std::string &msg) {
AbortNode(msg);
return Error();
} }
bool IsValid() { bool IsValid() {
return mode == MODE_VALID; return mode == MODE_VALID;