Move only: extract WriteChainState and UpdatedTip from SetBestChain.

This commit is contained in:
Pieter Wuille 2013-11-16 18:40:55 +01:00
parent ca1913e8f6
commit 0ec16f35d6

View File

@ -1746,6 +1746,66 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return true; return true;
} }
bool static WriteChainState(CValidationState &state) {
if (!IsInitialBlockDownload() || pcoinsTip->GetCacheSize() > nCoinCacheSize) {
// Typical CCoins structures on disk are around 100 bytes in size.
// Pushing a new one to the database can cause it to be written
// twice (once in the log, and once in the tables). This is already
// an overestimation, as most will delete an existing entry or
// overwrite one. Still, use a conservative safety factor of 2.
if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize()))
return state.Error();
FlushBlockFile();
pblocktree->Sync();
if (!pcoinsTip->Flush())
return state.Abort(_("Failed to write to coin database"));
}
return true;
}
void static UpdateTip(CBlockIndex *pindexNew) {
chainActive.SetTip(pindexNew);
// Update best block in wallet (so we can detect restored wallets)
bool fIsInitialDownload = IsInitialBlockDownload();
if ((chainActive.Height() % 20160) == 0 || (!fIsInitialDownload && (chainActive.Height() % 144) == 0))
g_signals.SetBestChain(chainActive.GetLocator());
// New best block
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
LogPrintf("UpdateTip: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainActive.Tip()));
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
{
int nUpgraded = 0;
const CBlockIndex* pindex = chainActive.Tip();
for (int i = 0; i < 100 && pindex != NULL; i++)
{
if (pindex->nVersion > CBlock::CURRENT_VERSION)
++nUpgraded;
pindex = pindex->pprev;
}
if (nUpgraded > 0)
LogPrintf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, (int)CBlock::CURRENT_VERSION);
if (nUpgraded > 100/2)
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
}
std::string strCmd = GetArg("-blocknotify", "");
if (!fIsInitialDownload && !strCmd.empty())
{
boost::replace_all(strCmd, "%s", chainActive.Tip()->GetBlockHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free
}
}
bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew) bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
{ {
mempool.check(pcoinsTip); mempool.check(pcoinsTip);
@ -1839,27 +1899,8 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
if (fBenchmark) if (fBenchmark)
LogPrintf("- Flush %i transactions: %.2fms (%.4fms/tx)\n", nModified, 0.001 * nTime, 0.001 * nTime / nModified); LogPrintf("- Flush %i transactions: %.2fms (%.4fms/tx)\n", nModified, 0.001 * nTime, 0.001 * nTime / nModified);
// Make sure it's successfully written to disk before changing memory structure if (!WriteChainState(state))
bool fIsInitialDownload = IsInitialBlockDownload(); return false;
if (!fIsInitialDownload || pcoinsTip->GetCacheSize() > nCoinCacheSize) {
// Typical CCoins structures on disk are around 100 bytes in size.
// Pushing a new one to the database can cause it to be written
// twice (once in the log, and once in the tables). This is already
// an overestimation, as most will delete an existing entry or
// overwrite one. Still, use a conservative safety factor of 2.
if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize()))
return state.Error();
FlushBlockFile();
pblocktree->Sync();
if (!pcoinsTip->Flush())
return state.Abort(_("Failed to write to coin database"));
}
// At this point, all changes have been done to the database.
// Proceed by updating the memory structures.
// Register new best chain
chainActive.SetTip(pindexNew);
// Resurrect memory transactions that were in the disconnected branch // Resurrect memory transactions that were in the disconnected branch
BOOST_FOREACH(CTransaction& tx, vResurrect) { BOOST_FOREACH(CTransaction& tx, vResurrect) {
@ -1877,48 +1918,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
mempool.check(pcoinsTip); mempool.check(pcoinsTip);
// Update best block in wallet (so we can detect restored wallets) UpdateTip(pindexNew);
if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
g_signals.SetBestChain(chainActive.GetLocator(pindexNew));
// New best block
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
LogPrintf("SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainActive.Tip()));
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
{
int nUpgraded = 0;
const CBlockIndex* pindex = chainActive.Tip();
for (int i = 0; i < 100 && pindex != NULL; i++)
{
if (pindex->nVersion > CBlock::CURRENT_VERSION)
++nUpgraded;
pindex = pindex->pprev;
}
if (nUpgraded > 0)
LogPrintf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, (int)CBlock::CURRENT_VERSION);
if (nUpgraded > 100/2)
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
}
std::string strCmd = GetArg("-blocknotify", "");
if (!fIsInitialDownload && !strCmd.empty())
{
boost::replace_all(strCmd, "%s", chainActive.Tip()->GetBlockHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free
}
return true; return true;
} }
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos) bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{ {
// Check for duplicate // Check for duplicate