aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/addrman.h20
-rw-r--r--src/bitcoinrpc.cpp87
-rw-r--r--src/crypter.cpp24
-rw-r--r--src/db.cpp64
-rw-r--r--src/init.cpp50
-rw-r--r--src/keystore.cpp32
-rw-r--r--src/keystore.h18
-rw-r--r--src/main.cpp81
-rw-r--r--src/main.h5
-rw-r--r--src/makefile.linux-mingw14
-rw-r--r--src/makefile.mingw4
-rw-r--r--src/makefile.osx25
-rw-r--r--src/makefile.unix15
-rw-r--r--src/net.cpp253
-rw-r--r--src/net.h87
-rw-r--r--src/qt/aboutdialog.cpp2
-rw-r--r--src/qt/addressbookpage.cpp10
-rw-r--r--src/qt/addresstablemodel.cpp14
-rw-r--r--src/qt/bitcoin.cpp22
-rw-r--r--src/qt/bitcoin.qrc2
-rw-r--r--src/qt/bitcoingui.cpp47
-rw-r--r--src/qt/bitcoingui.h6
-rw-r--r--src/qt/clientmodel.cpp5
-rw-r--r--src/qt/clientmodel.h1
-rw-r--r--src/qt/forms/aboutdialog.ui9
-rw-r--r--src/qt/forms/messagepage.ui2
-rw-r--r--src/qt/forms/qrcodedialog.ui15
-rw-r--r--src/qt/guiutil.cpp64
-rw-r--r--src/qt/guiutil.h39
-rw-r--r--src/qt/optionsdialog.cpp10
-rw-r--r--src/qt/qrcodedialog.cpp82
-rw-r--r--src/qt/qrcodedialog.h4
-rw-r--r--src/qt/qtipcserver.cpp13
-rw-r--r--src/qt/qtipcserver.h2
-rw-r--r--src/qt/res/icons/connect4_16.pngbin611 -> 673 bytes
-rw-r--r--src/qt/sendcoinsdialog.cpp4
-rw-r--r--src/qt/sendcoinsdialog.h2
-rw-r--r--src/qt/test/test_main.cpp4
-rw-r--r--src/qt/test/uritests.cpp (renamed from src/qt/test/urltests.cpp)48
-rw-r--r--src/qt/test/uritests.h15
-rw-r--r--src/qt/test/urltests.h15
-rw-r--r--src/qt/transactiondesc.cpp6
-rw-r--r--src/qt/transactiontablemodel.cpp12
-rw-r--r--src/qt/walletmodel.cpp10
-rw-r--r--src/rpcdump.cpp13
-rw-r--r--src/test/util_tests.cpp7
-rw-r--r--src/ui_interface.h2
-rw-r--r--src/util.cpp243
-rw-r--r--src/util.h188
-rw-r--r--src/version.cpp77
-rw-r--r--src/version.h14
-rw-r--r--src/wallet.cpp81
-rw-r--r--src/wallet.h6
53 files changed, 957 insertions, 918 deletions
diff --git a/src/addrman.h b/src/addrman.h
index 91e1f87f05..7652df66ae 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -266,8 +266,8 @@ public:
//
// This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
// changes to the ADDRMAN_ parameters without breaking the on-disk structure.
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
unsigned char nVersion = 0;
READWRITE(nVersion);
READWRITE(nKey);
@@ -398,8 +398,8 @@ public:
void Check()
{
#ifdef DEBUG_ADDRMAN
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
int err;
if ((err=Check_()))
printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
@@ -411,8 +411,8 @@ public:
bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0)
{
bool fRet = false;
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
fRet |= Add_(addr, source, nTimePenalty);
Check();
@@ -426,8 +426,8 @@ public:
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0)
{
int nAdd = 0;
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
@@ -441,8 +441,8 @@ public:
// Mark an entry as accessible.
void Good(const CService &addr, int64 nTime = GetAdjustedTime())
{
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
Good_(addr, nTime);
Check();
@@ -452,8 +452,8 @@ public:
// Mark an entry as connection attempted to.
void Attempt(const CService &addr, int64 nTime = GetAdjustedTime())
{
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
Attempt_(addr, nTime);
Check();
@@ -465,8 +465,8 @@ public:
CAddress Select(int nUnkBias = 50)
{
CAddress addrRet;
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
addrRet = Select_(nUnkBias);
Check();
@@ -479,8 +479,10 @@ public:
{
Check();
std::vector<CAddress> vAddr;
- CRITICAL_BLOCK(cs)
+ {
+ LOCK(cs);
GetAddr_(vAddr);
+ }
Check();
return vAddr;
}
@@ -488,8 +490,8 @@ public:
// Mark an entry as currently-connected-to.
void Connected(const CService &addr, int64 nTime = GetAdjustedTime())
{
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
Connected_(addr, nTime);
Check();
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 115164dc8b..7c991144d3 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -14,12 +14,10 @@
#include <boost/iostreams/stream.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
-#ifdef USE_SSL
#include <boost/asio/ssl.hpp>
-#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
-#endif
+
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
@@ -986,8 +984,6 @@ Value addmultisigaddress(const Array& params, bool fHelp)
"If [account] is specified, assign address to [account].";
throw runtime_error(msg);
}
- if (!fTestNet)
- throw runtime_error("addmultisigaddress available only when running -testnet\n");
int nRequired = params[0].get_int();
const Array& keys = params[1].get_array();
@@ -1659,8 +1655,8 @@ Value walletlock(const Array& params, bool fHelp)
if (!pwalletMain->IsCrypted())
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
- CRITICAL_BLOCK(cs_nWalletUnlockTime)
{
+ LOCK(cs_nWalletUnlockTime);
pwalletMain->Lock();
nWalletUnlockTime = 0;
}
@@ -2283,7 +2279,6 @@ bool ClientAllowed(const string& strAddress)
return false;
}
-#ifdef USE_SSL
//
// IOStream device that speaks SSL but can also speak non-SSL
//
@@ -2335,7 +2330,6 @@ private:
bool fUseSSL;
SSLStream& stream;
};
-#endif
void ThreadRPCServer(void* parg)
{
@@ -2378,7 +2372,7 @@ void ThreadRPCServer2(void* parg)
"(you do not need to remember this password)\n"
"If the file does not exist, create it with owner-readable-only file permissions.\n"),
strWhatAmI.c_str(),
- GetConfigFile().c_str(),
+ GetConfigFile().string().c_str(),
EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
_("Error"), wxOK | wxMODAL);
QueueShutdown();
@@ -2390,51 +2384,51 @@ void ThreadRPCServer2(void* parg)
asio::io_service io_service;
ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
- ip::tcp::acceptor acceptor(io_service, endpoint);
-
- acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ ip::tcp::acceptor acceptor(io_service);
+ try
+ {
+ acceptor.open(endpoint.protocol());
+ acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor.bind(endpoint);
+ acceptor.listen(socket_base::max_connections);
+ }
+ catch(boost::system::system_error &e)
+ {
+ ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
+ _("Error"), wxOK | wxMODAL);
+ QueueShutdown();
+ return;
+ }
-#ifdef USE_SSL
ssl::context context(io_service, ssl::context::sslv23);
if (fUseSSL)
{
context.set_options(ssl::context::no_sslv2);
- filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
- if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
- if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
- else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
- filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
- if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
- if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
- else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
-
- string ciphers = GetArg("-rpcsslciphers",
- "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
- SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
- }
-#else
- if (fUseSSL)
- throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
-#endif
+
+ filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
+ if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
+ if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
+ else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
+
+ filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
+ if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
+ if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
+ else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
+
+ string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
+ SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
+ }
loop
{
// Accept connection
-#ifdef USE_SSL
SSLStream sslStream(io_service, context);
SSLIOStreamDevice d(sslStream, fUseSSL);
iostreams::stream<SSLIOStreamDevice> stream(d);
-#else
- ip::tcp::iostream stream;
-#endif
ip::tcp::endpoint peer;
vnThreadsRunning[THREAD_RPCSERVER]--;
-#ifdef USE_SSL
acceptor.accept(sslStream.lowest_layer(), peer);
-#else
- acceptor.accept(*stream.rdbuf(), peer);
-#endif
vnThreadsRunning[4]++;
if (fShutdown)
return;
@@ -2524,9 +2518,10 @@ void ThreadRPCServer2(void* parg)
{
// Execute
Value result;
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(pwalletMain->cs_wallet)
+ {
+ LOCK2(cs_main, pwalletMain->cs_wallet);
result = (*(*mi).second)(params, false);
+ }
// Send reply
string strReply = JSONRPCReply(result, Value::null, id);
@@ -2557,11 +2552,10 @@ Object CallRPC(const string& strMethod, const Array& params)
throw runtime_error(strprintf(
_("You must set rpcpassword=<password> in the configuration file:\n%s\n"
"If the file does not exist, create it with owner-readable-only file permissions."),
- GetConfigFile().c_str()));
+ GetConfigFile().string().c_str()));
// Connect to localhost
bool fUseSSL = GetBoolArg("-rpcssl");
-#ifdef USE_SSL
asio::io_service io_service;
ssl::context context(io_service, ssl::context::sslv23);
context.set_options(ssl::context::no_sslv2);
@@ -2570,15 +2564,6 @@ Object CallRPC(const string& strMethod, const Array& params)
iostreams::stream<SSLIOStreamDevice> stream(d);
if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
throw runtime_error("couldn't connect to server");
-#else
- if (fUseSSL)
- throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
-
- ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
- if (stream.fail())
- throw runtime_error("couldn't connect to server");
-#endif
-
// HTTP basic authentication
string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
diff --git a/src/crypter.cpp b/src/crypter.cpp
index 6643bcddcd..83041addb4 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -73,14 +73,16 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned
EVP_CIPHER_CTX ctx;
- EVP_CIPHER_CTX_init(&ctx);
- EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
-
- EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
- EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen);
+ bool fOk = true;
+ EVP_CIPHER_CTX_init(&ctx);
+ if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
+ if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
+ if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen);
EVP_CIPHER_CTX_cleanup(&ctx);
+ if (!fOk) return false;
+
vchCiphertext.resize(nCLen + nFLen);
return true;
}
@@ -98,14 +100,16 @@ bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingM
EVP_CIPHER_CTX ctx;
- EVP_CIPHER_CTX_init(&ctx);
- EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
-
- EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
- EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen);
+ bool fOk = true;
+ EVP_CIPHER_CTX_init(&ctx);
+ if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
+ if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
+ if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen);
EVP_CIPHER_CTX_cleanup(&ctx);
+ if (!fOk) return false;
+
vchPlaintext.resize(nPLen + nFLen);
return true;
}
diff --git a/src/db.cpp b/src/db.cpp
index 2a09e2e673..839c0807cc 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -28,7 +28,6 @@ static bool fDbEnvInit = false;
DbEnv dbenv(0);
static map<string, int> mapFileUseCount;
static map<string, Db*> mapDb;
-static int64 nTxn = 0;
static void EnvShutdown()
{
@@ -44,7 +43,7 @@ static void EnvShutdown()
{
printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
}
- DbEnv(0).remove(GetDataDir().c_str(), 0);
+ DbEnv(0).remove(GetDataDir().string().c_str(), 0);
}
class CDBInit
@@ -61,7 +60,7 @@ public:
instance_of_cdbinit;
-CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
+CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
{
int ret;
if (pszFile == NULL)
@@ -73,29 +72,29 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
if (fCreate)
nFlags |= DB_CREATE;
- CRITICAL_BLOCK(cs_db)
{
+ LOCK(cs_db);
if (!fDbEnvInit)
{
if (fShutdown)
return;
- string strDataDir = GetDataDir();
- string strLogDir = strDataDir + "/database";
- filesystem::create_directory(strLogDir.c_str());
- string strErrorFile = strDataDir + "/db.log";
- printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
+ filesystem::path pathDataDir = GetDataDir();
+ filesystem::path pathLogDir = pathDataDir / "database";
+ filesystem::create_directory(pathLogDir);
+ filesystem::path pathErrorFile = pathDataDir / "db.log";
+ printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
int nDbCache = GetArg("-dbcache", 25);
- dbenv.set_lg_dir(strLogDir.c_str());
+ dbenv.set_lg_dir(pathLogDir.string().c_str());
dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
dbenv.set_lg_bsize(1048576);
dbenv.set_lg_max(10485760);
dbenv.set_lk_max_locks(10000);
dbenv.set_lk_max_objects(10000);
- dbenv.set_errfile(fopen(strErrorFile.c_str(), "a")); /// debug
+ dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
dbenv.set_flags(DB_AUTO_COMMIT, 1);
dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
- ret = dbenv.open(strDataDir.c_str(),
+ ret = dbenv.open(pathDataDir.string().c_str(),
DB_CREATE |
DB_INIT_LOCK |
DB_INIT_LOG |
@@ -127,8 +126,10 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
{
delete pdb;
pdb = NULL;
- CRITICAL_BLOCK(cs_db)
+ {
+ LOCK(cs_db);
--mapFileUseCount[strFile];
+ }
strFile = "";
throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret));
}
@@ -164,22 +165,18 @@ void CDB::Close()
if (strFile == "blkindex.dat" && IsInitialBlockDownload())
nMinutes = 5;
- if (nMinutes == 0 || nTxn > 200000)
- {
- nTxn = 0;
- nMinutes = 0;
- }
-
- dbenv.txn_checkpoint(0, nMinutes, 0);
+ dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
- CRITICAL_BLOCK(cs_db)
+ {
+ LOCK(cs_db);
--mapFileUseCount[strFile];
+ }
}
void static CloseDb(const string& strFile)
{
- CRITICAL_BLOCK(cs_db)
{
+ LOCK(cs_db);
if (mapDb[strFile] != NULL)
{
// Close the database handle
@@ -195,8 +192,8 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
{
while (!fShutdown)
{
- CRITICAL_BLOCK(cs_db)
{
+ LOCK(cs_db);
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
{
// Flush log data to the dat file
@@ -293,8 +290,8 @@ void DBFlush(bool fShutdown)
printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
if (!fDbEnvInit)
return;
- CRITICAL_BLOCK(cs_db)
{
+ LOCK(cs_db);
map<string, int>::iterator mi = mapFileUseCount.begin();
while (mi != mapFileUseCount.end())
{
@@ -344,7 +341,6 @@ bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
{
assert(!fClient);
- nTxn++;
return Write(make_pair(string("tx"), hash), txindex);
}
@@ -355,7 +351,6 @@ bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeigh
// Add to tx index
uint256 hash = tx.GetHash();
CTxIndex txindex(pos, tx.vout.size());
- nTxn++;
return Write(make_pair(string("tx"), hash), txindex);
}
@@ -886,8 +881,8 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
bool fIsEncrypted = false;
//// todo: shouldn't we catch exceptions and try to recover and continue?
- CRITICAL_BLOCK(pwallet->cs_wallet)
{
+ LOCK(pwallet->cs_wallet);
int nMinVersion = 0;
if (Read((string)"minversion", nMinVersion))
{
@@ -1092,13 +1087,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
return DB_NEED_REWRITE;
if (nFileVersion < CLIENT_VERSION) // Update
- {
- // Get rid of old debug.log file in current directory
- if (nFileVersion <= 105 && !pszSetDataDir[0])
- unlink("debug.log");
-
WriteVersion(CLIENT_VERSION);
- }
return DB_LOAD_OK;
}
@@ -1128,7 +1117,8 @@ void ThreadFlushWalletDB(void* parg)
if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
{
- TRY_CRITICAL_BLOCK(cs_db)
+ TRY_LOCK(cs_db,lockDb);
+ if (lockDb)
{
// Don't do this if any databases are in use
int nRefCount = 0;
@@ -1169,8 +1159,8 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
return false;
while (!fShutdown)
{
- CRITICAL_BLOCK(cs_db)
{
+ LOCK(cs_db);
if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
{
// Flush log data to the dat file
@@ -1180,10 +1170,10 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
mapFileUseCount.erase(wallet.strWalletFile);
// Copy wallet.dat
- filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
+ filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
filesystem::path pathDest(strDest);
if (filesystem::is_directory(pathDest))
- pathDest = pathDest / wallet.strWalletFile;
+ pathDest /= wallet.strWalletFile;
try {
#if BOOST_VERSION >= 104000
diff --git a/src/init.cpp b/src/init.cpp
index eecbc83edb..2be0027a5b 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -40,10 +40,13 @@ void Shutdown(void* parg)
static CCriticalSection cs_Shutdown;
static bool fTaken;
bool fFirstThread = false;
- TRY_CRITICAL_BLOCK(cs_Shutdown)
{
- fFirstThread = !fTaken;
- fTaken = true;
+ TRY_LOCK(cs_Shutdown, lockShutdown);
+ if (lockShutdown)
+ {
+ fFirstThread = !fTaken;
+ fTaken = true;
+ }
}
static bool fExit;
if (fFirstThread)
@@ -171,6 +174,7 @@ bool AppInit2(int argc, char* argv[])
" -splash \t\t " + _("Show splash screen on startup (default: 1)") + "\n" +
" -datadir=<dir> \t\t " + _("Specify data directory") + "\n" +
" -dbcache=<n> \t\t " + _("Set database cache size in megabytes (default: 25)") + "\n" +
+ " -dblogsize=<n> \t\t " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" +
" -proxy=<ip:port> \t " + _("Connect through socks4 proxy") + "\n" +
" -dns \t " + _("Allow DNS lookups for addnode and connect") + "\n" +
@@ -221,14 +225,12 @@ bool AppInit2(int argc, char* argv[])
" -checkblocks=<n> \t\t " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
" -checklevel=<n> \t\t " + _("How thorough the block verification is (0-6, default: 1)") + "\n";
-#ifdef USE_SSL
strUsage += string() +
_("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" +
" -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" +
" -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)") + "\n" +
" -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)") + "\n" +
" -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n";
-#endif
strUsage += string() +
" -? \t\t " + _("This help message") + "\n";
@@ -305,11 +307,11 @@ bool AppInit2(int argc, char* argv[])
}
#endif
- if (!fDebug && !pszSetDataDir[0])
+ if (!fDebug)
ShrinkDebugFile();
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
- printf("Bitcoin version %s\n", FormatFullVersion().c_str());
- printf("Default data directory %s\n", GetDefaultDataDir().c_str());
+ printf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str());
+ printf("Default data directory %s\n", GetDefaultDataDir().string().c_str());
if (GetBoolArg("-loadblockindextest"))
{
@@ -320,13 +322,13 @@ bool AppInit2(int argc, char* argv[])
}
// Make sure only a single bitcoin process is using the data directory.
- string strLockFile = GetDataDir() + "/.lock";
- FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist.
+ boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
+ FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
if (file) fclose(file);
- static boost::interprocess::file_lock lock(strLockFile.c_str());
+ static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
if (!lock.try_lock())
{
- ThreadSafeMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), _("Bitcoin"), wxOK|wxMODAL);
+ ThreadSafeMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str()), _("Bitcoin"), wxOK|wxMODAL);
return false;
}
@@ -582,20 +584,20 @@ bool AppInit2(int argc, char* argv[])
}
#ifdef WIN32
-string StartupShortcutPath()
+boost::filesystem::path StartupShortcutPath()
{
- return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
+ return MyGetSpecialFolderPath(CSIDL_STARTUP, true) / "Bitcoin.lnk";
}
bool GetStartOnSystemStartup()
{
- return filesystem::exists(StartupShortcutPath().c_str());
+ return filesystem::exists(StartupShortcutPath());
}
bool SetStartOnSystemStartup(bool fAutoStart)
{
// If the shortcut exists already, remove it for updating
- remove(StartupShortcutPath().c_str());
+ boost::filesystem::remove(StartupShortcutPath());
if (fAutoStart)
{
@@ -631,7 +633,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
{
WCHAR pwsz[MAX_PATH];
// Ensure that the string is ANSI.
- MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
+ MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(pwsz, TRUE);
ppf->Release();
@@ -657,15 +659,15 @@ boost::filesystem::path GetAutostartDir()
namespace fs = boost::filesystem;
char* pszConfigHome = getenv("XDG_CONFIG_HOME");
- if (pszConfigHome) return fs::path(pszConfigHome) / fs::path("autostart");
+ if (pszConfigHome) return fs::path(pszConfigHome) / "autostart";
char* pszHome = getenv("HOME");
- if (pszHome) return fs::path(pszHome) / fs::path(".config/autostart");
+ if (pszHome) return fs::path(pszHome) / ".config" / "autostart";
return fs::path();
}
boost::filesystem::path GetAutostartFilePath()
{
- return GetAutostartDir() / boost::filesystem::path("bitcoin.desktop");
+ return GetAutostartDir() / "bitcoin.desktop";
}
bool GetStartOnSystemStartup()
@@ -690,13 +692,7 @@ bool GetStartOnSystemStartup()
bool SetStartOnSystemStartup(bool fAutoStart)
{
if (!fAutoStart)
- {
-#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
- unlink(GetAutostartFilePath().string().c_str());
-#else
- unlink(GetAutostartFilePath().native_file_string().c_str());
-#endif
- }
+ boost::filesystem::remove(GetAutostartFilePath());
else
{
char pszExePath[MAX_PATH+1];
diff --git a/src/keystore.cpp b/src/keystore.cpp
index e76f7790f1..7b46f6b07a 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -21,31 +21,37 @@ bool CBasicKeyStore::AddKey(const CKey& key)
{
bool fCompressed = false;
CSecret secret = key.GetSecret(fCompressed);
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
+ }
return true;
}
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
{
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
mapScripts[Hash160(redeemScript)] = redeemScript;
+ }
return true;
}
bool CBasicKeyStore::HaveCScript(const uint160& hash) const
{
bool result;
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
result = (mapScripts.count(hash) > 0);
+ }
return result;
}
bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
ScriptMap::const_iterator mi = mapScripts.find(hash);
if (mi != mapScripts.end())
{
@@ -58,8 +64,8 @@ bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) c
bool CCryptoKeyStore::SetCrypted()
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (fUseCrypto)
return true;
if (!mapKeys.empty())
@@ -71,8 +77,8 @@ bool CCryptoKeyStore::SetCrypted()
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!SetCrypted())
return false;
@@ -84,6 +90,8 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
CSecret vchSecret;
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
return false;
+ if (vchSecret.size() != 32)
+ return false;
CKey key;
key.SetPubKey(vchPubKey);
key.SetSecret(vchSecret);
@@ -98,8 +106,8 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
bool CCryptoKeyStore::AddKey(const CKey& key)
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::AddKey(key);
@@ -121,8 +129,8 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!SetCrypted())
return false;
@@ -133,8 +141,8 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey,
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::GetKey(address, keyOut);
@@ -146,6 +154,8 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
CSecret vchSecret;
if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
return false;
+ if (vchSecret.size() != 32)
+ return false;
keyOut.SetPubKey(vchPubKey);
keyOut.SetSecret(vchSecret);
return true;
@@ -156,8 +166,8 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!IsCrypted())
return CKeyStore::GetPubKey(address, vchPubKeyOut);
@@ -173,8 +183,8 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsi
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!mapCryptedKeys.empty() || IsCrypted())
return false;
diff --git a/src/keystore.h b/src/keystore.h
index c32db2620a..282eaaa047 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -54,15 +54,17 @@ public:
bool HaveKey(const CBitcoinAddress &address) const
{
bool result;
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
result = (mapKeys.count(address) > 0);
+ }
return result;
}
void GetKeys(std::set<CBitcoinAddress> &setAddress) const
{
setAddress.clear();
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
KeyMap::const_iterator mi = mapKeys.begin();
while (mi != mapKeys.end())
{
@@ -73,8 +75,8 @@ public:
}
bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end())
{
@@ -129,8 +131,10 @@ public:
if (!IsCrypted())
return false;
bool result;
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
result = vMasterKey.empty();
+ }
return result;
}
@@ -139,8 +143,10 @@ public:
if (!SetCrypted())
return false;
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
vMasterKey.clear();
+ }
return true;
}
@@ -149,8 +155,8 @@ public:
bool AddKey(const CKey& key);
bool HaveKey(const CBitcoinAddress &address) const
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::HaveKey(address);
return mapCryptedKeys.count(address) > 0;
diff --git a/src/main.cpp b/src/main.cpp
index 7c49316b4a..bdafae8eb8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,11 +18,6 @@ using namespace boost;
// Global state
//
-// Name of client reported in the 'version' message. Report the same name
-// for both bitcoind and bitcoin-qt, to make it harder for attackers to
-// target servers or GUI users specifically.
-const std::string CLIENT_NAME("Satoshi");
-
CCriticalSection cs_setpwalletRegistered;
set<CWallet*> setpwalletRegistered;
@@ -75,16 +70,16 @@ int64 nTransactionFee = 0;
void RegisterWallet(CWallet* pwalletIn)
{
- CRITICAL_BLOCK(cs_setpwalletRegistered)
{
+ LOCK(cs_setpwalletRegistered);
setpwalletRegistered.insert(pwalletIn);
}
}
void UnregisterWallet(CWallet* pwalletIn)
{
- CRITICAL_BLOCK(cs_setpwalletRegistered)
{
+ LOCK(cs_setpwalletRegistered);
setpwalletRegistered.erase(pwalletIn);
}
}
@@ -478,9 +473,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
// Do we already have it?
uint256 hash = GetHash();
- CRITICAL_BLOCK(cs_mapTransactions)
+ {
+ LOCK(cs_mapTransactions);
if (mapTransactions.count(hash))
return false;
+ }
if (fCheckInputs)
if (txdb.ContainsTx(hash))
return false;
@@ -552,8 +549,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
static int64 nLastTime;
int64 nNow = GetTime();
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
// Use an exponentially decaying ~10-minute window:
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
nLastTime = nNow;
@@ -576,8 +573,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
}
// Store transaction in memory
- CRITICAL_BLOCK(cs_mapTransactions)
{
+ LOCK(cs_mapTransactions);
if (ptxOld)
{
printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
@@ -608,8 +605,8 @@ bool CTransaction::AddToMemoryPoolUnchecked()
printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mapTransactions.size());
// Add to memory pool without checking anything. Don't call this directly,
// call AcceptToMemoryPool to properly check the transaction first.
- CRITICAL_BLOCK(cs_mapTransactions)
{
+ LOCK(cs_mapTransactions);
uint256 hash = GetHash();
mapTransactions[hash] = *this;
for (int i = 0; i < vin.size(); i++)
@@ -624,8 +621,8 @@ bool CTransaction::AddToMemoryPoolUnchecked()
bool CTransaction::RemoveFromMemoryPool()
{
// Remove transaction from memory pool
- CRITICAL_BLOCK(cs_mapTransactions)
{
+ LOCK(cs_mapTransactions);
uint256 hash = GetHash();
if (mapTransactions.count(hash))
{
@@ -702,8 +699,9 @@ bool CMerkleTx::AcceptToMemoryPool()
bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
{
- CRITICAL_BLOCK(cs_mapTransactions)
+
{
+ LOCK(cs_mapTransactions);
// Add previous supporting transactions first
BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
{
@@ -1024,8 +1022,8 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
if (!fFound || txindex.pos == CDiskTxPos(1,1,1))
{
// Get prev tx from single transactions in memory
- CRITICAL_BLOCK(cs_mapTransactions)
{
+ LOCK(cs_mapTransactions);
if (!mapTransactions.count(prevout.hash))
return error("FetchInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
txPrev = mapTransactions[prevout.hash];
@@ -1190,8 +1188,8 @@ bool CTransaction::ClientConnectInputs()
return false;
// Take over previous transactions' spent pointers
- CRITICAL_BLOCK(cs_mapTransactions)
{
+ LOCK(cs_mapTransactions);
int64 nValueIn = 0;
for (int i = 0; i < vin.size(); i++)
{
@@ -1707,10 +1705,12 @@ bool CBlock::AcceptBlock()
// Relay inventory, but don't relay old inventory during initial block download
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
if (hashBestChain == hash)
- CRITICAL_BLOCK(cs_vNodes)
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
- pnode->PushInventory(CInv(MSG_BLOCK, hash));
+ {
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
+ pnode->PushInventory(CInv(MSG_BLOCK, hash));
+ }
return true;
}
@@ -1822,7 +1822,7 @@ FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszM
{
if (nFile == -1)
return NULL;
- FILE* file = fopen(strprintf("%s/blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);
+ FILE* file = fopen((GetDataDir() / strprintf("blk%04d.dat", nFile)).string().c_str(), pszMode);
if (!file)
return NULL;
if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
@@ -2052,8 +2052,8 @@ string GetWarnings(string strFor)
}
// Alerts
- CRITICAL_BLOCK(cs_mapAlerts)
{
+ LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
{
const CAlert& alert = item.second;
@@ -2080,8 +2080,8 @@ bool CAlert::ProcessAlert()
if (!IsInEffect())
return false;
- CRITICAL_BLOCK(cs_mapAlerts)
{
+ LOCK(cs_mapAlerts);
// Cancel previous alerts
for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
{
@@ -2260,9 +2260,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
// Relay alerts
- CRITICAL_BLOCK(cs_mapAlerts)
+ {
+ LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
item.second.RelayTo(pfrom);
+ }
pfrom->fSuccessfullyConnected = true;
@@ -2316,8 +2318,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{
// Relay to a limited number of other nodes
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
// Use deterministic randomness to send to the same nodes for 24 hours
// at a time so the setAddrKnowns of the chosen nodes prevent repeats
static uint256 hashSalt;
@@ -2428,8 +2430,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else if (inv.IsKnownType())
{
// Send stream from relay memory
- CRITICAL_BLOCK(cs_mapRelay)
{
+ LOCK(cs_mapRelay);
map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
if (mi != mapRelay.end())
pfrom->PushMessage(inv.GetCommand(), (*mi).second);
@@ -2634,8 +2636,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> hashReply;
CRequestTracker tracker;
- CRITICAL_BLOCK(pfrom->cs_mapRequests)
{
+ LOCK(pfrom->cs_mapRequests);
map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
if (mi != pfrom->mapRequests.end())
{
@@ -2662,9 +2664,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
// Relay
pfrom->setKnown.insert(alert.GetHash());
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
alert.RelayTo(pnode);
+ }
}
}
@@ -2763,8 +2767,10 @@ bool ProcessMessages(CNode* pfrom)
bool fRet = false;
try
{
- CRITICAL_BLOCK(cs_main)
+ {
+ LOCK(cs_main);
fRet = ProcessMessage(pfrom, strCommand, vMsg);
+ }
if (fShutdown)
return true;
}
@@ -2802,8 +2808,8 @@ bool ProcessMessages(CNode* pfrom)
bool SendMessages(CNode* pto, bool fSendTrickle)
{
- CRITICAL_BLOCK(cs_main)
{
+ LOCK(cs_main);
// Don't send anything until we get their version message
if (pto->nVersion == 0)
return true;
@@ -2819,8 +2825,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
static int64 nLastRebroadcast;
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
{
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
// Periodically clear setAddrKnown to allow refresh broadcasts
@@ -2871,8 +2877,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
//
vector<CInv> vInv;
vector<CInv> vInvWait;
- CRITICAL_BLOCK(pto->cs_inventory)
{
+ LOCK(pto->cs_inventory);
vInv.reserve(pto->vInventoryToSend.size());
vInvWait.reserve(pto->vInventoryToSend.size());
BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
@@ -3087,9 +3093,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
// Collect memory pool transactions into the block
int64 nFees = 0;
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_mapTransactions)
{
+ LOCK2(cs_main, cs_mapTransactions);
CTxDB txdb("r");
// Priority order to process transactions
@@ -3317,8 +3322,8 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
// Found a solution
- CRITICAL_BLOCK(cs_main)
{
+ LOCK(cs_main);
if (pblock->hashPrevBlock != hashBestChain)
return error("BitcoinMiner : generated block is stale");
@@ -3326,8 +3331,10 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
reservekey.KeepKey();
// Track how many getdata requests this block gets
- CRITICAL_BLOCK(wallet.cs_wallet)
+ {
+ LOCK(wallet.cs_wallet);
wallet.mapRequestCount[pblock->GetHash()] = 0;
+ }
// Process this block the same as if we had received it from another node
if (!ProcessBlock(NULL, pblock))
@@ -3354,8 +3361,6 @@ void static BitcoinMiner(CWallet *pwallet)
while (fGenerateBitcoins)
{
- if (AffinityBugWorkaround(ThreadBitcoinMiner))
- return;
if (fShutdown)
return;
while (vNodes.empty() || IsInitialBlockDownload())
@@ -3443,8 +3448,8 @@ void static BitcoinMiner(CWallet *pwallet)
if (GetTimeMillis() - nHPSTimerStart > 4000)
{
static CCriticalSection cs;
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
if (GetTimeMillis() - nHPSTimerStart > 4000)
{
dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
diff --git a/src/main.h b/src/main.h
index 6c81abad56..1d46851ac2 100644
--- a/src/main.h
+++ b/src/main.h
@@ -10,6 +10,7 @@
#include "key.h"
#include "script.h"
#include "db.h"
+#include "version.h"
#ifdef WIN32
#include <io.h> /* for _commit */
@@ -30,10 +31,6 @@ class CInv;
class CRequestTracker;
class CNode;
-static const int CLIENT_VERSION = 60099;
-static const bool VERSION_IS_BETA = true;
-extern const std::string CLIENT_NAME;
-
static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index 0bbe612a06..9f005424f6 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -10,7 +10,8 @@ INCLUDEPATHS= \
-I"$(DEPSDIR)/boost_1_47_0" \
-I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
-I"$(DEPSDIR)/openssl-1.0.0e/include" \
- -I"$(DEPSDIR)"
+ -I"$(DEPSDIR)" \
+ -I"$(CURDIR)"/obj \
LIBPATHS= \
-L"$(DEPSDIR)/boost_1_47_0/stage/lib" \
@@ -26,7 +27,7 @@ LIBS= \
-l ssl \
-l crypto
-DEFS=-D_MT -DWIN32 -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
+DEFS=-D_MT -DWIN32 -D_WINDOWS -DNOPCH -DBOOST_THREAD_USE_LIB
DEBUGFLAGS=-g
CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
@@ -43,6 +44,7 @@ LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l w
HEADERS = $(wildcard *.h)
OBJS= \
+ obj/version.o \
obj/checkpoints.o \
obj/netbase.o \
obj/addrman.o \
@@ -64,6 +66,11 @@ OBJS= \
all: bitcoind.exe
+obj/build.h: FORCE
+ ../share/genbuild.sh obj/build.h
+version.cpp: obj/build.h
+DEFS += -DHAVE_BUILD_INFO
+
obj/%.o: %.cpp $(HEADERS)
i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
@@ -85,3 +92,6 @@ clean:
-rm -f headers.h.gch
-rm -f bitcoind.exe
-rm -f test_bitcoin.exe
+ -rm -f src/build.h
+
+FORCE:
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 307fca7834..397fdf4f32 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -23,7 +23,7 @@ LIBS= \
-l ssl \
-l crypto
-DEFS=-DWIN32 -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
+DEFS=-DWIN32 -D_WINDOWS -DNOPCH -DBOOST_THREAD_USE_LIB
DEBUGFLAGS=-g
CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
@@ -41,6 +41,7 @@ LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell
HEADERS = $(wildcard *.h)
OBJS= \
+ obj/version.o \
obj/checkpoints.o \
obj/netbase.o \
obj/addrman.o \
@@ -82,3 +83,4 @@ clean:
-del /Q obj\test\*
-del /Q test\*.o
-del /Q headers.h.gch
+ -del /Q build.h
diff --git a/src/makefile.osx b/src/makefile.osx
index 6388a71e11..c5d3edbdc9 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -11,6 +11,7 @@ DEPSDIR=/opt/local
INCLUDEPATHS= \
-I"$(CURDIR)" \
+ -I"$(CURDIR)"/obj \
-I"$(DEPSDIR)/include" \
-I"$(DEPSDIR)/include/db48"
@@ -49,15 +50,23 @@ LIBS += \
TESTDEFS += -DBOOST_TEST_DYN_LINK
endif
-DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DUSE_SSL
+DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0
+
+ifdef RELEASE
+# Compile for maximum compatibility and smallest size.
+# This requires that dependencies are compiled
+# the same way.
+CFLAGS = -mmacosx-version-min=10.5 -arch i386 -O3
+else
+CFLAGS = -g
+endif
-DEBUGFLAGS=-g
# ppc doesn't work because we don't support big-endian
-CFLAGS=-mmacosx-version-min=10.5 -arch i386 -O3 \
- -Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-offsetof -Wformat-security \
+CFLAGS += -Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-offsetof -Wformat-security \
$(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
OBJS= \
+ obj/version.o \
obj/checkpoints.o \
obj/netbase.o \
obj/addrman.o \
@@ -92,6 +101,11 @@ all: bitcoind
-include obj/*.P
-include obj-test/*.P
+obj/build.h: FORCE
+ ../share/genbuild.sh obj/build.h
+version.cpp: obj/build.h
+DEFS += -DHAVE_BUILD_INFO
+
obj/%.o: %.cpp
$(CXX) -c $(CFLAGS) -MMD -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
@@ -120,3 +134,6 @@ clean:
-rm -f obj-test/*.o
-rm -f obj/*.P
-rm -f obj-test/*.P
+ -rm -f src/build.h
+
+FORCE:
diff --git a/src/makefile.unix b/src/makefile.unix
index 66e020bbef..79251dc7a6 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -6,7 +6,7 @@ USE_UPNP:=0
DEFS=-DNOPCH
-DEFS += $(addprefix -I,$(CURDIR) $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
+DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
LMODE = dynamic
@@ -39,10 +39,6 @@ ifneq (${USE_UPNP}, -)
DEFS += -DUSE_UPNP=$(USE_UPNP)
endif
-ifneq (${USE_SSL}, 0)
- DEFS += -DUSE_SSL
-endif
-
LIBS+= \
-Wl,-B$(LMODE2) \
-l z \
@@ -89,6 +85,7 @@ xCXXFLAGS=-pthread -Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-o
$(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
OBJS= \
+ obj/version.o \
obj/checkpoints.o \
obj/netbase.o \
obj/addrman.o \
@@ -115,6 +112,11 @@ all: bitcoind
-include obj/*.P
-include obj-test/*.P
+obj/build.h: FORCE
+ ../share/genbuild.sh obj/build.h
+version.cpp: obj/build.h
+DEFS += -DHAVE_BUILD_INFO
+
obj/%.o: %.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
@@ -143,3 +145,6 @@ clean:
-rm -f obj-test/*.o
-rm -f obj/*.P
-rm -f obj-test/*.P
+ -rm -f src/build.h
+
+FORCE:
diff --git a/src/net.cpp b/src/net.cpp
index 37e73c421a..8272b25561 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -64,6 +64,9 @@ map<CInv, int64> mapAlreadyAskedFor;
set<CNetAddr> setservAddNodeAddresses;
CCriticalSection cs_setservAddNodeAddresses;
+static CWaitableCriticalSection csOutbound;
+static int nOutbound = 0;
+static CConditionVariable condOutbound;
unsigned short GetListenPort()
@@ -269,9 +272,11 @@ void ThreadGetMyExternalIP(void* parg)
// setAddrKnown automatically filters any duplicate sends.
CAddress addr(addrLocalHost);
addr.nTime = GetAdjustedTime();
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
pnode->PushAddress(addr);
+ }
}
}
}
@@ -289,111 +294,12 @@ void AddressCurrentlyConnected(const CService& addr)
-void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
-{
- // If the dialog might get closed before the reply comes back,
- // call this in the destructor so it doesn't get called after it's deleted.
- CRITICAL_BLOCK(cs_vNodes)
- {
- BOOST_FOREACH(CNode* pnode, vNodes)
- {
- CRITICAL_BLOCK(pnode->cs_mapRequests)
- {
- for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
- {
- CRequestTracker& tracker = (*mi).second;
- if (tracker.fn == fn && tracker.param1 == param1)
- pnode->mapRequests.erase(mi++);
- else
- mi++;
- }
- }
- }
- }
-}
-
-
-
-
-
-
-
-//
-// Subscription methods for the broadcast and subscription system.
-// Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
-//
-// The subscription system uses a meet-in-the-middle strategy.
-// With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
-// subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
-//
-
-bool AnySubscribed(unsigned int nChannel)
-{
- if (pnodeLocalHost->IsSubscribed(nChannel))
- return true;
- CRITICAL_BLOCK(cs_vNodes)
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (pnode->IsSubscribed(nChannel))
- return true;
- return false;
-}
-
-bool CNode::IsSubscribed(unsigned int nChannel)
-{
- if (nChannel >= vfSubscribe.size())
- return false;
- return vfSubscribe[nChannel];
-}
-
-void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
-{
- if (nChannel >= vfSubscribe.size())
- return;
-
- if (!AnySubscribed(nChannel))
- {
- // Relay subscribe
- CRITICAL_BLOCK(cs_vNodes)
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (pnode != this)
- pnode->PushMessage("subscribe", nChannel, nHops);
- }
-
- vfSubscribe[nChannel] = true;
-}
-
-void CNode::CancelSubscribe(unsigned int nChannel)
-{
- if (nChannel >= vfSubscribe.size())
- return;
-
- // Prevent from relaying cancel if wasn't subscribed
- if (!vfSubscribe[nChannel])
- return;
- vfSubscribe[nChannel] = false;
-
- if (!AnySubscribed(nChannel))
- {
- // Relay subscription cancel
- CRITICAL_BLOCK(cs_vNodes)
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (pnode != this)
- pnode->PushMessage("sub-cancel", nChannel);
- }
-}
-
-
-
-
-
-
-
CNode* FindNode(const CNetAddr& ip)
{
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
if ((CNetAddr)pnode->addr == ip)
return (pnode);
@@ -403,8 +309,8 @@ CNode* FindNode(const CNetAddr& ip)
CNode* FindNode(const CService& addr)
{
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
if ((CService)pnode->addr == addr)
return (pnode);
@@ -458,8 +364,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
pnode->AddRef(nTimeout);
else
pnode->AddRef();
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
vNodes.push_back(pnode);
+ }
+ {
+ WAITABLE_LOCK(csOutbound);
+ nOutbound++;
+ }
pnode->nTimeConnected = GetTime();
return pnode;
@@ -486,13 +398,6 @@ void CNode::CloseSocketDisconnect()
void CNode::Cleanup()
{
- // All of a nodes broadcasts and subscriptions are automatically torn down
- // when it goes down, so a node has to stay up to keep its broadcast going.
-
- // Cancel subscriptions
- for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
- if (vfSubscribe[nChannel])
- CancelSubscribe(nChannel);
}
@@ -522,8 +427,8 @@ void CNode::ClearBanned()
bool CNode::IsBanned(CNetAddr ip)
{
bool fResult = false;
- CRITICAL_BLOCK(cs_setBanned)
{
+ LOCK(cs_setBanned);
std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
if (i != setBanned.end())
{
@@ -547,9 +452,11 @@ bool CNode::Misbehaving(int howmuch)
if (nMisbehavior >= GetArg("-banscore", 100))
{
int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
- CRITICAL_BLOCK(cs_setBanned)
+ {
+ LOCK(cs_setBanned);
if (setBanned[addr] < banTime)
setBanned[addr] = banTime;
+ }
CloseSocketDisconnect();
printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
return true;
@@ -598,8 +505,8 @@ void ThreadSocketHandler2(void* parg)
//
// Disconnect nodes
//
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
// Disconnect unused nodes
vector<CNode*> vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
@@ -610,6 +517,15 @@ void ThreadSocketHandler2(void* parg)
// remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
+ if (!pnode->fInbound)
+ {
+ WAITABLE_LOCK(csOutbound);
+ nOutbound--;
+
+ // Connection slot(s) were removed, notify connection creator(s)
+ NOTIFY(condOutbound);
+ }
+
// close socket and cleanup
pnode->CloseSocketDisconnect();
pnode->Cleanup();
@@ -630,11 +546,23 @@ void ThreadSocketHandler2(void* parg)
if (pnode->GetRefCount() <= 0)
{
bool fDelete = false;
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
- TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
- TRY_CRITICAL_BLOCK(pnode->cs_inventory)
- fDelete = true;
+ {
+ TRY_LOCK(pnode->cs_vSend, lockSend);
+ if (lockSend)
+ {
+ TRY_LOCK(pnode->cs_vRecv, lockRecv);
+ if (lockRecv)
+ {
+ TRY_LOCK(pnode->cs_mapRequests, lockReq);
+ if (lockReq)
+ {
+ TRY_LOCK(pnode->cs_inventory, lockInv);
+ if (lockInv)
+ fDelete = true;
+ }
+ }
+ }
+ }
if (fDelete)
{
vNodesDisconnected.remove(pnode);
@@ -668,8 +596,8 @@ void ThreadSocketHandler2(void* parg)
if(hListenSocket != INVALID_SOCKET)
FD_SET(hListenSocket, &fdsetRecv);
hSocketMax = max(hSocketMax, hListenSocket);
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if (pnode->hSocket == INVALID_SOCKET)
@@ -677,9 +605,11 @@ void ThreadSocketHandler2(void* parg)
FD_SET(pnode->hSocket, &fdsetRecv);
FD_SET(pnode->hSocket, &fdsetError);
hSocketMax = max(hSocketMax, pnode->hSocket);
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- if (!pnode->vSend.empty())
+ {
+ TRY_LOCK(pnode->cs_vSend, lockSend);
+ if (lockSend && !pnode->vSend.empty())
FD_SET(pnode->hSocket, &fdsetSend);
+ }
}
}
@@ -717,10 +647,12 @@ void ThreadSocketHandler2(void* parg)
if (hSocket != INVALID_SOCKET)
addr = CAddress(sockaddr);
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
- if (pnode->fInbound)
- nInbound++;
+ if (pnode->fInbound)
+ nInbound++;
+ }
if (hSocket == INVALID_SOCKET)
{
@@ -729,9 +661,11 @@ void ThreadSocketHandler2(void* parg)
}
else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
{
- CRITICAL_BLOCK(cs_setservAddNodeAddresses)
+ {
+ LOCK(cs_setservAddNodeAddresses);
if (!setservAddNodeAddresses.count(addr))
closesocket(hSocket);
+ }
}
else if (CNode::IsBanned(addr))
{
@@ -743,8 +677,10 @@ void ThreadSocketHandler2(void* parg)
printf("accepted connection %s\n", addr.ToString().c_str());
CNode* pnode = new CNode(hSocket, addr, true);
pnode->AddRef();
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
vNodes.push_back(pnode);
+ }
}
}
@@ -753,8 +689,8 @@ void ThreadSocketHandler2(void* parg)
// Service each socket
//
vector<CNode*> vNodesCopy;
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->AddRef();
@@ -771,7 +707,8 @@ void ThreadSocketHandler2(void* parg)
continue;
if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
{
- TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
+ TRY_LOCK(pnode->cs_vRecv, lockRecv);
+ if (lockRecv)
{
CDataStream& vRecv = pnode->vRecv;
unsigned int nPos = vRecv.size();
@@ -820,7 +757,8 @@ void ThreadSocketHandler2(void* parg)
continue;
if (FD_ISSET(pnode->hSocket, &fdsetSend))
{
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
+ TRY_LOCK(pnode->cs_vSend, lockSend);
+ if (lockSend)
{
CDataStream& vSend = pnode->vSend;
if (!vSend.empty())
@@ -874,8 +812,8 @@ void ThreadSocketHandler2(void* parg)
}
}
}
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->Release();
}
@@ -1278,8 +1216,6 @@ void ThreadOpenConnections2(void* parg)
int64 nStart = GetTime();
loop
{
- int nOutbound = 0;
-
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(500);
vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
@@ -1287,23 +1223,15 @@ void ThreadOpenConnections2(void* parg)
return;
// Limit outbound connections
- loop
+ int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
{
- nOutbound = 0;
- CRITICAL_BLOCK(cs_vNodes)
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (!pnode->fInbound)
- nOutbound++;
- int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
- nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
- if (nOutbound < nMaxOutboundConnections)
- break;
- vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
- Sleep(2000);
- vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
- if (fShutdown)
- return;
+ WAITABLE_LOCK(csOutbound);
+ WAIT(condOutbound, fShutdown || nOutbound < nMaxOutbound);
}
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
+ if (fShutdown)
+ return;
bool fAddSeeds = false;
@@ -1337,9 +1265,11 @@ void ThreadOpenConnections2(void* parg)
// Only connect to one address per a.b.?.? range.
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
set<vector<unsigned char> > setConnected;
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
setConnected.insert(pnode->addr.GetGroup());
+ }
int64 nANow = GetAdjustedTime();
@@ -1405,9 +1335,11 @@ void ThreadOpenAddedConnections2(void* parg)
if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
{
vservAddressesToAdd.push_back(vservNode);
- CRITICAL_BLOCK(cs_setservAddNodeAddresses)
+ {
+ LOCK(cs_setservAddNodeAddresses);
BOOST_FOREACH(CService& serv, vservNode)
setservAddNodeAddresses.insert(serv);
+ }
}
}
loop
@@ -1415,7 +1347,8 @@ void ThreadOpenAddedConnections2(void* parg)
vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
// Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
// (keeping in mind that addnode entries can have many IPs if fAllowDNS)
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
BOOST_FOREACH(CService& addrNode, *(it))
@@ -1425,6 +1358,7 @@ void ThreadOpenAddedConnections2(void* parg)
it--;
break;
}
+ }
BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
{
OpenNetworkConnection(CAddress(*(vserv.begin())));
@@ -1498,8 +1432,8 @@ void ThreadMessageHandler2(void* parg)
while (!fShutdown)
{
vector<CNode*> vNodesCopy;
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->AddRef();
@@ -1512,20 +1446,26 @@ void ThreadMessageHandler2(void* parg)
BOOST_FOREACH(CNode* pnode, vNodesCopy)
{
// Receive messages
- TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
- ProcessMessages(pnode);
+ {
+ TRY_LOCK(pnode->cs_vRecv, lockRecv);
+ if (lockRecv)
+ ProcessMessages(pnode);
+ }
if (fShutdown)
return;
// Send messages
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- SendMessages(pnode, pnode == pnodeTrickle);
+ {
+ TRY_LOCK(pnode->cs_vSend, lockSend);
+ if (lockSend)
+ SendMessages(pnode, pnode == pnodeTrickle);
+ }
if (fShutdown)
return;
}
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->Release();
}
@@ -1752,6 +1692,7 @@ bool StopNode()
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
+ NOTIFY_ALL(condOutbound);
do
{
int nThreadsRunning = 0;
diff --git a/src/net.h b/src/net.h
index ed9954bd7d..3c84650c27 100644
--- a/src/net.h
+++ b/src/net.h
@@ -29,7 +29,6 @@ extern int nBestHeight;
inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
-static const unsigned int PUBLISH_HOPS = 5;
bool RecvLine(SOCKET hSocket, std::string& strLine);
bool GetMyExternalIP(CNetAddr& ipRet);
@@ -37,8 +36,6 @@ void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const CService& ip);
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
-void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
-bool AnySubscribed(unsigned int nChannel);
void MapPort(bool fMapPort);
bool BindListenPort(std::string& strError=REF(std::string()));
void StartNode(void* parg);
@@ -160,9 +157,6 @@ public:
CCriticalSection cs_inventory;
std::multimap<int64, CInv> mapAskFor;
- // publish and subscription
- std::vector<char> vfSubscribe;
-
CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
{
nServices = 0;
@@ -192,7 +186,6 @@ public:
hashLastGetBlocksEnd = 0;
nStartingHeight = -1;
fGetAddr = false;
- vfSubscribe.assign(256, false);
nMisbehavior = 0;
setInventoryKnown.max_size(SendBufferSize() / 1000);
@@ -254,15 +247,19 @@ public:
void AddInventoryKnown(const CInv& inv)
{
- CRITICAL_BLOCK(cs_inventory)
+ {
+ LOCK(cs_inventory);
setInventoryKnown.insert(inv);
+ }
}
void PushInventory(const CInv& inv)
{
- CRITICAL_BLOCK(cs_inventory)
+ {
+ LOCK(cs_inventory);
if (!setInventoryKnown.count(inv))
vInventoryToSend.push_back(inv);
+ }
}
void AskFor(const CInv& inv)
@@ -526,8 +523,10 @@ public:
uint256 hashReply;
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
- CRITICAL_BLOCK(cs_mapRequests)
+ {
+ LOCK(cs_mapRequests);
mapRequests[hashReply] = CRequestTracker(fn, param1);
+ }
PushMessage(pszCommand, hashReply);
}
@@ -539,8 +538,10 @@ public:
uint256 hashReply;
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
- CRITICAL_BLOCK(cs_mapRequests)
+ {
+ LOCK(cs_mapRequests);
mapRequests[hashReply] = CRequestTracker(fn, param1);
+ }
PushMessage(pszCommand, hashReply, a1);
}
@@ -552,8 +553,10 @@ public:
uint256 hashReply;
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
- CRITICAL_BLOCK(cs_mapRequests)
+ {
+ LOCK(cs_mapRequests);
mapRequests[hashReply] = CRequestTracker(fn, param1);
+ }
PushMessage(pszCommand, hashReply, a1, a2);
}
@@ -599,9 +602,11 @@ public:
inline void RelayInventory(const CInv& inv)
{
// Put on lists to offer to the other nodes
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
pnode->PushInventory(inv);
+ }
}
template<typename T>
@@ -616,8 +621,8 @@ void RelayMessage(const CInv& inv, const T& a)
template<>
inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
{
- CRITICAL_BLOCK(cs_mapRelay)
{
+ LOCK(cs_mapRelay);
// Expire old relay messages
while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
{
@@ -634,58 +639,4 @@ inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
}
-
-
-
-
-
-
-//
-// Templates for the publish and subscription system.
-// The object being published as T& obj needs to have:
-// a set<unsigned int> setSources member
-// specializations of AdvertInsert and AdvertErase
-// Currently implemented for CTable and CProduct.
-//
-
-template<typename T>
-void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
-{
- // Add to sources
- obj.setSources.insert(pfrom->addr.ip);
-
- if (!AdvertInsert(obj))
- return;
-
- // Relay
- CRITICAL_BLOCK(cs_vNodes)
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
- pnode->PushMessage("publish", nChannel, nHops, obj);
-}
-
-template<typename T>
-void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
-{
- uint256 hash = obj.GetHash();
-
- CRITICAL_BLOCK(cs_vNodes)
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
- pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
-
- AdvertErase(obj);
-}
-
-template<typename T>
-void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
-{
- // Remove a source
- obj.setSources.erase(pfrom->addr.ip);
-
- // If no longer supported by any sources, cancel it
- if (obj.setSources.empty())
- AdvertStopPublish(pfrom, nChannel, nHops, obj);
-}
-
#endif
diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp
index 08d7774067..0b98befe8d 100644
--- a/src/qt/aboutdialog.cpp
+++ b/src/qt/aboutdialog.cpp
@@ -2,6 +2,8 @@
#include "ui_aboutdialog.h"
#include "clientmodel.h"
+#include "version.h"
+
AboutDialog::AboutDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::AboutDialog)
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 88212835de..3e55c39e04 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -310,16 +310,12 @@ void AddressBookPage::on_showQRCode_clicked()
QTableView *table = ui->tableView;
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
-
- QRCodeDialog *d;
foreach (QModelIndex index, indexes)
{
- QString address = index.data().toString(),
- label = index.sibling(index.row(), 0).data().toString(),
- title = QString("%1 << %2 >>").arg(label).arg(address);
+ QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();
- QRCodeDialog *d = new QRCodeDialog(title, address, label, tab == ReceivingTab, this);
- d->show();
+ QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
+ dialog->show();
}
#endif
}
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 198a857b2d..05f3a81698 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -39,8 +39,8 @@ struct AddressTablePriv
{
cachedAddressTable.clear();
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
@@ -169,8 +169,8 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
// Double-check that we're not overwriting a receiving address
if(rec->type == AddressTableEntry::Sending)
{
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
// Remove old entry
wallet->DelAddressBookName(rec->address.toStdString());
// Add new entry with new address
@@ -254,8 +254,8 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
return QString();
}
// Check for duplicate addresses
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
if(wallet->mapAddressBook.count(strAddress))
{
editStatus = DUPLICATE_ADDRESS;
@@ -286,8 +286,10 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
return QString();
}
// Add entry
- CRITICAL_BLOCK(wallet->cs_wallet)
+ {
+ LOCK(wallet->cs_wallet);
wallet->SetAddressBookName(strAddress, strLabel);
+ }
return QString::fromStdString(strAddress);
}
@@ -301,8 +303,8 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
// Also refuse to remove receiving addresses.
return false;
}
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
wallet->DelAddressBookName(rec->address.toStdString());
}
return true;
@@ -312,8 +314,8 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
*/
QString AddressTableModel::labelForAddress(const QString &address) const
{
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
CBitcoinAddress address_parsed(address.toStdString());
std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed);
if (mi != wallet->mapAddressBook.end())
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 394e4a7661..bfb49cbcab 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -74,13 +74,13 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
return payFee;
}
-void ThreadSafeHandleURL(const std::string& strURL)
+void ThreadSafeHandleURI(const std::string& strURI)
{
if(!guiref)
return;
- QMetaObject::invokeMethod(guiref, "handleURL", GUIUtil::blockingGUIThreadConnection(),
- Q_ARG(QString, QString::fromStdString(strURL)));
+ QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
+ Q_ARG(QString, QString::fromStdString(strURI)));
}
void MainFrameRepaint()
@@ -133,10 +133,10 @@ int main(int argc, char *argv[])
{
if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
{
- const char *strURL = argv[i];
+ const char *strURI = argv[i];
try {
- boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
- if(mq.try_send(strURL, strlen(strURL), 0))
+ boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
+ if(mq.try_send(strURI, strlen(strURI), 0))
exit(0);
else
break;
@@ -248,21 +248,21 @@ int main(int argc, char *argv[])
window.show();
}
- // Place this here as guiref has to be defined if we dont want to lose URLs
+ // Place this here as guiref has to be defined if we dont want to lose URIs
ipcInit();
#if !defined(MAC_OSX) && !defined(WIN32)
// TODO: implement qtipcserver.cpp for Mac and Windows
- // Check for URL in argv
+ // Check for URI in argv
for (int i = 1; i < argc; i++)
{
if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
{
- const char *strURL = argv[i];
+ const char *strURI = argv[i];
try {
- boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
- mq.try_send(strURL, strlen(strURL), 0);
+ boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
+ mq.try_send(strURI, strlen(strURI), 0);
}
catch (boost::interprocess::interprocess_exception &ex) {
}
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index 8f2bba2737..e631a65155 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -1,5 +1,5 @@
<RCC>
- <qresource prefix="/icons" lang="edit">
+ <qresource prefix="/icons">
<file alias="bitcoin">res/icons/bitcoin.png</file>
<file alias="address-book">res/icons/address-book.png</file>
<file alias="quit">res/icons/quit.png</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index a60b585225..3c31f291c2 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -23,6 +23,7 @@
#include "guiconstants.h"
#include "askpassphrasedialog.h"
#include "notificator.h"
+#include "guiutil.h"
#ifdef Q_WS_MAC
#include "macdockiconhandler.h"
@@ -239,8 +240,8 @@ void BitcoinGUI::createActions()
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
optionsAction->setToolTip(tr("Modify configuration options for bitcoin"));
optionsAction->setMenuRole(QAction::PreferencesRole);
- openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this);
- openBitcoinAction->setToolTip(tr("Show the Bitcoin window"));
+ toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("Show/Hide &Bitcoin"), this);
+ toggleHideAction->setToolTip(tr("Show or Hide the Bitcoin window"));
exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
exportAction->setToolTip(tr("Export the data in the current tab to a file"));
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet"), this);
@@ -255,7 +256,7 @@ void BitcoinGUI::createActions()
connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
- connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
+ connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
@@ -387,12 +388,12 @@ void BitcoinGUI::createTrayIcon()
#else
// Note: On Mac, the dock icon is used to provide the tray's functionality.
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
- connect(dockIconHandler, SIGNAL(dockIconClicked()), openBitcoinAction, SLOT(trigger()));
+ connect(dockIconHandler, SIGNAL(dockIconClicked()), toggleHideAction, SLOT(trigger()));
trayIconMenu = dockIconHandler->dockMenu();
#endif
// Configuration of the tray icon (or dock icon) icon menu
- trayIconMenu->addAction(openBitcoinAction);
+ trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(messageAction);
#ifndef FIRST_CLASS_MESSAGING
@@ -416,11 +417,33 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
if(reason == QSystemTrayIcon::Trigger)
{
// Click on system tray icon triggers "open bitcoin"
- openBitcoinAction->trigger();
+ toggleHideAction->trigger();
}
}
#endif
+void BitcoinGUI::toggleHidden()
+{
+ // activateWindow() (sometimes) helps with keyboard focus on Windows
+ if(isHidden())
+ {
+ show();
+ activateWindow();
+ }
+ else if(isMinimized())
+ {
+ showNormal();
+ activateWindow();
+ }
+ else if(GUIUtil::isObscured(this))
+ {
+ raise();
+ activateWindow();
+ }
+ else
+ hide();
+}
+
void BitcoinGUI::optionsClicked()
{
if(!clientModel || !clientModel->getOptionsModel())
@@ -715,7 +738,7 @@ void BitcoinGUI::gotoMessagePage(QString addr)
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
{
- // Accept only URLs
+ // Accept only URIs
if(event->mimeData()->hasUrls())
event->acceptProposedAction();
}
@@ -725,20 +748,20 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
if(event->mimeData()->hasUrls())
{
gotoSendCoinsPage();
- QList<QUrl> urls = event->mimeData()->urls();
- foreach(const QUrl &url, urls)
+ QList<QUrl> uris = event->mimeData()->urls();
+ foreach(const QUrl &uri, uris)
{
- sendCoinsPage->handleURL(url.toString());
+ sendCoinsPage->handleURI(uri.toString());
}
}
event->acceptProposedAction();
}
-void BitcoinGUI::handleURL(QString strURL)
+void BitcoinGUI::handleURI(QString strURI)
{
gotoSendCoinsPage();
- sendCoinsPage->handleURL(strURL);
+ sendCoinsPage->handleURI(strURI);
if(!isActiveWindow())
activateWindow();
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index c684d7cc3a..2cce8d3459 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -81,7 +81,7 @@ private:
QAction *aboutAction;
QAction *receiveCoinsAction;
QAction *optionsAction;
- QAction *openBitcoinAction;
+ QAction *toggleHideAction;
QAction *exportAction;
QAction *encryptWalletAction;
QAction *backupWalletAction;
@@ -125,7 +125,7 @@ public slots:
@param[out] payFee true to pay the fee, false to not pay the fee
*/
void askFee(qint64 nFeeRequired, bool *payFee);
- void handleURL(QString strURL);
+ void handleURI(QString strURI);
void gotoMessagePage();
void gotoMessagePage(QString);
@@ -166,6 +166,8 @@ private slots:
/** Show window if hidden, unminimize when minimized */
void showNormalIfMinimized();
+ /** Hide window if visible, show if hidden */
+ void toggleHidden();
};
#endif
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 8163da0915..284bee0e8e 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -88,3 +88,8 @@ QString ClientModel::formatFullVersion() const
{
return QString::fromStdString(FormatFullVersion());
}
+
+QString ClientModel::formatBuildDate() const
+{
+ return QString::fromStdString(CLIENT_DATE);
+}
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 6366b4d617..8e7431a2f3 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -37,6 +37,7 @@ public:
QString getStatusBarWarnings() const;
QString formatFullVersion() const;
+ QString formatBuildDate() const;
private:
OptionsModel *optionsModel;
diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui
index 127b90965a..6e342e5e8a 100644
--- a/src/qt/forms/aboutdialog.ui
+++ b/src/qt/forms/aboutdialog.ui
@@ -52,6 +52,9 @@
<property name="text">
<string>&lt;b&gt;Bitcoin&lt;/b&gt; version</string>
</property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
<item>
@@ -62,6 +65,9 @@
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
<item>
@@ -93,6 +99,9 @@ This product includes software developed by the OpenSSL Project for use in the O
<property name="wordWrap">
<bool>true</bool>
</property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
<item>
diff --git a/src/qt/forms/messagepage.ui b/src/qt/forms/messagepage.ui
index 131e15bdb3..8bd6d8b54b 100644
--- a/src/qt/forms/messagepage.ui
+++ b/src/qt/forms/messagepage.ui
@@ -35,7 +35,7 @@
<item>
<widget class="QValidatedLineEdit" name="signFrom">
<property name="toolTip">
- <string>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
+ <string>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
</property>
<property name="maxLength">
<number>34</number>
diff --git a/src/qt/forms/qrcodedialog.ui b/src/qt/forms/qrcodedialog.ui
index fa21f60b9e..714b1d6cd8 100644
--- a/src/qt/forms/qrcodedialog.ui
+++ b/src/qt/forms/qrcodedialog.ui
@@ -34,6 +34,9 @@
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item>
@@ -44,7 +47,7 @@
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QCheckBox" name="chkReq">
+ <widget class="QCheckBox" name="chkReqPayment">
<property name="enabled">
<bool>true</bool>
</property>
@@ -56,7 +59,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QLabel" name="lblAm1">
+ <widget class="QLabel" name="lblAmount">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -91,7 +94,7 @@
</widget>
</item>
<item>
- <widget class="QLabel" name="lblAm2">
+ <widget class="QLabel" name="lblBTC">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -113,7 +116,7 @@
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
- <widget class="QLabel" name="label_3">
+ <widget class="QLabel" name="lblLabel">
<property name="text">
<string>Label:</string>
</property>
@@ -136,7 +139,7 @@
</widget>
</item>
<item row="1" column="0">
- <widget class="QLabel" name="label_4">
+ <widget class="QLabel" name="lblMessage">
<property name="text">
<string>Message:</string>
</property>
@@ -194,7 +197,7 @@
<resources/>
<connections>
<connection>
- <sender>chkReq</sender>
+ <sender>chkReqPayment</sender>
<signal>clicked(bool)</signal>
<receiver>lnReqAmount</receiver>
<slot>setEnabled(bool)</slot>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index ad530a78e4..cb2473240e 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -19,31 +19,33 @@
#include <QDesktopServices>
#include <QThread>
-QString GUIUtil::dateTimeStr(qint64 nTime)
+namespace GUIUtil {
+
+QString dateTimeStr(const QDateTime &date)
{
- return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
+ return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm");
}
-QString GUIUtil::dateTimeStr(const QDateTime &date)
+QString dateTimeStr(qint64 nTime)
{
- return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm");
+ return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
}
-QFont GUIUtil::bitcoinAddressFont()
+QFont bitcoinAddressFont()
{
QFont font("Monospace");
font.setStyleHint(QFont::TypeWriter);
return font;
}
-void GUIUtil::setupAddressWidget(QLineEdit *widget, QWidget *parent)
+void setupAddressWidget(QLineEdit *widget, QWidget *parent)
{
widget->setMaxLength(BitcoinAddressValidator::MaxAddressLength);
widget->setValidator(new BitcoinAddressValidator(parent));
widget->setFont(bitcoinAddressFont());
}
-void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
+void setupAmountWidget(QLineEdit *widget, QWidget *parent)
{
QDoubleValidator *amountValidator = new QDoubleValidator(parent);
amountValidator->setDecimals(8);
@@ -52,15 +54,15 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
}
-bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
+bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
- if(url.scheme() != QString("bitcoin"))
+ if(uri.scheme() != QString("bitcoin"))
return false;
SendCoinsRecipient rv;
- rv.address = url.path();
+ rv.address = uri.path();
rv.amount = 0;
- QList<QPair<QString, QString> > items = url.queryItems();
+ QList<QPair<QString, QString> > items = uri.queryItems();
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
{
bool fShouldReturnFalse = false;
@@ -97,21 +99,21 @@ bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
return true;
}
-bool GUIUtil::parseBitcoinURL(QString url, SendCoinsRecipient *out)
+bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
{
// Convert bitcoin:// to bitcoin:
//
// Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
// which will lowercase it (and thus invalidate the address).
- if(url.startsWith("bitcoin://"))
+ if(uri.startsWith("bitcoin://"))
{
- url.replace(0, 10, "bitcoin:");
+ uri.replace(0, 10, "bitcoin:");
}
- QUrl urlInstance(url);
- return parseBitcoinURL(urlInstance, out);
+ QUrl uriInstance(uri);
+ return parseBitcoinURI(uriInstance, out);
}
-QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine)
+QString HtmlEscape(const QString& str, bool fMultiLine)
{
QString escaped = Qt::escape(str);
if(fMultiLine)
@@ -121,12 +123,12 @@ QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine)
return escaped;
}
-QString GUIUtil::HtmlEscape(const std::string& str, bool fMultiLine)
+QString HtmlEscape(const std::string& str, bool fMultiLine)
{
return HtmlEscape(QString::fromStdString(str), fMultiLine);
}
-void GUIUtil::copyEntryData(QAbstractItemView *view, int column, int role)
+void copyEntryData(QAbstractItemView *view, int column, int role)
{
if(!view || !view->selectionModel())
return;
@@ -139,7 +141,7 @@ void GUIUtil::copyEntryData(QAbstractItemView *view, int column, int role)
}
}
-QString GUIUtil::getSaveFileName(QWidget *parent, const QString &caption,
+QString getSaveFileName(QWidget *parent, const QString &caption,
const QString &dir,
const QString &filter,
QString *selectedSuffixOut)
@@ -185,7 +187,7 @@ QString GUIUtil::getSaveFileName(QWidget *parent, const QString &caption,
return result;
}
-Qt::ConnectionType GUIUtil::blockingGUIThreadConnection()
+Qt::ConnectionType blockingGUIThreadConnection()
{
if(QThread::currentThread() != QCoreApplication::instance()->thread())
{
@@ -196,3 +198,23 @@ Qt::ConnectionType GUIUtil::blockingGUIThreadConnection()
return Qt::DirectConnection;
}
}
+
+bool checkPoint(const QPoint &p, const QWidget *w)
+{
+ QWidget *atW = qApp->widgetAt(w->mapToGlobal(p));
+ if(!atW) return false;
+ return atW->topLevelWidget() == w;
+}
+
+bool isObscured(QWidget *w)
+{
+
+ return !(checkPoint(QPoint(0, 0), w)
+ && checkPoint(QPoint(w->width() - 1, 0), w)
+ && checkPoint(QPoint(0, w->height() - 1), w)
+ && checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
+ && checkPoint(QPoint(w->width()/2, w->height()/2), w));
+}
+
+} // namespace GUIUtil
+
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 06426d76bc..ea1a4795c0 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -13,30 +13,29 @@ class QAbstractItemView;
QT_END_NAMESPACE
class SendCoinsRecipient;
-/** Static utility functions used by the Bitcoin Qt UI.
+/** Utility functions used by the Bitcoin Qt UI.
*/
-class GUIUtil
+namespace GUIUtil
{
-public:
// Create human-readable string from date
- static QString dateTimeStr(qint64 nTime);
- static QString dateTimeStr(const QDateTime &datetime);
+ QString dateTimeStr(const QDateTime &datetime);
+ QString dateTimeStr(qint64 nTime);
// Render bitcoin addresses in monospace font
- static QFont bitcoinAddressFont();
+ QFont bitcoinAddressFont();
// Set up widgets for address and amounts
- static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
- static void setupAmountWidget(QLineEdit *widget, QWidget *parent);
+ void setupAddressWidget(QLineEdit *widget, QWidget *parent);
+ void setupAmountWidget(QLineEdit *widget, QWidget *parent);
- // Parse "bitcoin:" URL into recipient object, return true on succesful parsing
- // See Bitcoin URL definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
- static bool parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out);
- static bool parseBitcoinURL(QString url, SendCoinsRecipient *out);
+ // Parse "bitcoin:" URI into recipient object, return true on succesful parsing
+ // See Bitcoin URI definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
+ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out);
+ bool parseBitcoinURI(QString uri, SendCoinsRecipient *out);
// HTML escaping for rich text controls
- static QString HtmlEscape(const QString& str, bool fMultiLine=false);
- static QString HtmlEscape(const std::string& str, bool fMultiLine=false);
+ QString HtmlEscape(const QString& str, bool fMultiLine=false);
+ QString HtmlEscape(const std::string& str, bool fMultiLine=false);
/** Copy a field of the currently selected entry of a view to the clipboard. Does nothing if nothing
is selected.
@@ -44,7 +43,7 @@ public:
@param[in] role Data role to extract from the model
@see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress
*/
- static void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole);
+ void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole);
/** Get save file name, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
when no suffix is provided by the user.
@@ -56,18 +55,20 @@ public:
@param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0).
Can be useful when choosing the save file format based on suffix.
*/
- static QString getSaveFileName(QWidget *parent=0, const QString &caption=QString(),
+ QString getSaveFileName(QWidget *parent=0, const QString &caption=QString(),
const QString &dir=QString(), const QString &filter=QString(),
QString *selectedSuffixOut=0);
-
/** Get connection type to call object slot in GUI thread with invokeMethod. The call will be blocking.
@returns If called from the GUI thread, return a Qt::DirectConnection.
If called from another thread, return a Qt::BlockingQueuedConnection.
*/
- static Qt::ConnectionType blockingGUIThreadConnection();
+ Qt::ConnectionType blockingGUIThreadConnection();
+
+ // Determine whether a widget is hidden behind other windows
+ bool isObscured(QWidget *w);
-};
+} // namespace GUIUtil
#endif // GUIUTIL_H
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 75fd4ccf18..34d303233c 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -175,18 +175,16 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar"));
minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window"));
layout->addWidget(minimize_to_tray);
-#endif
-
- map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
- map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled."));
- layout->addWidget(map_port_upnp);
-#ifndef Q_WS_MAC
minimize_on_close = new QCheckBox(tr("M&inimize on close"));
minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
layout->addWidget(minimize_on_close);
#endif
+ map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
+ map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled."));
+ layout->addWidget(map_port_upnp);
+
connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:"));
connect_socks4->setToolTip(tr("Connect to the Bitcon network through a SOCKS4 proxy (e.g. when connecting through Tor)"));
layout->addWidget(connect_socks4);
diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp
index 82959831de..9965f1438f 100644
--- a/src/qt/qrcodedialog.cpp
+++ b/src/qt/qrcodedialog.cpp
@@ -8,21 +8,19 @@
#include <qrencode.h>
-#define EXPORT_IMAGE_SIZE 256
+#define EXPORT_IMAGE_SIZE 256
-QRCodeDialog::QRCodeDialog(const QString &title, const QString &addr, const QString &label, bool enableReq, QWidget *parent) :
- QDialog(parent),
- ui(new Ui::QRCodeDialog),
- address(addr)
+QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent) :
+ QDialog(parent), ui(new Ui::QRCodeDialog), address(addr)
{
ui->setupUi(this);
- setWindowTitle(title);
+ setWindowTitle(QString("%1").arg(address));
setAttribute(Qt::WA_DeleteOnClose);
- ui->chkReq->setVisible(enableReq);
+ ui->chkReqPayment->setVisible(enableReq);
ui->lnReqAmount->setVisible(enableReq);
- ui->lblAm1->setVisible(enableReq);
- ui->lblAm2->setVisible(enableReq);
+ ui->lblAmount->setVisible(enableReq);
+ ui->lblBTC->setVisible(enableReq);
ui->lnLabel->setText(label);
@@ -37,19 +35,28 @@ QRCodeDialog::~QRCodeDialog()
void QRCodeDialog::genCode()
{
QString uri = getURI();
- //qDebug() << "Encoding:" << uri.toUtf8().constData();
- QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
- myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
- myImage.fill(0xffffff);
- unsigned char *p = code->data;
- for(int y = 0; y < code->width; y++) {
- for(int x = 0; x < code->width; x++) {
- myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
- p++;
+
+ if (uri != "")
+ {
+ ui->lblQRCode->setText("");
+
+ QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
+ myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
+ myImage.fill(0xffffff);
+ unsigned char *p = code->data;
+ for (int y = 0; y < code->width; y++)
+ {
+ for (int x = 0; x < code->width; x++)
+ {
+ myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
+ p++;
+ }
}
+ QRcode_free(code);
+ ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300));
}
- QRcode_free(code);
- ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300));
+ else
+ ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message."));
}
QString QRCodeDialog::getURI()
@@ -57,41 +64,49 @@ QString QRCodeDialog::getURI()
QString ret = QString("bitcoin:%1").arg(address);
int paramCount = 0;
- if(ui->chkReq->isChecked() && ui->lnReqAmount->text().isEmpty() == false) {
- bool ok= false;
- double amount = ui->lnReqAmount->text().toDouble(&ok);
- if(ok) {
- ret += QString("?amount=%1X8").arg(ui->lnReqAmount->text());
+ if (ui->chkReqPayment->isChecked() && !ui->lnReqAmount->text().isEmpty())
+ {
+ bool ok = false;
+ ui->lnReqAmount->text().toDouble(&ok);
+ if (ok)
+ {
+ ret += QString("?amount=%1").arg(ui->lnReqAmount->text());
paramCount++;
}
}
- if(ui->lnLabel->text().isEmpty() == false) {
+ if (!ui->lnLabel->text().isEmpty())
+ {
QString lbl(QUrl::toPercentEncoding(ui->lnLabel->text()));
ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl);
paramCount++;
}
- if(ui->lnMessage->text().isEmpty() == false) {
+ if (!ui->lnMessage->text().isEmpty())
+ {
QString msg(QUrl::toPercentEncoding(ui->lnMessage->text()));
ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg);
paramCount++;
}
- return ret;
+ // limit URI length to 255 chars, to prevent a DoS against the QR-Code dialog
+ if (ret.length() < 256)
+ return ret;
+ else
+ return QString("");
}
-void QRCodeDialog::on_lnReqAmount_textChanged(const QString &)
+void QRCodeDialog::on_lnReqAmount_textChanged(const QString &arg1)
{
genCode();
}
-void QRCodeDialog::on_lnLabel_textChanged(const QString &)
+void QRCodeDialog::on_lnLabel_textChanged(const QString &arg1)
{
genCode();
}
-void QRCodeDialog::on_lnMessage_textChanged(const QString &)
+void QRCodeDialog::on_lnMessage_textChanged(const QString &arg1)
{
genCode();
}
@@ -99,12 +114,11 @@ void QRCodeDialog::on_lnMessage_textChanged(const QString &)
void QRCodeDialog::on_btnSaveAs_clicked()
{
QString fn = GUIUtil::getSaveFileName(this, tr("Save Image..."), QString(), tr("PNG Images (*.png)"));
- if(!fn.isEmpty()) {
+ if (!fn.isEmpty())
myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn);
- }
}
-void QRCodeDialog::on_chkReq_toggled(bool)
+void QRCodeDialog::on_chkReqPayment_toggled(bool)
{
genCode();
}
diff --git a/src/qt/qrcodedialog.h b/src/qt/qrcodedialog.h
index 7463a8810e..ad0611605b 100644
--- a/src/qt/qrcodedialog.h
+++ b/src/qt/qrcodedialog.h
@@ -13,7 +13,7 @@ class QRCodeDialog : public QDialog
Q_OBJECT
public:
- explicit QRCodeDialog(const QString &title, const QString &address, const QString &label, bool allowReq, QWidget *parent = 0);
+ explicit QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent = 0);
~QRCodeDialog();
private slots:
@@ -22,7 +22,7 @@ private slots:
void on_lnMessage_textChanged(const QString &arg1);
void on_btnSaveAs_clicked();
- void on_chkReq_toggled(bool checked);
+ void on_chkReqPayment_toggled(bool checked);
private:
Ui::QRCodeDialog *ui;
diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp
index 8b9270e178..3c7889ca71 100644
--- a/src/qt/qtipcserver.cpp
+++ b/src/qt/qtipcserver.cpp
@@ -8,6 +8,7 @@
#include <boost/date_time/posix_time/posix_time.hpp>
#include "headers.h"
+#include "qtipcserver.h"
using namespace boost::interprocess;
using namespace boost::posix_time;
@@ -16,7 +17,7 @@ using namespace std;
void ipcShutdown()
{
- message_queue::remove("BitcoinURL");
+ message_queue::remove(BITCOINURI_QUEUE_NAME);
}
void ipcThread(void* parg)
@@ -30,7 +31,7 @@ void ipcThread(void* parg)
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
{
- ThreadSafeHandleURL(std::string(strBuf, nSize));
+ ThreadSafeHandleURI(std::string(strBuf, nSize));
Sleep(1000);
}
if (fShutdown)
@@ -60,7 +61,7 @@ void ipcInit()
size_t nSize;
unsigned int nPriority;
try {
- mq = new message_queue(open_or_create, "BitcoinURL", 2, 256);
+ mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
// Make sure we don't lose any bitcoin: URIs
for (int i = 0; i < 2; i++)
@@ -68,15 +69,15 @@ void ipcInit()
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
{
- ThreadSafeHandleURL(std::string(strBuf, nSize));
+ ThreadSafeHandleURI(std::string(strBuf, nSize));
}
else
break;
}
// Make sure only one bitcoin instance is listening
- message_queue::remove("BitcoinURL");
- mq = new message_queue(open_or_create, "BitcoinURL", 2, 256);
+ message_queue::remove(BITCOINURI_QUEUE_NAME);
+ mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
}
catch (interprocess_exception &ex) {
return;
diff --git a/src/qt/qtipcserver.h b/src/qt/qtipcserver.h
index 1de0334afd..fcff10d8da 100644
--- a/src/qt/qtipcserver.h
+++ b/src/qt/qtipcserver.h
@@ -1,2 +1,4 @@
+#define BITCOINURI_QUEUE_NAME "BitcoinURI"
+
void ipcInit();
void ipcShutdown();
diff --git a/src/qt/res/icons/connect4_16.png b/src/qt/res/icons/connect4_16.png
index e2fe97d496..c1232f5682 100644
--- a/src/qt/res/icons/connect4_16.png
+++ b/src/qt/res/icons/connect4_16.png
Binary files differ
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 964313ea81..592ae6f45a 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -265,10 +265,10 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
}
-void SendCoinsDialog::handleURL(const QString &url)
+void SendCoinsDialog::handleURI(const QString &uri)
{
SendCoinsRecipient rv;
- if(!GUIUtil::parseBitcoinURL(url, &rv))
+ if(!GUIUtil::parseBitcoinURI(uri, &rv))
{
return;
}
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index 4dc3f08bc5..5dcbfbeb61 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -30,7 +30,7 @@ public:
QWidget *setupTabChain(QWidget *prev);
void pasteEntry(const SendCoinsRecipient &rv);
- void handleURL(const QString &url);
+ void handleURI(const QString &uri);
public slots:
void clear();
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 0a08eafa1e..5b11e39ea3 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -1,11 +1,11 @@
#include <QTest>
#include <QObject>
-#include "urltests.h"
+#include "uritests.h"
// This is all you need to run all the tests
int main(int argc, char *argv[])
{
- URLTests test1;
+ URITests test1;
QTest::qExec(&test1);
}
diff --git a/src/qt/test/urltests.cpp b/src/qt/test/uritests.cpp
index 1f11795a9b..70c20be0ea 100644
--- a/src/qt/test/urltests.cpp
+++ b/src/qt/test/uritests.cpp
@@ -1,4 +1,4 @@
-#include "urltests.h"
+#include "uritests.h"
#include "../guiutil.h"
#include "../walletmodel.h"
@@ -13,59 +13,59 @@ struct SendCoinsRecipient
};
*/
-void URLTests::urlTests()
+void URITests::uriTests()
{
SendCoinsRecipient rv;
- QUrl url;
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
- QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+ QUrl uri;
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
+ QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
- QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
+ QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
QVERIFY(rv.amount == 0);
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
- QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
+ QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString("Wikipedia Example Address"));
QVERIFY(rv.amount == 0);
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
- QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
+ QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
QVERIFY(rv.amount == 100000);
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
- QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
+ QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
QVERIFY(rv.amount == 100100000);
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
- QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
+ QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.amount == 10000000000);
QVERIFY(rv.label == QString("Wikipedia Example"));
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
- QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
+ QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
- QVERIFY(GUIUtil::parseBitcoinURL("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
+ QVERIFY(GUIUtil::parseBitcoinURI("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
// We currently dont implement the message paramenter (ok, yea, we break spec...)
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
- QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
+ QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
- QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
+ QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
- url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
- QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
+ uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
+ QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
}
diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h
new file mode 100644
index 0000000000..1237516e5f
--- /dev/null
+++ b/src/qt/test/uritests.h
@@ -0,0 +1,15 @@
+#ifndef URITESTS_H
+#define URITESTS_H
+
+#include <QTest>
+#include <QObject>
+
+class URITests : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void uriTests();
+};
+
+#endif // URITESTS_H
diff --git a/src/qt/test/urltests.h b/src/qt/test/urltests.h
deleted file mode 100644
index 393c511390..0000000000
--- a/src/qt/test/urltests.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef URLTESTS_H
-#define URLTESTS_H
-
-#include <QTest>
-#include <QObject>
-
-class URLTests : public QObject
-{
- Q_OBJECT
-
-private slots:
- void urlTests();
-};
-
-#endif // URLTESTS_H
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index c32a006f71..dd7dd61390 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -34,8 +34,9 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
{
QString strHTML;
- CRITICAL_BLOCK(wallet->cs_wallet)
+
{
+ LOCK(wallet->cs_wallet);
strHTML.reserve(4000);
strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
@@ -243,8 +244,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
strHTML += "<br><b>Inputs:</b>";
strHTML += "<ul>";
- CRITICAL_BLOCK(wallet->cs_wallet)
+
{
+ LOCK(wallet->cs_wallet);
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{
COutPoint prevout = txin.prevout;
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 480d4ac25e..aa11df979f 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -69,8 +69,8 @@ struct TransactionTablePriv
qDebug() << "refreshWallet";
#endif
cachedWallet.clear();
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
{
cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second));
@@ -95,8 +95,8 @@ struct TransactionTablePriv
QList<uint256> updated_sorted = updated;
qSort(updated_sorted);
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx)
{
const uint256 &hash = updated_sorted.at(update_idx);
@@ -171,8 +171,8 @@ struct TransactionTablePriv
// simply re-use the cached status.
if(rec->statusUpdateNeeded())
{
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != wallet->mapWallet.end())
@@ -191,8 +191,8 @@ struct TransactionTablePriv
QString describe(TransactionRecord *rec)
{
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != wallet->mapWallet.end())
{
@@ -229,9 +229,9 @@ void TransactionTableModel::update()
QList<uint256> updated;
// Check if there are changes to wallet map
- TRY_CRITICAL_BLOCK(wallet->cs_wallet)
{
- if(!wallet->vWalletUpdated.empty())
+ TRY_LOCK(wallet->cs_wallet, lockWallet);
+ if (lockWallet && !wallet->vWalletUpdated.empty())
{
BOOST_FOREACH(uint256 hash, wallet->vWalletUpdated)
{
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 6cc023792d..9c28a8abc8 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -32,8 +32,8 @@ qint64 WalletModel::getUnconfirmedBalance() const
int WalletModel::getNumTransactions() const
{
int numTransactions = 0;
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
numTransactions = wallet->mapWallet.size();
}
return numTransactions;
@@ -115,9 +115,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee);
}
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK2(cs_main, wallet->cs_wallet);
+
// Sendmany
std::vector<std::pair<CScript, int64> > vecSend;
foreach(const SendCoinsRecipient &rcp, recipients)
@@ -155,8 +155,8 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
foreach(const SendCoinsRecipient &rcp, recipients)
{
std::string strAddress = rcp.address.toStdString();
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
if (!wallet->mapAddressBook.count(strAddress))
wallet->SetAddressBookName(strAddress, rcp.label.toStdString());
}
@@ -227,8 +227,8 @@ bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
{
bool retval;
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
wallet->Lock(); // Make sure wallet is locked before attempting pass change
retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
}
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index d59536e254..5bb4789cd3 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -6,15 +6,8 @@
#include "init.h" // for pwalletMain
#include "bitcoinrpc.h"
-// #include <boost/asio.hpp>
-// #include <boost/iostreams/concepts.hpp>
-// #include <boost/iostreams/stream.hpp>
#include <boost/lexical_cast.hpp>
-// #ifdef USE_SSL
-// #include <boost/asio/ssl.hpp>
-// typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
-// #endif
-// #include <boost/xpressive/xpressive_dynamic.hpp>
+
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
@@ -67,9 +60,9 @@ Value importprivkey(const Array& params, bool fHelp)
key.SetSecret(secret, fCompressed);
CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey());
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
pwalletMain->MarkDirty();
pwalletMain->SetAddressBookName(vchAddress, strLabel);
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 94c0c77a44..db31f4988a 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -15,14 +15,15 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
CCriticalSection cs;
do {
- CRITICAL_BLOCK(cs)
- break;
+ LOCK(cs);
+ break;
BOOST_ERROR("break was swallowed!");
} while(0);
do {
- TRY_CRITICAL_BLOCK(cs)
+ TRY_LOCK(cs, lockTest);
+ if (lockTest)
break;
BOOST_ERROR("break was swallowed!");
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 2e29f2af16..514768086d 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -40,7 +40,7 @@
extern int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK);
extern bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption);
-extern void ThreadSafeHandleURL(const std::string& strURL);
+extern void ThreadSafeHandleURI(const std::string& strURI);
extern void MainFrameRepaint();
extern void AddressBookRepaint();
extern void QueueShutdown();
diff --git a/src/util.cpp b/src/util.cpp
index 4f34ab6163..5579a09351 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
#include "headers.h"
#include "strlcpy.h"
#include <boost/algorithm/string/join.hpp>
@@ -21,7 +22,6 @@ map<string, vector<string> > mapMultiArgs;
bool fDebug = false;
bool fPrintToConsole = false;
bool fPrintToDebugger = false;
-char pszSetDataDir[MAX_PATH] = "";
bool fRequestShutdown = false;
bool fShutdown = false;
bool fDaemon = false;
@@ -33,16 +33,6 @@ bool fNoListen = false;
bool fLogTimestamps = false;
CMedianFilter<int64> vTimeOffsets(200,0);
-
-
-// Workaround for "multiple definition of `_tls_used'"
-// http://svn.boost.org/trac/boost/ticket/4258
-extern "C" void tss_cleanup_implemented() { }
-
-
-
-
-
// Init openssl library multithreading support
static boost::interprocess::interprocess_mutex** ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line)
@@ -174,10 +164,8 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
if (!fileout)
{
- char pszFile[MAX_PATH+100];
- GetDataDir(pszFile);
- strlcat(pszFile, "/debug.log", sizeof(pszFile));
- fileout = fopen(pszFile, "a");
+ boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
+ fileout = fopen(pathDebug.string().c_str(), "a");
if (fileout) setbuf(fileout, NULL); // unbuffered
}
if (fileout)
@@ -205,8 +193,8 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
static CCriticalSection cs_OutputDebugStringF;
// accumulate a line at a time
- CRITICAL_BLOCK(cs_OutputDebugStringF)
{
+ LOCK(cs_OutputDebugStringF);
static char pszBuffer[50000];
static char* pend;
if (pend == NULL)
@@ -777,101 +765,94 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread)
}
#ifdef WIN32
-string MyGetSpecialFolderPath(int nFolder, bool fCreate)
+boost::filesystem::path MyGetSpecialFolderPath(int nFolder, bool fCreate)
{
+ namespace fs = boost::filesystem;
+
char pszPath[MAX_PATH] = "";
if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
{
- return pszPath;
+ return fs::path(pszPath);
}
else if (nFolder == CSIDL_STARTUP)
{
- return string(getenv("USERPROFILE")) + "\\Start Menu\\Programs\\Startup";
+ return fs::path(getenv("USERPROFILE")) / "Start Menu" / "Programs" / "Startup";
}
else if (nFolder == CSIDL_APPDATA)
{
- return getenv("APPDATA");
+ return fs::path(getenv("APPDATA"));
}
- return "";
+ return fs::path("");
}
#endif
-string GetDefaultDataDir()
+boost::filesystem::path GetDefaultDataDir()
{
+ namespace fs = boost::filesystem;
+
// Windows: C:\Documents and Settings\username\Application Data\Bitcoin
// Mac: ~/Library/Application Support/Bitcoin
// Unix: ~/.bitcoin
#ifdef WIN32
// Windows
- return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin";
+ return MyGetSpecialFolderPath(CSIDL_APPDATA, true) / "Bitcoin";
#else
+ fs::path pathRet;
char* pszHome = getenv("HOME");
if (pszHome == NULL || strlen(pszHome) == 0)
- pszHome = (char*)"/";
- string strHome = pszHome;
- if (strHome[strHome.size()-1] != '/')
- strHome += '/';
+ pathRet = fs::path("/");
+ else
+ pathRet = fs::path(pszHome);
#ifdef MAC_OSX
// Mac
- strHome += "Library/Application Support/";
- filesystem::create_directory(strHome.c_str());
- return strHome + "Bitcoin";
+ pathRet /= "Library/Application Support";
+ filesystem::create_directory(pathRet);
+ return pathRet / "Bitcoin";
#else
// Unix
- return strHome + ".bitcoin";
+ return pathRet / ".bitcoin";
#endif
#endif
}
-void GetDataDir(char* pszDir)
+const boost::filesystem::path &GetDataDir(bool fNetSpecific)
{
- // pszDir must be at least MAX_PATH length.
- int nVariation;
- if (pszSetDataDir[0] != 0)
- {
- strlcpy(pszDir, pszSetDataDir, MAX_PATH);
- nVariation = 0;
- }
- else
- {
- // This can be called during exceptions by printf, so we cache the
- // value so we don't have to do memory allocations after that.
- static char pszCachedDir[MAX_PATH];
- if (pszCachedDir[0] == 0)
- strlcpy(pszCachedDir, GetDefaultDataDir().c_str(), sizeof(pszCachedDir));
- strlcpy(pszDir, pszCachedDir, MAX_PATH);
- nVariation = 1;
- }
- if (fTestNet)
- {
- char* p = pszDir + strlen(pszDir);
- if (p > pszDir && p[-1] != '/' && p[-1] != '\\')
- *p++ = '/';
- strcpy(p, "testnet");
- nVariation += 2;
- }
- static bool pfMkdir[4];
- if (!pfMkdir[nVariation])
- {
- pfMkdir[nVariation] = true;
- boost::filesystem::create_directory(pszDir);
+ namespace fs = boost::filesystem;
+
+ static fs::path pathCached[2];
+ static CCriticalSection csPathCached;
+ static bool cachedPath[2] = {false, false};
+
+ fs::path &path = pathCached[fNetSpecific];
+
+ // This can be called during exceptions by printf, so we cache the
+ // value so we don't have to do memory allocations after that.
+ if (cachedPath[fNetSpecific])
+ return path;
+
+ LOCK(csPathCached);
+
+ if (mapArgs.count("-datadir")) {
+ path = mapArgs["-datadir"];
+ } else {
+ path = GetDefaultDataDir();
+ if (fNetSpecific && GetBoolArg("-testnet", false))
+ path /= "testnet";
}
-}
-string GetDataDir()
-{
- char pszDir[MAX_PATH];
- GetDataDir(pszDir);
- return pszDir;
+ fs::create_directory(path);
+
+ cachedPath[fNetSpecific]=true;
+ return path;
}
-string GetConfigFile()
+boost::filesystem::path GetConfigFile()
{
namespace fs = boost::filesystem;
- fs::path pathConfig(GetArg("-conf", "bitcoin.conf"));
- if (!pathConfig.is_complete())
- pathConfig = fs::path(GetDataDir()) / pathConfig;
- return pathConfig.string();
+
+ fs::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
+ if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile;
+ return pathConfigFile;
}
bool ReadConfigFile(map<string, string>& mapSettingsRet,
@@ -880,26 +861,13 @@ bool ReadConfigFile(map<string, string>& mapSettingsRet,
namespace fs = boost::filesystem;
namespace pod = boost::program_options::detail;
- if (mapSettingsRet.count("-datadir"))
- {
- if (fs::is_directory(fs::system_complete(mapSettingsRet["-datadir"])))
- {
- fs::path pathDataDir = fs::system_complete(mapSettingsRet["-datadir"]);
- strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
- }
- else
- {
- return false;
- }
- }
-
fs::ifstream streamConfig(GetConfigFile());
if (!streamConfig.good())
return true; // No bitcoin.conf file is OK
set<string> setOptions;
setOptions.insert("*");
-
+
for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
{
// Don't overwrite existing settings so command line settings override bitcoin.conf
@@ -915,18 +883,18 @@ bool ReadConfigFile(map<string, string>& mapSettingsRet,
return true;
}
-string GetPidFile()
+boost::filesystem::path GetPidFile()
{
namespace fs = boost::filesystem;
- fs::path pathConfig(GetArg("-pid", "bitcoind.pid"));
- if (!pathConfig.is_complete())
- pathConfig = fs::path(GetDataDir()) / pathConfig;
- return pathConfig.string();
+
+ fs::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
+ if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
+ return pathPidFile;
}
-void CreatePidFile(string pidFile, pid_t pid)
+void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
{
- FILE* file = fopen(pidFile.c_str(), "w");
+ FILE* file = fopen(path.string().c_str(), "w");
if (file)
{
fprintf(file, "%d\n", pid);
@@ -947,8 +915,8 @@ int GetFilesize(FILE* file)
void ShrinkDebugFile()
{
// Scroll debug.log if it's getting too big
- string strFile = GetDataDir() + "/debug.log";
- FILE* file = fopen(strFile.c_str(), "r");
+ boost::filesystem::path pathLog = GetDataDir() / "debug.log";
+ FILE* file = fopen(pathLog.string().c_str(), "r");
if (file && GetFilesize(file) > 10 * 1000000)
{
// Restart the file with some of the end
@@ -957,7 +925,7 @@ void ShrinkDebugFile()
int nBytes = fread(pch, 1, sizeof(pch), file);
fclose(file);
- file = fopen(strFile.c_str(), "w");
+ file = fopen(pathLog.string().c_str(), "w");
if (file)
{
fwrite(pch, 1, nBytes, file);
@@ -1071,12 +1039,7 @@ string FormatVersion(int nVersion)
string FormatFullVersion()
{
- string s = FormatVersion(CLIENT_VERSION);
- if (VERSION_IS_BETA) {
- s += "-";
- s += _("beta");
- }
- return s;
+ return CLIENT_BUILD;
}
// Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
@@ -1125,25 +1088,25 @@ private:
int sourceLine;
};
-typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack;
+typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
static boost::interprocess::interprocess_mutex dd_mutex;
-static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders;
+static std::map<std::pair<void*, void*>, LockStack> lockorders;
static boost::thread_specific_ptr<LockStack> lockstack;
-static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2)
+static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
printf("POTENTIAL DEADLOCK DETECTED\n");
printf("Previous lock order was:\n");
- BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
+ BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
{
if (i.first == mismatch.first) printf(" (1)");
if (i.first == mismatch.second) printf(" (2)");
printf(" %s\n", i.second.ToString().c_str());
}
printf("Current lock order is:\n");
- BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
+ BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
{
if (i.first == mismatch.first) printf(" (1)");
if (i.first == mismatch.second) printf(" (2)");
@@ -1151,7 +1114,7 @@ static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCrit
}
}
-static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
+static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
{
bool fOrderOK = true;
if (lockstack.get() == NULL)
@@ -1162,16 +1125,16 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
(*lockstack).push_back(std::make_pair(c, locklocation));
- BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack))
+ if (!fTry) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack))
{
if (i.first == c) break;
- std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c);
+ std::pair<void*, void*> p1 = std::make_pair(i.first, c);
if (lockorders.count(p1))
continue;
lockorders[p1] = (*lockstack);
- std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
+ std::pair<void*, void*> p2 = std::make_pair(c, i.first);
if (lockorders.count(p2))
{
potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
@@ -1193,62 +1156,14 @@ static void pop_lock()
dd_mutex.unlock();
}
-void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
-{
- push_lock(this, CLockLocation(pszName, pszFile, nLine));
-#ifdef DEBUG_LOCKCONTENTION
- bool result = mutex.try_lock();
- if (!result)
- {
- printf("LOCKCONTENTION: %s\n", pszName);
- printf("Locker: %s:%d\n", pszFile, nLine);
- mutex.lock();
- printf("Locked\n");
- }
-#else
- mutex.lock();
-#endif
-}
-void CCriticalSection::Leave()
+void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{
- mutex.unlock();
- pop_lock();
-}
-bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine)
-{
- push_lock(this, CLockLocation(pszName, pszFile, nLine));
- bool result = mutex.try_lock();
- if (!result) pop_lock();
- return result;
-}
-
-#else
-
-void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
-{
-#ifdef DEBUG_LOCKCONTENTION
- bool result = mutex.try_lock();
- if (!result)
- {
- printf("LOCKCONTENTION: %s\n", pszName);
- printf("Locker: %s:%d\n", pszFile, nLine);
- mutex.lock();
- }
-#else
- mutex.lock();
-#endif
-}
-
-void CCriticalSection::Leave()
-{
- mutex.unlock();
+ push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
}
-bool CCriticalSection::TryEnter(const char*, const char*, int)
+void LeaveCritical()
{
- bool result = mutex.try_lock();
- return result;
+ pop_lock();
}
#endif /* DEBUG_LOCKORDER */
-
diff --git a/src/util.h b/src/util.h
index e4cf83f433..f6cb3caa1d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -19,7 +19,12 @@ typedef int pid_t; /* define for windows compatiblity */
#include <string>
#include <boost/thread.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <boost/interprocess/sync/lock_options.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
@@ -108,7 +113,6 @@ extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
extern bool fDebug;
extern bool fPrintToConsole;
extern bool fPrintToDebugger;
-extern char pszSetDataDir[MAX_PATH];
extern bool fRequestShutdown;
extern bool fShutdown;
extern bool fDaemon;
@@ -150,16 +154,15 @@ 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);
int GetFilesize(FILE* file);
-void GetDataDir(char* pszDirRet);
-std::string GetConfigFile();
-std::string GetPidFile();
-void CreatePidFile(std::string pidFile, pid_t pid);
+boost::filesystem::path GetDefaultDataDir();
+const boost::filesystem::path &GetDataDir(bool fNetSpecific = true);
+boost::filesystem::path GetConfigFile();
+boost::filesystem::path GetPidFile();
+void CreatePidFile(const boost::filesystem::path &path, pid_t pid);
bool ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
#ifdef WIN32
-std::string MyGetSpecialFolderPath(int nFolder, bool fCreate);
+boost::filesystem::path MyGetSpecialFolderPath(int nFolder, bool fCreate);
#endif
-std::string GetDefaultDataDir();
-std::string GetDataDir();
void ShrinkDebugFile();
int GetRandInt(int nMax);
uint64 GetRand(uint64 nMax);
@@ -180,82 +183,127 @@ void AddTimeData(const CNetAddr& ip, int64 nTime);
+/** Wrapped boost mutex: supports recursive locking, but no waiting */
+typedef boost::interprocess::interprocess_recursive_mutex CCriticalSection;
-/** Wrapper to automatically initialize mutex. */
-class CCriticalSection
-{
-protected:
- boost::interprocess::interprocess_recursive_mutex mutex;
-public:
- explicit CCriticalSection() { }
- ~CCriticalSection() { }
- void Enter(const char* pszName, const char* pszFile, int nLine);
- void Leave();
- bool TryEnter(const char* pszName, const char* pszFile, int nLine);
-};
+/** Wrapped boost mutex: supports waiting but not recursive locking */
+typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection;
-/** RAII object that acquires mutex. Needed for exception safety. */
-class CCriticalBlock
-{
-protected:
- CCriticalSection* pcs;
+#ifdef DEBUG_LOCKORDER
+void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
+void LeaveCritical();
+#else
+void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
+void static inline LeaveCritical() {}
+#endif
+/** Wrapper around boost::interprocess::scoped_lock */
+template<typename Mutex>
+class CMutexLock
+{
+private:
+ boost::interprocess::scoped_lock<Mutex> lock;
public:
- CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+
+ void Enter(const char* pszName, const char* pszFile, int nLine)
{
- pcs = &csIn;
- pcs->Enter(pszName, pszFile, nLine);
+ if (!lock.owns())
+ {
+ EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
+#ifdef DEBUG_LOCKCONTENTION
+ if (!lock.try_lock())
+ {
+ printf("LOCKCONTENTION: %s\n", pszName);
+ printf("Locker: %s:%d\n", pszFile, nLine);
+ }
+#endif
+ lock.lock();
+ }
}
- operator bool() const
+ void Leave()
{
- return true;
+ if (lock.owns())
+ {
+ lock.unlock();
+ LeaveCritical();
+ }
}
- ~CCriticalBlock()
+ bool TryEnter(const char* pszName, const char* pszFile, int nLine)
{
- pcs->Leave();
+ if (!lock.owns())
+ {
+ EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
+ lock.try_lock();
+ if (!lock.owns())
+ LeaveCritical();
+ }
+ return lock.owns();
}
-};
-
-#define CRITICAL_BLOCK(cs) \
- if (CCriticalBlock criticalblock = CCriticalBlock(cs, #cs, __FILE__, __LINE__))
-#define ENTER_CRITICAL_SECTION(cs) \
- (cs).Enter(#cs, __FILE__, __LINE__)
-
-#define LEAVE_CRITICAL_SECTION(cs) \
- (cs).Leave()
-
-/** RAII object that tries to acquire mutex. Needed for exception safety. */
-class CTryCriticalBlock
-{
-protected:
- CCriticalSection* pcs;
+ CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::interprocess::defer_lock)
+ {
+ if (fTry)
+ TryEnter(pszName, pszFile, nLine);
+ else
+ Enter(pszName, pszFile, nLine);
+ }
-public:
- CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+ ~CMutexLock()
{
- pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL);
+ if (lock.owns())
+ LeaveCritical();
}
- operator bool() const
+ operator bool()
{
- return Entered();
+ return lock.owns();
}
- ~CTryCriticalBlock()
+ boost::interprocess::scoped_lock<Mutex> &GetLock()
{
- if (pcs)
- {
- pcs->Leave();
- }
+ return lock;
}
- bool Entered() const { return pcs != NULL; }
};
-#define TRY_CRITICAL_BLOCK(cs) \
- if (CTryCriticalBlock criticalblock = CTryCriticalBlock(cs, #cs, __FILE__, __LINE__))
+typedef CMutexLock<CCriticalSection> CCriticalBlock;
+typedef CMutexLock<CWaitableCriticalSection> CWaitableCriticalBlock;
+typedef boost::interprocess::interprocess_condition CConditionVariable;
+
+/** Wait for a given condition inside a WAITABLE_CRITICAL_BLOCK */
+#define WAIT(name,condition) \
+ do { while(!(condition)) { (name).wait(waitablecriticalblock.GetLock()); } } while(0)
+
+/** Notify waiting threads that a condition may hold now */
+#define NOTIFY(name) \
+ do { (name).notify_one(); } while(0)
+
+#define NOTIFY_ALL(name) \
+ do { (name).notify_all(); } while(0)
+
+#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
+#define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
+#define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
+#define WAITABLE_LOCK(cs) CWaitableCriticalBlock waitablecriticalblock(cs, #cs, __FILE__, __LINE__)
+
+#define ENTER_CRITICAL_SECTION(cs) \
+ { \
+ EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
+ (cs).lock(); \
+ }
+
+#define LEAVE_CRITICAL_SECTION(cs) \
+ { \
+ (cs).unlock(); \
+ LeaveCritical(); \
+ }
+
+
+// This is exactly like std::string, but with a custom allocator.
+// (secure_allocator<> is defined in serialize.h)
+typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
+
@@ -658,26 +706,6 @@ inline void ExitThread(size_t nExitCode)
-inline bool AffinityBugWorkaround(void(*pfn)(void*))
-{
-#ifdef WIN32
- // Sometimes after a few hours affinity gets stuck on one processor
- DWORD_PTR dwProcessAffinityMask = -1;
- DWORD_PTR dwSystemAffinityMask = -1;
- GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
- DWORD dwPrev1 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
- DWORD dwPrev2 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
- if (dwPrev2 != dwProcessAffinityMask)
- {
- printf("AffinityBugWorkaround() : SetThreadAffinityMask=%d, ProcessAffinityMask=%d, restarting thread\n", dwPrev2, dwProcessAffinityMask);
- if (!CreateThread(pfn, NULL))
- printf("Error: CreateThread() failed\n");
- return true;
- }
-#endif
- return false;
-}
-
inline uint32_t ByteReverse(uint32_t value)
{
value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
diff --git a/src/version.cpp b/src/version.cpp
new file mode 100644
index 0000000000..e1be5f491b
--- /dev/null
+++ b/src/version.cpp
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#include <string>
+
+#include "version.h"
+
+// Name of client reported in the 'version' message. Report the same name
+// for both bitcoind and bitcoin-qt, to make it harder for attackers to
+// target servers or GUI users specifically.
+const std::string CLIENT_NAME("Satoshi");
+
+// Client version number
+#define CLIENT_VERSION_MAJOR 0
+#define CLIENT_VERSION_MINOR 6
+#define CLIENT_VERSION_REVISION 0
+#define CLIENT_VERSION_BUILD 99
+#define CLIENT_VERSION_SUFFIX "-beta"
+
+const int CLIENT_VERSION = 1000000 * CLIENT_VERSION_MAJOR
+ + 10000 * CLIENT_VERSION_MINOR
+ + 100 * CLIENT_VERSION_REVISION
+ + 1 * CLIENT_VERSION_BUILD;
+
+
+
+// The following part of the code determines the CLIENT_BUILD variable.
+// Several mechanisms are used for this:
+// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
+// generated by the build environment, possibly containing the output
+// of git-describe in a macro called BUILD_DESC
+// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
+// be defined (automatically using the export-subst git attribute), and
+// GIT_COMMIT will contain the commit id.
+// * then, three options exist for determining CLIENT_BUILD:
+// * if BUILD_DESC is defined, use that literally (output of git-describe)
+// * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
+// * otherwise, use v[maj].[min].[rev].[build]-unk
+// finally CLIENT_VERSION_SUFFIX is added
+
+// First, include build.h if requested
+#ifdef HAVE_BUILD_INFO
+# include "build.h"
+#endif
+
+// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
+#ifdef GIT_ARCHIVE
+# define GIT_COMMIT_ID "$Format:%h$"
+# define GIT_COMMIT_DATE "$Format:%cD"
+#endif
+
+#define STRINGIFY(s) #s
+
+#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
+ "v" STRINGIFY(maj) "." STRINGIFY(min) "." STRINGIFY(rev) "." STRINGIFY(build) "-g" commit
+
+#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
+ "v" STRINGIFY(maj) "." STRINGIFY(min) "." STRINGIFY(rev) "." STRINGIFY(build) "-unk"
+
+#ifndef BUILD_DESC
+# ifdef GIT_COMMIT_ID
+# define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
+# else
+# define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
+# endif
+#endif
+
+#ifndef BUILD_DATE
+# ifdef GIT_COMMIT_DATE
+# define BUILD_DATE GIT_COMMIT_DATE
+# else
+# define BUILD_DATE __DATE__ ", " __TIME__
+# endif
+#endif
+
+const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
+const std::string CLIENT_DATE(BUILD_DATE);
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000000..c93b28fb7d
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_VERSION_H
+#define BITCOIN_VERSION_H
+
+#include <string>
+
+extern const std::string CLIENT_NAME;
+extern const std::string CLIENT_BUILD;
+extern const std::string CLIENT_DATE;
+extern const int CLIENT_VERSION;
+
+#endif
diff --git a/src/wallet.cpp b/src/wallet.cpp
index e444e5f696..97ed6aa580 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -49,8 +49,8 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
return false;
if (!fFileBacked)
return true;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
if (pwalletdbEncryption)
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
else
@@ -76,7 +76,8 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
CCrypter crypter;
CKeyingMaterial vMasterKey;
- CRITICAL_BLOCK(cs_wallet)
+ {
+ LOCK(cs_wallet);
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
{
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
@@ -86,6 +87,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
if (CCryptoKeyStore::Unlock(vMasterKey))
return true;
}
+ }
return false;
}
@@ -93,8 +95,8 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
{
bool fWasLocked = IsLocked();
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
Lock();
CCrypter crypter;
@@ -228,8 +230,8 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
return false;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
if (fFileBacked)
{
@@ -275,8 +277,8 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
// Anytime a signature is successfully verified, it's proof the outpoint is spent.
// Update the wallet spent flag if it doesn't know due to wallet.dat being
// restored from backup or the user making copies of wallet.dat.
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
@@ -297,8 +299,8 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
void CWallet::MarkDirty()
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
item.second.MarkDirty();
}
@@ -307,8 +309,8 @@ void CWallet::MarkDirty()
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
// Inserts only if not already there, returns tx inserted or tx found
pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
CWalletTx& wtx = (*ret.first).second;
@@ -382,8 +384,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
{
uint256 hash = tx.GetHash();
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
bool fExisted = mapWallet.count(hash);
if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx) || IsFromMe(tx))
@@ -404,8 +406,8 @@ bool CWallet::EraseFromWallet(uint256 hash)
{
if (!fFileBacked)
return false;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
if (mapWallet.erase(hash))
CWalletDB(strWalletFile).EraseTx(hash);
}
@@ -415,8 +417,8 @@ bool CWallet::EraseFromWallet(uint256 hash)
bool CWallet::IsMine(const CTxIn &txin) const
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
@@ -431,8 +433,8 @@ bool CWallet::IsMine(const CTxIn &txin) const
int64 CWallet::GetDebit(const CTxIn &txin) const
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
@@ -457,9 +459,11 @@ bool CWallet::IsChange(const CTxOut& txout) const
// 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change).
if (ExtractAddress(txout.scriptPubKey, address) && HaveKey(address))
- CRITICAL_BLOCK(cs_wallet)
- if (!mapAddressBook.count(address))
- return true;
+ {
+ LOCK(cs_wallet);
+ if (!mapAddressBook.count(address))
+ return true;
+ }
return false;
}
@@ -472,8 +476,8 @@ int CWalletTx::GetRequestCount() const
{
// Returns -1 if it wasn't being tracked
int nRequests = -1;
- CRITICAL_BLOCK(pwallet->cs_wallet)
{
+ LOCK(pwallet->cs_wallet);
if (IsCoinBase())
{
// Generated block
@@ -577,8 +581,8 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
nSent += s.second;
nFee = allFee;
}
- CRITICAL_BLOCK(pwallet->cs_wallet)
{
+ LOCK(pwallet->cs_wallet);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
{
if (pwallet->mapAddressBook.count(r.first))
@@ -607,8 +611,8 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
vWorkQueue.push_back(txin.prevout.hash);
// This critsect is OK because txdb is already open
- CRITICAL_BLOCK(pwallet->cs_wallet)
{
+ LOCK(pwallet->cs_wallet);
map<uint256, const CMerkleTx*> mapWalletPrev;
set<uint256> setAlreadyDone;
for (int i = 0; i < vWorkQueue.size(); i++)
@@ -666,8 +670,8 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
int ret = 0;
CBlockIndex* pindex = pindexStart;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
while (pindex)
{
CBlock block;
@@ -696,8 +700,9 @@ void CWallet::ReacceptWalletTransactions()
{
CTxDB txdb("r");
bool fRepeat = true;
- while (fRepeat) CRITICAL_BLOCK(cs_wallet)
+ while (fRepeat)
{
+ LOCK(cs_wallet);
fRepeat = false;
vector<CDiskTxPos> vMissingTx;
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
@@ -799,8 +804,8 @@ void CWallet::ResendWalletTransactions()
// Rebroadcast any of our txes that aren't in a block yet
printf("ResendWalletTransactions()\n");
CTxDB txdb("r");
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
// Sort them in chronological order
multimap<unsigned int, CWalletTx*> mapSorted;
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
@@ -833,8 +838,8 @@ void CWallet::ResendWalletTransactions()
int64 CWallet::GetBalance() const
{
int64 nTotal = 0;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
@@ -850,8 +855,8 @@ int64 CWallet::GetBalance() const
int64 CWallet::GetUnconfirmedBalance() const
{
int64 nTotal = 0;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
@@ -875,8 +880,8 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe
vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
int64 nTotalLower = 0;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
vector<const CWalletTx*> vCoins;
vCoins.reserve(mapWallet.size());
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
@@ -1032,9 +1037,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
wtxNew.BindWallet(this);
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK2(cs_main, cs_wallet);
// txdb must be opened before the mapWallet lock
CTxDB txdb("r");
{
@@ -1146,9 +1150,8 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w
// Call after CreateTransaction unless you want to abort
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK2(cs_main, cs_wallet);
printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
{
// This is only to keep the database open to defeat the auto-flush for the
@@ -1297,8 +1300,8 @@ bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
void CWallet::PrintWallet(const CBlock& block)
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
if (mapWallet.count(block.vtx[0].GetHash()))
{
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
@@ -1310,8 +1313,8 @@ void CWallet::PrintWallet(const CBlock& block)
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
if (mi != mapWallet.end())
{
@@ -1347,8 +1350,8 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
//
bool CWallet::NewKeyPool()
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
CWalletDB walletdb(strWalletFile);
BOOST_FOREACH(int64 nIndex, setKeyPool)
walletdb.ErasePool(nIndex);
@@ -1371,8 +1374,9 @@ bool CWallet::NewKeyPool()
bool CWallet::TopUpKeyPool()
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
+
if (IsLocked())
return false;
@@ -1398,8 +1402,9 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{
nIndex = -1;
keypool.vchPubKey.clear();
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
+
if (!IsLocked())
TopUpKeyPool();
@@ -1422,9 +1427,8 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
int64 CWallet::AddReserveKey(const CKeyPool& keypool)
{
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK2(cs_main, cs_wallet);
CWalletDB walletdb(strWalletFile);
int64 nIndex = 1 + *(--setKeyPool.end());
@@ -1450,8 +1454,10 @@ void CWallet::KeepKey(int64 nIndex)
void CWallet::ReturnKey(int64 nIndex)
{
// Return to key pool
- CRITICAL_BLOCK(cs_wallet)
+ {
+ LOCK(cs_wallet);
setKeyPool.insert(nIndex);
+ }
printf("keypool return %"PRI64d"\n", nIndex);
}
@@ -1459,8 +1465,8 @@ bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
{
int64 nIndex = 0;
CKeyPool keypool;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
ReserveKeyFromKeyPool(nIndex, keypool);
if (nIndex == -1)
{
@@ -1530,8 +1536,7 @@ void CWallet::GetAllReserveAddresses(set<CBitcoinAddress>& setAddress)
CWalletDB walletdb(strWalletFile);
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_wallet)
+ LOCK2(cs_main, cs_wallet);
BOOST_FOREACH(const int64& id, setKeyPool)
{
CKeyPool keypool;
diff --git a/src/wallet.h b/src/wallet.h
index e1065cff38..f864370acf 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -211,16 +211,18 @@ public:
void UpdatedTransaction(const uint256 &hashTx)
{
- CRITICAL_BLOCK(cs_wallet)
+ {
+ LOCK(cs_wallet);
vWalletUpdated.push_back(hashTx);
+ }
}
void PrintWallet(const CBlock& block);
void Inventory(const uint256 &hash)
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
if (mi != mapRequestCount.end())
(*mi).second++;