aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--bitcoin-qt.pro2
-rw-r--r--doc/build-unix.txt2
-rw-r--r--src/bitcoinrpc.cpp8
-rw-r--r--src/db.cpp134
-rw-r--r--src/db.h18
-rw-r--r--src/init.cpp14
-rw-r--r--src/irc.cpp2
-rw-r--r--src/main.cpp12
-rw-r--r--src/main.h27
-rw-r--r--src/makefile.linux-mingw2
-rw-r--r--src/makefile.osx2
-rw-r--r--src/makefile.unix2
-rw-r--r--src/net.cpp21
-rw-r--r--src/net.h1
-rw-r--r--src/util.cpp22
-rw-r--r--src/util.h2
-rw-r--r--src/wallet.cpp3
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;
+}
diff --git a/src/db.h b/src/db.h
index 3ce8f1758f..9cec267e98 100644
--- a/src/db.h
+++ b/src/db.h
@@ -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)
diff --git a/src/net.h b/src/net.h
index 6c053b5360..fcb5824d8a 100644
--- a/src/net.h
+++ b/src/net.h
@@ -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);
}