diff --git a/db.cpp b/db.cpp index 7116b0aa..8134a905 100644 --- a/db.cpp +++ b/db.cpp @@ -459,6 +459,29 @@ bool CTxDB::LoadBlockIndex() // Load bnBestInvalidWork, OK if it doesn't exist ReadBestInvalidWork(bnBestInvalidWork); + // Verify blocks in the best chain + CBlockIndex* pindexFork = NULL; + for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) + { + CBlock block; + if (!block.ReadFromDisk(pindex)) + return error("LoadBlockIndex() : block.ReadFromDisk failed"); + if (!block.CheckBlock()) + { + printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); + pindexFork = pindex->pprev; + } + } + if (pindexFork) + { + printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight); + CBlock block; + if (!block.ReadFromDisk(pindexFork)) + return error("LoadBlockIndex() : block.ReadFromDisk failed"); + CTxDB txdb; + block.SetBestChain(txdb, pindexFork); + } + return true; } diff --git a/main.cpp b/main.cpp index 6fe0c0e9..6311735e 100644 --- a/main.cpp +++ b/main.cpp @@ -1234,6 +1234,57 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) } +bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) +{ + uint256 hash = GetHash(); + + txdb.TxnBegin(); + if (pindexGenesisBlock == NULL && hash == hashGenesisBlock) + { + pindexGenesisBlock = pindexNew; + txdb.WriteHashBestChain(hash); + } + else if (hashPrevBlock == hashBestChain) + { + // Adding to current best branch + if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash)) + { + txdb.TxnAbort(); + Lockdown(pindexNew); + return error("SetBestChain() : ConnectBlock failed"); + } + txdb.TxnCommit(); + pindexNew->pprev->pnext = pindexNew; + + // Delete redundant memory transactions + foreach(CTransaction& tx, vtx) + tx.RemoveFromMemoryPool(); + } + else + { + // New best branch + if (!Reorganize(txdb, pindexNew)) + { + txdb.TxnAbort(); + Lockdown(pindexNew); + return error("SetBestChain() : Reorganize failed"); + } + } + txdb.TxnCommit(); + + // New best block + hashBestChain = hash; + pindexBest = pindexNew; + nBestHeight = pindexBest->nHeight; + bnBestChainWork = pindexNew->bnChainWork; + nTimeBestReceived = GetTime(); + nTransactionsUpdated++; + printf("SetBestChain: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,22).c_str(), nBestHeight, bnBestChainWork.ToString().c_str()); + + return true; +} + + bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) { // Check for duplicate @@ -1260,50 +1311,8 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) // New best if (pindexNew->bnChainWork > bnBestChainWork) - { - txdb.TxnBegin(); - if (pindexGenesisBlock == NULL && hash == hashGenesisBlock) - { - pindexGenesisBlock = pindexNew; - txdb.WriteHashBestChain(hash); - } - else if (hashPrevBlock == hashBestChain) - { - // Adding to current best branch - if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash)) - { - txdb.TxnAbort(); - Lockdown(pindexNew); - return error("AddToBlockIndex() : ConnectBlock failed"); - } - txdb.TxnCommit(); - pindexNew->pprev->pnext = pindexNew; - - // Delete redundant memory transactions - foreach(CTransaction& tx, vtx) - tx.RemoveFromMemoryPool(); - } - else - { - // New best branch - if (!Reorganize(txdb, pindexNew)) - { - txdb.TxnAbort(); - Lockdown(pindexNew); - return error("AddToBlockIndex() : Reorganize failed"); - } - } - txdb.TxnCommit(); - - // New best block - hashBestChain = hash; - pindexBest = pindexNew; - nBestHeight = pindexBest->nHeight; - bnBestChainWork = pindexNew->bnChainWork; - nTimeBestReceived = GetTime(); - nTransactionsUpdated++; - printf("AddToBlockIndex: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,22).c_str(), nBestHeight, bnBestChainWork.ToString().c_str()); - } + if (!SetBestChain(txdb, pindexNew)) + return false; txdb.Close(); diff --git a/main.h b/main.h index 771b21bf..1cc410be 100644 --- a/main.h +++ b/main.h @@ -1065,6 +1065,7 @@ public: bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex); bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex); bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions=true); + bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew); bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos); bool CheckBlock() const; bool AcceptBlock(); diff --git a/rpc.cpp b/rpc.cpp index d03a7ce7..679951af 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -120,7 +120,7 @@ Value getblockcount(const Array& params, bool fHelp) "getblockcount\n" "Returns the number of blocks in the longest block chain."); - return nBestHeight + 1; + return nBestHeight; } @@ -240,7 +240,7 @@ Value getinfo(const Array& params, bool fHelp) Object obj; obj.push_back(Pair("version", (int)VERSION)); obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN)); - obj.push_back(Pair("blocks", (int)nBestHeight + 1)); + obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); obj.push_back(Pair("generate", (bool)fGenerateBitcoins)); diff --git a/serialize.h b/serialize.h index 208a96d2..e5e1f0f8 100644 --- a/serialize.h +++ b/serialize.h @@ -20,7 +20,7 @@ class CDataStream; class CAutoFile; static const int VERSION = 310; -static const char* pszSubVer = ".1"; +static const char* pszSubVer = ".2"; diff --git a/ui.cpp b/ui.cpp index 885adeaa..b8f50b45 100644 --- a/ui.cpp +++ b/ui.cpp @@ -1027,7 +1027,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) strGen = _("(not connected)"); m_statusBar->SetStatusText(strGen, 1); - string strStatus = strprintf(_(" %d connections %d blocks %d transactions"), vNodes.size(), nBestHeight + 1, nTransactionCount); + string strStatus = strprintf(_(" %d connections %d blocks %d transactions"), vNodes.size(), nBestHeight, nTransactionCount); m_statusBar->SetStatusText(strStatus, 2); if (fDebug && GetTime() - nThreadSocketHandlerHeartbeat > 60)