aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bignum.h2
-rw-r--r--src/bitcoinrpc.cpp41
-rw-r--r--src/checkpoints.cpp1
-rw-r--r--src/db.cpp17
-rw-r--r--src/db.h5
-rw-r--r--src/init.cpp22
-rw-r--r--src/irc.cpp51
-rw-r--r--src/irc.h1
-rw-r--r--src/key.h7
-rw-r--r--src/keystore.cpp10
-rw-r--r--src/keystore.h2
-rw-r--r--src/main.cpp91
-rw-r--r--src/main.h1
-rw-r--r--src/net.cpp159
-rw-r--r--src/net.h40
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/protocol.h1
-rw-r--r--src/qt/addressbookpage.cpp6
-rw-r--r--src/qt/bitcoin.cpp34
-rw-r--r--src/qt/bitcoin.qrc1
-rw-r--r--src/qt/bitcoingui.cpp41
-rw-r--r--src/qt/bitcoingui.h3
-rw-r--r--src/qt/forms/messagepage.ui2
-rw-r--r--src/qt/guiutil.cpp71
-rw-r--r--src/qt/guiutil.h17
-rw-r--r--src/qt/qrcodedialog.cpp22
-rw-r--r--src/qt/qtipcserver.cpp22
-rw-r--r--src/qt/res/icons/filesave.pngbin0 -> 1741 bytes
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/sendcoinsdialog.h2
-rw-r--r--src/qt/sendcoinsentry.cpp5
-rw-r--r--src/qt/test/urltests.cpp23
-rw-r--r--src/qt/transactionview.cpp6
-rw-r--r--src/qt/walletmodel.cpp6
-rw-r--r--src/qt/walletmodel.h2
-rw-r--r--src/serialize.h1
-rw-r--r--src/test/multisig_tests.cpp8
-rw-r--r--src/test/script_P2SH_tests.cpp6
-rw-r--r--src/test/script_tests.cpp14
-rw-r--r--src/test/sigopcount_tests.cpp2
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/uint256.h7
-rw-r--r--src/util.cpp32
-rw-r--r--src/wallet.cpp50
-rw-r--r--src/wallet.h11
45 files changed, 528 insertions, 323 deletions
diff --git a/src/bignum.h b/src/bignum.h
index 4143f6003d..a750025f3d 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -243,7 +243,7 @@ public:
std::vector<unsigned char> getvch() const
{
unsigned int nSize = BN_bn2mpi(this, NULL);
- if (nSize < 4)
+ if (nSize <= 4)
return std::vector<unsigned char>();
std::vector<unsigned char> vch(nSize);
BN_bn2mpi(this, &vch[0]);
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index cf5bc64bb9..c677b174ca 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -120,6 +120,17 @@ Value ValueFromAmount(int64 amount)
return (double)amount / (double)COIN;
}
+std::string
+HexBits(unsigned int nBits)
+{
+ union {
+ int32_t nBits;
+ char cBits[4];
+ } uBits;
+ uBits.nBits = htonl((int32_t)nBits);
+ return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
+}
+
void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
{
int confirms = wtx.GetDepthInMainChain();
@@ -147,11 +158,13 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
{
Object result;
result.push_back(Pair("hash", block.GetHash().GetHex()));
- result.push_back(Pair("blockcount", blockindex->nHeight));
+ result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
+ result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
+ result.push_back(Pair("bits", HexBits(block.nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
Array txhashes;
BOOST_FOREACH (const CTransaction&tx, block.vtx)
@@ -159,9 +172,9 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
result.push_back(Pair("tx", txhashes));
if (blockindex->pprev)
- result.push_back(Pair("hashprevious", blockindex->pprev->GetBlockHash().GetHex()));
+ result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
if (blockindex->pnext)
- result.push_back(Pair("hashnext", blockindex->pnext->GetBlockHash().GetHex()));
+ result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
return result;
}
@@ -1816,7 +1829,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
@@ -1916,7 +1929,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;
@@ -1939,13 +1952,7 @@ Value getmemorypool(const Array& params, bool fHelp)
result.push_back(Pair("time", (int64_t)pblock->nTime));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
-
- union {
- int32_t nBits;
- char cBits[4];
- } uBits;
- uBits.nBits = htonl((int32_t)pblock->nBits);
- result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
+ result.push_back(Pair("bits", HexBits(pblock->nBits)));
return result;
}
@@ -2355,15 +2362,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");
@@ -2443,7 +2450,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/checkpoints.cpp b/src/checkpoints.cpp
index f78712ef4b..f5ce053870 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -30,6 +30,7 @@ namespace Checkpoints
(118000, uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553"))
(134444, uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"))
(140700, uint256("0x000000000000033b512028abb90e1626d8b346fd0ed598ac0a3c371138dce2bd"))
+ (168000, uint256("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763"))
;
bool CheckBlock(int nHeight, const uint256& hash)
diff --git a/src/db.cpp b/src/db.cpp
index 3bdda61569..ea6d46a6e5 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>
@@ -939,6 +940,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
ssValue >> nMinVersion;
if (nMinVersion > CLIENT_VERSION)
return DB_TOO_NEW;
+ pwallet->LoadMinVersion(nMinVersion);
}
else if (strType == "cscript")
{
@@ -1064,14 +1066,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/db.h b/src/db.h
index 27479fef0e..2611faa461 100644
--- a/src/db.h
+++ b/src/db.h
@@ -486,6 +486,11 @@ public:
return Write(std::make_pair(std::string("setting"), strKey), value);
}
+ bool WriteMinVersion(int nVersion)
+ {
+ return Write(std::string("minversion"), nVersion);
+ }
+
bool ReadAccount(const std::string& strAccount, CAccount& account);
bool WriteAccount(const std::string& strAccount, const CAccount& account);
bool WriteAccountingEntry(const CAccountingEntry& acentry);
diff --git a/src/init.cpp b/src/init.cpp
index 22f34aa755..3a8fcdf524 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -187,6 +187,7 @@ bool AppInit2(int argc, char* argv[])
" -gen \t\t " + _("Generate coins") + "\n" +
" -gen=0 \t\t " + _("Don't generate coins") + "\n" +
" -min \t\t " + _("Start minimized") + "\n" +
+ " -splash \t\t " + _("Show splash screen on startup (default: 1)") + "\n" +
" -datadir=<dir> \t\t " + _("Specify data directory") + "\n" +
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" +
" -proxy=<ip:port> \t " + _("Connect through socks4 proxy") + "\n" +
@@ -197,6 +198,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 +214,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" +
@@ -246,14 +250,24 @@ bool AppInit2(int argc, char* argv[])
// Remove tabs
strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
+#if defined(QT_GUI) && defined(WIN32)
+ // On windows, show a message box, as there is no stderr
+ wxMessageBox(strUsage, "Usage");
+#else
fprintf(stderr, "%s", strUsage.c_str());
+#endif
return false;
}
fTestNet = GetBoolArg("-testnet");
+ if (fTestNet)
+ {
+ SoftSetBoolArg("-irc", true);
+ }
+
fDebug = GetBoolArg("-debug");
-#ifndef WIN32
+#if !defined(WIN32) && !defined(QT_GUI)
fDaemon = GetBoolArg("-daemon");
#else
fDaemon = false;
@@ -284,7 +298,7 @@ bool AppInit2(int argc, char* argv[])
}
#endif
-#ifndef WIN32
+#if !defined(WIN32) && !defined(QT_GUI)
if (fDaemon)
{
// Daemonize
diff --git a/src/irc.cpp b/src/irc.cpp
index e79577269e..7a6f40cfad 100644
--- a/src/irc.cpp
+++ b/src/irc.cpp
@@ -76,57 +76,6 @@ static bool Send(SOCKET hSocket, const char* pszSend)
return true;
}
-bool RecvLine(SOCKET hSocket, string& strLine)
-{
- strLine = "";
- loop
- {
- char c;
- int nBytes = recv(hSocket, &c, 1, 0);
- if (nBytes > 0)
- {
- if (c == '\n')
- continue;
- if (c == '\r')
- return true;
- strLine += c;
- if (strLine.size() >= 9000)
- return true;
- }
- else if (nBytes <= 0)
- {
- if (fShutdown)
- return false;
- if (nBytes < 0)
- {
- int nErr = WSAGetLastError();
- if (nErr == WSAEMSGSIZE)
- continue;
- if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
- {
- Sleep(10);
- continue;
- }
- }
- if (!strLine.empty())
- return true;
- if (nBytes == 0)
- {
- // socket closed
- printf("IRC socket closed\n");
- return false;
- }
- else
- {
- // socket error
- int nErr = WSAGetLastError();
- printf("IRC recv failed: %d\n", nErr);
- return false;
- }
- }
- }
-}
-
bool RecvLineIRC(SOCKET hSocket, string& strLine)
{
loop
diff --git a/src/irc.h b/src/irc.h
index f5adaa1276..08d62b83d2 100644
--- a/src/irc.h
+++ b/src/irc.h
@@ -5,7 +5,6 @@
#ifndef BITCOIN_IRC_H
#define BITCOIN_IRC_H
-bool RecvLine(SOCKET hSocket, std::string& strLine);
void ThreadIRCSeed(void* parg);
extern int nGotIRCAddresses;
diff --git a/src/key.h b/src/key.h
index 9e92897e26..4058f115fd 100644
--- a/src/key.h
+++ b/src/key.h
@@ -114,7 +114,7 @@ public:
return fCompressedPubKey;
}
- void MakeNewKey(bool fCompressed = true)
+ void MakeNewKey(bool fCompressed)
{
if (!EC_KEY_generate_key(pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
@@ -141,10 +141,13 @@ public:
if (vchSecret.size() != 32)
throw key_error("CKey::SetSecret() : secret must be 32 bytes");
BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
- if (bn == NULL)
+ if (bn == NULL)
throw key_error("CKey::SetSecret() : BN_bin2bn failed");
if (!EC_KEY_regenerate_key(pkey,bn))
+ {
+ BN_clear_free(bn);
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
+ }
BN_clear_free(bn);
fSet = true;
if (fCompressed || fCompressedPubKey)
diff --git a/src/keystore.cpp b/src/keystore.cpp
index 18e5c377dc..e76f7790f1 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -8,16 +8,6 @@
#include "db.h"
#include "script.h"
-std::vector<unsigned char> CKeyStore::GenerateNewKey()
-{
- RandAddSeedPerfmon();
- CKey key;
- key.MakeNewKey();
- if (!AddKey(key))
- throw std::runtime_error("CKeyStore::GenerateNewKey() : AddKey failed");
- return key.GetPubKey();
-}
-
bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
{
CKey key;
diff --git a/src/keystore.h b/src/keystore.h
index 7eea02def3..6757834bd8 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -29,8 +29,6 @@ public:
virtual bool HaveCScript(const uint160 &hash) const =0;
virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const =0;
- // Generate a new key, and add it to the store
- virtual std::vector<unsigned char> GenerateNewKey();
virtual bool GetSecret(const CBitcoinAddress &address, CSecret& vchSecret, bool &fCompressed) const
{
CKey key;
diff --git a/src/main.cpp b/src/main.cpp
index e4c6714eae..a9311e2ceb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -21,7 +21,7 @@ using namespace boost;
// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
-const std::string CLIENT_NAME("bitcoin-qt");
+const std::string CLIENT_NAME("Satoshi");
CCriticalSection cs_setpwalletRegistered;
set<CWallet*> setpwalletRegistered;
@@ -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);
+}
+
@@ -1396,6 +1405,9 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
BOOST_FOREACH(CTransaction& tx, vDelete)
tx.RemoveFromMemoryPool();
+ printf("REORGANIZE: Disconnected %i blocks; %s..%s\n", vDisconnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexBest->GetBlockHash().ToString().substr(0,20).c_str());
+ printf("REORGANIZE: Connected %i blocks; %s..%s\n", vConnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->GetBlockHash().ToString().substr(0,20).c_str());
+
return true;
}
@@ -1643,7 +1655,8 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
if (deltaTime < 0)
{
- pfrom->Misbehaving(100);
+ if (pfrom)
+ pfrom->Misbehaving(100);
return error("ProcessBlock() : block with timestamp before last checkpoint");
}
CBigNum bnNewBlock;
@@ -1652,7 +1665,8 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
if (bnNewBlock > bnRequired)
{
- pfrom->Misbehaving(100);
+ if (pfrom)
+ pfrom->Misbehaving(100);
return error("ProcessBlock() : block with too little proof-of-work");
}
}
@@ -2091,18 +2105,24 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CAddress addrFrom;
uint64 nNonce = 1;
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
+ if (pfrom->nVersion < 209)
+ {
+ // Since Februari 20, 2012, the protocol is initiated at version 209,
+ // and earlier versions are no longer supported
+ printf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString().c_str(), pfrom->nVersion);
+ pfrom->fDisconnect = true;
+ return false;
+ }
+
if (pfrom->nVersion == 10300)
pfrom->nVersion = 300;
- if (pfrom->nVersion >= 106 && !vRecv.empty())
+ if (!vRecv.empty())
vRecv >> addrFrom >> nNonce;
- if (pfrom->nVersion >= 106 && !vRecv.empty())
+ if (!vRecv.empty())
vRecv >> pfrom->strSubVer;
- if (pfrom->nVersion >= 209 && !vRecv.empty())
+ if (!vRecv.empty())
vRecv >> pfrom->nStartingHeight;
- if (pfrom->nVersion == 0)
- return false;
-
// Disconnect if we connected to ourself
if (nNonce == nLocalHostNonce && nNonce > 1)
{
@@ -2120,11 +2140,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
AddTimeData(pfrom->addr, nTime);
// Change version
- if (pfrom->nVersion >= 209)
- pfrom->PushMessage("verack");
+ pfrom->PushMessage("verack");
pfrom->vSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
- if (pfrom->nVersion < 209)
- pfrom->vRecv.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
if (!pfrom->fInbound)
{
@@ -2188,8 +2205,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> vAddr;
// Don't want addr from older versions unless seeding
- if (pfrom->nVersion < 209)
- return true;
if (pfrom->nVersion < 31402 && mapAddresses.size() > 1000)
return true;
if (vAddr.size() > 1000)
@@ -2651,17 +2666,14 @@ bool ProcessMessages(CNode* pfrom)
}
// Checksum
- if (vRecv.GetVersion() >= 209)
+ uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
+ unsigned int nChecksum = 0;
+ memcpy(&nChecksum, &hash, sizeof(nChecksum));
+ if (nChecksum != hdr.nChecksum)
{
- uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
- unsigned int nChecksum = 0;
- memcpy(&nChecksum, &hash, sizeof(nChecksum));
- if (nChecksum != hdr.nChecksum)
- {
- printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
- strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
- continue;
- }
+ printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
+ strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
+ continue;
}
// Copy message to its own buffer
@@ -3168,7 +3180,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 +3338,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 +3403,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 +3414,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 +3426,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 +3443,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 +3478,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/net.cpp b/src/net.cpp
index 3a1777f3f2..546bc6adc8 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()));
@@ -86,6 +83,57 @@ void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
+bool RecvLine(SOCKET hSocket, string& strLine)
+{
+ strLine = "";
+ loop
+ {
+ char c;
+ int nBytes = recv(hSocket, &c, 1, 0);
+ if (nBytes > 0)
+ {
+ if (c == '\n')
+ continue;
+ if (c == '\r')
+ return true;
+ strLine += c;
+ if (strLine.size() >= 9000)
+ return true;
+ }
+ else if (nBytes <= 0)
+ {
+ if (fShutdown)
+ return false;
+ if (nBytes < 0)
+ {
+ int nErr = WSAGetLastError();
+ if (nErr == WSAEMSGSIZE)
+ continue;
+ if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
+ {
+ Sleep(10);
+ continue;
+ }
+ }
+ if (!strLine.empty())
+ return true;
+ if (nBytes == 0)
+ {
+ // socket closed
+ printf("socket closed\n");
+ return false;
+ }
+ else
+ {
+ // socket error
+ int nErr = WSAGetLastError();
+ printf("recv failed: %d\n", nErr);
+ return false;
+ }
+ }
+ }
+}
+
bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
@@ -602,15 +650,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 +760,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)
@@ -927,15 +975,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");
@@ -1056,7 +1104,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");
@@ -1090,15 +1138,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");
@@ -1236,15 +1284,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");
@@ -1278,9 +1326,9 @@ void ThreadOpenConnections2(void* parg)
int64 nStart = GetTime();
loop
{
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(500);
- vnThreadsRunning[1]++;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown)
return;
@@ -1296,9 +1344,9 @@ void ThreadOpenConnections2(void* parg)
nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
if (nOutbound < nMaxOutboundConnections)
break;
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(2000);
- vnThreadsRunning[1]++;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown)
return;
}
@@ -1410,15 +1458,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");
@@ -1467,9 +1515,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;
}
@@ -1486,9 +1534,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)
@@ -1510,15 +1558,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");
@@ -1566,11 +1614,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;
}
@@ -1773,23 +1821,26 @@ bool StopNode()
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
- while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 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);
diff --git a/src/net.h b/src/net.h
index a66bc15438..51a816d4d3 100644
--- a/src/net.h
+++ b/src/net.h
@@ -29,6 +29,7 @@ inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer"
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
static const unsigned int PUBLISH_HOPS = 5;
+bool RecvLine(SOCKET hSocket, std::string& strLine);
bool GetMyExternalIP(CNetAddr& ipRet);
bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
void AddressCurrentlyConnected(const CService& addr);
@@ -68,14 +69,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;
@@ -154,15 +167,9 @@ public:
nServices = 0;
hSocket = hSocketIn;
vSend.SetType(SER_NETWORK);
- vSend.SetVersion(0);
vRecv.SetType(SER_NETWORK);
- vRecv.SetVersion(0);
- // Version 0.2 obsoletes 20 Feb 2012
- if (GetTime() > 1329696000)
- {
- vSend.SetVersion(209);
- vRecv.SetVersion(209);
- }
+ vSend.SetVersion(209);
+ vRecv.SetVersion(209);
nLastSend = 0;
nLastRecv = 0;
nLastSendEmpty = GetTime();
@@ -321,14 +328,11 @@ public:
memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
// Set the checksum
- if (vSend.GetVersion() >= 209)
- {
- uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
- unsigned int nChecksum = 0;
- memcpy(&nChecksum, &hash, sizeof(nChecksum));
- assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
- memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
- }
+ uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
+ unsigned int nChecksum = 0;
+ memcpy(&nChecksum, &hash, sizeof(nChecksum));
+ assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
+ memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
if (fDebug) {
printf("(%d bytes)\n", nSize);
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/protocol.h b/src/protocol.h
index 9ebbfad701..b70dd71b82 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -45,7 +45,6 @@ class CMessageHeader
READWRITE(FLATDATA(pchMessageStart));
READWRITE(FLATDATA(pchCommand));
READWRITE(nMessageSize);
- if (nVersion >= 209)
READWRITE(nChecksum);
)
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index b5a798ca31..76aa87b134 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -9,7 +9,6 @@
#include <QSortFilterProxyModel>
#include <QClipboard>
-#include <QFileDialog>
#include <QMessageBox>
#include <QMenu>
@@ -277,10 +276,9 @@ void AddressBookPage::done(int retval)
void AddressBookPage::exportClicked()
{
// CSV is currently the only supported format
- QString filename = QFileDialog::getSaveFileName(
+ QString filename = GUIUtil::getSaveFileName(
this,
- tr("Export Address Book Data"),
- QDir::currentPath(),
+ tr("Export Address Book Data"), QString(),
tr("Comma separated file (*.csv)"));
if (filename.isNull()) return;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 8c4b0e6c10..03b89f06fc 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -27,18 +27,10 @@ QSplashScreen *splashref;
int MyMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
{
- // Message from main thread
- if(guiref)
- {
- guiref->error(QString::fromStdString(caption),
- QString::fromStdString(message));
- }
- else
- {
- QMessageBox::critical(0, QString::fromStdString(caption),
- QString::fromStdString(message),
- QMessageBox::Ok, QMessageBox::Ok);
- }
+ // Message from AppInit2(), always in main thread before main window is constructed
+ QMessageBox::critical(0, QString::fromStdString(caption),
+ QString::fromStdString(message),
+ QMessageBox::Ok, QMessageBox::Ok);
return 4;
}
@@ -162,11 +154,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;
@@ -189,9 +183,12 @@ int main(int argc, char *argv[])
app.setApplicationName(QApplication::translate("main", "Bitcoin-Qt"));
QSplashScreen splash(QPixmap(":/images/splash"), 0);
- splash.show();
- splash.setAutoFillBackground(true);
- splashref = &splash;
+ if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
+ {
+ splash.show();
+ splash.setAutoFillBackground(true);
+ splashref = &splash;
+ }
app.processEvents();
@@ -205,7 +202,8 @@ int main(int argc, char *argv[])
// Put this in a block, so that BitcoinGUI is cleaned up properly before
// calling Shutdown() in case of exceptions.
BitcoinGUI window;
- splash.finish(&window);
+ if (splashref)
+ splash.finish(&window);
OptionsModel optionsModel(pwalletMain);
ClientModel clientModel(&optionsModel);
WalletModel walletModel(pwalletMain, &optionsModel);
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 3d6d7d7344..abf2c381a5 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>
@@ -159,6 +161,8 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
BitcoinGUI::~BitcoinGUI()
{
+ if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
+ trayIcon->hide();
#ifdef Q_WS_MAC
delete appMenuBar;
#endif
@@ -238,6 +242,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"));
@@ -247,6 +253,7 @@ void BitcoinGUI::createActions()
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
+ connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
}
@@ -262,11 +269,12 @@ void BitcoinGUI::createMenuBar()
// Configure the menus
QMenu *file = appMenuBar->addMenu(tr("&File"));
+ file->addAction(backupWalletAction);
file->addAction(exportAction);
#ifndef FIRST_CLASS_MESSAGING
file->addAction(messageAction);
- file->addSeparator();
#endif
+ file->addSeparator();
file->addAction(quitAction);
QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
@@ -484,7 +492,11 @@ void BitcoinGUI::setNumBlocks(int count)
QString text;
// Represent time from last generated block in human readable text
- if(secs < 60)
+ if(secs <= 0)
+ {
+ // Fully up to date. Leave text empty.
+ }
+ else if(secs < 60)
{
text = tr("%n second(s) ago","",secs);
}
@@ -504,7 +516,7 @@ void BitcoinGUI::setNumBlocks(int count)
// Set icon state: spinning if catching up, tick otherwise
if(secs < 30*60)
{
- tooltip = tr("Up to date") + QString("\n") + tooltip;
+ tooltip = tr("Up to date") + QString(".\n") + tooltip;
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
}
else
@@ -514,8 +526,11 @@ void BitcoinGUI::setNumBlocks(int count)
syncIconMovie->start();
}
- tooltip += QString("\n");
- tooltip += tr("Last received block was generated %1.").arg(text);
+ if(!text.isEmpty())
+ {
+ tooltip += QString("\n");
+ tooltip += tr("Last received block was generated %1.").arg(text);
+ }
labelBlocksIcon->setToolTip(tooltip);
progressBarLabel->setToolTip(tooltip);
@@ -714,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());
}
}
@@ -724,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)
@@ -769,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 f996e6ba25..dbc32640b8 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -84,6 +84,7 @@ private:
QAction *openBitcoinAction;
QAction *exportAction;
QAction *encryptWalletAction;
+ QAction *backupWalletAction;
QAction *changePassphraseAction;
QAction *aboutQtAction;
@@ -158,6 +159,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/forms/messagepage.ui b/src/qt/forms/messagepage.ui
index 8afa4b59dd..131e15bdb3 100644
--- a/src/qt/forms/messagepage.ui
+++ b/src/qt/forms/messagepage.ui
@@ -17,7 +17,7 @@
<item>
<widget class="QLabel" name="labelExplanation">
<property name="text">
- <string>You can sign messages with your addresses to prove you own them. Be careful to only sign statement you agree to with full details, as phishing attacks may try to trick you into signing access to them.</string>
+ <string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 29ef554ac3..ac69bd07e9 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -15,6 +15,8 @@
#include <QAbstractItemView>
#include <QApplication>
#include <QClipboard>
+#include <QFileDialog>
+#include <QDesktopServices>
QString GUIUtil::dateTimeStr(qint64 nTime)
{
@@ -49,15 +51,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 +96,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);
@@ -121,3 +137,50 @@ void GUIUtil::copyEntryData(QAbstractItemView *view, int column, int role)
QApplication::clipboard()->setText(selection.at(0).data(role).toString());
}
}
+
+QString GUIUtil::getSaveFileName(QWidget *parent, const QString &caption,
+ const QString &dir,
+ const QString &filter,
+ QString *selectedSuffixOut)
+{
+ QString selectedFilter;
+ QString myDir;
+ if(dir.isEmpty()) // Default to user documents location
+ {
+ myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
+ }
+ else
+ {
+ myDir = dir;
+ }
+ QString result = QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter);
+
+ /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */
+ QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]");
+ QString selectedSuffix;
+ if(filter_re.exactMatch(selectedFilter))
+ {
+ selectedSuffix = filter_re.cap(1);
+ }
+
+ /* Add suffix if needed */
+ QFileInfo info(result);
+ if(!result.isEmpty())
+ {
+ if(info.suffix().isEmpty() && !selectedSuffix.isEmpty())
+ {
+ /* No suffix specified, add selected suffix */
+ if(!result.endsWith("."))
+ result.append(".");
+ result.append(selectedSuffix);
+ }
+ }
+
+ /* Return selected suffix if asked to */
+ if(selectedSuffixOut)
+ {
+ *selectedSuffixOut = selectedSuffix;
+ }
+ return result;
+}
+
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 3a81bd2f00..75ba53f206 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);
@@ -45,6 +46,20 @@ public:
*/
static void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole);
+ /** Get save file name, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
+ when no suffix is provided by the user.
+
+ @param[in] parent Parent window (or 0)
+ @param[in] caption Window caption (or empty, for default)
+ @param[in] dir Starting directory (or empty, to default to documents directory)
+ @param[in] filter Filter specification such as "Comma Separated Files (*.csv)"
+ @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0).
+ Can be useful when choosing the save file format based on suffix.
+ */
+ static QString getSaveFileName(QWidget *parent=0, const QString &caption=QString(),
+ const QString &dir=QString(), const QString &filter=QString(),
+ QString *selectedSuffixOut=0);
+
};
#endif // GUIUTIL_H
diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp
index ed4c758e38..82959831de 100644
--- a/src/qt/qrcodedialog.cpp
+++ b/src/qt/qrcodedialog.cpp
@@ -1,9 +1,9 @@
#include "qrcodedialog.h"
#include "ui_qrcodedialog.h"
+#include "guiutil.h"
+
#include <QPixmap>
#include <QUrl>
-#include <QFileDialog>
-#include <QDesktopServices>
#include <QDebug>
#include <qrencode.h>
@@ -34,8 +34,8 @@ QRCodeDialog::~QRCodeDialog()
delete ui;
}
-void QRCodeDialog::genCode() {
-
+void QRCodeDialog::genCode()
+{
QString uri = getURI();
//qDebug() << "Encoding:" << uri.toUtf8().constData();
QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
@@ -52,7 +52,8 @@ void QRCodeDialog::genCode() {
ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300));
}
-QString QRCodeDialog::getURI() {
+QString QRCodeDialog::getURI()
+{
QString ret = QString("bitcoin:%1").arg(address);
int paramCount = 0;
@@ -80,21 +81,24 @@ QString QRCodeDialog::getURI() {
return ret;
}
-void QRCodeDialog::on_lnReqAmount_textChanged(const QString &) {
+void QRCodeDialog::on_lnReqAmount_textChanged(const QString &)
+{
genCode();
}
-void QRCodeDialog::on_lnLabel_textChanged(const QString &) {
+void QRCodeDialog::on_lnLabel_textChanged(const QString &)
+{
genCode();
}
-void QRCodeDialog::on_lnMessage_textChanged(const QString &) {
+void QRCodeDialog::on_lnMessage_textChanged(const QString &)
+{
genCode();
}
void QRCodeDialog::on_btnSaveAs_clicked()
{
- QString fn = QFileDialog::getSaveFileName(this, "Save Image...", QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation), "Images (*.png)");
+ QString fn = GUIUtil::getSaveFileName(this, tr("Save Image..."), QString(), tr("PNG Images (*.png)"));
if(!fn.isEmpty()) {
myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn);
}
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
new file mode 100644
index 0000000000..ae13a151d5
--- /dev/null
+++ b/src/qt/res/icons/filesave.png
Binary files differ
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/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index ab5460f8c2..d98400c260 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -59,8 +59,9 @@ void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
if(!model)
return;
- ui->addAsLabel->setText(model->getAddressTableModel()->labelForAddress(address));
-}
+ // Fill in label from address book, if no label is filled in yet
+ if(ui->addAsLabel->text().isEmpty())
+ ui->addAsLabel->setText(model->getAddressTableModel()->labelForAddress(address));}
void SendCoinsEntry::setModel(WalletModel *model)
{
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/transactionview.cpp b/src/qt/transactionview.cpp
index 4c357d1379..eaed48bfdf 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -21,7 +21,6 @@
#include <QTableView>
#include <QHeaderView>
#include <QPushButton>
-#include <QFileDialog>
#include <QMessageBox>
#include <QPoint>
#include <QMenu>
@@ -264,10 +263,9 @@ void TransactionView::changedAmount(const QString &amount)
void TransactionView::exportClicked()
{
// CSV is currently the only supported format
- QString filename = QFileDialog::getSaveFileName(
+ QString filename = GUIUtil::getSaveFileName(
this,
- tr("Export Transaction Data"),
- QDir::currentPath(),
+ tr("Export Transaction Data"), QString(),
tr("Comma separated file (*.csv)"));
if (filename.isNull()) return;
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/serialize.h b/src/serialize.h
index 6eb4f4ee41..c046bf37ef 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -23,6 +23,7 @@ typedef long long int64;
typedef unsigned long long uint64;
#ifdef WIN32
+#define _WIN32_WINNT 0x0501
#include <windows.h>
// This is used to attempt to keep keying material out of swap
// Note that VirtualLock does not provide this as a guarantee on Windows,
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 56b18044b8..8ae9290fcc 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
{
CKey key[4];
for (int i = 0; i < 4; i++)
- key[i].MakeNewKey();
+ key[i].MakeNewKey(true);
CScript a_and_b;
a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
@@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
{
CKey key[4];
for (int i = 0; i < 4; i++)
- key[i].MakeNewKey();
+ key[i].MakeNewKey(true);
CScript a_and_b;
a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
@@ -178,7 +178,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
CBitcoinAddress keyaddr[3];
for (int i = 0; i < 3; i++)
{
- key[i].MakeNewKey();
+ key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
keyaddr[i].SetPubKey(key[i].GetPubKey());
}
@@ -257,7 +257,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
CKey key[4];
for (int i = 0; i < 4; i++)
{
- key[i].MakeNewKey();
+ key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
}
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index e3899113a3..aa72c00092 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(sign)
CKey key[4];
for (int i = 0; i < 4; i++)
{
- key[i].MakeNewKey();
+ key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
}
@@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(set)
std::vector<CKey> keys;
for (int i = 0; i < 4; i++)
{
- key[i].MakeNewKey();
+ key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
keys.push_back(key[i]);
}
@@ -249,7 +249,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
vector<CKey> keys;
for (int i = 0; i < 3; i++)
{
- key[i].MakeNewKey();
+ key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
keys.push_back(key[i]);
}
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 79dd7f1bd3..493ea69d93 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -72,9 +72,9 @@ sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction)
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
{
CKey key1, key2, key3;
- key1.MakeNewKey();
- key2.MakeNewKey();
- key3.MakeNewKey();
+ key1.MakeNewKey(true);
+ key2.MakeNewKey(false);
+ key3.MakeNewKey(true);
CScript scriptPubKey12;
scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG;
@@ -105,10 +105,10 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
{
CKey key1, key2, key3, key4;
- key1.MakeNewKey();
- key2.MakeNewKey();
- key3.MakeNewKey();
- key4.MakeNewKey();
+ key1.MakeNewKey(true);
+ key2.MakeNewKey(false);
+ key3.MakeNewKey(true);
+ key4.MakeNewKey(false);
CScript scriptPubKey23;
scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG;
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 0b0a4a62d8..d301313a9d 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
for (int i = 0; i < 3; i++)
{
CKey k;
- k.MakeNewKey();
+ k.MakeNewKey(true);
keys.push_back(k);
}
CScript s2;
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index cd4d7eed96..99163e55f2 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -38,7 +38,7 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
CKey key[4];
for (int i = 0; i < 4; i++)
{
- key[i].MakeNewKey();
+ key[i].MakeNewKey(i % 2);
keystoreRet.AddKey(key[i]);
}
diff --git a/src/uint256.h b/src/uint256.h
index 5b1ba9f6f7..caf6fa118b 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -92,13 +92,6 @@ public:
return *this;
}
- base_uint& operator&=(uint64 b)
- {
- pn[0] &= (unsigned int)b;
- pn[1] &= (unsigned int)(b >> 32);
- return *this;
- }
-
base_uint& operator|=(uint64 b)
{
pn[0] |= (unsigned int)b;
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/wallet.cpp b/src/wallet.cpp
index 1e769d7e61..30590c80e6 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -15,6 +15,23 @@ using namespace std;
// mapWallet
//
+std::vector<unsigned char> CWallet::GenerateNewKey()
+{
+ bool fCompressed = true; // default to compressed public keys
+
+ RandAddSeedPerfmon();
+ CKey key;
+ key.MakeNewKey(fCompressed);
+
+ // Compressed public keys were introduced in version 0.6.0
+ if (fCompressed)
+ SetMinVersion(59900);
+
+ if (!AddKey(key))
+ throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
+ return key.GetPubKey();
+}
+
bool CWallet::AddKey(const CKey& key)
{
if (!CCryptoKeyStore::AddKey(key))
@@ -131,6 +148,32 @@ public:
)
};
+bool CWallet::SetMinVersion(int nVersion, CWalletDB* pwalletdbIn)
+{
+ if (nWalletVersion >= nVersion)
+ return true;
+
+ nWalletVersion = nVersion;
+
+ if (fFileBacked)
+ {
+ CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
+ if (nWalletVersion >= 40000)
+ {
+ // Versions prior to 0.4.0 did not support the "minversion" record.
+ // Use a CCorruptAddress to make them crash instead.
+ CCorruptAddress corruptAddress;
+ pwalletdb->WriteSetting("addrIncoming", corruptAddress);
+ }
+ if (nWalletVersion > 40000)
+ pwalletdb->WriteMinVersion(nWalletVersion);
+ if (!pwalletdbIn)
+ delete pwalletdb;
+ }
+
+ return true;
+}
+
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
{
if (IsCrypted())
@@ -184,14 +227,15 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
}
+ // Encryption was introduced in version 0.4.0
+ SetMinVersion(40000, pwalletdbEncryption);
+
if (fFileBacked)
{
- CCorruptAddress corruptAddress;
- pwalletdbEncryption->WriteSetting("addrIncoming", corruptAddress);
if (!pwalletdbEncryption->TxnCommit())
exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
- pwalletdbEncryption->Close();
+ delete pwalletdbEncryption;
pwalletdbEncryption = NULL;
}
diff --git a/src/wallet.h b/src/wallet.h
index 3fdef50c03..fea3297788 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -25,6 +25,8 @@ private:
CWalletDB *pwalletdbEncryption;
+ int nWalletVersion;
+
public:
mutable CCriticalSection cs_wallet;
@@ -33,18 +35,21 @@ public:
std::set<int64> setKeyPool;
+
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
unsigned int nMasterKeyMaxID;
CWallet()
{
+ nWalletVersion = 0;
fFileBacked = false;
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
}
CWallet(std::string strWalletFileIn)
{
+ nWalletVersion = 0;
strWalletFile = strWalletFileIn;
fFileBacked = true;
nMasterKeyMaxID = 0;
@@ -61,11 +66,15 @@ public:
std::vector<unsigned char> vchDefaultKey;
// keystore implementation
+ // Generate a new key
+ std::vector<unsigned char> GenerateNewKey();
// Adds a key to the store, and saves it to disk.
bool AddKey(const CKey& key);
// Adds a key to the store, without saving it to disk (used by LoadWallet)
bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
+ bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; return true; }
+
// Adds an encrypted key to the store, and saves it to disk.
bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
// Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
@@ -206,6 +215,8 @@ public:
bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
+
+ bool SetMinVersion(int nVersion, CWalletDB* pwalletdbIn = NULL);
};