diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | bitcoin-qt.pro | 2 | ||||
-rw-r--r-- | doc/build-unix.txt | 2 | ||||
-rw-r--r-- | src/bitcoinrpc.cpp | 8 | ||||
-rw-r--r-- | src/db.cpp | 134 | ||||
-rw-r--r-- | src/db.h | 18 | ||||
-rw-r--r-- | src/init.cpp | 14 | ||||
-rw-r--r-- | src/irc.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 12 | ||||
-rw-r--r-- | src/main.h | 27 | ||||
-rw-r--r-- | src/makefile.linux-mingw | 2 | ||||
-rw-r--r-- | src/makefile.osx | 2 | ||||
-rw-r--r-- | src/makefile.unix | 2 | ||||
-rw-r--r-- | src/net.cpp | 21 | ||||
-rw-r--r-- | src/net.h | 1 | ||||
-rw-r--r-- | src/util.cpp | 22 | ||||
-rw-r--r-- | src/util.h | 2 | ||||
-rw-r--r-- | src/wallet.cpp | 3 |
18 files changed, 156 insertions, 119 deletions
diff --git a/.gitignore b/.gitignore index dafbc2b6bc..fe93caafbf 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ qrc_*.cpp *.pro.user #mac specific .DS_Store +build diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 055fecbfc7..ae4ef79cb8 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -83,7 +83,7 @@ contains(BITCOIN_NEED_QT_PLUGINS, 1) { # regenerate src/build.h !windows || contains(USE_BUILD_INFO, 1) { genbuild.depends = FORCE - genbuild.commands = cd $$PWD; share/genbuild.sh $$OUT_PWD/build/build.h + genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h genbuild.target = $$OUT_PWD/build/build.h PRE_TARGETDEPS += $$OUT_PWD/build/build.h QMAKE_EXTRA_TARGETS += genbuild diff --git a/doc/build-unix.txt b/doc/build-unix.txt index eb59736816..c32563814d 100644 --- a/doc/build-unix.txt +++ b/doc/build-unix.txt @@ -40,7 +40,7 @@ turned off by default. Set USE_UPNP to a different value to control this: libqrencode may be used for QRCode image generation. It can be downloaded from http://fukuchi.org/works/qrencode/index.html.en, or installed via your package manager. Set USE_QRCODE to control this: - USE_QRCODE=0 (the default) No QRCode support - libarcode not required + USE_QRCODE=0 (the default) No QRCode support - libqrcode not required USE_QRCODE=1 QRCode support enabled IPv6 support may be enabled by setting diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index e058978ebf..e840ffc98b 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1037,7 +1037,8 @@ Value movecmd(const Array& params, bool fHelp) strComment = params[4].get_str(); CWalletDB walletdb(pwalletMain->strWalletFile); - walletdb.TxnBegin(); + if (!walletdb.TxnBegin()) + throw JSONRPCError(-20, "database error"); int64 nNow = GetAdjustedTime(); @@ -1059,7 +1060,8 @@ Value movecmd(const Array& params, bool fHelp) credit.strComment = strComment; walletdb.WriteAccountingEntry(credit); - walletdb.TxnCommit(); + if (!walletdb.TxnCommit()) + throw JSONRPCError(-20, "database error"); return true; } @@ -2621,7 +2623,7 @@ void ThreadRPCServer(void* parg) vnThreadsRunning[THREAD_RPCLISTENER]--; PrintException(NULL, "ThreadRPCServer()"); } - printf("ThreadRPCServer exiting\n"); + printf("ThreadRPCServer exited\n"); } void ThreadRPCServer2(void* parg) diff --git a/src/db.cpp b/src/db.cpp index 5bd0528202..4c38873eed 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -164,8 +164,6 @@ void CDB::Close() unsigned int nMinutes = 0; if (fReadOnly) nMinutes = 1; - if (strFile == "addr.dat") - nMinutes = 2; if (strFile == "blkindex.dat") nMinutes = 2; if (strFile == "blkindex.dat" && IsInitialBlockDownload()) @@ -310,7 +308,7 @@ void DBFlush(bool fShutdown) CloseDb(strFile); printf("%s checkpoint\n", strFile.c_str()); dbenv.txn_checkpoint(0, 0, 0); - if ((strFile != "blkindex.dat" && strFile != "addr.dat") || fDetachDB) { + if (strFile != "blkindex.dat" || fDetachDB) { printf("%s detach\n", strFile.c_str()); dbenv.lsn_reset(strFile.c_str(), 0); } @@ -463,11 +461,6 @@ bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex); } -bool CTxDB::EraseBlockIndex(uint256 hash) -{ - return Erase(make_pair(string("blockindex"), hash)); -} - bool CTxDB::ReadHashBestChain(uint256& hashBestChain) { return Read(string("hashBestChain"), hashBestChain); @@ -737,65 +730,96 @@ bool CTxDB::LoadBlockIndex() // CAddrDB // -bool CAddrDB::WriteAddrman(const CAddrMan& addrman) + +CAddrDB::CAddrDB() { - return Write(string("addrman"), addrman); + pathAddr = GetDataDir() / "peers.dat"; } -bool CAddrDB::LoadAddresses() +bool CAddrDB::Write(const CAddrMan& addr) { - if (Read(string("addrman"), addrman)) - { - printf("Loaded %i addresses\n", addrman.size()); - return true; + // 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; } - - // Read pre-0.6 addr records + catch (std::exception &e) { + return error("CAddrman::Write() : I/O error"); + } + FileCommit(fileout); + fileout.fclose(); - vector<CAddress> vAddr; - vector<vector<unsigned char> > vDelete; + // replace existing peers.dat, if any, with new peers.dat.XXXX + if (!RenameOver(pathTmp, pathAddr)) + return error("CAddrman::Write() : Rename-into-place failed"); - // Get cursor - Dbc* pcursor = GetCursor(); - if (!pcursor) - return false; - - loop - { - // Read next record - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = ReadAtCursor(pcursor, ssKey, ssValue); - if (ret == DB_NOTFOUND) - break; - else if (ret != 0) - return false; + return true; +} - // Unserialize - string strType; - ssKey >> strType; - if (strType == "addr") - { - CAddress addr; - ssValue >> addr; - vAddr.push_back(addr); - } +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); + vector<unsigned char> vchData; + vchData.resize(dataSize); + uint256 hashIn; + + // read data and checksum from file + try { + filein.read((char *)&vchData[0], dataSize); + filein >> hashIn; } - pcursor->close(); + catch (std::exception &e) { + return error("CAddrman::Read() 2 : I/O error or stream data corrupted"); + } + filein.fclose(); - addrman.Add(vAddr, CNetAddr("0.0.0.0")); - printf("Loaded %i addresses\n", addrman.size()); + CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); - // Note: old records left; we ran into hangs-on-startup - // bugs for some users who (we think) were running after - // an unclean shutdown. + // verify stored checksum matches input data + uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); + if (hashIn != hashTmp) + return error("CAddrman::Read() : checksum mismatch; data corrupted"); - return true; -} + // de-serialize address data + unsigned char pchMsgTmp[4]; + try { + ssPeers >> FLATDATA(pchMsgTmp); + ssPeers >> addr; + } + catch (std::exception &e) { + return error("CAddrman::Read() : I/O error or stream data corrupted"); + } -bool LoadAddresses() -{ - return CAddrDB("cr+").LoadAddresses(); -} + // finally, verify the network matches ours + if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp))) + return error("CAddrman::Read() : invalid network magic number"); + return true; +} @@ -285,7 +285,6 @@ public: bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex); bool ReadDiskTx(COutPoint outpoint, CTransaction& tx); bool WriteBlockIndex(const CDiskBlockIndex& blockindex); - bool EraseBlockIndex(uint256 hash); bool ReadHashBestChain(uint256& hashBestChain); bool WriteHashBestChain(uint256 hashBestChain); bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork); @@ -296,20 +295,15 @@ public: -/** Access to the (IP) address database (addr.dat) */ -class CAddrDB : public CDB +/** Access to the (IP) address database (peers.dat) */ +class CAddrDB { -public: - CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { } private: - CAddrDB(const CAddrDB&); - void operator=(const CAddrDB&); + boost::filesystem::path pathAddr; public: - bool WriteAddrman(const CAddrMan& addr); - bool LoadAddresses(); + CAddrDB(); + bool Write(const CAddrMan& addr); + bool Read(CAddrMan& addr); }; -bool LoadAddresses(); - - #endif // BITCOIN_DB_H diff --git a/src/init.cpp b/src/init.cpp index 9b12ab0aa4..b027a53d81 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -62,7 +62,7 @@ void Shutdown(void* parg) delete pwalletMain; CreateThread(ExitTimeout, NULL); Sleep(50); - printf("Bitcoin exiting\n\n"); + printf("Bitcoin exited\n\n"); fExit = true; exit(0); } @@ -371,9 +371,15 @@ bool AppInit2() InitMessage(_("Loading addresses...")); printf("Loading addresses...\n"); nStart = GetTimeMillis(); - if (!LoadAddresses()) - strErrors << _("Error loading addr.dat") << "\n"; - printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart); + + { + CAddrDB adb; + if (!adb.Read(addrman)) + printf("Invalid or missing peers.dat; recreating\n"); + } + + printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n", + addrman.size(), GetTimeMillis() - nStart); InitMessage(_("Loading block index...")); printf("Loading block index...\n"); diff --git a/src/irc.cpp b/src/irc.cpp index 4baffedb54..f21772ac1f 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -200,7 +200,7 @@ void ThreadIRCSeed(void* parg) } catch (...) { PrintExceptionContinue(NULL, "ThreadIRCSeed()"); } - printf("ThreadIRCSeed exiting\n"); + printf("ThreadIRCSeed exited\n"); } void ThreadIRCSeed2(void* parg) diff --git a/src/main.cpp b/src/main.cpp index e40acf6d32..6096ee3e60 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1514,7 +1514,9 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) { uint256 hash = GetHash(); - txdb.TxnBegin(); + if (!txdb.TxnBegin()) + return error("SetBestChain() : TxnBegin failed"); + if (pindexGenesisBlock == NULL && hash == hashGenesisBlock) { txdb.WriteHashBestChain(hash); @@ -1563,7 +1565,10 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) printf("SetBestChain() : ReadFromDisk failed\n"); break; } - txdb.TxnBegin(); + if (!txdb.TxnBegin()) { + printf("SetBestChain() : TxnBegin 2 failed\n"); + break; + } // errors now are not fatal, we still did a reorganisation to a new chain in a valid way if (!block.SetBestChainInner(txdb, pindex)) break; @@ -1621,7 +1626,8 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork(); CTxDB txdb; - txdb.TxnBegin(); + if (!txdb.TxnBegin()) + return false; txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew)); if (!txdb.TxnCommit()) return false; diff --git a/src/main.h b/src/main.h index 5ac5547a3e..3da2e0c5b3 100644 --- a/src/main.h +++ b/src/main.h @@ -10,10 +10,6 @@ #include "net.h" #include "script.h" -#ifdef WIN32 -#include <io.h> /* for _commit */ -#endif - #include <list> class CWallet; @@ -956,13 +952,7 @@ public: // Flush stdio buffers and commit to disk before returning fflush(fileout); if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0) - { -#ifdef WIN32 - _commit(_fileno(fileout)); -#else - fsync(fileno(fileout)); -#endif - } + FileCommit(fileout); return true; } @@ -1130,21 +1120,6 @@ public: return CheckProofOfWork(GetBlockHash(), nBits); } - bool EraseBlockFromDisk() - { - // Open history file - CAutoFile fileout = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb+"), SER_DISK, CLIENT_VERSION); - if (!fileout) - return false; - - // Overwrite with empty null block - CBlock block; - block.SetNull(); - fileout << block; - - return true; - } - enum { nMedianTimeSpan=11 }; int64 GetMedianTimePast() const diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index 1df1e28f1d..61b38a663e 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -70,7 +70,7 @@ OBJS= \ all: bitcoind.exe obj/build.h: FORCE - ../share/genbuild.sh obj/build.h + /bin/sh ../share/genbuild.sh obj/build.h version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO diff --git a/src/makefile.osx b/src/makefile.osx index c927330c9c..227756f274 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -107,7 +107,7 @@ all: bitcoind -include obj-test/*.P obj/build.h: FORCE - ../share/genbuild.sh obj/build.h + /bin/sh ../share/genbuild.sh obj/build.h version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO diff --git a/src/makefile.unix b/src/makefile.unix index b1cc89d0cb..04e17866e5 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -119,7 +119,7 @@ all: bitcoind -include obj-test/*.P obj/build.h: FORCE - ../share/genbuild.sh obj/build.h + /bin/sh ../share/genbuild.sh obj/build.h version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO diff --git a/src/net.cpp b/src/net.cpp index 636db2952c..65b78bf6fa 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -628,7 +628,7 @@ void ThreadSocketHandler(void* parg) vnThreadsRunning[THREAD_SOCKETHANDLER]--; throw; // support pthread_cancel() } - printf("ThreadSocketHandler exiting\n"); + printf("ThreadSocketHandler exited\n"); } void ThreadSocketHandler2(void* parg) @@ -985,7 +985,7 @@ void ThreadMapPort(void* parg) vnThreadsRunning[THREAD_UPNP]--; PrintException(NULL, "ThreadMapPort()"); } - printf("ThreadMapPort exiting\n"); + printf("ThreadMapPort exited\n"); } void ThreadMapPort2(void* parg) @@ -1147,7 +1147,7 @@ void ThreadDNSAddressSeed(void* parg) vnThreadsRunning[THREAD_DNSSEED]--; throw; // support pthread_cancel() } - printf("ThreadDNSAddressSeed exiting\n"); + printf("ThreadDNSAddressSeed exited\n"); } void ThreadDNSAddressSeed2(void* parg) @@ -1278,8 +1278,13 @@ unsigned int pnSeed[] = void DumpAddresses() { + int64 nStart = GetTimeMillis(); + CAddrDB adb; - adb.WriteAddrman(addrman); + adb.Write(addrman); + + printf("Flushed %d addresses to peers.dat %"PRI64d"ms\n", + addrman.size(), GetTimeMillis() - nStart); } void ThreadDumpAddress2(void* parg) @@ -1305,7 +1310,7 @@ void ThreadDumpAddress(void* parg) catch (std::exception& e) { PrintException(&e, "ThreadDumpAddress()"); } - printf("ThreadDumpAddress exiting\n"); + printf("ThreadDumpAddress exited\n"); } void ThreadOpenConnections(void* parg) @@ -1324,7 +1329,7 @@ void ThreadOpenConnections(void* parg) vnThreadsRunning[THREAD_OPENCONNECTIONS]--; PrintException(NULL, "ThreadOpenConnections()"); } - printf("ThreadOpenConnections exiting\n"); + printf("ThreadOpenConnections exited\n"); } void static ProcessOneShot() @@ -1477,7 +1482,7 @@ void ThreadOpenAddedConnections(void* parg) vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; PrintException(NULL, "ThreadOpenAddedConnections()"); } - printf("ThreadOpenAddedConnections exiting\n"); + printf("ThreadOpenAddedConnections exited\n"); } void ThreadOpenAddedConnections2(void* parg) @@ -1606,7 +1611,7 @@ void ThreadMessageHandler(void* parg) vnThreadsRunning[THREAD_MESSAGEHANDLER]--; PrintException(NULL, "ThreadMessageHandler()"); } - printf("ThreadMessageHandler exiting\n"); + printf("ThreadMessageHandler exited\n"); } void ThreadMessageHandler2(void* parg) @@ -19,7 +19,6 @@ #include "protocol.h" #include "addrman.h" -class CAddrDB; class CRequestTracker; class CNode; class CBlockIndex; diff --git a/src/util.cpp b/src/util.cpp index 823d00a4ee..7a163632c8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -47,6 +47,7 @@ namespace boost { #ifndef NOMINMAX #define NOMINMAX #endif +#include <io.h> /* for _commit */ #include "shlobj.h" #endif @@ -910,6 +911,27 @@ void CreatePidFile(const boost::filesystem::path &path, pid_t pid) } } +bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) +{ +#ifdef WIN32 + return MoveFileExA(src.string().c_str(), dest.string().c_str(), + MOVEFILE_REPLACE_EXISTING); +#else + int rc = std::rename(src.string().c_str(), dest.string().c_str()); + return (rc == 0); +#endif /* WIN32 */ +} + +void FileCommit(FILE *fileout) +{ + fflush(fileout); // harmless if redundantly called +#ifdef WIN32 + _commit(_fileno(fileout)); +#else + fsync(fileno(fileout)); +#endif +} + int GetFilesize(FILE* file) { int nSavePos = ftell(file); diff --git a/src/util.h b/src/util.h index 8e65fa7864..f7bdaf5332 100644 --- a/src/util.h +++ b/src/util.h @@ -152,7 +152,9 @@ std::string EncodeBase64(const std::string& str); void ParseParameters(int argc, const char*const argv[]); bool WildcardMatch(const char* psz, const char* mask); bool WildcardMatch(const std::string& str, const std::string& mask); +void FileCommit(FILE *fileout); int GetFilesize(FILE* file); +bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); boost::filesystem::path GetConfigFile(); diff --git a/src/wallet.cpp b/src/wallet.cpp index 998909897f..96dc986edf 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -242,7 +242,8 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) if (fFileBacked) { pwalletdbEncryption = new CWalletDB(strWalletFile); - pwalletdbEncryption->TxnBegin(); + if (!pwalletdbEncryption->TxnBegin()) + return false; pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey); } |