aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bitcoinrpc.cpp1
-rw-r--r--src/bitcoinrpc.h1
-rw-r--r--src/core.cpp294
-rw-r--r--src/core.h249
-rw-r--r--src/db.cpp1
-rw-r--r--src/init.cpp6
-rw-r--r--src/key.cpp5
-rw-r--r--src/main.cpp104
-rw-r--r--src/main.h4
-rw-r--r--src/makefile.mingw2
-rw-r--r--src/net.cpp4
-rw-r--r--src/qt/bitcoin.cpp100
-rw-r--r--src/qt/bitcoinstrings.cpp5
-rw-r--r--src/qt/forms/intro.ui266
-rw-r--r--src/qt/guiutil.cpp3
-rw-r--r--src/qt/intro.cpp270
-rw-r--r--src/qt/intro.h67
-rw-r--r--src/qt/locale/bitcoin_en.ts210
-rw-r--r--src/rpcblockchain.cpp9
-rw-r--r--src/sync.h42
-rw-r--r--src/test/script_P2SH_tests.cpp8
-rw-r--r--src/test/transaction_tests.cpp9
-rw-r--r--src/test/util_tests.cpp34
-rw-r--r--src/version.cpp2
-rw-r--r--src/walletdb.cpp1
25 files changed, 1225 insertions, 472 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 5908126200..11fac42213 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -195,6 +195,7 @@ static const CRPCCommand vRPCCommands[] =
{ "help", &help, true, true },
{ "stop", &stop, true, true },
{ "getblockcount", &getblockcount, true, false },
+ { "getbestblockhash", &getbestblockhash, true, false },
{ "getconnectioncount", &getconnectioncount, true, false },
{ "getpeerinfo", &getpeerinfo, true, false },
{ "addnode", &addnode, true, true },
diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
index 247c47adf9..4d5599be84 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -201,6 +201,7 @@ extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, b
extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getblockcount(const json_spirit::Array& params, bool fHelp); // in rpcblockchain.cpp
+extern json_spirit::Value getbestblockhash(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getdifficulty(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value settxfee(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getrawmempool(const json_spirit::Array& params, bool fHelp);
diff --git a/src/core.cpp b/src/core.cpp
index b12c90efe8..afba0959cf 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -4,4 +4,298 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "core.h"
+#include "util.h"
+std::string COutPoint::ToString() const
+{
+ return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n);
+}
+
+void COutPoint::print() const
+{
+ printf("%s\n", ToString().c_str());
+}
+
+CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, unsigned int nSequenceIn)
+{
+ prevout = prevoutIn;
+ scriptSig = scriptSigIn;
+ nSequence = nSequenceIn;
+}
+
+CTxIn::CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn, unsigned int nSequenceIn)
+{
+ prevout = COutPoint(hashPrevTx, nOut);
+ scriptSig = scriptSigIn;
+ nSequence = nSequenceIn;
+}
+
+std::string CTxIn::ToString() const
+{
+ std::string str;
+ str += "CTxIn(";
+ str += prevout.ToString();
+ if (prevout.IsNull())
+ str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
+ else
+ str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
+ if (nSequence != std::numeric_limits<unsigned int>::max())
+ str += strprintf(", nSequence=%u", nSequence);
+ str += ")";
+ return str;
+}
+
+void CTxIn::print() const
+{
+ printf("%s\n", ToString().c_str());
+}
+
+CTxOut::CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
+{
+ nValue = nValueIn;
+ scriptPubKey = scriptPubKeyIn;
+}
+
+uint256 CTxOut::GetHash() const
+{
+ return SerializeHash(*this);
+}
+
+std::string CTxOut::ToString() const
+{
+ if (scriptPubKey.size() < 6)
+ return "CTxOut(error)";
+ return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
+}
+
+void CTxOut::print() const
+{
+ printf("%s\n", ToString().c_str());
+}
+
+uint256 CTransaction::GetHash() const
+{
+ return SerializeHash(*this);
+}
+
+bool CTransaction::IsNewerThan(const CTransaction& old) const
+{
+ if (vin.size() != old.vin.size())
+ return false;
+ for (unsigned int i = 0; i < vin.size(); i++)
+ if (vin[i].prevout != old.vin[i].prevout)
+ return false;
+
+ bool fNewer = false;
+ unsigned int nLowest = std::numeric_limits<unsigned int>::max();
+ for (unsigned int i = 0; i < vin.size(); i++)
+ {
+ if (vin[i].nSequence != old.vin[i].nSequence)
+ {
+ if (vin[i].nSequence <= nLowest)
+ {
+ fNewer = false;
+ nLowest = vin[i].nSequence;
+ }
+ if (old.vin[i].nSequence < nLowest)
+ {
+ fNewer = true;
+ nLowest = old.vin[i].nSequence;
+ }
+ }
+ }
+ return fNewer;
+}
+
+std::string CTransaction::ToString() const
+{
+ std::string str;
+ str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
+ GetHash().ToString().substr(0,10).c_str(),
+ nVersion,
+ vin.size(),
+ vout.size(),
+ nLockTime);
+ for (unsigned int i = 0; i < vin.size(); i++)
+ str += " " + vin[i].ToString() + "\n";
+ for (unsigned int i = 0; i < vout.size(); i++)
+ str += " " + vout[i].ToString() + "\n";
+ return str;
+}
+
+void CTransaction::print() const
+{
+ printf("%s", ToString().c_str());
+}
+
+// Amount compression:
+// * If the amount is 0, output 0
+// * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9)
+// * if e<9, the last digit of the resulting number cannot be 0; store it as d, and drop it (divide by 10)
+// * call the result n
+// * output 1 + 10*(9*n + d - 1) + e
+// * if e==9, we only know the resulting number is not zero, so output 1 + 10*(n - 1) + 9
+// (this is decodable, as d is in [1-9] and e is in [0-9])
+
+uint64 CTxOutCompressor::CompressAmount(uint64 n)
+{
+ if (n == 0)
+ return 0;
+ int e = 0;
+ while (((n % 10) == 0) && e < 9) {
+ n /= 10;
+ e++;
+ }
+ if (e < 9) {
+ int d = (n % 10);
+ assert(d >= 1 && d <= 9);
+ n /= 10;
+ return 1 + (n*9 + d - 1)*10 + e;
+ } else {
+ return 1 + (n - 1)*10 + 9;
+ }
+}
+
+uint64 CTxOutCompressor::DecompressAmount(uint64 x)
+{
+ // x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
+ if (x == 0)
+ return 0;
+ x--;
+ // x = 10*(9*n + d - 1) + e
+ int e = x % 10;
+ x /= 10;
+ uint64 n = 0;
+ if (e < 9) {
+ // x = 9*n + d - 1
+ int d = (x % 9) + 1;
+ x /= 9;
+ // x = n
+ n = x*10 + d;
+ } else {
+ n = x+1;
+ }
+ while (e) {
+ n *= 10;
+ e--;
+ }
+ return n;
+}
+
+// calculate number of bytes for the bitmask, and its number of non-zero bytes
+// each bit in the bitmask represents the availability of one output, but the
+// availabilities of the first two outputs are encoded separately
+void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
+ unsigned int nLastUsedByte = 0;
+ for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
+ bool fZero = true;
+ for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
+ if (!vout[2+b*8+i].IsNull()) {
+ fZero = false;
+ continue;
+ }
+ }
+ if (!fZero) {
+ nLastUsedByte = b + 1;
+ nNonzeroBytes++;
+ }
+ }
+ nBytes += nLastUsedByte;
+}
+
+bool CCoins::Spend(const COutPoint &out, CTxInUndo &undo) {
+ if (out.n >= vout.size())
+ return false;
+ if (vout[out.n].IsNull())
+ return false;
+ undo = CTxInUndo(vout[out.n]);
+ vout[out.n].SetNull();
+ Cleanup();
+ if (vout.size() == 0) {
+ undo.nHeight = nHeight;
+ undo.fCoinBase = fCoinBase;
+ undo.nVersion = this->nVersion;
+ }
+ return true;
+}
+
+bool CCoins::Spend(int nPos) {
+ CTxInUndo undo;
+ COutPoint out(0, nPos);
+ return Spend(out, undo);
+}
+
+uint256 CBlockHeader::GetHash() const
+{
+ return Hash(BEGIN(nVersion), END(nNonce));
+}
+
+uint256 CBlock::BuildMerkleTree() const
+{
+ vMerkleTree.clear();
+ BOOST_FOREACH(const CTransaction& tx, vtx)
+ vMerkleTree.push_back(tx.GetHash());
+ int j = 0;
+ for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ for (int i = 0; i < nSize; i += 2)
+ {
+ int i2 = std::min(i+1, nSize-1);
+ vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
+ BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
+ }
+ j += nSize;
+ }
+ return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
+}
+
+std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
+{
+ if (vMerkleTree.empty())
+ BuildMerkleTree();
+ std::vector<uint256> vMerkleBranch;
+ int j = 0;
+ for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ int i = std::min(nIndex^1, nSize-1);
+ vMerkleBranch.push_back(vMerkleTree[j+i]);
+ nIndex >>= 1;
+ j += nSize;
+ }
+ return vMerkleBranch;
+}
+
+uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
+{
+ if (nIndex == -1)
+ return 0;
+ BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
+ {
+ if (nIndex & 1)
+ hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
+ else
+ hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
+ nIndex >>= 1;
+ }
+ return hash;
+}
+
+void CBlock::print() const
+{
+ printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
+ GetHash().ToString().c_str(),
+ nVersion,
+ hashPrevBlock.ToString().c_str(),
+ hashMerkleRoot.ToString().c_str(),
+ nTime, nBits, nNonce,
+ vtx.size());
+ for (unsigned int i = 0; i < vtx.size(); i++)
+ {
+ printf(" ");
+ vtx[i].print();
+ }
+ printf(" vMerkleTree: ");
+ for (unsigned int i = 0; i < vMerkleTree.size(); i++)
+ printf("%s ", vMerkleTree[i].ToString().c_str());
+ printf("\n");
+}
diff --git a/src/core.h b/src/core.h
index fce9ccc162..1b9d4dd765 100644
--- a/src/core.h
+++ b/src/core.h
@@ -7,7 +7,6 @@
#include "uint256.h"
#include "serialize.h"
-#include "util.h"
#include "script.h"
#include <stdio.h>
@@ -42,15 +41,8 @@ public:
return !(a == b);
}
- std::string ToString() const
- {
- return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n);
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
+ std::string ToString() const;
+ void print() const;
};
/** An inpoint - a combination of a transaction and an index n into its vin */
@@ -82,19 +74,8 @@ public:
nSequence = std::numeric_limits<unsigned int>::max();
}
- explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
- {
- prevout = prevoutIn;
- scriptSig = scriptSigIn;
- nSequence = nSequenceIn;
- }
-
- CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
- {
- prevout = COutPoint(hashPrevTx, nOut);
- scriptSig = scriptSigIn;
- nSequence = nSequenceIn;
- }
+ explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max());
+ CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max());
IMPLEMENT_SERIALIZE
(
@@ -120,25 +101,8 @@ public:
return !(a == b);
}
- std::string ToString() const
- {
- std::string str;
- str += "CTxIn(";
- str += prevout.ToString();
- if (prevout.IsNull())
- str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
- else
- str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
- if (nSequence != std::numeric_limits<unsigned int>::max())
- str += strprintf(", nSequence=%u", nSequence);
- str += ")";
- return str;
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
+ std::string ToString() const;
+ void print() const;
};
@@ -158,11 +122,7 @@ public:
SetNull();
}
- CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
- {
- nValue = nValueIn;
- scriptPubKey = scriptPubKeyIn;
- }
+ CTxOut(int64 nValueIn, CScript scriptPubKeyIn);
IMPLEMENT_SERIALIZE
(
@@ -181,10 +141,7 @@ public:
return (nValue == -1);
}
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
+ uint256 GetHash() const;
bool IsDust(int64 nMinRelayTxFee) const
{
@@ -210,17 +167,8 @@ public:
return !(a == b);
}
- std::string ToString() const
- {
- if (scriptPubKey.size() < 6)
- return "CTxOut(error)";
- return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
+ std::string ToString() const;
+ void print() const;
};
@@ -265,39 +213,8 @@ public:
return (vin.empty() && vout.empty());
}
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
-
- bool IsNewerThan(const CTransaction& old) const
- {
- if (vin.size() != old.vin.size())
- return false;
- for (unsigned int i = 0; i < vin.size(); i++)
- if (vin[i].prevout != old.vin[i].prevout)
- return false;
-
- bool fNewer = false;
- unsigned int nLowest = std::numeric_limits<unsigned int>::max();
- for (unsigned int i = 0; i < vin.size(); i++)
- {
- if (vin[i].nSequence != old.vin[i].nSequence)
- {
- if (vin[i].nSequence <= nLowest)
- {
- fNewer = false;
- nLowest = vin[i].nSequence;
- }
- if (old.vin[i].nSequence < nLowest)
- {
- fNewer = true;
- nLowest = old.vin[i].nSequence;
- }
- }
- }
- return fNewer;
- }
+ uint256 GetHash() const;
+ bool IsNewerThan(const CTransaction& old) const;
bool IsCoinBase() const
{
@@ -318,26 +235,8 @@ public:
}
- std::string ToString() const
- {
- std::string str;
- str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
- GetHash().ToString().substr(0,10).c_str(),
- nVersion,
- vin.size(),
- vout.size(),
- nLockTime);
- for (unsigned int i = 0; i < vin.size(); i++)
- str += " " + vin[i].ToString() + "\n";
- for (unsigned int i = 0; i < vout.size(); i++)
- str += " " + vout[i].ToString() + "\n";
- return str;
- }
-
- void print() const
- {
- printf("%s", ToString().c_str());
- }
+ std::string ToString() const;
+ void print() const;
};
/** wrapper for CTxOut that provides a more compact serialization */
@@ -521,26 +420,7 @@ public:
return !(a == b);
}
- // calculate number of bytes for the bitmask, and its number of non-zero bytes
- // each bit in the bitmask represents the availability of one output, but the
- // availabilities of the first two outputs are encoded separately
- void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
- unsigned int nLastUsedByte = 0;
- for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
- bool fZero = true;
- for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
- if (!vout[2+b*8+i].IsNull()) {
- fZero = false;
- continue;
- }
- }
- if (!fZero) {
- nLastUsedByte = b + 1;
- nNonzeroBytes++;
- }
- }
- nBytes += nLastUsedByte;
- }
+ void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const;
bool IsCoinBase() const {
return fCoinBase;
@@ -633,28 +513,10 @@ public:
}
// mark an outpoint spent, and construct undo information
- bool Spend(const COutPoint &out, CTxInUndo &undo) {
- if (out.n >= vout.size())
- return false;
- if (vout[out.n].IsNull())
- return false;
- undo = CTxInUndo(vout[out.n]);
- vout[out.n].SetNull();
- Cleanup();
- if (vout.size() == 0) {
- undo.nHeight = nHeight;
- undo.fCoinBase = fCoinBase;
- undo.nVersion = this->nVersion;
- }
- return true;
- }
+ bool Spend(const COutPoint &out, CTxInUndo &undo);
// mark a vout spent
- bool Spend(int nPos) {
- CTxInUndo undo;
- COutPoint out(0, nPos);
- return Spend(out, undo);
- }
+ bool Spend(int nPos);
// check whether a particular output is still available
bool IsAvailable(unsigned int nPos) const {
@@ -722,10 +584,7 @@ public:
return (nBits == 0);
}
- uint256 GetHash() const
- {
- return Hash(BEGIN(nVersion), END(nNonce));
- }
+ uint256 GetHash() const;
int64 GetBlockTime() const
{
@@ -779,24 +638,7 @@ public:
return block;
}
- uint256 BuildMerkleTree() const
- {
- vMerkleTree.clear();
- BOOST_FOREACH(const CTransaction& tx, vtx)
- vMerkleTree.push_back(tx.GetHash());
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- for (int i = 0; i < nSize; i += 2)
- {
- int i2 = std::min(i+1, nSize-1);
- vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
- BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
- }
- j += nSize;
- }
- return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
- }
+ uint256 BuildMerkleTree() const;
const uint256 &GetTxHash(unsigned int nIndex) const {
assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
@@ -804,56 +646,9 @@ public:
return vMerkleTree[nIndex];
}
- std::vector<uint256> GetMerkleBranch(int nIndex) const
- {
- if (vMerkleTree.empty())
- BuildMerkleTree();
- std::vector<uint256> vMerkleBranch;
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- int i = std::min(nIndex^1, nSize-1);
- vMerkleBranch.push_back(vMerkleTree[j+i]);
- nIndex >>= 1;
- j += nSize;
- }
- return vMerkleBranch;
- }
-
- static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
- {
- if (nIndex == -1)
- return 0;
- BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
- {
- if (nIndex & 1)
- hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
- else
- hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
- nIndex >>= 1;
- }
- return hash;
- }
-
- void print() const
- {
- printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
- GetHash().ToString().c_str(),
- nVersion,
- hashPrevBlock.ToString().c_str(),
- hashMerkleRoot.ToString().c_str(),
- nTime, nBits, nNonce,
- vtx.size());
- for (unsigned int i = 0; i < vtx.size(); i++)
- {
- printf(" ");
- vtx[i].print();
- }
- printf(" vMerkleTree: ");
- for (unsigned int i = 0; i < vMerkleTree.size(); i++)
- printf("%s ", vMerkleTree[i].ToString().c_str());
- printf("\n");
- }
+ std::vector<uint256> GetMerkleBranch(int nIndex) const;
+ static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
+ void print() const;
};
#endif
diff --git a/src/db.cpp b/src/db.cpp
index 93f3f5d8c4..03f46f3c26 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -8,7 +8,6 @@
#include "util.h"
#include "hash.h"
#include "addrman.h"
-#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <openssl/rand.h>
diff --git a/src/init.cpp b/src/init.cpp
index 44477081be..c5a8cc9fbe 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -119,7 +119,7 @@ void Shutdown()
}
bitdb.Flush(true);
boost::filesystem::remove(GetPidFile());
- UnregisterWallet(pwalletMain);
+ UnregisterAllWallets();
delete pwalletMain;
}
@@ -237,12 +237,12 @@ std::string HelpMessage()
strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + "\n";
strUsage += " -par=<n> " + _("Set the number of script verification threads (up to 16, 0 = auto, <0 = leave that many cores free, default: 0)") + "\n";
- strUsage += "\n"; _("Block creation options:") + "\n";
+ strUsage += "\n" + _("Block creation options:") + "\n";
strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n";
strUsage += " -blockmaxsize=<n> " + _("Set maximum block size in bytes (default: 250000)") + "\n";
strUsage += " -blockprioritysize=<n> " + _("Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)") + "\n";
- strUsage += "\n"; _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
+ strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
strUsage += " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n";
strUsage += " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n";
diff --git a/src/key.cpp b/src/key.cpp
index f73708199a..1ab4c62ebf 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -155,7 +155,8 @@ public:
BN_clear_free(&bn);
}
- void GetPrivKey(CPrivKey &privkey) {
+ void GetPrivKey(CPrivKey &privkey, bool fCompressed) {
+ EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED);
int nSize = i2d_ECPrivateKey(pkey, NULL);
assert(nSize);
privkey.resize(nSize);
@@ -304,7 +305,7 @@ CPrivKey CKey::GetPrivKey() const {
CECKey key;
key.SetSecretBytes(vch);
CPrivKey privkey;
- key.GetPrivKey(privkey);
+ key.GetPrivKey(privkey, fCompressed);
return privkey;
}
diff --git a/src/main.cpp b/src/main.cpp
index f3ce436606..d358914406 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -99,9 +99,16 @@ void UnregisterWallet(CWallet* pwalletIn)
}
}
+void UnregisterAllWallets()
+{
+ LOCK(cs_setpwalletRegistered);
+ setpwalletRegistered.clear();
+}
+
// get the wallet transaction with the given hash (if it exists)
bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
if (pwallet->GetTransaction(hashTx,wtx))
return true;
@@ -111,6 +118,7 @@ bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
// erases transaction with the given hash from all wallets
void static EraseFromWallets(uint256 hash)
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->EraseFromWallet(hash);
}
@@ -118,6 +126,7 @@ void static EraseFromWallets(uint256 hash)
// make sure all wallets know about the given transaction, in the given block
void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->AddToWalletIfInvolvingMe(hash, tx, pblock, fUpdate);
}
@@ -125,6 +134,7 @@ void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock*
// notify wallets about a new best chain
void static SetBestChain(const CBlockLocator& loc)
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->SetBestChain(loc);
}
@@ -132,6 +142,7 @@ void static SetBestChain(const CBlockLocator& loc)
// notify wallets about an updated transaction
void static UpdatedTransaction(const uint256& hashTx)
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->UpdatedTransaction(hashTx);
}
@@ -139,6 +150,7 @@ void static UpdatedTransaction(const uint256& hashTx)
// dump all wallets
void static PrintWallets(const CBlock& block)
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->PrintWallet(block);
}
@@ -146,6 +158,7 @@ void static PrintWallets(const CBlock& block)
// notify wallets about an incoming inventory (for request counts)
void static Inventory(const uint256& hash)
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->Inventory(hash);
}
@@ -153,6 +166,7 @@ void static Inventory(const uint256& hash)
// ask wallets to resend their transactions
void static ResendWalletTransactions()
{
+ LOCK(cs_setpwalletRegistered);
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
pwallet->ResendWalletTransactions();
}
@@ -457,38 +471,53 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
-bool IsStandardTx(const CTransaction& tx)
+bool IsStandardTx(const CTransaction& tx, string& reason)
{
- if (tx.nVersion > CTransaction::CURRENT_VERSION)
+ if (tx.nVersion > CTransaction::CURRENT_VERSION) {
+ reason = "version";
return false;
+ }
- if (!IsFinalTx(tx))
+ if (!IsFinalTx(tx)) {
+ reason = "non-final";
return false;
+ }
// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
- if (sz >= MAX_STANDARD_TX_SIZE)
+ if (sz >= MAX_STANDARD_TX_SIZE) {
+ reason = "tx-size";
return false;
+ }
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
// ~65-byte public keys, plus a few script ops.
- if (txin.scriptSig.size() > 500)
+ if (txin.scriptSig.size() > 500) {
+ reason = "scriptsig-size";
return false;
- if (!txin.scriptSig.IsPushOnly())
+ }
+ if (!txin.scriptSig.IsPushOnly()) {
+ reason = "scriptsig-not-pushonly";
return false;
+ }
}
BOOST_FOREACH(const CTxOut& txout, tx.vout) {
- if (!::IsStandard(txout.scriptPubKey))
+ if (!::IsStandard(txout.scriptPubKey)) {
+ reason = "scriptpubkey";
return false;
- if (txout.IsDust(CTransaction::nMinRelayTxFee))
+ }
+ if (txout.IsDust(CTransaction::nMinRelayTxFee)) {
+ reason = "dust";
return false;
+ }
}
+
return true;
}
@@ -782,8 +811,10 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
// Rather not work on nonstandard transactions (unless -testnet)
- if (!TestNet() && !IsStandardTx(tx))
- return error("CTxMemPool::accept() : nonstandard transaction type");
+ string reason;
+ if (!TestNet() && !IsStandardTx(tx, reason))
+ return error("CTxMemPool::accept() : nonstandard transaction: %s",
+ reason.c_str());
// is it already in the memory pool?
uint256 hash = tx.GetHash();
@@ -4747,59 +4778,6 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
}
-// Amount compression:
-// * If the amount is 0, output 0
-// * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9)
-// * if e<9, the last digit of the resulting number cannot be 0; store it as d, and drop it (divide by 10)
-// * call the result n
-// * output 1 + 10*(9*n + d - 1) + e
-// * if e==9, we only know the resulting number is not zero, so output 1 + 10*(n - 1) + 9
-// (this is decodable, as d is in [1-9] and e is in [0-9])
-
-uint64 CTxOutCompressor::CompressAmount(uint64 n)
-{
- if (n == 0)
- return 0;
- int e = 0;
- while (((n % 10) == 0) && e < 9) {
- n /= 10;
- e++;
- }
- if (e < 9) {
- int d = (n % 10);
- assert(d >= 1 && d <= 9);
- n /= 10;
- return 1 + (n*9 + d - 1)*10 + e;
- } else {
- return 1 + (n - 1)*10 + 9;
- }
-}
-
-uint64 CTxOutCompressor::DecompressAmount(uint64 x)
-{
- // x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
- if (x == 0)
- return 0;
- x--;
- // x = 10*(9*n + d - 1) + e
- int e = x % 10;
- x /= 10;
- uint64 n = 0;
- if (e < 9) {
- // x = 9*n + d - 1
- int d = (x % 9) + 1;
- x /= 9;
- // x = n
- n = x*10 + d;
- } else {
- n = x+1;
- }
- while (e) {
- n *= 10;
- e--;
- }
- return n;
-}
class CMainCleanup
diff --git a/src/main.h b/src/main.h
index 9e0235fa57..8ad2437c63 100644
--- a/src/main.h
+++ b/src/main.h
@@ -119,6 +119,8 @@ struct CBlockTemplate;
void RegisterWallet(CWallet* pwalletIn);
/** Unregister a wallet from core */
void UnregisterWallet(CWallet* pwalletIn);
+/** Unregister all wallets from core */
+void UnregisterAllWallets();
/** Push an updated transaction to all registered wallets */
void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false);
@@ -324,7 +326,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state);
/** Check for standard transaction types
@return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
-bool IsStandardTx(const CTransaction& tx);
+bool IsStandardTx(const CTransaction& tx, std::string& reason);
bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64 nBlockTime = 0);
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 3659f52040..002e36d3e2 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -21,7 +21,7 @@ USE_UPNP:=-
USE_IPV6:=1
DEPSDIR?=/usr/local
-BOOST_SUFFIX?=-mgw46-mt-sd-1_52
+BOOST_SUFFIX?=-mgw46-mt-s-1_52
INCLUDEPATHS= \
-I"$(CURDIR)" \
diff --git a/src/net.cpp b/src/net.cpp
index 5418c3de40..bd9aa1f50f 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1598,8 +1598,12 @@ bool BindListenPort(const CService &addrBind, string& strError)
// and enable it by default or not. Try to enable it, if possible.
if (addrBind.IsIPv6()) {
#ifdef IPV6_V6ONLY
+#ifdef WIN32
+ setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
+#else
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
#endif
+#endif
#ifdef WIN32
int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 76e88b36a7..b0c45d6863 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -15,6 +15,7 @@
#include "ui_interface.h"
#include "paymentserver.h"
#include "splashscreen.h"
+#include "intro.h"
#include <QMessageBox>
#if QT_VERSION < 0x050000
@@ -24,6 +25,7 @@
#include <QTimer>
#include <QTranslator>
#include <QLibraryInfo>
+#include <QSettings>
#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
#define _BITCOIN_QT_PLUGINS_INCLUDED
@@ -110,6 +112,46 @@ static void handleRunawayException(std::exception *e)
exit(1);
}
+/** Set up translations */
+static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
+{
+ QSettings settings;
+
+ // Get desired locale (e.g. "de_DE")
+ // 1) System default language
+ QString lang_territory = QLocale::system().name();
+ // 2) Language from QSettings
+ QString lang_territory_qsettings = settings.value("language", "").toString();
+ if(!lang_territory_qsettings.isEmpty())
+ lang_territory = lang_territory_qsettings;
+ // 3) -lang command line argument
+ lang_territory = QString::fromStdString(GetArg("-lang", lang_territory.toStdString()));
+
+ // Convert to "de" only by truncating "_DE"
+ QString lang = lang_territory;
+ lang.truncate(lang_territory.lastIndexOf('_'));
+
+ // Load language files for configured locale:
+ // - First load the translator for the base language, without territory
+ // - Then load the more specific locale translator
+
+ // Load e.g. qt_de.qm
+ if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ QApplication::installTranslator(&qtTranslatorBase);
+
+ // Load e.g. qt_de_DE.qm
+ if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ QApplication::installTranslator(&qtTranslator);
+
+ // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
+ if (translatorBase.load(lang, ":/translations/"))
+ QApplication::installTranslator(&translatorBase);
+
+ // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
+ if (translator.load(lang_territory, ":/translations/"))
+ QApplication::installTranslator(&translator);
+}
+
#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
@@ -130,6 +172,22 @@ int main(int argc, char *argv[])
// Register meta types used for QMetaObject::invokeMethod
qRegisterMetaType< bool* >();
+ // Application identification (must be set before OptionsModel is initialized,
+ // as it is used to locate QSettings)
+ QApplication::setOrganizationName("Bitcoin");
+ QApplication::setOrganizationDomain("bitcoin.org");
+ if (GetBoolArg("-testnet", false)) // Separate UI settings for testnet
+ QApplication::setApplicationName("Bitcoin-Qt-testnet");
+ else
+ QApplication::setApplicationName("Bitcoin-Qt");
+
+ // Now that QSettings are accessible, initialize translations
+ QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
+ initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
+
+ // User language is set up: pick a data directory
+ Intro::pickDataDirectory();
+
// Do this early as we don't want to bother initializing if we are just calling IPC
// ... but do it after creating app, so QCoreApplication::arguments is initialized:
if (PaymentServer::ipcSendCommandLine())
@@ -142,53 +200,15 @@ int main(int argc, char *argv[])
// ... then bitcoin.conf:
if (!boost::filesystem::is_directory(GetDataDir(false)))
{
- // This message can not be translated, as translation is not initialized yet
- // (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory)
- QMessageBox::critical(0, "Bitcoin",
- QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
+ QMessageBox::critical(0, QObject::tr("Bitcoin"),
+ QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
return 1;
}
ReadConfigFile(mapArgs, mapMultiArgs);
- // Application identification (must be set before OptionsModel is initialized,
- // as it is used to locate QSettings)
- QApplication::setOrganizationName("Bitcoin");
- QApplication::setOrganizationDomain("bitcoin.org");
- if (GetBoolArg("-testnet", false)) // Separate UI settings for testnet
- QApplication::setApplicationName("Bitcoin-Qt-testnet");
- else
- QApplication::setApplicationName("Bitcoin-Qt");
-
// ... then GUI settings:
OptionsModel optionsModel;
- // Get desired locale (e.g. "de_DE") from command line or use system locale
- QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
- QString lang = lang_territory;
- // Convert to "de" only by truncating "_DE"
- lang.truncate(lang_territory.lastIndexOf('_'));
-
- QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
- // Load language files for configured locale:
- // - First load the translator for the base language, without territory
- // - Then load the more specific locale translator
-
- // Load e.g. qt_de.qm
- if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
- app.installTranslator(&qtTranslatorBase);
-
- // Load e.g. qt_de_DE.qm
- if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
- app.installTranslator(&qtTranslator);
-
- // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
- if (translatorBase.load(lang, ":/translations/"))
- app.installTranslator(&translatorBase);
-
- // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
- if (translator.load(lang_territory, ":/translations/"))
- app.installTranslator(&translator);
-
// Subscribe to global signals from core
uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 1afce2eb7c..cb09e93e76 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -33,6 +33,10 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Cannot obtain a lock on data directory %s. Bitcoin is probably already "
"running."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Enter regression test mode, which uses a special chain in which blocks can "
+"be solved instantly. This is intended for regression testing tools and app "
+"development."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: The transaction was rejected! This might happen if some of the coins "
"in your wallet were already spent, such as if you used a copy of wallet.dat "
"and coins were spent in the copy but not marked as spent here."),
@@ -133,6 +137,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"),
QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 288, 0 = all)"),
QT_TRANSLATE_NOOP("bitcoin-core", "How thorough the block verification is (0-4, default: 3)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000??.dat file"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"),
QT_TRANSLATE_NOOP("bitcoin-core", "Information"),
QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"),
diff --git a/src/qt/forms/intro.ui b/src/qt/forms/intro.ui
new file mode 100644
index 0000000000..0f6ae5a7d0
--- /dev/null
+++ b/src/qt/forms/intro.ui
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Intro</class>
+ <widget class="QDialog" name="Intro">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>674</width>
+ <height>363</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Welcome</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="styleSheet">
+ <string notr="true">QLabel { font-style:italic; }</string>
+ </property>
+ <property name="text">
+ <string>Welcome to Bitcoin-Qt.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>15</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>As this is the first time the program is launched, you can choose where Bitcoin-Qt will store its data.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="sizeWarningLabel">
+ <property name="text">
+ <string>Bitcoin-Qt will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="dataDirDefault">
+ <property name="text">
+ <string>Use the default data directory</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="dataDirCustom">
+ <property name="text">
+ <string>Use a custom data directory:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>60</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="dataDirectory"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="ellipsisButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">…</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="freeSpace">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="errorMessage">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Intro</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Intro</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 88a6e7226e..3d1e91efdc 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -500,7 +500,8 @@ HelpMessageBox::HelpMessageBox(QWidget *parent) :
uiOptions = tr("UI options") + ":\n" +
" -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
" -min " + tr("Start minimized") + "\n" +
- " -splash " + tr("Show splash screen on startup (default: 1)") + "\n";
+ " -splash " + tr("Show splash screen on startup (default: 1)") + "\n" +
+ " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n";
setWindowTitle(tr("Bitcoin-Qt"));
setTextFormat(Qt::PlainText);
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
new file mode 100644
index 0000000000..51f3c812e4
--- /dev/null
+++ b/src/qt/intro.cpp
@@ -0,0 +1,270 @@
+#include "intro.h"
+#include "ui_intro.h"
+#include "util.h"
+
+#include <QFileDialog>
+#include <QSettings>
+#include <QMessageBox>
+
+#include <boost/filesystem.hpp>
+
+/* Minimum free space (in bytes) needed for data directory */
+static const uint64 GB_BYTES = 1000000000LL;
+static const uint64 BLOCK_CHAIN_SIZE = 10LL * GB_BYTES;
+
+/* Check free space asynchronously to prevent hanging the UI thread.
+
+ Up to one request to check a path is in flight to this thread; when the check()
+ function runs, the current path is requested from the associated Intro object.
+ The reply is sent back through a signal.
+
+ This ensures that no queue of checking requests is built up while the user is
+ still entering the path, and that always the most recently entered path is checked as
+ soon as the thread becomes available.
+*/
+class FreespaceChecker : public QObject
+{
+ Q_OBJECT
+public:
+ FreespaceChecker(Intro *intro);
+
+ enum Status {
+ ST_OK,
+ ST_ERROR
+ };
+
+public slots:
+ void check();
+
+signals:
+ void reply(int status, const QString &message, quint64 available);
+
+private:
+ Intro *intro;
+};
+
+#include "intro.moc"
+
+FreespaceChecker::FreespaceChecker(Intro *intro)
+{
+ this->intro = intro;
+}
+
+void FreespaceChecker::check()
+{
+ namespace fs = boost::filesystem;
+ QString dataDirStr = intro->getPathToCheck();
+ fs::path dataDir = fs::path(dataDirStr.toStdString());
+ uint64 freeBytesAvailable = 0;
+ int replyStatus = ST_OK;
+ QString replyMessage = tr("A new data directory will be created.");
+
+ /* Find first parent that exists, so that fs::space does not fail */
+ fs::path parentDir = dataDir;
+ while(parentDir.has_parent_path() && !fs::exists(parentDir))
+ {
+ parentDir = parentDir.parent_path();
+ }
+
+ try {
+ freeBytesAvailable = fs::space(parentDir).available;
+ if(fs::exists(dataDir))
+ {
+ if(fs::is_directory(dataDir))
+ {
+ QString separator = QDir::toNativeSeparators("/");
+ replyStatus = ST_OK;
+ replyMessage = tr("Directory already exists. Add <code>%1name</code> if you intend to create a new directory here.").arg(separator);
+ } else {
+ replyStatus = ST_ERROR;
+ replyMessage = tr("Path already exists, and is not a directory.");
+ }
+ }
+ } catch(fs::filesystem_error &e)
+ {
+ /* Parent directory does not exist or is not accessible */
+ replyStatus = ST_ERROR;
+ replyMessage = tr("Cannot create data directory here.");
+ }
+ emit reply(replyStatus, replyMessage, freeBytesAvailable);
+}
+
+
+Intro::Intro(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::Intro),
+ thread(0),
+ signalled(false)
+{
+ ui->setupUi(this);
+ ui->sizeWarningLabel->setText(ui->sizeWarningLabel->text().arg(BLOCK_CHAIN_SIZE/GB_BYTES));
+ startThread();
+}
+
+Intro::~Intro()
+{
+ delete ui;
+ /* Ensure thread is finished before it is deleted */
+ emit stopThread();
+ thread->wait();
+}
+
+QString Intro::getDataDirectory()
+{
+ return ui->dataDirectory->text();
+}
+
+void Intro::setDataDirectory(const QString &dataDir)
+{
+ ui->dataDirectory->setText(dataDir);
+ if(dataDir == getDefaultDataDirectory())
+ {
+ ui->dataDirDefault->setChecked(true);
+ ui->dataDirectory->setEnabled(false);
+ ui->ellipsisButton->setEnabled(false);
+ } else {
+ ui->dataDirCustom->setChecked(true);
+ ui->dataDirectory->setEnabled(true);
+ ui->ellipsisButton->setEnabled(true);
+ }
+}
+
+QString Intro::getDefaultDataDirectory()
+{
+ return QString::fromStdString(GetDefaultDataDir().string());
+}
+
+void Intro::pickDataDirectory()
+{
+ namespace fs = boost::filesystem;;
+ QSettings settings;
+ /* If data directory provided on command line, no need to look at settings
+ or show a picking dialog */
+ if(!GetArg("-datadir", "").empty())
+ return;
+ /* 1) Default data directory for operating system */
+ QString dataDir = getDefaultDataDirectory();
+ /* 2) Allow QSettings to override default dir */
+ dataDir = settings.value("strDataDir", dataDir).toString();
+
+ if(!fs::exists(dataDir.toStdString()) || GetBoolArg("-choosedatadir", false))
+ {
+ /* If current default data directory does not exist, let the user choose one */
+ Intro intro;
+ intro.setDataDirectory(dataDir);
+ while(true)
+ {
+ if(!intro.exec())
+ {
+ /* Cancel clicked */
+ exit(0);
+ }
+ dataDir = intro.getDataDirectory();
+ try {
+ fs::create_directory(dataDir.toStdString());
+ break;
+ } catch(fs::filesystem_error &e) {
+ QMessageBox::critical(0, QObject::tr("Bitcoin"),
+ QObject::tr("Error: Specified data directory \"%1\" can not be created.").arg(dataDir));
+ /* fall through, back to choosing screen */
+ }
+ }
+
+ settings.setValue("strDataDir", dataDir);
+ }
+ SoftSetArg("-datadir", dataDir.toStdString());
+}
+
+void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable)
+{
+ switch(status)
+ {
+ case FreespaceChecker::ST_OK:
+ ui->errorMessage->setText(message);
+ ui->errorMessage->setStyleSheet("");
+ break;
+ case FreespaceChecker::ST_ERROR:
+ ui->errorMessage->setText(tr("Error") + ": " + message);
+ ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
+ break;
+ }
+ /* Indicate number of bytes available */
+ if(status == FreespaceChecker::ST_ERROR)
+ {
+ ui->freeSpace->setText("");
+ } else {
+ QString freeString = QString::number(bytesAvailable/GB_BYTES) + tr("GB of free space available");
+ if(bytesAvailable < BLOCK_CHAIN_SIZE)
+ {
+ freeString += " " + tr("(of %1GB needed)").arg(BLOCK_CHAIN_SIZE/GB_BYTES);
+ ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
+ } else {
+ ui->freeSpace->setStyleSheet("");
+ }
+ ui->freeSpace->setText(freeString+".");
+ }
+ /* Don't allow confirm in ERROR state */
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR);
+}
+
+void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)
+{
+ /* Disable OK button until check result comes in */
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+ checkPath(dataDirStr);
+}
+
+void Intro::on_ellipsisButton_clicked()
+{
+ QString dir = QFileDialog::getExistingDirectory(0, "Choose data directory", ui->dataDirectory->text());
+ if(!dir.isEmpty())
+ ui->dataDirectory->setText(dir);
+}
+
+void Intro::on_dataDirDefault_clicked()
+{
+ setDataDirectory(getDefaultDataDirectory());
+}
+
+void Intro::on_dataDirCustom_clicked()
+{
+ ui->dataDirectory->setEnabled(true);
+ ui->ellipsisButton->setEnabled(true);
+}
+
+void Intro::startThread()
+{
+ thread = new QThread(this);
+ FreespaceChecker *executor = new FreespaceChecker(this);
+ executor->moveToThread(thread);
+
+ connect(executor, SIGNAL(reply(int,QString,quint64)), this, SLOT(setStatus(int,QString,quint64)));
+ connect(this, SIGNAL(requestCheck()), executor, SLOT(check()));
+ /* make sure executor object is deleted in its own thread */
+ connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
+ connect(this, SIGNAL(stopThread()), thread, SLOT(quit()));
+
+ thread->start();
+}
+
+void Intro::checkPath(const QString &dataDir)
+{
+ mutex.lock();
+ pathToCheck = dataDir;
+ if(!signalled)
+ {
+ signalled = true;
+ emit requestCheck();
+ }
+ mutex.unlock();
+}
+
+QString Intro::getPathToCheck()
+{
+ QString retval;
+ mutex.lock();
+ retval = pathToCheck;
+ signalled = false; /* new request can be queued now */
+ mutex.unlock();
+ return retval;
+}
diff --git a/src/qt/intro.h b/src/qt/intro.h
new file mode 100644
index 0000000000..b246c65a82
--- /dev/null
+++ b/src/qt/intro.h
@@ -0,0 +1,67 @@
+#ifndef INTRO_H
+#define INTRO_H
+
+#include <QDialog>
+#include <QThread>
+#include <QMutex>
+
+namespace Ui {
+class Intro;
+}
+class FreespaceChecker;
+
+/** Introduction screen (pre-GUI startup).
+ Allows the user to choose a data directory,
+ in which the wallet and block chain will be stored.
+ */
+class Intro : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit Intro(QWidget *parent = 0);
+ ~Intro();
+
+ QString getDataDirectory();
+ void setDataDirectory(const QString &dataDir);
+
+ /**
+ * Determine data directory. Let the user choose if the current one doesn't exist.
+ *
+ * @note do NOT call global GetDataDir() before calling this function, this
+ * will cause the wrong path to be cached.
+ */
+ static void pickDataDirectory();
+
+ /**
+ * Determine default data directory for operating system.
+ */
+ static QString getDefaultDataDirectory();
+signals:
+ void requestCheck();
+ void stopThread();
+
+public slots:
+ void setStatus(int status, const QString &message, quint64 bytesAvailable);
+
+private slots:
+ void on_dataDirectory_textChanged(const QString &arg1);
+ void on_ellipsisButton_clicked();
+ void on_dataDirDefault_clicked();
+ void on_dataDirCustom_clicked();
+
+private:
+ Ui::Intro *ui;
+ QThread *thread;
+ QMutex mutex;
+ bool signalled;
+ QString pathToCheck;
+
+ void startThread();
+ void checkPath(const QString &dataDir);
+ QString getPathToCheck();
+
+ friend class FreespaceChecker;
+};
+
+#endif // INTRO_H
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 2006a5296b..7628b39bd3 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -143,7 +143,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Send &amp;Coins</translation>
</message>
<message>
- <location line="+260"/>
+ <location line="+265"/>
<source>Export Address Book Data</source>
<translation>Export Address Book Data</translation>
</message>
@@ -325,17 +325,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+233"/>
+ <location filename="../bitcoingui.cpp" line="+257"/>
<source>Sign &amp;message...</source>
<translation>Sign &amp;message...</translation>
</message>
<message>
- <location line="+280"/>
+ <location line="+268"/>
<source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-349"/>
+ <location line="-343"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -375,7 +375,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Quit application</translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+7"/>
<source>Show information about Bitcoin</source>
<translation>Show information about Bitcoin</translation>
</message>
@@ -395,7 +395,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Options...</translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+9"/>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Encrypt Wallet...</translation>
</message>
@@ -410,7 +410,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Change Passphrase...</translation>
</message>
<message>
- <location line="+285"/>
+ <location line="+273"/>
<source>Importing blocks from disk...</source>
<translation>Importing blocks from disk...</translation>
</message>
@@ -420,17 +420,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Reindexing blocks on disk...</translation>
</message>
<message>
- <location line="-347"/>
+ <location line="-341"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
<message>
- <location line="+49"/>
+ <location line="+52"/>
<source>Modify configuration options for Bitcoin</source>
<translation>Modify configuration options for Bitcoin</translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+12"/>
<source>Backup wallet to another location</source>
<translation>Backup wallet to another location</translation>
</message>
@@ -455,18 +455,20 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Verify message...</translation>
</message>
<message>
- <location line="-165"/>
+ <location line="-183"/>
+ <location line="+6"/>
<location line="+530"/>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
- <location line="-530"/>
+ <location line="-536"/>
+ <location line="+6"/>
<source>Wallet</source>
<translation>Wallet</translation>
</message>
<message>
- <location line="+101"/>
+ <location line="+107"/>
<source>&amp;Send</source>
<translation>&amp;Send</translation>
</message>
@@ -481,12 +483,14 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Addresses</translation>
</message>
<message>
- <location line="+22"/>
+ <location line="+23"/>
+ <location line="+2"/>
<source>&amp;About Bitcoin</source>
<translation>&amp;About Bitcoin</translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+10"/>
+ <location line="+2"/>
<source>&amp;Show / Hide</source>
<translation>&amp;Show / Hide</translation>
</message>
@@ -531,18 +535,19 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="+17"/>
- <location line="+10"/>
+ <location line="-228"/>
+ <location line="+288"/>
<source>[testnet]</source>
<translation>[testnet]</translation>
</message>
<message>
- <location line="+47"/>
+ <location line="-5"/>
+ <location line="+5"/>
<source>Bitcoin client</source>
<translation>Bitcoin client</translation>
</message>
<message numerus="yes">
- <location line="+141"/>
+ <location line="+143"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -684,7 +689,7 @@ Address: %4
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+111"/>
+ <location filename="../bitcoin.cpp" line="+109"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
<translation>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</translation>
</message>
@@ -692,7 +697,7 @@ Address: %4
<context>
<name>ClientModel</name>
<message>
- <location filename="../clientmodel.cpp" line="+104"/>
+ <location filename="../clientmodel.cpp" line="+105"/>
<source>Network Alert</source>
<translation>Network Alert</translation>
</message>
@@ -768,7 +773,7 @@ Address: %4
<context>
<name>GUIUtil::HelpMessageBox</name>
<message>
- <location filename="../guiutil.cpp" line="+424"/>
+ <location filename="../guiutil.cpp" line="+493"/>
<location line="+12"/>
<source>Bitcoin-Qt</source>
<translation>Bitcoin-Qt</translation>
@@ -982,7 +987,7 @@ Address: %4
<translation>&amp;Apply</translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="+53"/>
+ <location filename="../optionsdialog.cpp" line="+54"/>
<source>default</source>
<translation>default</translation>
</message>
@@ -1028,17 +1033,12 @@ Address: %4
</message>
<message>
<location line="+50"/>
- <location line="+166"/>
+ <location line="+202"/>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
<translation>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</translation>
</message>
<message>
- <location line="-124"/>
- <source>Balance:</source>
- <translation>Balance:</translation>
- </message>
- <message>
- <location line="+29"/>
+ <location line="-131"/>
<source>Unconfirmed:</source>
<translation>Unconfirmed:</translation>
</message>
@@ -1048,7 +1048,22 @@ Address: %4
<translation>Wallet</translation>
</message>
<message>
- <location line="+107"/>
+ <location line="+49"/>
+ <source>Confirmed:</source>
+ <translation>Confirmed:</translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Your current spendable balance</source>
+ <translation>Your current spendable balance</translation>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</translation>
+ </message>
+ <message>
+ <location line="+13"/>
<source>Immature:</source>
<translation>Immature:</translation>
</message>
@@ -1058,19 +1073,19 @@ Address: %4
<translation>Mined balance that has not yet matured</translation>
</message>
<message>
- <location line="+46"/>
- <source>&lt;b&gt;Recent transactions&lt;/b&gt;</source>
- <translation>&lt;b&gt;Recent transactions&lt;/b&gt;</translation>
+ <location line="+13"/>
+ <source>Total:</source>
+ <translation>Total:</translation>
</message>
<message>
- <location line="-101"/>
- <source>Your current balance</source>
- <translation>Your current balance</translation>
+ <location line="+16"/>
+ <source>Your current total balance</source>
+ <translation>Your current total balance</translation>
</message>
<message>
- <location line="+29"/>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</source>
- <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</translation>
+ <location line="+53"/>
+ <source>&lt;b&gt;Recent transactions&lt;/b&gt;</source>
+ <translation>&lt;b&gt;Recent transactions&lt;/b&gt;</translation>
</message>
<message>
<location filename="../overviewpage.cpp" line="+116"/>
@@ -1082,7 +1097,7 @@ Address: %4
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+107"/>
+ <location filename="../paymentserver.cpp" line="+109"/>
<source>Cannot start bitcoin: click-to-pay handler</source>
<translation>Cannot start bitcoin: click-to-pay handler</translation>
</message>
@@ -1120,7 +1135,7 @@ Address: %4
<translation>&amp;Save As...</translation>
</message>
<message>
- <location filename="../qrcodedialog.cpp" line="+62"/>
+ <location filename="../qrcodedialog.cpp" line="+64"/>
<source>Error encoding URI into QR Code.</source>
<translation>Error encoding URI into QR Code.</translation>
</message>
@@ -1162,7 +1177,7 @@ Address: %4
<location line="+53"/>
<location line="+23"/>
<location line="+23"/>
- <location filename="../rpcconsole.cpp" line="+339"/>
+ <location filename="../rpcconsole.cpp" line="+343"/>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1296,7 +1311,7 @@ Address: %4
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+124"/>
+ <location filename="../sendcoinsdialog.cpp" line="+128"/>
<location line="+5"/>
<location line="+5"/>
<location line="+5"/>
@@ -1347,12 +1362,13 @@ Address: %4
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-59"/>
+ <location filename="../sendcoinsdialog.cpp" line="-62"/>
+ <location line="+2"/>
<source>&lt;b&gt;%1&lt;/b&gt; to %2 (%3)</source>
<translation>&lt;b&gt;%1&lt;/b&gt; to %2 (%3)</translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+6"/>
<source>Confirm send coins</source>
<translation>Confirm send coins</translation>
</message>
@@ -1662,7 +1678,7 @@ Address: %4
<context>
<name>SplashScreen</name>
<message>
- <location filename="../splashscreen.cpp" line="+22"/>
+ <location filename="../splashscreen.cpp" line="+23"/>
<source>The Bitcoin developers</source>
<translation>The Bitcoin developers</translation>
</message>
@@ -2096,7 +2112,7 @@ Address: %4
<translation>Show transaction details</translation>
</message>
<message>
- <location line="+139"/>
+ <location line="+143"/>
<source>Export Transaction Data</source>
<translation>Export Transaction Data</translation>
</message>
@@ -2172,7 +2188,7 @@ Address: %4
<context>
<name>WalletView</name>
<message>
- <location filename="../walletview.cpp" line="+42"/>
+ <location filename="../walletview.cpp" line="+46"/>
<source>&amp;Export</source>
<translation>&amp;Export</translation>
</message>
@@ -2182,7 +2198,7 @@ Address: %4
<translation>Export the data in the current tab to a file</translation>
</message>
<message>
- <location line="+193"/>
+ <location line="+197"/>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
@@ -2215,12 +2231,12 @@ Address: %4
<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="+94"/>
+ <location filename="../bitcoinstrings.cpp" line="+98"/>
<source>Bitcoin version</source>
<translation>Bitcoin version</translation>
</message>
<message>
- <location line="+102"/>
+ <location line="+103"/>
<source>Usage:</source>
<translation>Usage:</translation>
</message>
@@ -2235,12 +2251,12 @@ Address: %4
<translation>List commands</translation>
</message>
<message>
- <location line="-12"/>
+ <location line="-13"/>
<source>Get help for a command</source>
<translation>Get help for a command</translation>
</message>
<message>
- <location line="+24"/>
+ <location line="+25"/>
<source>Options:</source>
<translation>Options:</translation>
</message>
@@ -2275,12 +2291,12 @@ Address: %4
<translation>Maintain at most &lt;n&gt; connections to peers (default: 125)</translation>
</message>
<message>
- <location line="-48"/>
+ <location line="-49"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
</message>
<message>
- <location line="+82"/>
+ <location line="+83"/>
<source>Specify your own public address</source>
<translation>Specify your own public address</translation>
</message>
@@ -2290,17 +2306,17 @@ Address: %4
<translation>Threshold for disconnecting misbehaving peers (default: 100)</translation>
</message>
<message>
- <location line="-134"/>
+ <location line="-135"/>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
<translation>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</translation>
</message>
<message>
- <location line="-29"/>
+ <location line="-33"/>
<source>An error occurred while setting up the RPC port %u for listening on IPv4: %s</source>
<translation>An error occurred while setting up the RPC port %u for listening on IPv4: %s</translation>
</message>
<message>
- <location line="+27"/>
+ <location line="+31"/>
<source>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</source>
<translation>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</translation>
</message>
@@ -2310,7 +2326,7 @@ Address: %4
<translation>Accept command line and JSON-RPC commands</translation>
</message>
<message>
- <location line="+76"/>
+ <location line="+77"/>
<source>Run in the background as a daemon and accept commands</source>
<translation>Run in the background as a daemon and accept commands</translation>
</message>
@@ -2320,12 +2336,12 @@ Address: %4
<translation>Use the test network</translation>
</message>
<message>
- <location line="-112"/>
+ <location line="-113"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
<translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
</message>
<message>
- <location line="-80"/>
+ <location line="-84"/>
<source>%s, you must set a rpcpassword in the configuration file:
%s
It is recommended you use the following random password:
@@ -2366,6 +2382,11 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<location line="+3"/>
+ <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly. This is intended for regression testing tools and app development.</source>
+ <translation>Enter regression test mode, which uses a special chain in which blocks can be solved instantly. This is intended for regression testing tools and app development.</translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source>
<translation>Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</translation>
</message>
@@ -2560,7 +2581,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>How thorough the block verification is (0-4, default: 3)</translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+2"/>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>Incorrect or no genesis block found. Wrong datadir for network?</translation>
+ </message>
+ <message>
+ <location line="+18"/>
<source>Not enough file descriptors available.</source>
<translation>Not enough file descriptors available.</translation>
</message>
@@ -2585,7 +2611,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Verifying wallet...</translation>
</message>
<message>
- <location line="-69"/>
+ <location line="+4"/>
+ <source>You need to rebuild the database using -reindex to change -txindex</source>
+ <translation>You need to rebuild the database using -reindex to change -txindex</translation>
+ </message>
+ <message>
+ <location line="-74"/>
<source>Imports blocks from external blk000??.dat file</source>
<translation>Imports blocks from external blk000??.dat file</translation>
</message>
@@ -2595,7 +2626,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Set the number of script verification threads (up to 16, 0 = auto, &lt;0 = leave that many cores free, default: 0)</translation>
</message>
<message>
- <location line="+77"/>
+ <location line="+78"/>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -2750,12 +2781,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Warning: This version is obsolete, upgrade required!</translation>
</message>
<message>
- <location line="+1"/>
- <source>You need to rebuild the databases using -reindex to change -txindex</source>
- <translation>You need to rebuild the databases using -reindex to change -txindex</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+2"/>
<source>wallet.dat corrupt, salvage failed</source>
<translation>wallet.dat corrupt, salvage failed</translation>
</message>
@@ -2765,22 +2791,22 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Password for JSON-RPC connections</translation>
</message>
<message>
- <location line="-67"/>
+ <location line="-68"/>
<source>Allow JSON-RPC connections from specified IP address</source>
<translation>Allow JSON-RPC connections from specified IP address</translation>
</message>
<message>
- <location line="+76"/>
+ <location line="+77"/>
<source>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</source>
<translation>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</translation>
</message>
<message>
- <location line="-120"/>
+ <location line="-121"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
</message>
<message>
- <location line="+147"/>
+ <location line="+148"/>
<source>Upgrade wallet to latest format</source>
<translation>Upgrade wallet to latest format</translation>
</message>
@@ -2810,12 +2836,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Server private key (default: server.pem)</translation>
</message>
<message>
- <location line="-151"/>
+ <location line="-156"/>
<source>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</source>
<translation>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</translation>
</message>
<message>
- <location line="+165"/>
+ <location line="+170"/>
<source>This help message</source>
<translation>This help message</translation>
</message>
@@ -2825,7 +2851,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Unable to bind to %s on this computer (bind returned error %d, %s)</translation>
</message>
<message>
- <location line="-91"/>
+ <location line="-92"/>
<source>Connect through socks proxy</source>
<translation>Connect through socks proxy</translation>
</message>
@@ -2835,12 +2861,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
</message>
<message>
- <location line="+55"/>
+ <location line="+56"/>
<source>Loading addresses...</source>
<translation>Loading addresses...</translation>
</message>
<message>
- <location line="-35"/>
+ <location line="-36"/>
<source>Error loading wallet.dat: Wallet corrupted</source>
<translation>Error loading wallet.dat: Wallet corrupted</translation>
</message>
@@ -2850,17 +2876,17 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Error loading wallet.dat: Wallet requires newer version of Bitcoin</translation>
</message>
<message>
- <location line="+93"/>
+ <location line="+94"/>
<source>Wallet needed to be rewritten: restart Bitcoin to complete</source>
<translation>Wallet needed to be rewritten: restart Bitcoin to complete</translation>
</message>
<message>
- <location line="-95"/>
+ <location line="-96"/>
<source>Error loading wallet.dat</source>
<translation>Error loading wallet.dat</translation>
</message>
<message>
- <location line="+28"/>
+ <location line="+29"/>
<source>Invalid -proxy address: &apos;%s&apos;</source>
<translation>Invalid -proxy address: &apos;%s&apos;</translation>
</message>
@@ -2875,7 +2901,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Unknown -socks proxy version requested: %i</translation>
</message>
<message>
- <location line="-96"/>
+ <location line="-97"/>
<source>Cannot resolve -bind address: &apos;%s&apos;</source>
<translation>Cannot resolve -bind address: &apos;%s&apos;</translation>
</message>
@@ -2885,7 +2911,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Cannot resolve -externalip address: &apos;%s&apos;</translation>
</message>
<message>
- <location line="+44"/>
+ <location line="+45"/>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
<translation>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
@@ -2905,7 +2931,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Loading block index...</translation>
</message>
<message>
- <location line="-57"/>
+ <location line="-58"/>
<source>Add a node to connect to and attempt to keep the connection open</source>
<translation>Add a node to connect to and attempt to keep the connection open</translation>
</message>
@@ -2920,12 +2946,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Fee per KB to add to transactions you send</translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+20"/>
<source>Loading wallet...</source>
<translation>Loading wallet...</translation>
</message>
<message>
- <location line="-52"/>
+ <location line="-53"/>
<source>Cannot downgrade wallet</source>
<translation>Cannot downgrade wallet</translation>
</message>
@@ -2935,22 +2961,22 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Cannot write default address</translation>
</message>
<message>
- <location line="+64"/>
+ <location line="+65"/>
<source>Rescanning...</source>
<translation>Rescanning...</translation>
</message>
<message>
- <location line="-57"/>
+ <location line="-58"/>
<source>Done loading</source>
<translation>Done loading</translation>
</message>
<message>
- <location line="+82"/>
+ <location line="+83"/>
<source>To use the %s option</source>
<translation>To use the %s option</translation>
</message>
<message>
- <location line="-74"/>
+ <location line="-75"/>
<source>Error</source>
<translation>Error</translation>
</message>
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 3c24016fe3..edaa732225 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -82,6 +82,15 @@ Value getblockcount(const Array& params, bool fHelp)
return nBestHeight;
}
+Value getbestblockhash(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "getbestblockhash\n"
+ "Returns the hash of the best (tip) block in the longest block chain.");
+
+ return hashBestChain.GetHex();
+}
Value getdifficulty(const Array& params, bool fHelp)
{
diff --git a/src/sync.h b/src/sync.h
index 930c9b2b80..64de7cc57c 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -11,6 +11,48 @@
#include <boost/thread/condition_variable.hpp>
#include "threadsafety.h"
+
+////////////////////////////////////////////////
+// //
+// THE SIMPLE DEFINITON, EXCLUDING DEBUG CODE //
+// //
+////////////////////////////////////////////////
+
+/*
+
+
+
+CCriticalSection mutex;
+ boost::recursive_mutex mutex;
+
+LOCK(mutex);
+ boost::unique_lock<boost::recursive_mutex> criticalblock(mutex);
+
+LOCK2(mutex1, mutex2);
+ boost::unique_lock<boost::recursive_mutex> criticalblock1(mutex1);
+ boost::unique_lock<boost::recursive_mutex> criticalblock2(mutex2);
+
+TRY_LOCK(mutex, name);
+ boost::unique_lock<boost::recursive_mutex> name(mutex, boost::try_to_lock_t);
+
+ENTER_CRITICAL_SECTION(mutex); // no RAII
+ mutex.lock();
+
+LEAVE_CRITICAL_SECTION(mutex); // no RAII
+ mutex.unlock();
+
+
+
+ */
+
+
+
+///////////////////////////////
+// //
+// THE ACTUAL IMPLEMENTATION //
+// //
+///////////////////////////////
+
// Template mixin that adds -Wthread-safety locking annotations to a
// subset of the mutex API.
template <typename PARENT>
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index 23cb3a8e0a..3c666d2842 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -74,6 +74,7 @@ BOOST_AUTO_TEST_CASE(sign)
}
CTransaction txFrom; // Funding transaction:
+ string reason;
txFrom.vout.resize(8);
for (int i = 0; i < 4; i++)
{
@@ -82,7 +83,7 @@ BOOST_AUTO_TEST_CASE(sign)
txFrom.vout[i+4].scriptPubKey = standardScripts[i];
txFrom.vout[i+4].nValue = COIN;
}
- BOOST_CHECK(IsStandardTx(txFrom));
+ BOOST_CHECK(IsStandardTx(txFrom, reason));
CTransaction txTo[8]; // Spending transactions
for (int i = 0; i < 8; i++)
@@ -167,13 +168,14 @@ BOOST_AUTO_TEST_CASE(set)
}
CTransaction txFrom; // Funding transaction:
+ string reason;
txFrom.vout.resize(4);
for (int i = 0; i < 4; i++)
{
txFrom.vout[i].scriptPubKey = outer[i];
txFrom.vout[i].nValue = CENT;
}
- BOOST_CHECK(IsStandardTx(txFrom));
+ BOOST_CHECK(IsStandardTx(txFrom, reason));
CTransaction txTo[4]; // Spending transactions
for (int i = 0; i < 4; i++)
@@ -189,7 +191,7 @@ BOOST_AUTO_TEST_CASE(set)
for (int i = 0; i < 4; i++)
{
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
- BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i]), strprintf("txTo[%d].IsStandard", i));
+ BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i));
}
}
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 53d1307b69..0c7475b4f2 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -260,16 +260,17 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
key.MakeNewKey(true);
t.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
- BOOST_CHECK(IsStandardTx(t));
+ string reason;
+ BOOST_CHECK(IsStandardTx(t, reason));
t.vout[0].nValue = 5011; // dust
- BOOST_CHECK(!IsStandardTx(t));
+ BOOST_CHECK(!IsStandardTx(t, reason));
t.vout[0].nValue = 6011; // not dust
- BOOST_CHECK(IsStandardTx(t));
+ BOOST_CHECK(IsStandardTx(t, reason));
t.vout[0].scriptPubKey = CScript() << OP_1;
- BOOST_CHECK(!IsStandardTx(t));
+ BOOST_CHECK(!IsStandardTx(t, reason));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 64bd3a1b28..fd936517fd 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -263,28 +263,10 @@ BOOST_AUTO_TEST_CASE(util_IsHex)
BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
{
- // Expected results for the determinstic seed.
- const uint32_t exp_vals[11] = { 91632771U,1889679809U,3842137544U,3256031132U,
- 1761911779U, 489223532U,2692793790U,2737472863U,
- 2796262275U,1309899767U,840571781U};
- // Expected 0s in rand()%(idx+2) for the determinstic seed.
- const int exp_count[9] = {5013,3346,2415,1972,1644,1386,1176,1096,1009};
int i;
int count=0;
- seed_insecure_rand();
-
- //Does the non-determistic rand give us results that look too like the determinstic one?
- for (i=0;i<10;i++)
- {
- int match = 0;
- uint32_t rval = insecure_rand();
- for (int j=0;j<11;j++)match |= rval==exp_vals[j];
- count += match;
- }
- // sum(binomial(10,i)*(11/(2^32))^i*(1-(11/(2^32)))^(10-i),i,0,4) ~= 1-1/2^134.73
- // So _very_ unlikely to throw a false failure here.
- BOOST_CHECK(count<=4);
+ seed_insecure_rand(true);
for (int mod=2;mod<11;mod++)
{
@@ -307,20 +289,6 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
BOOST_CHECK(count<=10000/mod+err);
BOOST_CHECK(count>=10000/mod-err);
}
-
- seed_insecure_rand(true);
-
- for (i=0;i<11;i++)
- {
- BOOST_CHECK_EQUAL(insecure_rand(),exp_vals[i]);
- }
-
- for (int mod=2;mod<11;mod++)
- {
- count = 0;
- for (i=0;i<10000;i++) count += insecure_rand()%mod==0;
- BOOST_CHECK_EQUAL(count,exp_count[mod-2]);
- }
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/version.cpp b/src/version.cpp
index 8af406feab..d9d6724a02 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -36,7 +36,7 @@ const std::string CLIENT_NAME("Satoshi");
// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
#ifdef GIT_ARCHIVE
# define GIT_COMMIT_ID "$Format:%h$"
-# define GIT_COMMIT_DATE "$Format:%cD"
+# define GIT_COMMIT_DATE "$Format:%cD$"
#endif
#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 702e219a5b..7aad779767 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -5,6 +5,7 @@
#include "walletdb.h"
#include "wallet.h"
+#include <boost/version.hpp>
#include <boost/filesystem.hpp>
using namespace std;