contains(BITCOIN_QT_TEST, 1) {
SOURCES += src/qt/test/test_main.cpp \
- src/qt/test/urltests.cpp
-HEADERS += src/qt/test/urltests.h
+ src/qt/test/uritests.cpp
+HEADERS += src/qt/test/uritests.h
DEPENDPATH += src/qt/test
QT += testlib
TARGET = bitcoin-qt_test
Encoding=UTF-8
Name=Bitcoin
Comment=Bitcoin P2P Cryptocurrency
+Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair
+Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi
Exec=/usr/bin/bitcoin-qt
Terminal=false
Type=Application
+Code: src/strlcpy.h
+Author: Todd C. Miller <Todd.Miller@courtesan.com>
+License: ISC
+
Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
src/qt/res/src/*.svg
Designer: Wladimir van der Laan
//
// 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);
void Check()
{
#ifdef DEBUG_ADDRMAN
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
int err;
if ((err=Check_()))
printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
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();
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;
// Mark an entry as accessible.
void Good(const CService &addr, int64 nTime = GetAdjustedTime())
{
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
Good_(addr, nTime);
Check();
// 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();
CAddress Select(int nUnkBias = 50)
{
CAddress addrRet;
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
Check();
addrRet = Select_(nUnkBias);
Check();
{
Check();
std::vector<CAddress> vAddr;
- CRITICAL_BLOCK(cs)
+ {
+ LOCK(cs);
GetAddr_(vAddr);
+ }
Check();
return vAddr;
}
// 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();
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#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;
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;
}
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());
+ filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
+ if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
+ pathCertFile.make_preferred();
+ if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string().c_str());
+ 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;
+ pathPKFile.make_preferred();
+ if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string().c_str(), 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
{
// 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);
DbEnv dbenv(0);
static map<string, int> mapFileUseCount;
static map<string, Db*> mapDb;
-static int64 nTxn = 0;
static void EnvShutdown()
{
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 pathLogDir(strDataDir + "/database");
+ pathLogDir.make_preferred();
+ filesystem::create_directory(pathLogDir);
+ filesystem::path pathErrorFile(strDataDir + "/db.log");
+ pathErrorFile.make_preferred();
+ 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(),
{
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));
}
if (strFile == "blkindex.dat" && IsInitialBlockDownload())
nMinutes = 5;
- if (nMinutes == 0 || nTxn > 200000)
- {
- nTxn = 0;
- nMinutes = 0;
- }
+ dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
- dbenv.txn_checkpoint(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
{
while (!fShutdown)
{
- CRITICAL_BLOCK(cs_db)
{
+ LOCK(cs_db);
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
{
// Flush log data to the dat file
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())
{
bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
{
assert(!fClient);
- nTxn++;
return Write(make_pair(string("tx"), hash), txindex);
}
// Add to tx index
uint256 hash = tx.GetHash();
CTxIndex txindex(pos, tx.vout.size());
- nTxn++;
return Write(make_pair(string("tx"), hash), txindex);
}
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))
{
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;
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
// Copy wallet.dat
filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
+ pathSrc.make_preferred();
filesystem::path pathDest(strDest);
+ pathDest.make_preferred();
if (filesystem::is_directory(pathDest))
pathDest = pathDest / wallet.strWalletFile;
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)
" -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" +
{
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())
{
bool CCryptoKeyStore::SetCrypted()
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (fUseCrypto)
return true;
if (!mapKeys.empty())
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!SetCrypted())
return false;
bool CCryptoKeyStore::AddKey(const CKey& key)
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::AddKey(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;
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::GetKey(address, keyOut);
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);
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
{
- CRITICAL_BLOCK(cs_KeyStore)
{
+ LOCK(cs_KeyStore);
if (!mapCryptedKeys.empty() || IsCrypted())
return false;
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())
{
}
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())
{
if (!IsCrypted())
return false;
bool result;
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
result = vMasterKey.empty();
+ }
return result;
}
if (!SetCrypted())
return false;
- CRITICAL_BLOCK(cs_KeyStore)
+ {
+ LOCK(cs_KeyStore);
vMasterKey.clear();
+ }
return true;
}
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;
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);
}
}
// 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;
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;
}
// 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());
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++)
bool CTransaction::RemoveFromMemoryPool()
{
// Remove transaction from memory pool
- CRITICAL_BLOCK(cs_mapTransactions)
{
+ LOCK(cs_mapTransactions);
uint256 hash = GetHash();
if (mapTransactions.count(hash))
{
bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
{
- CRITICAL_BLOCK(cs_mapTransactions)
+
{
+ LOCK(cs_mapTransactions);
// Add previous supporting transactions first
BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
{
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];
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++)
{
// 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;
}
}
// Alerts
- CRITICAL_BLOCK(cs_mapAlerts)
{
+ LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
{
const CAlert& alert = item.second;
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();)
{
}
// Relay alerts
- CRITICAL_BLOCK(cs_mapAlerts)
+ {
+ LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
item.second.RelayTo(pfrom);
+ }
pfrom->fSuccessfullyConnected = true;
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;
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);
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())
{
{
// Relay
pfrom->setKnown.insert(alert.GetHash());
- CRITICAL_BLOCK(cs_vNodes)
+ {
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
alert.RelayTo(pnode);
+ }
}
}
bool fRet = false;
try
{
- CRITICAL_BLOCK(cs_main)
+ {
+ LOCK(cs_main);
fRet = ProcessMessage(pfrom, strCommand, vMsg);
+ }
if (fShutdown)
return true;
}
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;
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
//
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)
// 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
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");
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))
if (GetTimeMillis() - nHPSTimerStart > 4000)
{
static CCriticalSection cs;
- CRITICAL_BLOCK(cs)
{
+ LOCK(cs);
if (GetTimeMillis() - nHPSTimerStart > 4000)
{
dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
set<CNetAddr> setservAddNodeAddresses;
CCriticalSection cs_setservAddNodeAddresses;
+static CWaitableCriticalSection csOutbound;
+static int nOutbound = 0;
+static CConditionVariable condOutbound;
unsigned short GetListenPort()
// 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);
+ }
}
}
}
CNode* FindNode(const CNetAddr& ip)
{
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
if ((CNetAddr)pnode->addr == ip)
return (pnode);
CNode* FindNode(const CService& addr)
{
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
if ((CService)pnode->addr == addr)
return (pnode);
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;
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())
{
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;
//
// Disconnect nodes
//
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
// Disconnect unused nodes
vector<CNode*> vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
// 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();
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);
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)
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);
+ }
}
}
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)
{
}
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))
{
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);
+ }
}
}
// Service each socket
//
vector<CNode*> vNodesCopy;
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->AddRef();
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();
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())
}
}
}
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->Release();
}
int64 nStart = GetTime();
loop
{
- int nOutbound = 0;
-
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(500);
vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
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;
// 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();
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
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))
it--;
break;
}
+ }
BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
{
OpenNetworkConnection(CAddress(*(vserv.begin())));
while (!fShutdown)
{
vector<CNode*> vNodesCopy;
- CRITICAL_BLOCK(cs_vNodes)
{
+ LOCK(cs_vNodes);
vNodesCopy = vNodes;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->AddRef();
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();
}
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
+ NOTIFY_ALL(condOutbound);
do
{
int nThreadsRunning = 0;
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)
uint256 hashReply;
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
- CRITICAL_BLOCK(cs_mapRequests)
+ {
+ LOCK(cs_mapRequests);
mapRequests[hashReply] = CRequestTracker(fn, param1);
+ }
PushMessage(pszCommand, hashReply);
}
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);
}
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);
}
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>
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())
{
{
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;
// 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
return QString();
}
// Check for duplicate addresses
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
if(wallet->mapAddressBook.count(strAddress))
{
editStatus = DUPLICATE_ADDRESS;
return QString();
}
// Add entry
- CRITICAL_BLOCK(wallet->cs_wallet)
+ {
+ LOCK(wallet->cs_wallet);
wallet->SetAddressBookName(strAddress, strLabel);
+ }
return QString::fromStdString(strAddress);
}
// Also refuse to remove receiving addresses.
return false;
}
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
wallet->DelAddressBookName(rec->address.toStdString());
}
return true;
*/
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())
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()
{
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;
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) {
}
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
{
- // Accept only URLs
+ // Accept only URIs
if(event->mimeData()->hasUrls())
event->acceptProposedAction();
}
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();
@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);
<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>
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
}
-bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
+bool GUIUtil::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;
return true;
}
-bool GUIUtil::parseBitcoinURL(QString url, SendCoinsRecipient *out)
+bool GUIUtil::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)
static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
static 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
+ static bool parseBitcoinURI(const QUrl &, SendCoinsRecipient *out);
+ static bool parseBitcoinURI(QString uri, SendCoinsRecipient *out);
// HTML escaping for rich text controls
static QString HtmlEscape(const QString& str, bool fMultiLine=false);
#include <boost/date_time/posix_time/posix_time.hpp>
#include "headers.h"
+#include "qtipcserver.h"
using namespace boost::interprocess;
using namespace boost::posix_time;
void ipcShutdown()
{
- message_queue::remove("BitcoinURL");
+ message_queue::remove(BITCOINURI_QUEUE_NAME);
}
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)
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++)
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;
+#define BITCOINURI_QUEUE_NAME "BitcoinURI"
+
void ipcInit();
void ipcShutdown();
}
-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;
}
QWidget *setupTabChain(QWidget *prev);
void pasteEntry(const SendCoinsRecipient &rv);
- void handleURL(const QString &url);
+ void handleURI(const QString &uri);
public slots:
void clear();
#include <QTest>\r
#include <QObject>\r
\r
-#include "urltests.h"\r
+#include "uritests.h"\r
\r
// This is all you need to run all the tests\r
int main(int argc, char *argv[])\r
{\r
- URLTests test1;\r
+ URITests test1;\r
QTest::qExec(&test1);\r
}\r
-#include "urltests.h"
+#include "uritests.h"
#include "../guiutil.h"
#include "../walletmodel.h"
};
*/
-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));
}
--- /dev/null
+#ifndef URITESTS_H
+#define URITESTS_H
+
+#include <QTest>
+#include <QObject>
+
+class URITests : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void uriTests();
+};
+
+#endif // URITESTS_H
+++ /dev/null
-#ifndef URLTESTS_H
-#define URLTESTS_H
-
-#include <QTest>
-#include <QObject>
-
-class URLTests : public QObject
-{
- Q_OBJECT
-
-private slots:
- void urlTests();
-};
-
-#endif // URLTESTS_H
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'>";
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;
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));
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);
// 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())
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())
{
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)
{
int WalletModel::getNumTransactions() const
{
int numTransactions = 0;
- CRITICAL_BLOCK(wallet->cs_wallet)
{
+ LOCK(wallet->cs_wallet);
numTransactions = wallet->mapWallet.size();
}
return numTransactions;
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)
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());
}
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);
}
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);
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!");
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();
// 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>
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)
string 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 = fs::path(GetDataDir()) / pathConfigFile;
+ pathConfigFile.make_preferred();
+ return pathConfigFile.string();
}
bool ReadConfigFile(map<string, string>& mapSettingsRet,
{
if (fs::is_directory(fs::system_complete(mapSettingsRet["-datadir"])))
{
- fs::path pathDataDir = fs::system_complete(mapSettingsRet["-datadir"]);
+ fs::path pathDataDir(fs::system_complete(mapSettingsRet["-datadir"]));
+ pathDataDir.make_preferred();
+
strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
}
else
string 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 = fs::path(GetDataDir()) / pathPidFile;
+ pathPidFile.make_preferred();
+ return pathPidFile.string();
}
void CreatePidFile(string pidFile, pid_t pid)
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)");
}
}
-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)
(*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]);
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;
+ push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
}
-#else
-
-void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
+void LeaveCritical()
{
-#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();
-}
-
-bool CCriticalSection::TryEnter(const char*, const char*, int)
-{
- bool result = mutex.try_lock();
- return result;
+ pop_lock();
}
#endif /* DEBUG_LOCKORDER */
-
#include <boost/thread.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>
+/** 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;
+
return false;
if (!fFileBacked)
return true;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
if (pwalletdbEncryption)
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
else
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))
if (CCryptoKeyStore::Unlock(vMasterKey))
return true;
}
+ }
return false;
}
{
bool fWasLocked = IsLocked();
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
Lock();
CCrypter crypter;
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
return false;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
if (fFileBacked)
{
// 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);
void CWallet::MarkDirty()
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
item.second.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;
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))
{
if (!fFileBacked)
return false;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
if (mapWallet.erase(hash))
CWalletDB(strWalletFile).EraseTx(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())
{
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())
{
// '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;
}
{
// Returns -1 if it wasn't being tracked
int nRequests = -1;
- CRITICAL_BLOCK(pwallet->cs_wallet)
{
+ LOCK(pwallet->cs_wallet);
if (IsCoinBase())
{
// Generated block
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))
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++)
int ret = 0;
CBlockIndex* pindex = pindexStart;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
while (pindex)
{
CBlock block;
{
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)
// 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)
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;
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;
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)
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");
{
// 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
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()];
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())
{
//
bool CWallet::NewKeyPool()
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
CWalletDB walletdb(strWalletFile);
BOOST_FOREACH(int64 nIndex, setKeyPool)
walletdb.ErasePool(nIndex);
bool CWallet::TopUpKeyPool()
{
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
+
if (IsLocked())
return false;
{
nIndex = -1;
keypool.vchPubKey.clear();
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
+
if (!IsLocked())
TopUpKeyPool();
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());
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);
}
{
int64 nIndex = 0;
CKeyPool keypool;
- CRITICAL_BLOCK(cs_wallet)
{
+ LOCK(cs_wallet);
ReserveKeyFromKeyPool(nIndex, keypool);
if (nIndex == -1)
{
CWalletDB walletdb(strWalletFile);
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_wallet)
+ LOCK2(cs_main, cs_wallet);
BOOST_FOREACH(const int64& id, setKeyPool)
{
CKeyPool keypool;
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++;