From ec5bf94651fe4225875ecac605be2c6606ffc4f7 Mon Sep 17 00:00:00 2001 From: "Shawn M." Date: Tue, 3 Sep 2024 13:08:20 -0700 Subject: [PATCH] Update db.cpp --- src/db.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 2 deletions(-) diff --git a/src/db.cpp b/src/db.cpp index 2f1010d..49d98fc 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -113,6 +113,31 @@ bool CDBEnv::Open(boost::filesystem::path pathEnv_) fDbEnvInit = true; fMockDb = false; +#ifndef USE_LEVELDB + // Check that the number of locks is sufficient (to prevent chain fork possibility, read http://bitcoin.org/may15 for more info) + u_int32_t nMaxLocks; + if (!dbenv.get_lk_max_locks(&nMaxLocks)) + { + int nBlocks, nDeepReorg; + std::string strMessage; + + nBlocks = nMaxLocks / 48768; + nDeepReorg = (nBlocks - 1) / 2; + + printf("Final lk_max_locks is %lu, sufficient for (worst case) %d block%s in a single transaction (up to a %d-deep reorganization)\n", (unsigned long)nMaxLocks, nBlocks, (nBlocks == 1) ? "" : "s", nDeepReorg); + if (nDeepReorg < 3) + { + if (nBlocks < 1) + strMessage = strprintf(_("Warning: DB_CONFIG has set_lk_max_locks %lu, which may be too low for a single block. If this limit is reached, NovaCoin may stop working."), (unsigned long)nMaxLocks); + else + strMessage = strprintf(_("Warning: DB_CONFIG has set_lk_max_locks %lu, which may be too low for a common blockchain reorganization. If this limit is reached, NovaCoin may stop working."), (unsigned long)nMaxLocks); + + strMiscWarning = strMessage; + printf("*** %s\n", strMessage.c_str()); + } + } +#endif + return true; } @@ -294,6 +319,14 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : } } +static bool IsChainFile(std::string strFile) +{ + if (strFile == "blkindex.dat") + return true; + + return false; +} + void CDB::Close() { if (!pdb) @@ -342,7 +375,7 @@ bool CDBEnv::RemoveDb(const string& strFile) bool CDB::Rewrite(const string& strFile, const char* pszSkip) { - while (true) + while (!fShutdown) { { LOCK(bitdb.cs_db); @@ -368,7 +401,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) 0); if (ret > 0) { - LogPrintf("Cannot create database file %s\n", strFileRes); + LogPrintf("Cannot create database file %s\n", strFileRes.c_str()); fSuccess = false; } @@ -477,3 +510,105 @@ void CDBEnv::Flush(bool fShutdown) } } } + + +// +// CAddrDB +// + + +CAddrDB::CAddrDB() +{ + pathAddr = GetDataDir() / "peers.dat"; +} + +bool CAddrDB::Write(const CAddrMan& addr) +{ + // Generate random temporary filename + unsigned short randv = 0; + RAND_bytes((unsigned char *)&randv, sizeof(randv)); + std::string tmpfn = strprintf("peers.dat.%04x", randv); + + // serialize addresses, checksum data up to that point, then append csum + CDataStream ssPeers(SER_DISK, CLIENT_VERSION); + ssPeers << FLATDATA(pchMessageStart); + ssPeers << addr; + uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); + ssPeers << hash; + + // open temp output file, and associate with CAutoFile + boost::filesystem::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fopen(pathTmp.string().c_str(), "wb"); + CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION); + if (!fileout) + return error("CAddrman::Write() : open failed"); + + // Write and commit header, data + try { + fileout << ssPeers; + } + catch (const std::exception&) { + return error("CAddrman::Write() : I/O error"); + } + FileCommit(fileout); + fileout.fclose(); + + // replace existing peers.dat, if any, with new peers.dat.XXXX + if (!RenameOver(pathTmp, pathAddr)) + return error("CAddrman::Write() : Rename-into-place failed"); + + return true; +} + +bool CAddrDB::Read(CAddrMan& addr) +{ + // open input file, and associate with CAutoFile + FILE *file = fopen(pathAddr.string().c_str(), "rb"); + CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION); + if (!filein) + return error("CAddrman::Read() : open failed"); + + // use file size to size memory buffer + int fileSize = GetFilesize(filein); + int dataSize = fileSize - sizeof(uint256); + //Don't try to resize to a negative number if file is small + if ( dataSize < 0 ) dataSize = 0; + vector vchData; + vchData.resize(dataSize); + uint256 hashIn; + + // read data and checksum from file + try { + filein.read((char *)&vchData[0], dataSize); + filein >> hashIn; + } + catch (const std::exception&) { + return error("CAddrman::Read() 2 : I/O error or stream data corrupted"); + } + filein.fclose(); + + CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); + + // verify stored checksum matches input data + uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); + if (hashIn != hashTmp) + return error("CAddrman::Read() : checksum mismatch; data corrupted"); + + unsigned char pchMsgTmp[4]; + try { + // de-serialize file header (pchMessageStart magic number) and + ssPeers >> FLATDATA(pchMsgTmp); + + // verify the network matches ours + if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp))) + return error("CAddrman::Read() : invalid network magic number"); + + // de-serialize address data into one CAddrMan object + ssPeers >> addr; + } + catch (const std::exception&) { + return error("CAddrman::Read() : I/O error or stream data corrupted"); + } + + return true; +}