diff options
32 files changed, 286 insertions, 182 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index e2097fd4b0..933f4a70da 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -19,14 +19,6 @@ OBJECTS_DIR = build MOC_DIR = build UI_DIR = build -# use: qmake "USE_QRCODE=1" -# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support -contains(USE_QRCODE, 1) { - message(Building with QRCode support) - DEFINES += USE_QRCODE - LIBS += -lqrencode -} - # use: qmake "RELEASE=1" contains(RELEASE, 1) { # Mac: compile for maximum compatibility (10.5, 32-bit) @@ -38,6 +30,14 @@ contains(RELEASE, 1) { } } +# use: qmake "USE_QRCODE=1" +# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support +contains(USE_QRCODE, 1) { + message(Building with QRCode support) + DEFINES += USE_QRCODE + LIBS += -lqrencode +} + # use: qmake "USE_UPNP=1" ( enabled by default; default) # or: qmake "USE_UPNP=0" (disabled by default) # or: qmake "USE_UPNP=-" (not supported) diff --git a/contrib/debian/control b/contrib/debian/control index c41664ca6f..745fd71ea8 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -15,7 +15,8 @@ Build-Depends: debhelper, libboost-thread-dev (>> 1.35) | libboost-thread1.35-dev, libboost-test-dev (>> 1.35) | libboost-test1.35-dev, qt4-qmake, - libqt4-dev + libqt4-dev, + libqrencode-dev Standards-Version: 3.9.2 Homepage: http://www.bitcoin.org/ Vcs-Git: git://github.com/bitcoin/bitcoin.git diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 5db418df3a..71fa77cf6c 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -37,7 +37,7 @@ Files: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png, src/qt/res/icons/history.png, src/qt/res/icons/key.png, src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png, src/qt/res/icons/receive.png, src/qt/res/icons/send.png, - src/qt/res/icons/synced.png + src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png Copyright: David Vignoni (david@icon-king.com) ICON KING - www.icon-king.com License: LGPL diff --git a/contrib/debian/rules b/contrib/debian/rules index a1d65652e3..6d6f119b59 100755 --- a/contrib/debian/rules +++ b/contrib/debian/rules @@ -20,7 +20,7 @@ override_dh_auto_clean: cd src; $(MAKE) -f makefile.unix clean override_dh_auto_configure: - qmake bitcoin-qt.pro + qmake bitcoin-qt.pro USE_SSL=1 USE_QRCODE=1 override_dh_auto_test: cd src; $(MAKE) -f makefile.unix test_bitcoin diff --git a/contrib/gitian-descriptors/deps-win32.yml b/contrib/gitian-descriptors/deps-win32.yml index 4485f3658f..0107b306ec 100644 --- a/contrib/gitian-descriptors/deps-win32.yml +++ b/contrib/gitian-descriptors/deps-win32.yml @@ -59,5 +59,3 @@ script: | cd .. # tar cjvpf "$OUTDIR/bitcoin-deps-0.0.1.tbz2" "$HOME/build" - - diff --git a/contrib/gitian-descriptors/gitian.yml b/contrib/gitian-descriptors/gitian.yml index 8a0ee0e038..086e09743d 100644 --- a/contrib/gitian-descriptors/gitian.yml +++ b/contrib/gitian-descriptors/gitian.yml @@ -16,13 +16,15 @@ packages: - "libssl-dev" - "git-core" - "unzip" -- "libqrencode-dev" +- "pkg-config" +- "libpng12-dev" reference_datetime: "2011-01-30 00:00:00" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" files: - "miniupnpc-1.6.tar.gz" +- "qrencode-3.2.0.tar.bz2" script: | INSTDIR="$HOME/install" export LIBRARY_PATH="$INSTDIR/lib" @@ -32,6 +34,12 @@ script: | INSTALLPREFIX=$INSTDIR make $MAKEOPTS install cd .. # + tar xjf qrencode-3.2.0.tar.bz2 + cd qrencode-3.2.0 + ./configure --prefix=$INSTDIR --enable-static --disable-shared + make $MAKEOPTS install + cd .. + # cd bitcoin mkdir -p $OUTDIR/src cp -a . $OUTDIR/src diff --git a/doc/assets-attribution.txt b/doc/assets-attribution.txt index 5cf0a734bf..fabcdeea76 100644 --- a/doc/assets-attribution.txt +++ b/doc/assets-attribution.txt @@ -7,7 +7,7 @@ Icon: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png, src/qt/res/icons/history.png, src/qt/res/icons/key.png, src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png, src/qt/res/icons/receive.png, src/qt/res/icons/send.png, - src/qt/res/icons/synced.png + src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png Icon Pack: NUVOLA ICON THEME for KDE 3.x Designer: David Vignoni (david@icon-king.com) ICON KING - www.icon-king.com diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 5d38f042f9..be40e937b8 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -353,7 +353,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); if (pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); + obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000)); obj.push_back(Pair("errors", GetWarnings("statusbar"))); return obj; } @@ -1537,35 +1537,41 @@ void ThreadTopUpKeyPool(void* parg) void ThreadCleanWalletPassphrase(void* parg) { - int64 nMyWakeTime = GetTime() + *((int*)parg); + int64 nMyWakeTime = GetTimeMillis() + *((int*)parg) * 1000; + + ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); if (nWalletUnlockTime == 0) { - CRITICAL_BLOCK(cs_nWalletUnlockTime) + nWalletUnlockTime = nMyWakeTime; + + do { - nWalletUnlockTime = nMyWakeTime; - } + if (nWalletUnlockTime==0) + break; + int64 nToSleep = nWalletUnlockTime - GetTimeMillis(); + if (nToSleep <= 0) + break; + + LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime); + Sleep(nToSleep); + ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); - while (GetTime() < nWalletUnlockTime) - Sleep(GetTime() - nWalletUnlockTime); + } while(1); - CRITICAL_BLOCK(cs_nWalletUnlockTime) + if (nWalletUnlockTime) { nWalletUnlockTime = 0; + pwalletMain->Lock(); } } else { - CRITICAL_BLOCK(cs_nWalletUnlockTime) - { - if (nWalletUnlockTime < nMyWakeTime) - nWalletUnlockTime = nMyWakeTime; - } - delete (int*)parg; - return; + if (nWalletUnlockTime < nMyWakeTime) + nWalletUnlockTime = nMyWakeTime; } - pwalletMain->Lock(); + LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime); delete (int*)parg; } @@ -1655,9 +1661,9 @@ Value walletlock(const Array& params, bool fHelp) if (!pwalletMain->IsCrypted()) throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called."); - pwalletMain->Lock(); CRITICAL_BLOCK(cs_nWalletUnlockTime) { + pwalletMain->Lock(); nWalletUnlockTime = 0; } @@ -1810,7 +1816,7 @@ Value getwork(const Array& params, bool fHelp) } // Update nTime - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + pblock->UpdateTime(pindexPrev); pblock->nNonce = 0; // Update nExtraNonce @@ -1910,7 +1916,7 @@ Value getmemorypool(const Array& params, bool fHelp) } // Update nTime - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + pblock->UpdateTime(pindexPrev); pblock->nNonce = 0; Array transactions; @@ -2349,15 +2355,15 @@ void ThreadRPCServer(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg)); try { - vnThreadsRunning[4]++; + vnThreadsRunning[THREAD_RPCSERVER]++; ThreadRPCServer2(parg); - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; } catch (std::exception& e) { - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; PrintException(&e, "ThreadRPCServer()"); } catch (...) { - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; PrintException(NULL, "ThreadRPCServer()"); } printf("ThreadRPCServer exiting\n"); @@ -2437,7 +2443,7 @@ void ThreadRPCServer2(void* parg) #endif ip::tcp::endpoint peer; - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; #ifdef USE_SSL acceptor.accept(sslStream.lowest_layer(), peer); #else diff --git a/src/db.cpp b/src/db.cpp index 3bdda61569..9a904ec2e0 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -6,6 +6,7 @@ #include "headers.h" #include "db.h" #include "net.h" +#include <boost/version.hpp> #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> @@ -1064,14 +1065,19 @@ bool BackupWallet(const CWallet& wallet, const string& strDest) filesystem::path pathDest(strDest); if (filesystem::is_directory(pathDest)) pathDest = pathDest / wallet.strWalletFile; + + try { #if BOOST_VERSION >= 104000 - filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); + filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); #else - filesystem::copy_file(pathSrc, pathDest); + filesystem::copy_file(pathSrc, pathDest); #endif - printf("copied wallet.dat to %s\n", pathDest.string().c_str()); - - return true; + printf("copied wallet.dat to %s\n", pathDest.string().c_str()); + return true; + } catch(const filesystem::filesystem_error &e) { + printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what()); + return false; + } } } Sleep(100); diff --git a/src/init.cpp b/src/init.cpp index 22f34aa755..2adfed2ebb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -197,6 +197,9 @@ bool AppInit2(int argc, char* argv[]) " -connect=<ip> \t\t " + _("Connect only to the specified node") + "\n" + " -irc \t " + _("Find peers using internet relay chat (default: 0)") + "\n" + " -listen \t " + _("Accept connections from outside (default: 1)") + "\n" + +#ifdef QT_GUI + " -lang=<lang> \t\t " + _("Set language, for example \"de_DE\" (default: system locale)") + "\n" + +#endif " -dnsseed \t " + _("Find peers using DNS lookup (default: 1)") + "\n" + " -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" + " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" + @@ -210,10 +213,10 @@ bool AppInit2(int argc, char* argv[]) #endif #endif " -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send") + "\n" + -#ifdef GUI +#ifdef QT_GUI " -server \t\t " + _("Accept command line and JSON-RPC commands") + "\n" + #endif -#ifndef WIN32 +#if !defined(WIN32) && !defined(QT_GUI) " -daemon \t\t " + _("Run in the background as a daemon and accept commands") + "\n" + #endif " -testnet \t\t " + _("Use the test network") + "\n" + @@ -253,7 +256,7 @@ bool AppInit2(int argc, char* argv[]) fTestNet = GetBoolArg("-testnet"); fDebug = GetBoolArg("-debug"); -#ifndef WIN32 +#if !defined(WIN32) && !defined(QT_GUI) fDaemon = GetBoolArg("-daemon"); #else fDaemon = false; @@ -284,7 +287,7 @@ bool AppInit2(int argc, char* argv[]) } #endif -#ifndef WIN32 +#if !defined(WIN32) && !defined(QT_GUI) if (fDaemon) { // Daemonize diff --git a/src/main.cpp b/src/main.cpp index e4c6714eae..b73037fb6a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -922,6 +922,15 @@ void static InvalidChainFound(CBlockIndex* pindexNew) printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n"); } +void CBlock::UpdateTime(const CBlockIndex* pindexPrev) +{ + nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + + // Updating time can change work required on testnet: + if (fTestNet) + nBits = GetNextWorkRequired(pindexPrev, this); +} + @@ -3168,7 +3177,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + pblock->UpdateTime(pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock.get()); pblock->nNonce = 0; @@ -3326,6 +3335,7 @@ void static BitcoinMiner(CWallet *pwallet) FormatHashBuffers(pblock.get(), pmidstate, pdata, phash1); unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4); + unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8); unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12); @@ -3390,7 +3400,7 @@ void static BitcoinMiner(CWallet *pwallet) { nLogTime = GetTime(); printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str()); - printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[3], dHashesPerSec/1000.0); + printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[THREAD_MINER], dHashesPerSec/1000.0); } } } @@ -3401,7 +3411,7 @@ void static BitcoinMiner(CWallet *pwallet) return; if (!fGenerateBitcoins) return; - if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors) + if (fLimitProcessors && vnThreadsRunning[THREAD_MINER] > nLimitProcessors) return; if (vNodes.empty()) break; @@ -3413,8 +3423,14 @@ void static BitcoinMiner(CWallet *pwallet) break; // Update nTime every few seconds - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + pblock->UpdateTime(pindexPrev); nBlockTime = ByteReverse(pblock->nTime); + if (fTestNet) + { + // Changing pblock->nTime can change work required on testnet: + nBlockBits = ByteReverse(pblock->nBits); + hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + } } } } @@ -3424,22 +3440,22 @@ void static ThreadBitcoinMiner(void* parg) CWallet* pwallet = (CWallet*)parg; try { - vnThreadsRunning[3]++; + vnThreadsRunning[THREAD_MINER]++; BitcoinMiner(pwallet); - vnThreadsRunning[3]--; + vnThreadsRunning[THREAD_MINER]--; } catch (std::exception& e) { - vnThreadsRunning[3]--; + vnThreadsRunning[THREAD_MINER]--; PrintException(&e, "ThreadBitcoinMiner()"); } catch (...) { - vnThreadsRunning[3]--; + vnThreadsRunning[THREAD_MINER]--; PrintException(NULL, "ThreadBitcoinMiner()"); } UIThreadCall(boost::bind(CalledSetStatusBar, "", 0)); nHPSTimerStart = 0; - if (vnThreadsRunning[3] == 0) + if (vnThreadsRunning[THREAD_MINER] == 0) dHashesPerSec = 0; - printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]); + printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINER]); } @@ -3459,7 +3475,7 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet) nProcessors = 1; if (fLimitProcessors && nProcessors > nLimitProcessors) nProcessors = nLimitProcessors; - int nAddThreads = nProcessors - vnThreadsRunning[3]; + int nAddThreads = nProcessors - vnThreadsRunning[THREAD_MINER]; printf("Starting %d BitcoinMiner threads\n", nAddThreads); for (int i = 0; i < nAddThreads; i++) { diff --git a/src/main.h b/src/main.h index 908ada7d4f..d9f976c217 100644 --- a/src/main.h +++ b/src/main.h @@ -913,6 +913,7 @@ public: return (int64)nTime; } + void UpdateTime(const CBlockIndex* pindexPrev); uint256 BuildMerkleTree() const diff --git a/src/makefile.unix b/src/makefile.unix index 41452dec81..80b5bca341 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -7,7 +7,7 @@ USE_UPNP:=0 DEFS=-DNOPCH DEFS += $(addprefix -I,$(CURDIR) $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH)) -LIBS += $(addprefix -l,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH)) +LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH)) LMODE = dynamic LMODE2 = dynamic @@ -21,7 +21,7 @@ else endif # for boost 1.37, add -mt to the boost libraries -LIBS= \ +LIBS += \ -Wl,-B$(LMODE) \ -l boost_system$(BOOST_LIB_SUFFIX) \ -l boost_filesystem$(BOOST_LIB_SUFFIX) \ diff --git a/src/net.cpp b/src/net.cpp index 63829d0e0a..fd488ce671 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -38,8 +38,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect); - - // // Global state variables // @@ -49,7 +47,7 @@ uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices); static CNode* pnodeLocalHost = NULL; uint64 nLocalHostNonce = 0; -array<int, 10> vnThreadsRunning; +array<int, THREAD_MAX> vnThreadsRunning; static SOCKET hListenSocket = INVALID_SOCKET; vector<CNode*> vNodes; @@ -67,7 +65,6 @@ CCriticalSection cs_setservAddNodeAddresses; - unsigned short GetListenPort() { return (unsigned short)(GetArg("-port", GetDefaultPort())); @@ -602,15 +599,15 @@ void ThreadSocketHandler(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg)); try { - vnThreadsRunning[0]++; + vnThreadsRunning[THREAD_SOCKETHANDLER]++; ThreadSocketHandler2(parg); - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; } catch (std::exception& e) { - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; PrintException(&e, "ThreadSocketHandler()"); } catch (...) { - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; throw; // support pthread_cancel() } printf("ThreadSocketHandler exiting\n"); @@ -712,9 +709,9 @@ void ThreadSocketHandler2(void* parg) } } - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout); - vnThreadsRunning[0]++; + vnThreadsRunning[THREAD_SOCKETHANDLER]++; if (fShutdown) return; if (nSelect == SOCKET_ERROR) @@ -740,13 +737,17 @@ void ThreadSocketHandler2(void* parg) struct sockaddr_in sockaddr; socklen_t len = sizeof(sockaddr); SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); - CAddress addr(sockaddr); + CAddress addr; int nInbound = 0; + if (hSocket != INVALID_SOCKET) + addr = CAddress(sockaddr); + CRITICAL_BLOCK(cs_vNodes) BOOST_FOREACH(CNode* pnode, vNodes) if (pnode->fInbound) nInbound++; + if (hSocket == INVALID_SOCKET) { if (WSAGetLastError() != WSAEWOULDBLOCK) @@ -923,15 +924,15 @@ void ThreadMapPort(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg)); try { - vnThreadsRunning[5]++; + vnThreadsRunning[THREAD_UPNP]++; ThreadMapPort2(parg); - vnThreadsRunning[5]--; + vnThreadsRunning[THREAD_UPNP]--; } catch (std::exception& e) { - vnThreadsRunning[5]--; + vnThreadsRunning[THREAD_UPNP]--; PrintException(&e, "ThreadMapPort()"); } catch (...) { - vnThreadsRunning[5]--; + vnThreadsRunning[THREAD_UPNP]--; PrintException(NULL, "ThreadMapPort()"); } printf("ThreadMapPort exiting\n"); @@ -1052,7 +1053,7 @@ void MapPort(bool fMapPort) fUseUPnP = fMapPort; WriteSetting("fUseUPnP", fUseUPnP); } - if (fUseUPnP && vnThreadsRunning[5] < 1) + if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1) { if (!CreateThread(ThreadMapPort, NULL)) printf("Error: ThreadMapPort(ThreadMapPort) failed\n"); @@ -1086,15 +1087,15 @@ void ThreadDNSAddressSeed(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg)); try { - vnThreadsRunning[6]++; + vnThreadsRunning[THREAD_DNSSEED]++; ThreadDNSAddressSeed2(parg); - vnThreadsRunning[6]--; + vnThreadsRunning[THREAD_DNSSEED]--; } catch (std::exception& e) { - vnThreadsRunning[6]--; + vnThreadsRunning[THREAD_DNSSEED]--; PrintException(&e, "ThreadDNSAddressSeed()"); } catch (...) { - vnThreadsRunning[6]--; + vnThreadsRunning[THREAD_DNSSEED]--; throw; // support pthread_cancel() } printf("ThreadDNSAddressSeed exiting\n"); @@ -1232,15 +1233,15 @@ void ThreadOpenConnections(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg)); try { - vnThreadsRunning[1]++; + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; ThreadOpenConnections2(parg); - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; } catch (std::exception& e) { - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; PrintException(&e, "ThreadOpenConnections()"); } catch (...) { - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; PrintException(NULL, "ThreadOpenConnections()"); } printf("ThreadOpenConnections exiting\n"); @@ -1274,9 +1275,13 @@ void ThreadOpenConnections2(void* parg) int64 nStart = GetTime(); loop { - // Limit outbound connections - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; Sleep(500); + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; + if (fShutdown) + return; + + // Limit outbound connections loop { int nOutbound = 0; @@ -1288,13 +1293,12 @@ void ThreadOpenConnections2(void* parg) nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125)); if (nOutbound < nMaxOutboundConnections) break; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; Sleep(2000); + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; if (fShutdown) return; } - vnThreadsRunning[1]++; - if (fShutdown) - return; bool fAddSeeds = false; @@ -1403,15 +1407,15 @@ void ThreadOpenAddedConnections(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg)); try { - vnThreadsRunning[7]++; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; ThreadOpenAddedConnections2(parg); - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; } catch (std::exception& e) { - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; PrintException(&e, "ThreadOpenAddedConnections()"); } catch (...) { - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; PrintException(NULL, "ThreadOpenAddedConnections()"); } printf("ThreadOpenAddedConnections exiting\n"); @@ -1460,9 +1464,9 @@ void ThreadOpenAddedConnections2(void* parg) } if (fShutdown) return; - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; Sleep(120000); // Retry every 2 minutes - vnThreadsRunning[7]++; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; if (fShutdown) return; } @@ -1479,9 +1483,9 @@ bool OpenNetworkConnection(const CAddress& addrConnect) FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect)) return false; - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; CNode* pnode = ConnectNode(addrConnect); - vnThreadsRunning[1]++; + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; if (fShutdown) return false; if (!pnode) @@ -1503,15 +1507,15 @@ void ThreadMessageHandler(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg)); try { - vnThreadsRunning[2]++; + vnThreadsRunning[THREAD_MESSAGEHANDLER]++; ThreadMessageHandler2(parg); - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; } catch (std::exception& e) { - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; PrintException(&e, "ThreadMessageHandler()"); } catch (...) { - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; PrintException(NULL, "ThreadMessageHandler()"); } printf("ThreadMessageHandler exiting\n"); @@ -1559,11 +1563,11 @@ void ThreadMessageHandler2(void* parg) // Wait and allow messages to bunch up. // Reduce vnThreadsRunning so StopNode has permission to exit while // we're sleeping, but we must always check fShutdown after doing this. - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; Sleep(100); if (fRequestShutdown) Shutdown(NULL); - vnThreadsRunning[2]++; + vnThreadsRunning[THREAD_MESSAGEHANDLER]++; if (fShutdown) return; } @@ -1766,23 +1770,26 @@ bool StopNode() fShutdown = true; nTransactionsUpdated++; int64 nStart = GetTime(); - while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0 - || (fHaveUPnP && vnThreadsRunning[5] > 0) || vnThreadsRunning[6] > 0 || vnThreadsRunning[7] > 0 - ) + do { + int nThreadsRunning = 0; + for (int n = 0; n < THREAD_MAX; n++) + nThreadsRunning += vnThreadsRunning[n]; + if (nThreadsRunning == 0) + break; if (GetTime() - nStart > 20) break; Sleep(20); - } - if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n"); - if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n"); - if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n"); - if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n"); - if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n"); - if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n"); - if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n"); - if (vnThreadsRunning[7] > 0) printf("ThreadOpenAddedConnections still running\n"); - while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0) + } while(true); + if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n"); + if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n"); + if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n"); + if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n"); + if (vnThreadsRunning[THREAD_RPCSERVER] > 0) printf("ThreadRPCServer still running\n"); + if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n"); + if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n"); + if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n"); + while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCSERVER] > 0) Sleep(20); Sleep(50); @@ -68,14 +68,26 @@ public: - +enum threadId +{ + THREAD_SOCKETHANDLER, + THREAD_OPENCONNECTIONS, + THREAD_MESSAGEHANDLER, + THREAD_MINER, + THREAD_RPCSERVER, + THREAD_UPNP, + THREAD_DNSSEED, + THREAD_ADDEDCONNECTIONS, + + THREAD_MAX +}; extern bool fClient; extern bool fAllowDNS; extern uint64 nLocalServices; extern CAddress addrLocalHost; extern uint64 nLocalHostNonce; -extern boost::array<int, 10> vnThreadsRunning; +extern boost::array<int, THREAD_MAX> vnThreadsRunning; extern std::vector<CNode*> vNodes; extern CCriticalSection cs_vNodes; @@ -279,7 +291,7 @@ public: void BeginMessage(const char* pszCommand) { - cs_vSend.Enter("cs_vSend", __FILE__, __LINE__); + ENTER_CRITICAL_SECTION(cs_vSend); if (nHeaderStart != -1) AbortMessage(); nHeaderStart = vSend.size(); @@ -298,7 +310,7 @@ public: vSend.resize(nHeaderStart); nHeaderStart = -1; nMessageStart = -1; - cs_vSend.Leave(); + LEAVE_CRITICAL_SECTION(cs_vSend); if (fDebug) printf("(aborted)\n"); @@ -336,7 +348,7 @@ public: nHeaderStart = -1; nMessageStart = -1; - cs_vSend.Leave(); + LEAVE_CRITICAL_SECTION(cs_vSend); } void EndMessageAbortIfEmpty() diff --git a/src/netbase.cpp b/src/netbase.cpp index 54aa933a54..7799a65972 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -402,7 +402,7 @@ bool CNetAddr::IsRFC6145() const bool CNetAddr::IsRFC4843() const { - return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && GetByte(12) & 0xF0 == 0x10); + return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10); } bool CNetAddr::IsLocal() const diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 8c4b0e6c10..20c185ed27 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -162,11 +162,13 @@ int main(int argc, char *argv[]) ParseParameters(argc, argv); - // Load language files for system locale: + // Get desired locale ("en_US") from command line or system locale + QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString())); + // Load language files for configured locale: // - First load the translator for the base language, without territory // - Then load the more specific locale translator - QString lang_territory = QLocale::system().name(); // "en_US" QString lang = lang_territory; + lang.truncate(lang_territory.lastIndexOf('_')); // "en" QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator; diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 5693ae187e..d823752c9c 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -37,6 +37,7 @@ <file alias="lock_closed">res/icons/lock_closed.png</file> <file alias="lock_open">res/icons/lock_open.png</file> <file alias="key">res/icons/key.png</file> + <file alias="filesave">res/icons/filesave.png</file> </qresource> <qresource prefix="/images"> <file alias="about">res/images/about.png</file> diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b72f128291..c95afdcef3 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -46,6 +46,8 @@ #include <QStackedWidget> #include <QDateTime> #include <QMovie> +#include <QFileDialog> +#include <QDesktopServices> #include <QDragEnterEvent> #include <QUrl> @@ -243,6 +245,8 @@ void BitcoinGUI::createActions() encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet"), this); encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet")); encryptWalletAction->setCheckable(true); + backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet"), this); + backupWalletAction->setToolTip(tr("Backup wallet to another location")); changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase"), this); changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); @@ -252,6 +256,7 @@ void BitcoinGUI::createActions() connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormal())); connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool))); + connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet())); connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase())); } @@ -277,6 +282,7 @@ void BitcoinGUI::createMenuBar() QMenu *settings = appMenuBar->addMenu(tr("&Settings")); settings->addAction(encryptWalletAction); settings->addAction(changePassphraseAction); + settings->addAction(backupWalletAction); settings->addSeparator(); settings->addAction(optionsAction); @@ -723,7 +729,7 @@ void BitcoinGUI::dropEvent(QDropEvent *event) QList<QUrl> urls = event->mimeData()->urls(); foreach(const QUrl &url, urls) { - sendCoinsPage->handleURL(&url); + sendCoinsPage->handleURL(url.toString()); } } @@ -733,8 +739,7 @@ void BitcoinGUI::dropEvent(QDropEvent *event) void BitcoinGUI::handleURL(QString strURL) { gotoSendCoinsPage(); - QUrl url = QUrl(strURL); - sendCoinsPage->handleURL(&url); + sendCoinsPage->handleURL(strURL); } void BitcoinGUI::setEncryptionStatus(int status) @@ -778,6 +783,17 @@ void BitcoinGUI::encryptWallet(bool status) setEncryptionStatus(walletModel->getEncryptionStatus()); } +void BitcoinGUI::backupWallet() +{ + QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); + QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)")); + if(!filename.isEmpty()) { + if(!walletModel->backupWallet(filename)) { + QMessageBox::warning(this, tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location.")); + } + } +} + void BitcoinGUI::changePassphrase() { AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 37ab12577c..a522429000 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -86,6 +86,7 @@ private: QAction *openBitcoinAction; QAction *exportAction; QAction *encryptWalletAction; + QAction *backupWalletAction; QAction *changePassphraseAction; QAction *aboutQtAction; @@ -162,6 +163,8 @@ private slots: void incomingTransaction(const QModelIndex & parent, int start, int end); /** Encrypt the wallet */ void encryptWallet(bool status); + /** Backup the wallet */ + void backupWallet(); /** Change encrypted wallet passphrase */ void changePassphrase(); /** Ask for pass phrase to unlock wallet temporarily */ diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 29ef554ac3..02fc3b6700 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -49,15 +49,15 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent) widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter); } -bool GUIUtil::parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out) +bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out) { - if(url->scheme() != QString("bitcoin")) + if(url.scheme() != QString("bitcoin")) return false; SendCoinsRecipient rv; - rv.address = url->path(); + rv.address = url.path(); rv.amount = 0; - QList<QPair<QString, QString> > items = url->queryItems(); + QList<QPair<QString, QString> > items = url.queryItems(); for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++) { bool fShouldReturnFalse = false; @@ -94,6 +94,20 @@ bool GUIUtil::parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out) return true; } +bool GUIUtil::parseBitcoinURL(QString url, 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://")) + { + url.replace(0, 10, "bitcoin:"); + } + QUrl urlInstance(url); + return parseBitcoinURL(urlInstance, out); +} + QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine) { QString escaped = Qt::escape(str); diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 3a81bd2f00..0c8b17186f 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -31,7 +31,8 @@ public: // 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(const QUrl &url, SendCoinsRecipient *out); + static bool parseBitcoinURL(QString url, SendCoinsRecipient *out); // HTML escaping for rich text controls static QString HtmlEscape(const QString& str, bool fMultiLine=false); diff --git a/src/qt/messagepage.cpp b/src/qt/messagepage.cpp index dee1837ed6..46a0cbae24 100644 --- a/src/qt/messagepage.cpp +++ b/src/qt/messagepage.cpp @@ -1,6 +1,12 @@ #include <string> #include <vector> +#include <QClipboard> +#include <QInputDialog> +#include <QList> +#include <QListWidgetItem> +#include <QMessageBox> + #include "main.h" #include "wallet.h" #include "init.h" @@ -13,12 +19,6 @@ #include "guiutil.h" #include "walletmodel.h" -#include <QClipboard> -#include <QInputDialog> -#include <QList> -#include <QListWidgetItem> -#include <QMessageBox> - MessagePage::MessagePage(QWidget *parent) : QDialog(parent), ui(new Ui::MessagePage) diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp index 90d5c14211..018461a9b2 100644 --- a/src/qt/qtipcserver.cpp +++ b/src/qt/qtipcserver.cpp @@ -30,16 +30,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)) { - strBuf[nSize] = '\0'; - // Convert bitcoin:// URLs to bitcoin: URIs - if (strBuf[8] == '/' && strBuf[9] == '/') - { - for (int i = 8; i < 256; i++) - { - strBuf[i] = strBuf[i+2]; - } - } - ThreadSafeHandleURL(strBuf); + ThreadSafeHandleURL(std::string(strBuf, nSize)); Sleep(1000); } if (fShutdown) @@ -66,16 +57,7 @@ void ipcInit() ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1); if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d)) { - strBuf[nSize] = '\0'; - // Convert bitcoin:// URLs to bitcoin: URIs - if (strBuf[8] == '/' && strBuf[9] == '/') - { - for (int i = 8; i < 256; i++) - { - strBuf[i] = strBuf[i+2]; - } - } - ThreadSafeHandleURL(strBuf); + ThreadSafeHandleURL(std::string(strBuf, nSize)); } else break; diff --git a/src/qt/res/icons/filesave.png b/src/qt/res/icons/filesave.png Binary files differnew file mode 100644 index 0000000000..ae13a151d5 --- /dev/null +++ b/src/qt/res/icons/filesave.png diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 0d9a604d3b..964313ea81 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -265,7 +265,7 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv) } -void SendCoinsDialog::handleURL(const QUrl *url) +void SendCoinsDialog::handleURL(const QString &url) { SendCoinsRecipient rv; if(!GUIUtil::parseBitcoinURL(url, &rv)) diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 847ee8b697..4dc3f08bc5 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 QUrl *url); + void handleURL(const QString &url); public slots: void clear(); diff --git a/src/qt/test/urltests.cpp b/src/qt/test/urltests.cpp index 5ecc846203..1f11795a9b 100644 --- a/src/qt/test/urltests.cpp +++ b/src/qt/test/urltests.cpp @@ -18,51 +18,54 @@ void URLTests::urlTests() SendCoinsRecipient rv; QUrl url; url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist=")); - QVERIFY(!GUIUtil::parseBitcoinURL(&url, &rv)); + QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv)); url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist=")); - QVERIFY(GUIUtil::parseBitcoinURL(&url, &rv)); + QVERIFY(GUIUtil::parseBitcoinURL(url, &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)); + QVERIFY(GUIUtil::parseBitcoinURL(url, &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)); + QVERIFY(GUIUtil::parseBitcoinURL(url, &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)); + QVERIFY(GUIUtil::parseBitcoinURL(url, &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)); + QVERIFY(GUIUtil::parseBitcoinURL(url, &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)); + QVERIFY(GUIUtil::parseBitcoinURL(url, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); + + QVERIFY(GUIUtil::parseBitcoinURL("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)); + QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv)); url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example")); - QVERIFY(!GUIUtil::parseBitcoinURL(&url, &rv)); + QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv)); url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example")); - QVERIFY(!GUIUtil::parseBitcoinURL(&url, &rv)); + QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv)); } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index f028f10f6c..8344a653d5 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -5,6 +5,7 @@ #include "transactiontablemodel.h" #include "headers.h" +#include "db.h" // for BackupWallet #include <QTimer> #include <QSet> @@ -239,6 +240,11 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri return retval; } +bool WalletModel::backupWallet(const QString &filename) +{ + return BackupWallet(*wallet, filename.toLocal8Bit().data()); +} + // WalletModel::UnlockContext implementation WalletModel::UnlockContext WalletModel::requestUnlock() { diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 89e8cdd2a0..4123240e90 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -77,6 +77,8 @@ public: // Passphrase only needed when unlocking bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString()); bool changePassphrase(const SecureString &oldPass, const SecureString &newPass); + // Wallet backup + bool backupWallet(const QString &filename); // RAI object for unlocking wallet, returned by requestUnlock() class UnlockContext diff --git a/src/util.cpp b/src/util.cpp index 12ac076f0d..f1af91de27 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -454,6 +454,21 @@ vector<unsigned char> ParseHex(const string& str) return ParseHex(str.c_str()); } +static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet) +{ + // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set + if (name.find("-no") == 0) + { + std::string positive("-"); + positive.append(name.begin()+3, name.end()); + if (mapSettingsRet.count(positive) == 0) + { + bool value = !GetBoolArg(name); + mapSettingsRet[positive] = (value ? "1" : "0"); + } + } +} + void ParseParameters(int argc, const char*const argv[]) { mapArgs.clear(); @@ -494,17 +509,8 @@ void ParseParameters(int argc, const char*const argv[]) name = singleDash; } - // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1, as long as -foo not set) - if (name.find("-no") == 0) - { - std::string positive("-"); - positive.append(name.begin()+3, name.end()); - if (mapArgs.count(positive) == 0) - { - bool value = !GetBoolArg(name); - mapArgs[positive] = (value ? "1" : "0"); - } - } + // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set + InterpretNegativeSetting(name, mapArgs); } } @@ -920,7 +926,11 @@ void ReadConfigFile(map<string, string>& mapSettingsRet, // Don't overwrite existing settings so command line settings override bitcoin.conf string strKey = string("-") + it->string_key; if (mapSettingsRet.count(strKey) == 0) + { mapSettingsRet[strKey] = it->value[0]; + // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) + InterpretNegativeSetting(strKey, mapSettingsRet); + } mapMultiSettingsRet[strKey].push_back(it->value[0]); } } diff --git a/src/util.h b/src/util.h index 8dcedb147b..ddc8791b38 100644 --- a/src/util.h +++ b/src/util.h @@ -218,6 +218,12 @@ public: #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() + class CTryCriticalBlock { protected: |