Skip to content

Commit

Permalink
v1.3.0.1 disabled forced reindex on init
Browse files Browse the repository at this point in the history
  • Loading branch information
HellMar committed Feb 20, 2019
1 parent 9633c4c commit afb51a4
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 92 deletions.
4 changes: 2 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 1)
define(_CLIENT_VERSION_MINOR, 3)
define(_CLIENT_VERSION_REVISION, 0)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_BUILD, 1)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2018)
define(_COPYRIGHT_YEAR, 2019)
AC_INIT([XDNA Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[www.xdna.io],[xdna])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_HEADERS([src/config/xdna-config.h])
Expand Down
5 changes: 1 addition & 4 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1253,11 +1253,8 @@ bool AppInit2(boost::thread_group& threadGroup)
if (fReindex)
pblocktree->WriteReindexing(true);

uiInterface.InitMessage(_("Loading block index..."));
string strBlockIndexError = "";
if (!LoadBlockIndex(strBlockIndexError)) {
if (!LoadBlockIndex()) {
strLoadError = _("Error loading block database");
strLoadError = strprintf("%s : %s", strLoadError, strBlockIndexError);
break;
}

Expand Down
166 changes: 87 additions & 79 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ bool fReindex = false;
bool fTxIndex = true;
bool fIsBareMultisigStd = true;
bool fCheckBlockIndex = false;
bool fVerifyingBlocks = false;
unsigned int nCoinCacheSize = 5000;
bool fAlerts = DEFAULT_ALERTS;

Expand Down Expand Up @@ -1697,7 +1696,7 @@ int64_t GetMasternodePayment(int nHeight, uint32_t nTime, unsigned mnlevel, int6
bool IsInitialBlockDownload()
{
LOCK(cs_main);
if (fImporting || fReindex || fVerifyingBlocks || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
return true;
static bool lockIBDState = false;
if (lockIBDState)
Expand Down Expand Up @@ -2087,11 +2086,11 @@ static int64_t nTimeIndex = 0;
static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0;

bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck, bool fAlreadyChecked)
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
{
AssertLockHeld(cs_main);
// Check it again in case a previous version let a bad block in
if (!fAlreadyChecked && !CheckBlock(block, state, !fJustCheck, !fJustCheck))
if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
return false;

// verify that the view's current state corresponds to the previous block
Expand Down Expand Up @@ -2431,15 +2430,12 @@ static int64_t nTimePostConnect = 0;
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock* pblock, bool fAlreadyChecked)
bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock* pblock)
{
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
CCoinsViewCache view(pcoinsTip);

if (pblock == NULL)
fAlreadyChecked = false;

// Read block from disk.
int64_t nTime1 = GetTimeMicros();
CBlock block;
Expand All @@ -2455,7 +2451,7 @@ bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock*
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
{
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
bool rv = ConnectBlock(*pblock, state, pindexNew, view, false, fAlreadyChecked);
bool rv = ConnectBlock(*pblock, state, pindexNew, view);
g_signals.BlockChecked(*pblock, state);
if (!rv) {
if (state.IsInvalid())
Expand Down Expand Up @@ -2666,11 +2662,9 @@ static void PruneBlockIndexCandidates()
* Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMostWork, CBlock* pblock, bool fAlreadyChecked)
static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMostWork, CBlock* pblock)
{
AssertLockHeld(cs_main);
if (pblock == NULL)
fAlreadyChecked = false;
bool fInvalidFound = false;
const CBlockIndex* pindexOldTip = chainActive.Tip();
const CBlockIndex* pindexFork = chainActive.FindFork(pindexMostWork);
Expand Down Expand Up @@ -2700,7 +2694,7 @@ static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMo

// Connect new blocks.
BOOST_REVERSE_FOREACH (CBlockIndex* pindexConnect, vpindexToConnect) {
if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL, fAlreadyChecked)) {
if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
Expand Down Expand Up @@ -2738,7 +2732,7 @@ static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMo
* or an activated best chain. pblock is either NULL or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
*/
bool ActivateBestChain(CValidationState& state, CBlock* pblock, bool fAlreadyChecked)
bool ActivateBestChain(CValidationState& state, CBlock* pblock)
{
CBlockIndex* pindexNewTip = NULL;
CBlockIndex* pindexMostWork = NULL;
Expand All @@ -2759,7 +2753,7 @@ bool ActivateBestChain(CValidationState& state, CBlock* pblock, bool fAlreadyChe
if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip())
return true;

if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fAlreadyChecked))
if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL))
return false;

pindexNewTip = chainActive.Tip();
Expand Down Expand Up @@ -3423,7 +3417,7 @@ bool AcceptBlockHeader(const CBlock& block, CValidationState& state, CBlockIndex
return true;
}

bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp, bool fAlreadyCheckedBlock)
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp)
{
AssertLockHeld(cs_main);

Expand Down Expand Up @@ -3464,7 +3458,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
return true;
}

if ((!fAlreadyCheckedBlock && !CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
Expand Down Expand Up @@ -3590,7 +3584,7 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis

// Store to disk
CBlockIndex* pindex = NULL;
bool ret = AcceptBlock(*pblock, state, &pindex, dbp, checked);
bool ret = AcceptBlock(*pblock, state, &pindex, dbp);
if (pindex && pfrom) {
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
}
Expand All @@ -3599,7 +3593,7 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis
return error("%s : AcceptBlock FAILED", __func__);
}

if (!ActivateBestChain(state, pblock, checked))
if (!ActivateBestChain(state, pblock))
return error("%s : ActivateBestChain failed", __func__);

if (!fLiteMode) {
Expand Down Expand Up @@ -3739,7 +3733,7 @@ CBlockIndex* InsertBlockIndex(uint256 hash)
return pindexNew;
}

bool static LoadBlockIndexDB(string& strError)
bool static LoadBlockIndexDB()
{
if (!pblocktree->LoadBlockIndexGuts())
return false;
Expand Down Expand Up @@ -3818,69 +3812,83 @@ bool static LoadBlockIndexDB(string& strError)
LogPrintf("%s: Last shutdown was prepared: %s\n", __func__, fLastShutdownWasPrepared);

//Check for inconsistency with block file info and internal state
if (!fLastShutdownWasPrepared && !GetBoolArg("-forcestart", false) && !GetBoolArg("-reindex", false)) {
unsigned int nHeightLastBlockFile = vinfoBlockFile[nLastBlockFile].nHeightLast + 1;
if (vSortedByHeight.size() > nHeightLastBlockFile && pcoinsTip->GetBestBlock() != vSortedByHeight[nHeightLastBlockFile].second->GetBlockHash()) {
//The database is in a state where a block has been accepted and written to disk, but the
//transaction database (pcoinsTip) was not flushed to disk, and is therefore not in sync with
//the block index database.

if (!mapBlockIndex.count(pcoinsTip->GetBestBlock())) {
strError = "The wallet has been not been closed gracefully, causing the transaction database to be out of sync with the block database";
return false;
}
LogPrintf("%s : pcoinstip synced to block height %d, block index height %d\n", __func__,
mapBlockIndex[pcoinsTip->GetBestBlock()]->nHeight, vSortedByHeight.size());

//get the index associated with the point in the chain that pcoinsTip is synced to
CBlockIndex* pindexLastMeta = vSortedByHeight[vinfoBlockFile[nLastBlockFile].nHeightLast + 1].second;
CBlockIndex* pindex = vSortedByHeight[0].second;
unsigned int nSortedPos = 0;
for (unsigned int i = 0; i < vSortedByHeight.size(); i++) {
nSortedPos = i;
if (vSortedByHeight[i].first == mapBlockIndex[pcoinsTip->GetBestBlock()]->nHeight + 1) {
pindex = vSortedByHeight[i].second;
break;
}
}
if (!fLastShutdownWasPrepared && !GetBoolArg("-forcestart", false) && !GetBoolArg("-reindex", false) && (vSortedByHeight.size() != vinfoBlockFile[nLastBlockFile].nHeightLast + 1) && (vinfoBlockFile[nLastBlockFile].nHeightLast != 0)) {
//The database is in a state where a block has been accepted and written to disk, but not
//all of the block has perculated through the code. The block and the index should both be
//intact (although assertions are added if they are not), and the block will be reprocessed
//to ensure all data will be accounted for.
LogPrintf("%s: Inconsistent State Detected mapBlockIndex.size()=%d blockFileBlocks=%d\n", __func__, vSortedByHeight.size(), vinfoBlockFile[nLastBlockFile].nHeightLast + 1);
LogPrintf("%s: lastIndexPos=%d blockFileSize=%d\n", __func__, vSortedByHeight[vSortedByHeight.size() - 1].second->GetBlockPos().nPos,
vinfoBlockFile[nLastBlockFile].nSize);

//try reading the block from the last index we have
bool isFixed = true;
string strError = "";
LogPrintf("%s: Attempting to re-add last block that was recorded to disk\n", __func__);

//get the last block that was properly recorded to the block info file
CBlockIndex* pindexLastMeta = vSortedByHeight[vinfoBlockFile[nLastBlockFile].nHeightLast + 1].second;

//fix Assertion `hashPrevBlock == view.GetBestBlock()' failed. By adjusting height to the last recorded by coinsview
CBlockIndex* pindexCoinsView = mapBlockIndex[pcoinsTip->GetBestBlock()];
for(unsigned int i = vinfoBlockFile[nLastBlockFile].nHeightLast + 1; i < vSortedByHeight.size(); i++)
{
pindexLastMeta = vSortedByHeight[i].second;
if(pindexLastMeta->nHeight > pindexCoinsView->nHeight)
break;
}

// Start at the last block that was successfully added to the txdb (pcoinsTip) and manually add all transactions that occurred for each block up until
// the best known block from the block index db.
CCoinsViewCache view(pcoinsTip);
while (nSortedPos < vSortedByHeight.size()) {
CBlock block;
if (!ReadBlockFromDisk(block, pindex)) {
strError = "The wallet has been not been closed gracefully and has caused corruption of blocks stored to disk. Data directory is in an unusable state";
return false;
}
LogPrintf("%s: Last block properly recorded: #%d %s\n", __func__, pindexLastMeta->nHeight, pindexLastMeta->GetBlockHash().ToString().c_str());

vector<CTxUndo> vtxundo;
vtxundo.reserve(block.vtx.size() - 1);
uint256 hashBlock = block.GetHash();
for (unsigned int i = 0; i < block.vtx.size(); i++) {
CValidationState state;
CTxUndo undoDummy;
if (i > 0)
vtxundo.push_back(CTxUndo());
UpdateCoins(block.vtx[i], state, view, i == 0 ? undoDummy : vtxundo.back(), pindex->nHeight);
view.SetBestBlock(hashBlock);
}
CBlock lastMetaBlock;
if (!ReadBlockFromDisk(lastMetaBlock, pindexLastMeta)) {
isFixed = false;
strError = strprintf("failed to read block %d from disk", pindexLastMeta->nHeight);
}

if (pindex->nHeight >= pindexLastMeta->nHeight)
break;
//set the chain to the block before lastMeta so that the meta block will be seen as new
chainActive.SetTip(pindexLastMeta->pprev);

pindex = vSortedByHeight[++nSortedPos].second;
}
//Process the lastMetaBlock again, using the known location on disk
CDiskBlockPos blockPos = pindexLastMeta->GetBlockPos();
CValidationState state;
ProcessNewBlock(state, NULL, &lastMetaBlock, &blockPos);

// Save the updates to disk
if (!view.Flush() || !pcoinsTip->Flush())
LogPrintf("%s : failed to flush view\n", __func__);
//ensure that everything is as it should be
if (pcoinsTip->GetBestBlock() != vSortedByHeight[vSortedByHeight.size() - 1].second->GetBlockHash()) {
isFixed = false;
strError = "pcoinsTip best block is not correct";
}

//properly account for all of the blocks that were not in the meta data. If this is not done the file
//positioning will be wrong and blocks will be overwritten and later cause serialization errors
CBlockIndex *pindexLast = vSortedByHeight[vSortedByHeight.size() - 1].second;
CBlock lastBlock;
if (!ReadBlockFromDisk(lastBlock, pindexLast)) {
isFixed = false;
strError = strprintf("failed to read block %d from disk", pindexLast->nHeight);
}
vinfoBlockFile[nLastBlockFile].nHeightLast = pindexLast->nHeight;
vinfoBlockFile[nLastBlockFile].nSize = pindexLast->GetBlockPos().nPos + ::GetSerializeSize(lastBlock, SER_DISK, CLIENT_VERSION);;
setDirtyFileInfo.insert(nLastBlockFile);
FlushStateToDisk(state, FLUSH_STATE_ALWAYS);

//Print out file info again
pblocktree->ReadLastBlockFile(nLastBlockFile);
vinfoBlockFile.resize(nLastBlockFile + 1);
LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile);
for (int nFile = 0; nFile <= nLastBlockFile; nFile++) {
pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
}
LogPrintf("%s: last block file info: %s\n", __func__, vinfoBlockFile[nLastBlockFile].ToString());

LogPrintf("%s: Last block properly recorded: #%d %s\n", __func__, pindexLastMeta->nHeight,
pindexLastMeta->GetBlockHash().ToString().c_str());
LogPrintf("%s : pcoinstip=%d %s\n", __func__, mapBlockIndex[pcoinsTip->GetBestBlock()]->nHeight,
pcoinsTip->GetBestBlock().GetHex());
if (!isFixed) {
strError = "Failed reading from database. " + strError + ". The block database is in an inconsistent state and may cause issues in the future."
"To force start use -forcestart";
uiInterface.ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR);
abort();
}
LogPrintf("Passed corruption fix\n");
}

// Check whether we need to continue reindexing
Expand Down Expand Up @@ -3988,7 +3996,7 @@ bool CVerifyDB::VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth
CBlock block;
if (!ReadBlockFromDisk(block, pindex))
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!ConnectBlock(block, state, pindex, coins, false))
if (!ConnectBlock(block, state, pindex, coins))
return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
}
Expand All @@ -4006,10 +4014,10 @@ void UnloadBlockIndex()
pindexBestInvalid = NULL;
}

bool LoadBlockIndex(string& strError)
bool LoadBlockIndex()
{
// Load block index from databases
if (!fReindex && !LoadBlockIndexDB(strError))
if (!fReindex && !LoadBlockIndexDB())
return false;
return true;
}
Expand Down
8 changes: 4 additions & 4 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp = NULL);
/** Initialize a new block tree database + block data on disk */
bool InitBlockIndex();
/** Load the block tree and coins database from disk */
bool LoadBlockIndex(std::string& strError);
bool LoadBlockIndex();
/** Unload database information */
void UnloadBlockIndex();
/** See whether the protocol update is enforced for connected nodes */
Expand Down Expand Up @@ -230,7 +230,7 @@ bool DisconnectBlocksAndReprocess(int blocks);
double ConvertBitsToDouble(unsigned int nBits);
int64_t GetMasternodePayment(int nHeight, uint32_t nTime, unsigned mnlevel, int64_t blockValue);

bool ActivateBestChain(CValidationState& state, CBlock* pblock = NULL, bool fAlreadyChecked = false);
bool ActivateBestChain(CValidationState& state, CBlock* pblock = NULL);
CAmount GetBlockValue(int nHeight, uint32_t nTime);

/** Create a new block index entry for a given block hash */
Expand Down Expand Up @@ -431,7 +431,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
bool DisconnectBlocksAndReprocess(int blocks);

/** Apply the effects of this block (with given index) on the UTXO set represented by coins */
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck, bool fAlreadyChecked = false);
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);

/** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
Expand All @@ -446,7 +446,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);

/** Store block on disk. If dbp is provided, the file is known to already reside on disk */
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL, bool fAlreadyCheckedBlock = false);
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex = NULL);


Expand Down
7 changes: 4 additions & 3 deletions src/spork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,15 @@ void ReprocessBlocks(int nBlocks)
++it;
}

CValidationState state;
{
LOCK(cs_main);
DisconnectBlocksAndReprocess(nBlocks);
}

CValidationState state;

ActivateBestChain(state);
if (state.IsValid()) {
ActivateBestChain(state);
}
}

bool CSporkManager::CheckSignature(CSporkMessage& spork)
Expand Down

0 comments on commit afb51a4

Please sign in to comment.