diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2012-09-03 21:14:03 +0200 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2012-10-20 23:08:57 +0200 |
commit | 2d8a48292b0da96cda8d7b45a24a22adfb4667b2 (patch) | |
tree | 351935f27dcd037d68d514c3a79ff5d2d24da367 /src/main.cpp | |
parent | 44d40f26dcc73469bfbfda5f981c2c528d592ac7 (diff) |
LevelDB block and coin databases
Split off CBlockTreeDB and CCoinsViewDB into txdb-*.{cpp,h} files,
implemented by either LevelDB or BDB.
Based on code from earlier commits by Mike Hearn in his leveldb
branch.
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp index 44e690b959..94f1a93151 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "alert.h" #include "checkpoints.h" #include "db.h" +#include "txdb.h" #include "net.h" #include "init.h" #include "ui_interface.h" @@ -1719,6 +1720,7 @@ bool SetBestChain(CBlockIndex* pindexNew) bool fIsInitialDownload = IsInitialBlockDownload(); if (!fIsInitialDownload || view.GetCacheSize()>5000) { FlushBlockFile(); + pblocktree->Sync(); if (!view.Flush()) return false; } @@ -2203,6 +2205,116 @@ FILE *OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "rev", fReadOnly); } +CBlockIndex * InsertBlockIndex(uint256 hash) +{ + if (hash == 0) + return NULL; + + // Return existing + map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end()) + return (*mi).second; + + // Create new + CBlockIndex* pindexNew = new CBlockIndex(); + if (!pindexNew) + throw runtime_error("LoadBlockIndex() : new CBlockIndex failed"); + mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; + pindexNew->phashBlock = &((*mi).first); + + return pindexNew; +} + +bool static LoadBlockIndexDB() +{ + if (!pblocktree->LoadBlockIndexGuts()) + return false; + + if (fRequestShutdown) + return true; + + // Calculate bnChainWork + vector<pair<int, CBlockIndex*> > vSortedByHeight; + vSortedByHeight.reserve(mapBlockIndex.size()); + BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + { + CBlockIndex* pindex = item.second; + vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); + } + sort(vSortedByHeight.begin(), vSortedByHeight.end()); + BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) + { + CBlockIndex* pindex = item.second; + pindex->bnChainWork = (pindex->pprev ? pindex->pprev->bnChainWork : 0) + pindex->GetBlockWork(); + pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx; + if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS && !(pindex->nStatus & BLOCK_FAILED_MASK)) + setBlockIndexValid.insert(pindex); + } + + // Load block file info + pblocktree->ReadLastBlockFile(nLastBlockFile); + printf("LoadBlockIndex(): last block file = %i\n", nLastBlockFile); + if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile)) + printf("LoadBlockIndex(): last block file: %s\n", infoLastBlockFile.ToString().c_str()); + + // Load hashBestChain pointer to end of best chain + pindexBest = pcoinsTip->GetBestBlock(); + if (pindexBest == NULL) + { + if (pindexGenesisBlock == NULL) + return true; + } + hashBestChain = pindexBest->GetBlockHash(); + nBestHeight = pindexBest->nHeight; + bnBestChainWork = pindexBest->bnChainWork; + + // set 'next' pointers in best chain + CBlockIndex *pindex = pindexBest; + while(pindex != NULL && pindex->pprev != NULL) { + CBlockIndex *pindexPrev = pindex->pprev; + pindexPrev->pnext = pindex; + pindex = pindexPrev; + } + printf("LoadBlockIndex(): hashBestChain=%s height=%d date=%s\n", + hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, + DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); + + // Load bnBestInvalidWork, OK if it doesn't exist + pblocktree->ReadBestInvalidWork(bnBestInvalidWork); + + // Verify blocks in the best chain + int nCheckLevel = GetArg("-checklevel", 1); + int nCheckDepth = GetArg( "-checkblocks", 2500); + if (nCheckDepth == 0) + nCheckDepth = 1000000000; // suffices until the year 19000 + if (nCheckDepth > nBestHeight) + nCheckDepth = nBestHeight; + printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); + CBlockIndex* pindexFork = NULL; + for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) + { + if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth) + break; + CBlock block; + if (!block.ReadFromDisk(pindex)) + return error("LoadBlockIndex() : block.ReadFromDisk failed"); + // check level 1: verify block validity + if (nCheckLevel>0 && !block.CheckBlock()) + { + printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); + pindexFork = pindex->pprev; + } + // TODO: stronger verifications + } + if (pindexFork && !fRequestShutdown) + { + // TODO: reorg back + return error("LoadBlockIndex(): chain database corrupted"); + } + + return true; +} + bool LoadBlockIndex(bool fAllowNew) { if (fTestNet) |