|
|
|
@ -1746,6 +1746,66 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
@@ -1746,6 +1746,66 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
mempool.check(pcoinsTip); |
|
|
|
@ -1839,27 +1899,8 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
@@ -1839,27 +1899,8 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|
|
|
|
if (fBenchmark) |
|
|
|
|
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
|
|
|
|
|
bool fIsInitialDownload = IsInitialBlockDownload(); |
|
|
|
|
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); |
|
|
|
|
if (!WriteChainState(state)) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
// Resurrect memory transactions that were in the disconnected branch
|
|
|
|
|
BOOST_FOREACH(CTransaction& tx, vResurrect) { |
|
|
|
@ -1877,48 +1918,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
@@ -1877,48 +1918,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|
|
|
|
|
|
|
|
|
mempool.check(pcoinsTip); |
|
|
|
|
|
|
|
|
|
// Update best block in wallet (so we can detect restored wallets)
|
|
|
|
|
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
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UpdateTip(pindexNew); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos) |
|
|
|
|
{ |
|
|
|
|
// Check for duplicate
|
|
|
|
|