From d979e6e36ac6be0d40b2a6bb70c668f9e6989ff9 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 3 Sep 2012 15:26:57 +0200 Subject: [PATCH] Use singleton block tree database instance --- src/db.cpp | 30 +++++++++---------- src/db.h | 12 ++++---- src/init.cpp | 3 ++ src/main.cpp | 61 +++++++++++++++------------------------ src/main.h | 6 +++- src/test/test_bitcoin.cpp | 8 +++++ 6 files changed, 61 insertions(+), 59 deletions(-) diff --git a/src/db.cpp b/src/db.cpp index e77ddd77..5fe7e058 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -273,7 +273,7 @@ CDB::CDB(const char *pszFile, const char* pszMode) : static bool IsChainFile(std::string strFile) { - if (strFile == "coins.dat" || strFile == "chain.dat") + if (strFile == "coins.dat" || strFile == "blktree.dat") return true; return false; @@ -483,7 +483,7 @@ void CDBEnv::Flush(bool fShutdown) // -// CChainDB and CCoinsDB +// CBlockTreeDB and CCoinsDB // bool CCoinsDB::HaveCoins(uint256 hash) { @@ -504,7 +504,7 @@ bool CCoinsDB::WriteCoins(uint256 hash, const CCoins &coins) { return Write(make_pair('c', hash), coins); } -bool CChainDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) +bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) { return Write(make_pair('b', blockindex.GetBlockHash()), blockindex); } @@ -519,29 +519,29 @@ bool CCoinsDB::WriteHashBestChain(uint256 hashBestChain) return Write('B', hashBestChain); } -bool CChainDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork) +bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork) { return Read('I', bnBestInvalidWork); } -bool CChainDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork) +bool CBlockTreeDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork) { return Write('I', bnBestInvalidWork); } -bool CChainDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) { +bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) { return Write(make_pair('f', nFile), info); } -bool CChainDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { +bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { return Read(make_pair('f', nFile), info); } -bool CChainDB::WriteLastBlockFile(int nFile) { +bool CBlockTreeDB::WriteLastBlockFile(int nFile) { return Write('l', nFile); } -bool CChainDB::ReadLastBlockFile(int &nFile) { +bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { return Read('l', nFile); } @@ -601,9 +601,9 @@ CBlockIndex static * InsertBlockIndex(uint256 hash) return pindexNew; } -bool LoadBlockIndex(CChainDB &chaindb) +bool LoadBlockIndexDB() { - if (!chaindb.LoadBlockIndexGuts()) + if (!pblocktree->LoadBlockIndexGuts()) return false; if (fRequestShutdown) @@ -628,9 +628,9 @@ bool LoadBlockIndex(CChainDB &chaindb) } // Load block file info - chaindb.ReadLastBlockFile(nLastBlockFile); + pblocktree->ReadLastBlockFile(nLastBlockFile); printf("LoadBlockIndex(): last block file = %i\n", nLastBlockFile); - if (chaindb.ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile)) + if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile)) printf("LoadBlockIndex(): last block file: %s\n", infoLastBlockFile.ToString().c_str()); // Load hashBestChain pointer to end of best chain @@ -656,7 +656,7 @@ bool LoadBlockIndex(CChainDB &chaindb) DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); // Load bnBestInvalidWork, OK if it doesn't exist - chaindb.ReadBestInvalidWork(bnBestInvalidWork); + pblocktree->ReadBestInvalidWork(bnBestInvalidWork); // Verify blocks in the best chain int nCheckLevel = GetArg("-checklevel", 1); @@ -693,7 +693,7 @@ bool LoadBlockIndex(CChainDB &chaindb) -bool CChainDB::LoadBlockIndexGuts() +bool CBlockTreeDB::LoadBlockIndexGuts() { // Get database cursor Dbc* pcursor = GetCursor(); diff --git a/src/db.h b/src/db.h index bdab6354..d0696f3d 100644 --- a/src/db.h +++ b/src/db.h @@ -348,14 +348,14 @@ public: }; -/** Access to the block database (chain.dat) */ -class CChainDB : public CDB +/** Access to the block database (blktree.dat) */ +class CBlockTreeDB : public CDB { public: - CChainDB(const char* pszMode="r+") : CDB("chain.dat", pszMode) { } + CBlockTreeDB(const char* pszMode="r+") : CDB("blktree.dat", pszMode) { } private: - CChainDB(const CChainDB&); - void operator=(const CChainDB&); + CBlockTreeDB(const CBlockTreeDB&); + void operator=(const CBlockTreeDB&); public: bool WriteBlockIndex(const CDiskBlockIndex& blockindex); bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork); @@ -368,7 +368,7 @@ public: }; -bool LoadBlockIndex(CChainDB &chaindb); +bool LoadBlockIndexDB(); /** Access to the (IP) address database (peers.dat) */ diff --git a/src/init.cpp b/src/init.cpp index 99e2bba3..07e5d13d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -79,8 +79,10 @@ void Shutdown(void* parg) { LOCK(cs_main); pcoinsTip->Flush(); + pblocktree->Flush(); delete pcoinsTip; delete pcoinsdbview; + delete pblocktree; } bitdb.Flush(true); boost::filesystem::remove(GetPidFile()); @@ -650,6 +652,7 @@ bool AppInit2() uiInterface.InitMessage(_("Loading block index...")); printf("Loading block index...\n"); nStart = GetTimeMillis(); + pblocktree = new CBlockTreeDB("cr+"); pcoinsdbview = new CCoinsViewDB(); pcoinsTip = new CCoinsViewCache(*pcoinsdbview); diff --git a/src/main.cpp b/src/main.cpp index b077eb9d..6395a254 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -270,6 +270,7 @@ bool CCoinsViewMemPool::HaveCoins(uint256 txid) { } CCoinsViewCache *pcoinsTip = NULL; +CBlockTreeDB *pblocktree = NULL; ////////////////////////////////////////////////////////////////////////////// // @@ -1143,7 +1144,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) if (pindexNew->bnChainWork > bnBestInvalidWork) { bnBestInvalidWork = pindexNew->bnChainWork; - CChainDB().WriteBestInvalidWork(bnBestInvalidWork); + pblocktree->WriteBestInvalidWork(bnBestInvalidWork); uiInterface.NotifyBlocksChanged(); } printf("InvalidChainFound: invalid block=%s height=%d work=%s date=%s\n", @@ -1159,7 +1160,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) void static InvalidBlockFound(CBlockIndex *pindex) { pindex->nStatus |= BLOCK_FAILED_VALID; - CChainDB().WriteBlockIndex(CDiskBlockIndex(pindex)); + pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex)); setBlockIndexValid.erase(pindex); InvalidChainFound(pindex); if (pindex->pnext) @@ -1186,12 +1187,11 @@ bool ConnectBestBlock() { do { if (pindexTest->nStatus & BLOCK_FAILED_MASK) { // mark descendants failed - CChainDB chaindb; CBlockIndex *pindexFailed = pindexNewBest; while (pindexTest != pindexFailed) { pindexFailed->nStatus |= BLOCK_FAILED_CHILD; setBlockIndexValid.erase(pindexFailed); - chaindb.WriteBlockIndex(CDiskBlockIndex(pindexFailed)); + pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexFailed)); pindexFailed = pindexFailed->pprev; } InvalidChainFound(pindexNewBest); @@ -1498,7 +1498,7 @@ bool CBlock::DisconnectBlock(CBlockIndex *pindex, CCoinsViewCache &view) return true; } -bool FindUndoPos(CChainDB &chaindb, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); +bool FindUndoPos(int nFile, CDiskBlockPos &pos, unsigned int nAddSize); bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck) { @@ -1581,11 +1581,9 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust // Write undo information to disk if (pindex->GetUndoPos().IsNull() || (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) { - CChainDB chaindb; - if (pindex->GetUndoPos().IsNull()) { CDiskBlockPos pos; - if (!FindUndoPos(chaindb, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 8)) + if (!FindUndoPos(pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 8)) return error("ConnectBlock() : FindUndoPos failed"); if (!blockundo.WriteToDisk(pos)) return error("ConnectBlock() : CBlockUndo::WriteToDisk failed"); @@ -1598,7 +1596,7 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust pindex->nStatus = (pindex->nStatus & ~BLOCK_VALID_MASK) | BLOCK_VALID_SCRIPTS; CDiskBlockIndex blockindex(pindex); - if (!chaindb.WriteBlockIndex(blockindex)) + if (!pblocktree->WriteBlockIndex(blockindex)) return error("ConnectBlock() : WriteBlockIndex failed"); } @@ -1804,12 +1802,7 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos) pindexNew->nStatus = BLOCK_VALID_TRANSACTIONS | BLOCK_HAVE_DATA; setBlockIndexValid.insert(pindexNew); - CChainDB chaindb; - if (!chaindb.TxnBegin()) - return false; - chaindb.WriteBlockIndex(CDiskBlockIndex(pindexNew)); - if (!chaindb.TxnCommit()) - return false; + pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)); // New best? if (!ConnectBestBlock()) @@ -1823,13 +1816,15 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos) hashPrevBestCoinBase = GetTxHash(0); } + pblocktree->Flush(); + uiInterface.NotifyBlocksChanged(); return true; } -bool FindBlockPos(CChainDB &chaindb, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64 nTime) +bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64 nTime) { bool fUpdatedLast = false; @@ -1845,7 +1840,7 @@ bool FindBlockPos(CChainDB &chaindb, CDiskBlockPos &pos, unsigned int nAddSize, fclose(file); nLastBlockFile++; infoLastBlockFile.SetNull(); - chaindb.ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile); // check whether data for the new file somehow already exist; can fail just fine + pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile); // check whether data for the new file somehow already exist; can fail just fine fUpdatedLast = true; } @@ -1865,15 +1860,15 @@ bool FindBlockPos(CChainDB &chaindb, CDiskBlockPos &pos, unsigned int nAddSize, fclose(file); } - if (!chaindb.WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) + if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) return error("FindBlockPos() : cannot write updated block info"); if (fUpdatedLast) - chaindb.WriteLastBlockFile(nLastBlockFile); + pblocktree->WriteLastBlockFile(nLastBlockFile); return true; } -bool FindUndoPos(CChainDB &chaindb, int nFile, CDiskBlockPos &pos, unsigned int nAddSize) +bool FindUndoPos(int nFile, CDiskBlockPos &pos, unsigned int nAddSize) { pos.nFile = nFile; @@ -1883,15 +1878,15 @@ bool FindUndoPos(CChainDB &chaindb, int nFile, CDiskBlockPos &pos, unsigned int if (nFile == nLastBlockFile) { pos.nPos = infoLastBlockFile.nUndoSize; nNewSize = (infoLastBlockFile.nUndoSize += nAddSize); - if (!chaindb.WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) + if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) return error("FindUndoPos() : cannot write updated block info"); } else { CBlockFileInfo info; - if (!chaindb.ReadBlockFileInfo(nFile, info)) + if (!pblocktree->ReadBlockFileInfo(nFile, info)) return error("FindUndoPos() : cannot read block info"); pos.nPos = info.nUndoSize; nNewSize = (info.nUndoSize += nAddSize); - if (!chaindb.WriteBlockFileInfo(nFile, info)) + if (!pblocktree->WriteBlockFileInfo(nFile, info)) return error("FindUndoPos() : cannot write updated block info"); } @@ -2022,11 +2017,8 @@ bool CBlock::AcceptBlock() if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) return error("AcceptBlock() : out of disk space"); CDiskBlockPos blockPos; - { - CChainDB chaindb; - if (!FindBlockPos(chaindb, blockPos, nBlockSize+8, nHeight, nTime)) - return error("AcceptBlock() : FindBlockPos failed"); - } + if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, nTime)) + return error("AcceptBlock() : FindBlockPos failed"); if (!WriteToDisk(blockPos)) return error("AcceptBlock() : WriteToDisk failed"); if (!AddToBlockIndex(blockPos)) @@ -2210,12 +2202,10 @@ bool LoadBlockIndex(bool fAllowNew) } // - // Load block index + // Load block index from databases // - CChainDB chaindb("cr"); - if (!LoadBlockIndex(chaindb)) + if (!LoadBlockIndexDB()) return false; - chaindb.Close(); // // Init with genesis block @@ -2267,11 +2257,8 @@ bool LoadBlockIndex(bool fAllowNew) // Start new block file unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); CDiskBlockPos blockPos; - { - CChainDB chaindb; - if (!FindBlockPos(chaindb, blockPos, nBlockSize+8, 0, block.nTime)) - return error("AcceptBlock() : FindBlockPos failed"); - } + if (!FindBlockPos(blockPos, nBlockSize+8, 0, block.nTime)) + return error("AcceptBlock() : FindBlockPos failed"); if (!block.WriteToDisk(blockPos)) return error("LoadBlockIndex() : writing genesis block to disk failed"); if (!block.AddToBlockIndex(blockPos)) diff --git a/src/main.h b/src/main.h index 687171ef..2cab48c9 100644 --- a/src/main.h +++ b/src/main.h @@ -86,7 +86,7 @@ static const uint64 nMinDiskSpace = 52428800; class CReserveKey; class CCoinsDB; -class CChainDB; +class CBlockTreeDB; class CDiskBlockPos; class CCoins; class CTxUndo; @@ -1865,6 +1865,10 @@ public: bool HaveCoins(uint256 txid); }; +/** Global variable that points to the active CCoinsView (protected by cs_main) */ extern CCoinsViewCache *pcoinsTip; +/** Global variable that points to the active block tree (protected by cs_main) */ +extern CBlockTreeDB *pblocktree; + #endif diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index bcf09078..4580877c 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -12,10 +12,15 @@ extern bool fPrintToConsole; extern void noui_connect(); struct TestingSetup { + CCoinsViewDB *pcoinsdbview; + TestingSetup() { fPrintToDebugger = true; // don't want to write to debug.log file noui_connect(); bitdb.MakeMock(); + pblocktree = new CBlockTreeDB("cr+"); + pcoinsdbview = new CCoinsViewDB(); + pcoinsTip = new CCoinsViewCache(*pcoinsdbview); LoadBlockIndex(true); bool fFirstRun; pwalletMain = new CWallet("wallet.dat"); @@ -26,6 +31,9 @@ struct TestingSetup { { delete pwalletMain; pwalletMain = NULL; + delete pcoinsTip; + delete pcoinsdbview; + delete pblocktree; bitdb.Flush(true); } };