aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro13
-rw-r--r--contrib/debian/changelog38
-rw-r--r--doc/README2
-rw-r--r--doc/README_windows.txt2
-rw-r--r--share/setup.nsi6
-rw-r--r--src/addrman.cpp27
-rw-r--r--src/addrman.h4
-rw-r--r--src/bitcoinrpc.cpp468
-rw-r--r--src/bitcoinrpc.h15
-rw-r--r--src/db.cpp4
-rw-r--r--src/init.cpp49
-rw-r--r--src/init.h3
-rw-r--r--src/irc.cpp13
-rw-r--r--src/irc.h1
-rw-r--r--src/main.cpp131
-rw-r--r--src/main.h18
-rw-r--r--src/makefile.linux-mingw2
-rw-r--r--src/makefile.mingw2
-rw-r--r--src/makefile.osx2
-rw-r--r--src/makefile.unix13
-rw-r--r--src/net.cpp348
-rw-r--r--src/net.h30
-rw-r--r--src/netbase.cpp273
-rw-r--r--src/netbase.h5
-rw-r--r--src/qt/addressbookpage.cpp27
-rw-r--r--src/qt/bitcoin.cpp1
-rw-r--r--src/qt/bitcoin.qrc2
-rw-r--r--src/qt/bitcoingui.cpp23
-rw-r--r--src/qt/bitcoingui.h3
-rw-r--r--src/qt/clientmodel.cpp5
-rw-r--r--src/qt/clientmodel.h1
-rw-r--r--src/qt/forms/aboutdialog.ui12
-rw-r--r--src/qt/forms/addressbookpage.ui12
-rw-r--r--src/qt/forms/messagepage.ui7
-rw-r--r--src/qt/forms/overviewpage.ui44
-rw-r--r--src/qt/forms/qrcodedialog.ui6
-rw-r--r--src/qt/forms/rpcconsole.ui323
-rw-r--r--src/qt/forms/sendcoinsdialog.ui2
-rw-r--r--src/qt/forms/sendcoinsentry.ui6
-rw-r--r--src/qt/locale/bitcoin_en.ts776
-rw-r--r--src/qt/messagepage.cpp5
-rw-r--r--src/qt/optionsdialog.cpp290
-rw-r--r--src/qt/optionsdialog.h10
-rw-r--r--src/qt/optionsmodel.cpp9
-rw-r--r--src/qt/optionsmodel.h3
-rw-r--r--src/qt/overviewpage.cpp14
-rw-r--r--src/qt/qrcodedialog.cpp2
-rw-r--r--src/qt/qvaluecombobox.cpp6
-rw-r--r--src/qt/qvaluecombobox.h9
-rw-r--r--src/qt/res/icons/qrcode.pngbin0 -> 237 bytes
-rw-r--r--src/qt/res/images/qrcode.pngbin5993 -> 0 bytes
-rw-r--r--src/qt/rpcconsole.cpp312
-rw-r--r--src/qt/rpcconsole.h65
-rw-r--r--src/qt/sendcoinsentry.cpp6
-rw-r--r--src/qt/transactionrecord.cpp2
-rw-r--r--src/qt/transactionview.cpp2
-rw-r--r--src/qt/walletmodel.cpp13
-rw-r--r--src/script.cpp6
-rw-r--r--src/test/DoS_tests.cpp8
-rw-r--r--src/test/base58_tests.cpp4
-rw-r--r--src/test/base64_tests.cpp2
-rw-r--r--src/util.cpp75
-rw-r--r--src/util.h7
-rw-r--r--src/version.h4
-rw-r--r--src/walletdb.cpp2
65 files changed, 2694 insertions, 881 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index f586c53372..112e8e9389 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
TARGET =
-VERSION = 0.6.1
+VERSION = 0.6.99
INCLUDEPATH += src src/json src/qt
DEFINES += QT_GUI BOOST_THREAD_USE_LIB
CONFIG += no_include_pwd
@@ -90,7 +90,7 @@ contains(BITCOIN_NEED_QT_PLUGINS, 1) {
DEFINES += HAVE_BUILD_INFO
}
-QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wformat -Wformat-security -Wno-invalid-offsetof -Wno-sign-compare -Wno-unused-parameter
+QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter
# Input
DEPENDPATH += src src/json src/qt
@@ -158,7 +158,8 @@ HEADERS += src/qt/bitcoingui.h \
src/qt/notificator.h \
src/qt/qtipcserver.h \
src/allocators.h \
- src/ui_interface.h
+ src/ui_interface.h \
+ src/qt/rpcconsole.h
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactiontablemodel.cpp \
@@ -212,7 +213,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/askpassphrasedialog.cpp \
src/protocol.cpp \
src/qt/notificator.cpp \
- src/qt/qtipcserver.cpp
+ src/qt/qtipcserver.cpp \
+ src/qt/rpcconsole.cpp
RESOURCES += \
src/qt/bitcoin.qrc
@@ -226,7 +228,8 @@ FORMS += \
src/qt/forms/transactiondescdialog.ui \
src/qt/forms/overviewpage.ui \
src/qt/forms/sendcoinsentry.ui \
- src/qt/forms/askpassphrasedialog.ui
+ src/qt/forms/askpassphrasedialog.ui \
+ src/qt/forms/rpcconsole.ui
contains(USE_QRCODE, 1) {
HEADERS += src/qt/qrcodedialog.h
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
index db5e2682c6..cdd4a47e91 100644
--- a/contrib/debian/changelog
+++ b/contrib/debian/changelog
@@ -1,13 +1,43 @@
-bitcoin (0.5.1-natty1) natty; urgency=low
+bitcoin (0.6.1-natty0) natty; urgency=low
+
+ * New upstream release.
+
+ -- Matt Corallo <matt@bluematt.me> Sun, 6 May 2012 20:09:00 -0500
+
+bitcoin (0.6.0-natty0) natty; urgency=low
+
+ * New upstream release.
+ * Add GNOME/KDE support for bitcoin-qt's bitcoin: URI support.
+ Thanks to luke-jr for the KDE .protocol file.
+
+ -- Matt Corallo <matt@bluematt.me> Sat, 31 Mar 2012 15:35:00 -0500
+
+bitcoin (0.5.3-natty1) natty; urgency=low
+
+ * Mark for upload to PPA.
+
+ -- Matt Corallo <matt@bluematt.me> Wed, 14 Mar 2012 23:06:00 -0400
+
+bitcoin (0.5.3-natty0) natty; urgency=low
+
+ * New upstream release.
+
+ -- Luke Dashjr <luke+bitcoin+deb@dashjr.org> Tue, 10 Jan 2012 15:57:00 -0500
+
+bitcoin (0.5.2-natty1) natty; urgency=low
* Remove mentions on anonymity in package descriptions and manpage.
These should never have been there, bitcoin isnt anonymous without
a ton of work that virtually no users will ever be willing and
capable of doing
- * Add GNOME/KDE support for bitcoin-qt's bitcoin: URI support.
- Thanks to luke-jr for the KDE .protocol file.
- -- Matt Corallo <matt@bluematt.me> Fri, 23 Dec 2011 20:25:00 -0500
+ -- Matt Corallo <matt@bluematt.me> Sat, 7 Jan 2012 13:37:00 -0500
+
+bitcoin (0.5.2-natty0) natty; urgency=low
+
+ * New upstream release.
+
+ -- Luke Dashjr <luke+bitcoin+deb@dashjr.org> Fri, 16 Dec 2011 17:57:00 -0500
bitcoin (0.5.1-natty0) natty; urgency=low
diff --git a/doc/README b/doc/README
index a196a461e5..4eda8bcd76 100644
--- a/doc/README
+++ b/doc/README
@@ -1,4 +1,4 @@
-Bitcoin 0.6.1 BETA
+Bitcoin 0.6.99 BETA
Copyright (c) 2009-2012 Bitcoin Developers
Distributed under the MIT/X11 software license, see the accompanying
diff --git a/doc/README_windows.txt b/doc/README_windows.txt
index ec0225fd92..eec252931d 100644
--- a/doc/README_windows.txt
+++ b/doc/README_windows.txt
@@ -1,4 +1,4 @@
-Bitcoin 0.6.1 BETA
+Bitcoin 0.6.99 BETA
Copyright (c) 2009-2012 Bitcoin Developers
Distributed under the MIT/X11 software license, see the accompanying
diff --git a/share/setup.nsi b/share/setup.nsi
index 10bf36b4cf..fbbad3769e 100644
--- a/share/setup.nsi
+++ b/share/setup.nsi
@@ -5,7 +5,7 @@ SetCompressor /SOLID lzma
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
-!define VERSION 0.6.1
+!define VERSION 0.6.99
!define COMPANY "Bitcoin project"
!define URL http://www.bitcoin.org/
@@ -45,13 +45,13 @@ Var StartMenuGroup
!insertmacro MUI_LANGUAGE English
# Installer attributes
-OutFile bitcoin-0.6.1-win32-setup.exe
+OutFile bitcoin-0.6.99-win32-setup.exe
InstallDir $PROGRAMFILES\Bitcoin
CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
-VIProductVersion 0.6.1.3
+VIProductVersion 0.6.99.0
VIAddVersionKey ProductName Bitcoin
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 345261e229..56ac9ca12c 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -102,14 +102,19 @@ CAddrInfo* CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource, in
return &mapInfo[nId];
}
-void CAddrMan::SwapRandom(int nRndPos1, int nRndPos2)
+void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
{
if (nRndPos1 == nRndPos2)
return;
+ assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
+
int nId1 = vRandom[nRndPos1];
int nId2 = vRandom[nRndPos2];
+ assert(mapInfo.count(nId1) == 1);
+ assert(mapInfo.count(nId2) == 1);
+
mapInfo[nId1].nRandomPos = nRndPos2;
mapInfo[nId2].nRandomPos = nRndPos1;
@@ -124,26 +129,32 @@ int CAddrMan::SelectTried(int nKBucket)
// random shuffle the first few elements (using the entire list)
// find the least recently tried among them
int64 nOldest = -1;
+ int nOldestPos = -1;
for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++)
{
int nPos = GetRandInt(vTried.size() - i) + i;
int nTemp = vTried[nPos];
vTried[nPos] = vTried[i];
vTried[i] = nTemp;
- if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess)
+ assert(nOldest == -1 || mapInfo.count(nTemp) == 1);
+ if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess) {
nOldest = nTemp;
+ nOldestPos = nPos;
+ }
}
- return nOldest;
+ return nOldestPos;
}
int CAddrMan::ShrinkNew(int nUBucket)
{
+ assert(nUBucket >= 0 && (unsigned int)nUBucket < vvNew.size());
std::set<int> &vNew = vvNew[nUBucket];
// first look for deletable items
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
{
+ assert(mapInfo.count(*it));
CAddrInfo &info = mapInfo[*it];
if (info.IsTerrible())
{
@@ -168,11 +179,13 @@ int CAddrMan::ShrinkNew(int nUBucket)
{
if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3])
{
+ assert(nOldest == -1 || mapInfo.count(*it) == 1);
if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime)
nOldest = *it;
}
nI++;
}
+ assert(mapInfo.count(nOldest) == 1);
CAddrInfo &info = mapInfo[nOldest];
if (--info.nRefCount == 0)
{
@@ -189,6 +202,8 @@ int CAddrMan::ShrinkNew(int nUBucket)
void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
{
+ assert(vvNew[nOrigin].count(nId) == 1);
+
// remove the entry from all new buckets
for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++)
{
@@ -197,6 +212,8 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
}
nNew--;
+ assert(info.nRefCount == 0);
+
// what tried bucket to move the entry to
int nKBucket = info.GetTriedBucket(nKey);
std::vector<int> &vTried = vvTried[nKBucket];
@@ -214,6 +231,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
int nPos = SelectTried(nKBucket);
// find which new bucket it belongs to
+ assert(mapInfo.count(vTried[nPos]) == 1);
int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey);
std::set<int> &vNew = vvNew[nUBucket];
@@ -385,6 +403,7 @@ CAddress CAddrMan::Select_(int nUnkBias)
std::vector<int> &vTried = vvTried[nKBucket];
if (vTried.size() == 0) continue;
int nPos = GetRandInt(vTried.size());
+ assert(mapInfo.count(vTried[nPos]) == 1);
CAddrInfo &info = mapInfo[vTried[nPos]];
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
return info;
@@ -402,6 +421,7 @@ CAddress CAddrMan::Select_(int nUnkBias)
std::set<int>::iterator it = vNew.begin();
while (nPos--)
it++;
+ assert(mapInfo.count(*it) == 1);
CAddrInfo &info = mapInfo[*it];
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
return info;
@@ -481,6 +501,7 @@ void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr)
{
int nRndPos = GetRandInt(vRandom.size() - n) + n;
SwapRandom(n, nRndPos);
+ assert(mapInfo.count(vRandom[n]) == 1);
vAddr.push_back(mapInfo[vRandom[n]]);
}
}
diff --git a/src/addrman.h b/src/addrman.h
index 7652df66ae..43b6d35ed8 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -62,7 +62,7 @@ public:
nRandomPos = -1;
}
- CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn)
+ CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
{
Init();
}
@@ -204,7 +204,7 @@ protected:
CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL);
// Swap two elements in vRandom.
- void SwapRandom(int nRandomPos1, int nRandomPos2);
+ void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
// Return position in given bucket to replace.
int SelectTried(int nKBucket);
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 15bcf1da3d..5c78656fcd 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -44,6 +44,8 @@ static CCriticalSection cs_nWalletUnlockTime;
extern Value dumpprivkey(const Array& params, bool fHelp);
extern Value importprivkey(const Array& params, bool fHelp);
+const Object emptyobj;
+
Object JSONRPCError(int code, const string& message)
{
Object error;
@@ -111,6 +113,33 @@ HexBits(unsigned int nBits)
return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
}
+enum DecomposeMode {
+ DM_NONE = 0,
+ DM_HASH,
+ DM_HEX,
+ DM_ASM,
+ DM_OBJ,
+};
+
+enum DecomposeMode
+FindDecompose(const Object& decompositions, const char* pcType, const char* pcDefault)
+{
+ Value val = find_value(decompositions, pcType);
+ std::string strDecompose = (val.type() == null_type) ? pcDefault : val.get_str();
+
+ if (strDecompose == "no")
+ return DM_NONE;
+ if (strDecompose == "hash")
+ return DM_HASH;
+ if (strDecompose == "hex")
+ return DM_HEX;
+ if (strDecompose == "asm")
+ return DM_ASM;
+ if (strDecompose == "obj")
+ return DM_OBJ;
+ throw JSONRPCError(-18, "Invalid decomposition");
+}
+
void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
{
int confirms = wtx.GetDepthInMainChain();
@@ -126,6 +155,141 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair(item.first, item.second));
}
+void
+ScriptSigToJSON(const CTxIn& txin, Object& out)
+{
+ out.push_back(Pair("asm", txin.scriptSig.ToString()));
+ out.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
+
+ CTransaction txprev;
+ uint256 hashTxprevBlock;
+ if (!GetTransaction(txin.prevout.hash, txprev, hashTxprevBlock))
+ return;
+
+ txnouttype type;
+ vector<CBitcoinAddress> addresses;
+ int nRequired;
+
+ if (!ExtractAddresses(txprev.vout[txin.prevout.n].scriptPubKey, type,
+ addresses, nRequired))
+ {
+ out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
+ return;
+ }
+
+ out.push_back(Pair("type", GetTxnOutputType(type)));
+ if (type == TX_MULTISIG)
+ {
+ // TODO: Need to handle this specially since not all input addresses are required...
+ return;
+ }
+
+ Array a;
+ BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
+ a.push_back(addr.ToString());
+ out.push_back(Pair("addresses", a));
+}
+
+void
+ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
+{
+ txnouttype type;
+ vector<CBitcoinAddress> addresses;
+ int nRequired;
+
+ out.push_back(Pair("asm", scriptPubKey.ToString()));
+ out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
+
+ if (!ExtractAddresses(scriptPubKey, type, addresses, nRequired))
+ {
+ out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
+ return;
+ }
+
+ out.push_back(Pair("reqSigs", nRequired));
+ out.push_back(Pair("type", GetTxnOutputType(type)));
+
+ Array a;
+ BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
+ a.push_back(addr.ToString());
+ out.push_back(Pair("addresses", a));
+}
+
+void TxToJSON(const CTransaction &tx, Object& entry, const Object& decompositions)
+{
+ entry.push_back(Pair("version", tx.nVersion));
+ entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
+ entry.push_back(Pair("size", (boost::int64_t)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
+
+ enum DecomposeMode decomposeScript = FindDecompose(decompositions, "script", "asm");
+
+ Array vin;
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ {
+ Object in;
+ if (tx.IsCoinBase())
+ in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
+ else
+ {
+ Object prevout;
+ prevout.push_back(Pair("hash", txin.prevout.hash.GetHex()));
+ prevout.push_back(Pair("n", (boost::int64_t)txin.prevout.n));
+ in.push_back(Pair("prevout", prevout));
+ switch (decomposeScript) {
+ case DM_NONE:
+ break;
+ case DM_HEX:
+ in.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
+ break;
+ case DM_ASM:
+ in.push_back(Pair("scriptSig", txin.scriptSig.ToString()));
+ break;
+ case DM_OBJ:
+ {
+ Object o;
+ ScriptSigToJSON(txin, o);
+ in.push_back(Pair("scriptSig", o));
+ break;
+ }
+ default:
+ throw JSONRPCError(-18, "Invalid script decomposition");
+ }
+ }
+ in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
+ vin.push_back(in);
+ }
+ entry.push_back(Pair("vin", vin));
+ Array vout;
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ {
+ Object out;
+ out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
+ switch (decomposeScript) {
+ case DM_NONE:
+ break;
+ case DM_HEX:
+ out.push_back(Pair("scriptPubKey", HexStr(txout.scriptPubKey.begin(), txout.scriptPubKey.end())));
+ break;
+ case DM_ASM:
+ out.push_back(Pair("scriptPubKey", txout.scriptPubKey.ToString()));
+ break;
+ case DM_OBJ:
+ {
+ Object o;
+ ScriptPubKeyToJSON(txout.scriptPubKey, o);
+ out.push_back(Pair("scriptPubKey", o));
+ break;
+ }
+ default:
+ throw JSONRPCError(-18, "Invalid script decomposition");
+ }
+ vout.push_back(out);
+ }
+ entry.push_back(Pair("vout", vout));
+}
+
+void AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions);
+
string AccountFromValue(const Value& value)
{
string strAccount = value.get_str();
@@ -134,10 +298,13 @@ string AccountFromValue(const Value& value)
return strAccount;
}
-Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
+Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const Object& decompositions)
{
Object result;
result.push_back(Pair("hash", block.GetHash().GetHex()));
+ CMerkleTx txGen(block.vtx[0]);
+ txGen.SetMerkleBranch(&block);
+ result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
@@ -146,10 +313,38 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
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)
- txhashes.push_back(tx.GetHash().GetHex());
- result.push_back(Pair("tx", txhashes));
+
+ enum DecomposeMode decomposeTxn = FindDecompose(decompositions, "tx", "hash");
+ if (decomposeTxn)
+ {
+ Array txs;
+ switch (decomposeTxn) {
+ case DM_OBJ:
+ BOOST_FOREACH (const CTransaction&tx, block.vtx)
+ {
+ Object entry;
+ AnyTxToJSON(tx.GetHash(), &tx, entry, decompositions);
+ txs.push_back(entry);
+ }
+ break;
+ case DM_HEX:
+ BOOST_FOREACH (const CTransaction&tx, block.vtx)
+ {
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << tx;
+
+ txs.push_back(HexStr(ssTx.begin(), ssTx.end()));
+ }
+ break;
+ case DM_HASH:
+ BOOST_FOREACH (const CTransaction&tx, block.vtx)
+ txs.push_back(tx.GetHash().GetHex());
+ break;
+ default:
+ throw JSONRPCError(-18, "Invalid transaction decomposition");
+ }
+ result.push_back(Pair("tx", txs));
+ }
if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
@@ -160,6 +355,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
+
///
/// Note: This interface may still be subject to change.
///
@@ -999,10 +1195,12 @@ Value addmultisigaddress(const Array& params, bool fHelp)
strAccount = AccountFromValue(params[2]);
// Gather public keys
- if ((nRequired < 1) || ((int)keys.size() < nRequired))
+ if (nRequired < 1)
+ throw runtime_error("a multisignature address must require at least one key to redeem");
+ if ((int)keys.size() < nRequired)
throw runtime_error(
- strprintf("wrong number of keys"
- "(got %d, need at least %d)", keys.size(), nRequired));
+ strprintf("not enough keys supplied "
+ "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
std::vector<CKey> pubkeys;
pubkeys.resize(keys.size());
for (unsigned int i = 0; i < keys.size(); i++)
@@ -1327,7 +1525,7 @@ Value listtransactions(const Array& params, bool fHelp)
if (pacentry != 0)
AcentryToJSON(*pacentry, strAccount, ret);
- if (ret.size() >= (nCount+nFrom)) break;
+ if ((int)ret.size() >= (nCount+nFrom)) break;
}
// ret is newest to oldest
@@ -1462,11 +1660,69 @@ Value listsinceblock(const Array& params, bool fHelp)
return ret;
}
+void
+AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions)
+{
+ if (pwalletMain->mapWallet.count(hash))
+ {
+ const CWalletTx& wtx = pwalletMain->mapWallet[hash];
+
+ TxToJSON(wtx, entry, decompositions);
+
+ int64 nCredit = wtx.GetCredit();
+ int64 nDebit = wtx.GetDebit();
+ int64 nNet = nCredit - nDebit;
+ int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
+
+ entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
+ if (wtx.IsFromMe())
+ entry.push_back(Pair("fee", ValueFromAmount(nFee)));
+
+ WalletTxToJSON(wtx, entry);
+
+ Array details;
+ ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
+ entry.push_back(Pair("details", details));
+ }
+ else
+ {
+ CTransaction tx;
+ uint256 hashBlock = 0;
+ if ((!ptx) && GetTransaction(hash, tx, hashBlock))
+ ptx = &tx;
+ if (ptx)
+ {
+ entry.push_back(Pair("txid", hash.GetHex()));
+ TxToJSON(*ptx, entry, decompositions);
+ if (hashBlock == 0)
+ entry.push_back(Pair("confirmations", 0));
+ else
+ {
+ entry.push_back(Pair("blockhash", hashBlock.GetHex()));
+ map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ if (mi != mapBlockIndex.end() && (*mi).second)
+ {
+ CBlockIndex* pindex = (*mi).second;
+ if (pindex->IsInMainChain())
+ {
+ entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
+ entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
+ }
+ else
+ entry.push_back(Pair("confirmations", 0));
+ }
+ }
+ }
+ else
+ throw JSONRPCError(-5, "No information available about transaction");
+ }
+}
+
Value gettransaction(const Array& params, bool fHelp)
{
- if (fHelp || params.size() != 1)
+ if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "gettransaction <txid>\n"
+ "gettransaction <txid> [decompositions]\n"
"Get detailed information about <txid>");
uint256 hash;
@@ -1474,24 +1730,8 @@ Value gettransaction(const Array& params, bool fHelp)
Object entry;
- if (!pwalletMain->mapWallet.count(hash))
- throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
- const CWalletTx& wtx = pwalletMain->mapWallet[hash];
-
- int64 nCredit = wtx.GetCredit();
- int64 nDebit = wtx.GetDebit();
- int64 nNet = nCredit - nDebit;
- int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
-
- entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
- if (wtx.IsFromMe())
- entry.push_back(Pair("fee", ValueFromAmount(nFee)));
-
- WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
-
- Array details;
- ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
- entry.push_back(Pair("details", details));
+ AnyTxToJSON(hash, NULL, entry,
+ (params.size() > 1) ? params[1].get_obj() : emptyobj);
return entry;
}
@@ -1973,9 +2213,9 @@ Value getblockhash(const Array& params, bool fHelp)
Value getblock(const Array& params, bool fHelp)
{
- if (fHelp || params.size() != 1)
+ if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "getblock <hash>\n"
+ "getblock <hash> [decompositions]\n"
"Returns details of a block with given block-hash.");
std::string strHash = params[0].get_str();
@@ -1988,7 +2228,8 @@ Value getblock(const Array& params, bool fHelp)
CBlockIndex* pblockindex = mapBlockIndex[hash];
block.ReadFromDisk(pblockindex, true);
- return blockToJSON(block, pblockindex);
+ return blockToJSON(block, pblockindex,
+ (params.size() > 1) ? params[1].get_obj() : emptyobj);
}
@@ -2505,34 +2746,11 @@ void ThreadRPCServer2(void* parg)
else
throw JSONRPCError(-32600, "Params must be an array");
- // Find method
- const CRPCCommand *pcmd = tableRPC[strMethod];
- if (!pcmd)
- throw JSONRPCError(-32601, "Method not found");
-
- // Observe safe mode
- string strWarning = GetWarnings("rpc");
- if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
- !pcmd->okSafeMode)
- throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
+ Value result = tableRPC.execute(strMethod, params);
- try
- {
- // Execute
- Value result;
- {
- LOCK2(cs_main, pwalletMain->cs_wallet);
- result = pcmd->actor(params, false);
- }
-
- // Send reply
- string strReply = JSONRPCReply(result, Value::null, id);
- stream << HTTPReply(200, strReply) << std::flush;
- }
- catch (std::exception& e)
- {
- ErrorReply(stream, JSONRPCError(-1, e.what()), id);
- }
+ // Send reply
+ string strReply = JSONRPCReply(result, Value::null, id);
+ stream << HTTPReply(200, strReply) << std::flush;
}
catch (Object& objError)
{
@@ -2545,7 +2763,34 @@ void ThreadRPCServer2(void* parg)
}
}
+json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array &params) const
+{
+ // Find method
+ const CRPCCommand *pcmd = tableRPC[strMethod];
+ if (!pcmd)
+ throw JSONRPCError(-32601, "Method not found");
+ // Observe safe mode
+ string strWarning = GetWarnings("rpc");
+ if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
+ !pcmd->okSafeMode)
+ throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
+
+ try
+ {
+ // Execute
+ Value result;
+ {
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+ result = pcmd->actor(params, false);
+ }
+ return result;
+ }
+ catch (std::exception& e)
+ {
+ throw JSONRPCError(-1, e.what());
+ }
+}
Object CallRPC(const string& strMethod, const Array& params)
@@ -2619,6 +2864,62 @@ void ConvertTo(Value& value)
}
}
+// Convert strings to command-specific RPC representation
+Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
+{
+ Array params;
+ BOOST_FOREACH(const std::string &param, strParams)
+ params.push_back(param);
+
+ int n = params.size();
+
+ //
+ // Special case non-string parameter types
+ //
+ if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
+ if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
+ if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
+ if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
+ if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
+ if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "getblock" && n > 1) ConvertTo<Object>(params[1]);
+ if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "gettransaction" && n > 1) ConvertTo<Object>(params[1]);
+ if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
+ if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
+ if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
+ if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
+ if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
+ if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "sendmany" && n > 1)
+ {
+ string s = params[1].get_str();
+ Value v;
+ if (!read_string(s, v) || v.type() != obj_type)
+ throw runtime_error("type mismatch");
+ params[1] = v.get_obj();
+ }
+ if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
+ if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "addmultisigaddress" && n > 1)
+ {
+ string s = params[1].get_str();
+ Value v;
+ if (!read_string(s, v) || v.type() != array_type)
+ throw runtime_error("type mismatch "+s);
+ params[1] = v.get_array();
+ }
+ return params;
+}
+
int CommandLineRPC(int argc, char *argv[])
{
string strPrint;
@@ -2638,53 +2939,8 @@ int CommandLineRPC(int argc, char *argv[])
string strMethod = argv[1];
// Parameters default to strings
- Array params;
- for (int i = 2; i < argc; i++)
- params.push_back(argv[i]);
- int n = params.size();
-
- //
- // Special case non-string parameter types
- //
- if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
- if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
- if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
- if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
- if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
- if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
- if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
- if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
- if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
- if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
- if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
- if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
- if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
- if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
- if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
- if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
- if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
- if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
- if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
- if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
- if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
- if (strMethod == "sendmany" && n > 1)
- {
- string s = params[1].get_str();
- Value v;
- if (!read_string(s, v) || v.type() != obj_type)
- throw runtime_error("type mismatch");
- params[1] = v.get_obj();
- }
- if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
- if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
- if (strMethod == "addmultisigaddress" && n > 1)
- {
- string s = params[1].get_str();
- Value v;
- if (!read_string(s, v) || v.type() != array_type)
- throw runtime_error("type mismatch "+s);
- params[1] = v.get_array();
- }
+ std::vector<std::string> strParams(&argv[2], &argv[argc]);
+ Array params = RPCConvertValues(strMethod, strParams);
// Execute
Object reply = CallRPC(strMethod, params);
diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
index 6b7293ed19..dd18a504f3 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -16,6 +16,9 @@
void ThreadRPCServer(void* parg);
int CommandLineRPC(int argc, char *argv[]);
+/** Convert parameter values for RPC call from strings to command-specific JSON objects. */
+json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams);
+
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
class CRPCCommand
@@ -26,6 +29,9 @@ public:
bool okSafeMode;
};
+/**
+ * Bitcoin RPC command dispatcher.
+ */
class CRPCTable
{
private:
@@ -34,6 +40,15 @@ public:
CRPCTable();
const CRPCCommand* operator[](std::string name) const;
std::string help(std::string name) const;
+
+ /**
+ * Execute a method.
+ * @param method Method to execute
+ * @param params Array of arguments (JSON objects)
+ * @returns Result of the call.
+ * @throws an exception (json_spirit::Value) when an error happens.
+ */
+ json_spirit::Value execute(const std::string &method, const json_spirit::Array &params) const;
};
extern const CRPCTable tableRPC;
diff --git a/src/db.cpp b/src/db.cpp
index 12647e568a..5bd0528202 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -613,7 +613,7 @@ bool CTxDB::LoadBlockIndex()
map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
{
- if (pindex->nHeight < nBestHeight-nCheckDepth)
+ if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth)
break;
CBlock block;
if (!block.ReadFromDisk(pindex))
@@ -715,7 +715,7 @@ bool CTxDB::LoadBlockIndex()
}
}
}
- if (pindexFork)
+ if (pindexFork && !fRequestShutdown)
{
// Reorg back to the fork
printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight);
diff --git a/src/init.cpp b/src/init.cpp
index 3fe6d1b091..60927f20b3 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -178,12 +178,17 @@ bool AppInit2(int argc, char* argv[])
" -dbcache=<n> \t\t " + _("Set database cache size in megabytes (default: 25)") + "\n" +
" -dblogsize=<n> \t\t " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" +
- " -proxy=<ip:port> \t " + _("Connect through socks4 proxy") + "\n" +
- " -dns \t " + _("Allow DNS lookups for addnode and connect") + "\n" +
+ " -proxy=<ip:port> \t " + _("Connect through socks proxy") + "\n" +
+ " -socks=<n> \t " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" +
+ " -dns \t " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
+ " -proxydns \t " + _("Pass DNS requests to (SOCKS5) proxy") + "\n" +
" -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
" -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
" -addnode=<ip> \t " + _("Add a node to connect to and attempt to keep the connection open") + "\n" +
" -connect=<ip> \t\t " + _("Connect only to the specified node") + "\n" +
+ " -seednode=<ip> \t\t " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" +
+ " -externalip=<ip> \t " + _("Specify your own public address") + "\n" +
+ " -discover \t " + _("Try to discover public IP address (default: 1)") + "\n" +
" -irc \t " + _("Find peers using internet relay chat (default: 0)") + "\n" +
" -listen \t " + _("Accept connections from outside (default: 1)") + "\n" +
#ifdef QT_GUI
@@ -226,7 +231,8 @@ bool AppInit2(int argc, char* argv[])
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)") + "\n" +
" -rescan \t " + _("Rescan the block chain for missing wallet transactions") + "\n" +
" -checkblocks=<n> \t\t " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
- " -checklevel=<n> \t\t " + _("How thorough the block verification is (0-6, default: 1)") + "\n";
+ " -checklevel=<n> \t\t " + _("How thorough the block verification is (0-6, default: 1)") + "\n" +
+ " -loadblock=<file>\t " + _("Imports blocks from external blk000?.dat file") + "\n";
strUsage += string() +
_("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" +
@@ -367,6 +373,16 @@ bool AppInit2(int argc, char* argv[])
}
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ if (mapArgs.count("-loadblock"))
+ {
+ BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"])
+ {
+ FILE *file = fopen(strFile.c_str(), "rb");
+ if (file)
+ LoadExternalBlockFile(file);
+ }
+ }
+
InitMessage(_("Loading wallet..."));
printf("Loading wallet...\n");
nStart = GetTimeMillis();
@@ -516,6 +532,9 @@ bool AppInit2(int argc, char* argv[])
}
}
+ if (mapArgs.count("-connect"))
+ SoftSetBoolArg("-dnsseed", false);
+
bool fTor = (fUseProxy && addrProxy.GetPort() == 9050);
if (fTor)
{
@@ -523,13 +542,20 @@ bool AppInit2(int argc, char* argv[])
// Note: the GetBoolArg() calls for all of these must happen later.
SoftSetBoolArg("-listen", false);
SoftSetBoolArg("-irc", false);
- SoftSetBoolArg("-dnsseed", false);
+ SoftSetBoolArg("-proxydns", true);
SoftSetBoolArg("-upnp", false);
- SoftSetBoolArg("-dns", false);
+ SoftSetBoolArg("-discover", false);
}
- fAllowDNS = GetBoolArg("-dns");
+ fNameLookup = GetBoolArg("-dns");
+ fProxyNameLookup = GetBoolArg("-proxydns");
+ if (fProxyNameLookup)
+ fNameLookup = true;
fNoListen = !GetBoolArg("-listen", true);
+ nSocksVersion = GetArg("-socks", 5);
+
+ BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"])
+ AddOneShot(strDest);
// Continue to put "/P2SH/" in the coinbase to monitor
// BIP16 support.
@@ -547,15 +573,10 @@ bool AppInit2(int argc, char* argv[])
}
}
- if (mapArgs.count("-addnode"))
+ if (mapArgs.count("-externalip"))
{
- BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
- {
- CAddress addr(CService(strAddr, GetDefaultPort(), fAllowDNS));
- addr.nTime = 0; // so it won't relay unless successfully connected
- if (addr.IsValid())
- addrman.Add(addr, CNetAddr("127.0.0.1"));
- }
+ BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"])
+ AddLocal(CNetAddr(strAddr, fNameLookup), LOCAL_MANUAL);
}
if (mapArgs.count("-paytxfee"))
diff --git a/src/init.h b/src/init.h
index e3971c85e3..0a2f0d8932 100644
--- a/src/init.h
+++ b/src/init.h
@@ -13,7 +13,4 @@ void Shutdown(void* parg);
bool AppInit(int argc, char* argv[]);
bool AppInit2(int argc, char* argv[]);
-bool GetStartOnSystemStartup();
-bool SetStartOnSystemStartup(bool fAutoStart);
-
#endif
diff --git a/src/irc.cpp b/src/irc.cpp
index 237497055d..f20152495e 100644
--- a/src/irc.cpp
+++ b/src/irc.cpp
@@ -12,7 +12,6 @@ using namespace std;
using namespace boost;
int nGotIRCAddresses = 0;
-bool fGotExternalIP = false;
void ThreadIRCSeed2(void* parg);
@@ -216,7 +215,6 @@ void ThreadIRCSeed2(void* parg)
printf("ThreadIRCSeed started\n");
int nErrorWait = 10;
int nRetryWait = 10;
- bool fNameInUse = false;
while (!fShutdown)
{
@@ -248,9 +246,10 @@ void ThreadIRCSeed2(void* parg)
return;
}
+ CNetAddr addrLocal;
string strMyName;
- if (addrLocalHost.IsRoutable() && !fUseProxy && !fNameInUse)
- strMyName = EncodeAddress(addrLocalHost);
+ if (GetLocal(addrLocal, &addrConnect))
+ strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
else
strMyName = strprintf("x%u", GetRand(1000000000));
@@ -265,7 +264,6 @@ void ThreadIRCSeed2(void* parg)
if (nRet == 2)
{
printf("IRC name already in use\n");
- fNameInUse = true;
Wait(10);
continue;
}
@@ -285,9 +283,8 @@ void ThreadIRCSeed2(void* parg)
if (!fUseProxy && addrFromIRC.IsRoutable())
{
// IRC lets you to re-nick
- fGotExternalIP = true;
- addrLocalHost.SetIP(addrFromIRC);
- strMyName = EncodeAddress(addrLocalHost);
+ AddLocal(addrFromIRC, LOCAL_IRC);
+ strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
}
}
diff --git a/src/irc.h b/src/irc.h
index 08d62b83d2..a6073199ec 100644
--- a/src/irc.h
+++ b/src/irc.h
@@ -8,6 +8,5 @@
void ThreadIRCSeed(void* parg);
extern int nGotIRCAddresses;
-extern bool fGotExternalIP;
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 427e435a90..b0ed28aa14 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -740,7 +740,31 @@ int CTxIndex::GetDepthInMainChain() const
return 1 + nBestHeight - pindex->nHeight;
}
-
+// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
+bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock)
+{
+ {
+ LOCK(cs_main);
+ {
+ LOCK(mempool.cs);
+ if (mempool.exists(hash))
+ {
+ tx = mempool.lookup(hash);
+ return true;
+ }
+ }
+ CTxDB txdb("r");
+ CTxIndex txindex;
+ if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex))
+ {
+ CBlock block;
+ if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
+ hashBlock = block.GetHash();
+ return true;
+ }
+ }
+ return false;
+}
@@ -1836,7 +1860,7 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode)
{
- if (nFile == -1)
+ if ((nFile < 1) || (nFile == (unsigned int) -1))
return NULL;
FILE* file = fopen((GetDataDir() / strprintf("blk%04d.dat", nFile)).string().c_str(), pszMode);
if (!file)
@@ -2028,6 +2052,62 @@ void PrintBlockTree()
}
}
+bool LoadExternalBlockFile(FILE* fileIn)
+{
+ int nLoaded = 0;
+ {
+ LOCK(cs_main);
+ try {
+ CAutoFile blkdat(fileIn, SER_DISK, CLIENT_VERSION);
+ unsigned int nPos = 0;
+ while (nPos != (unsigned int)-1 && blkdat.good() && !fRequestShutdown)
+ {
+ unsigned char pchData[65536];
+ do {
+ fseek(blkdat, nPos, SEEK_SET);
+ int nRead = fread(pchData, 1, sizeof(pchData), blkdat);
+ if (nRead <= 8)
+ {
+ nPos = (unsigned int)-1;
+ break;
+ }
+ void* nFind = memchr(pchData, pchMessageStart[0], nRead+1-sizeof(pchMessageStart));
+ if (nFind)
+ {
+ if (memcmp(nFind, pchMessageStart, sizeof(pchMessageStart))==0)
+ {
+ nPos += ((unsigned char*)nFind - pchData) + sizeof(pchMessageStart);
+ break;
+ }
+ nPos += ((unsigned char*)nFind - pchData) + 1;
+ }
+ else
+ nPos += sizeof(pchData) - sizeof(pchMessageStart) + 1;
+ } while(!fRequestShutdown);
+ if (nPos == (unsigned int)-1)
+ break;
+ fseek(blkdat, nPos, SEEK_SET);
+ unsigned int nSize;
+ blkdat >> nSize;
+ if (nSize > 0 && nSize <= MAX_BLOCK_SIZE)
+ {
+ CBlock block;
+ blkdat >> block;
+ if (ProcessBlock(NULL,&block))
+ {
+ nLoaded++;
+ nPos += 4 + nSize;
+ }
+ }
+ }
+ }
+ catch (std::exception &e)
+ {
+ }
+ }
+ printf("Loaded %i blocks from external file\n", nLoaded);
+ return nLoaded > 0;
+}
@@ -2232,6 +2312,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (!vRecv.empty())
vRecv >> pfrom->nStartingHeight;
+ if (pfrom->fInbound && addrMe.IsRoutable())
+ {
+ pfrom->addrLocal = addrMe;
+ SeenLocal(addrMe);
+ }
+
// Disconnect if we connected to ourself
if (nNonce == nLocalHostNonce && nNonce > 1)
{
@@ -2255,16 +2341,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (!pfrom->fInbound)
{
// Advertise our address
- if (!fNoListen && !fUseProxy && addrLocalHost.IsRoutable() &&
- !IsInitialBlockDownload())
+ if (!fNoListen && !fUseProxy && !IsInitialBlockDownload())
{
- CAddress addr(addrLocalHost);
- addr.nTime = GetAdjustedTime();
- pfrom->PushAddress(addr);
+ CAddress addr = GetLocalAddress(&pfrom->addr);
+ if (addr.IsRoutable())
+ pfrom->PushAddress(addr);
}
// Get recent addresses
- if (pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000)
+ if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000)
{
pfrom->PushMessage("getaddr");
pfrom->fGetAddr = true;
@@ -2280,7 +2365,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Ask the first connected node for block updates
static int nAskedForBlocks = 0;
- if (!pfrom->fClient &&
+ if (!pfrom->fClient && !pfrom->fOneShot &&
(pfrom->nVersion < NOBLKS_VERSION_START ||
pfrom->nVersion >= NOBLKS_VERSION_END) &&
(nAskedForBlocks < 1 || vNodes.size() <= 1))
@@ -2378,6 +2463,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
addrman.Add(vAddr, pfrom->addr, 2 * 60 * 60);
if (vAddr.size() < 1000)
pfrom->fGetAddr = false;
+ if (pfrom->fOneShot)
+ pfrom->fDisconnect = true;
}
@@ -2391,6 +2478,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return error("message inv size() = %d", vInv.size());
}
+ // find last block in inv vector
+ unsigned int nLastBlock = (unsigned int)(-1);
+ for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
+ if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK)
+ nLastBlock = vInv.size() - 1 - nInv;
+ }
CTxDB txdb("r");
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
{
@@ -2407,9 +2500,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Always request the last block in an inv bundle (even if we already have it), as it is the
// trigger for the other side to send further invs. If we are stuck on a (very long) side chain,
// this is necessary to connect earlier received orphan blocks to the chain again.
- if (!fAlreadyHave || (inv.type == MSG_BLOCK && nInv==vInv.size()-1))
+ if (fAlreadyHave && nInv == nLastBlock) {
+ // bypass mapAskFor, and send request directly; it must go through.
+ std::vector<CInv> vGetData(1,inv);
+ pfrom->PushMessage("getdata", vGetData);
+ }
+
+ if (!fAlreadyHave)
pfrom->AskFor(inv);
- if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
+ else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
// Track requests for our stuff
@@ -2887,11 +2986,11 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pnode->setAddrKnown.clear();
// Rebroadcast our address
- if (!fNoListen && !fUseProxy && addrLocalHost.IsRoutable())
+ if (!fNoListen && !fUseProxy)
{
- CAddress addr(addrLocalHost);
- addr.nTime = GetAdjustedTime();
- pnode->PushAddress(addr);
+ CAddress addr = GetLocalAddress(&pnode->addr);
+ if (addr.IsRoutable())
+ pnode->PushAddress(addr);
}
}
}
@@ -3188,7 +3287,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
dPriority += (double)nValueIn * nConf;
if (fDebug && GetBoolArg("-printpriority"))
- printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
+ printf("priority nValueIn=%-12"PRI64d" nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
}
// Priority is sum(valuein * age) / txsize
diff --git a/src/main.h b/src/main.h
index 262e77e806..194d9fdc66 100644
--- a/src/main.h
+++ b/src/main.h
@@ -36,7 +36,7 @@ static const int64 MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
static const int COINBASE_MATURITY = 100;
// Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
-static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
+static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
#ifdef USE_UPNP
static const int fHaveUPnP = true;
#else
@@ -69,6 +69,7 @@ extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
extern CCriticalSection cs_setpwalletRegistered;
extern std::set<CWallet*> setpwalletRegistered;
+extern unsigned char pchMessageStart[4];
// Settings
extern int64 nTransactionFee;
@@ -91,6 +92,7 @@ bool LoadBlockIndex(bool fAllowNew=true);
void PrintBlockTree();
bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
+bool LoadExternalBlockFile(FILE* fileIn);
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
CBlock* CreateNewBlock(CReserveKey& reservekey);
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
@@ -101,7 +103,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
int GetNumBlocksOfPeers();
bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor);
-
+bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock);
@@ -136,8 +138,8 @@ public:
}
IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
- void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }
- bool IsNull() const { return (nFile == -1); }
+ void SetNull() { nFile = (unsigned int) -1; nBlockPos = 0; nTxPos = 0; }
+ bool IsNull() const { return (nFile == (unsigned int) -1); }
friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)
{
@@ -176,8 +178,8 @@ public:
CInPoint() { SetNull(); }
CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
- void SetNull() { ptx = NULL; n = -1; }
- bool IsNull() const { return (ptx == NULL && n == -1); }
+ void SetNull() { ptx = NULL; n = (unsigned int) -1; }
+ bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
};
@@ -192,8 +194,8 @@ public:
COutPoint() { SetNull(); }
COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
- void SetNull() { hash = 0; n = -1; }
- bool IsNull() const { return (hash == 0 && n == -1); }
+ void SetNull() { hash = 0; n = (unsigned int) -1; }
+ bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); }
friend bool operator<(const COutPoint& a, const COutPoint& b)
{
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index 81934187e2..645f0a16e4 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -29,7 +29,7 @@ LIBS= \
DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB
DEBUGFLAGS=-g
-CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
+CFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 917eb12fcf..bb6466954f 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -25,7 +25,7 @@ LIBS= \
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB
DEBUGFLAGS=-g
-CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
+CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
diff --git a/src/makefile.osx b/src/makefile.osx
index be95aab446..eb9ae4ba7f 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -65,7 +65,7 @@ CFLAGS = -g
endif
# ppc doesn't work because we don't support big-endian
-CFLAGS += -Wextra -Wno-sign-compare -Wno-invalid-offsetof -Wformat-security \
+CFLAGS += -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
$(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
OBJS= \
diff --git a/src/makefile.unix b/src/makefile.unix
index 90be398976..53fb1f0b8d 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -82,9 +82,8 @@ LIBS+= \
DEBUGFLAGS=-g
-CXXFLAGS=-O2
-xCXXFLAGS=-pthread -Wall -Wextra -Wno-sign-compare -Wno-invalid-offsetof -Wno-unused-parameter -Wformat -Wformat-security \
- $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
+CXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
+ $(DEBUGFLAGS) $(DEFS) $(HARDENING)
OBJS= \
obj/version.o \
@@ -121,26 +120,26 @@ version.cpp: obj/build.h
DEFS += -DHAVE_BUILD_INFO
obj/%.o: %.cpp
- $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $<
+ $(CXX) -c $(CXXFLAGS) -MMD -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
bitcoind: $(OBJS:obj/%=obj/%)
- $(CXX) $(xCXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
+ $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
obj-test/%.o: test/%.cpp
- $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -o $@ $<
+ $(CXX) -c $(TESTDEFS) $(CXXFLAGS) -MMD -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
- $(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
+ $(CXX) $(CXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
clean:
-rm -f bitcoind test_bitcoin
diff --git a/src/net.cpp b/src/net.cpp
index 92b4a3173f..8603514f91 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -35,7 +35,7 @@ void ThreadOpenAddedConnections2(void* parg);
void ThreadMapPort2(void* parg);
#endif
void ThreadDNSAddressSeed2(void* parg);
-bool OpenNetworkConnection(const CAddress& addrConnect);
+bool OpenNetworkConnection(const CAddress& addrConnect, const char *strDest = NULL, bool fOneShot = false);
@@ -43,10 +43,10 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
// Global state variables
//
bool fClient = false;
-bool fAllowDNS = false;
static bool fUseUPnP = false;
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
-CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices);
+CCriticalSection cs_mapLocalHost;
+map<CNetAddr, int> mapLocalHost;
static CNode* pnodeLocalHost = NULL;
uint64 nLocalHostNonce = 0;
array<int, THREAD_MAX> vnThreadsRunning;
@@ -60,6 +60,8 @@ deque<pair<int64, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay;
map<CInv, int64> mapAlreadyAskedFor;
+static deque<string> vOneShots;
+CCriticalSection cs_vOneShots;
set<CNetAddr> setservAddNodeAddresses;
CCriticalSection cs_setservAddNodeAddresses;
@@ -69,6 +71,12 @@ static int nOutbound = 0;
static CConditionVariable condOutbound;
+void AddOneShot(string strDest)
+{
+ LOCK(cs_vOneShots);
+ vOneShots.push_back(strDest);
+}
+
unsigned short GetListenPort()
{
return (unsigned short)(GetArg("-port", GetDefaultPort()));
@@ -85,7 +93,45 @@ void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
}
+// find 'best' local address for a particular peer
+bool GetLocal(CNetAddr& addr, const CNetAddr *paddrPeer)
+{
+ if (fUseProxy || mapArgs.count("-connect") || fNoListen)
+ return false;
+ int nBestCount = -1;
+ int nBestReachability = -1;
+ {
+ LOCK(cs_mapLocalHost);
+ for (map<CNetAddr, int>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
+ {
+ int nCount = (*it).second;
+ int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
+ if (nReachability > nBestReachability || (nReachability == nBestReachability && nCount > nBestCount))
+ {
+ addr = (*it).first;
+ nBestReachability = nReachability;
+ nBestCount = nCount;
+ }
+ }
+ }
+ return nBestCount >= 0;
+}
+
+// get best local address for a particular peer as a CAddress
+CAddress GetLocalAddress(const CNetAddr *paddrPeer)
+{
+ CAddress ret(CService("0.0.0.0",0),0);
+ CNetAddr addr;
+ if (GetLocal(addr, paddrPeer))
+ {
+ ret.SetIP(addr);
+ ret.SetPort(GetListenPort());
+ ret.nServices = nLocalServices;
+ ret.nTime = GetAdjustedTime();
+ }
+ return ret;
+}
bool RecvLine(SOCKET hSocket, string& strLine)
{
@@ -138,6 +184,64 @@ bool RecvLine(SOCKET hSocket, string& strLine)
}
}
+// used when scores of local addresses may have changed
+// pushes better local address to peers
+void static AdvertizeLocal()
+{
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ {
+ if (pnode->fSuccessfullyConnected)
+ {
+ CAddress addrLocal = GetLocalAddress(&pnode->addr);
+ if (addrLocal.IsRoutable() && (CNetAddr)addrLocal != (CNetAddr)pnode->addrLocal)
+ {
+ pnode->PushAddress(addrLocal);
+ pnode->addrLocal = addrLocal;
+ }
+ }
+ }
+}
+
+// learn a new local address
+bool AddLocal(const CNetAddr& addr, int nScore)
+{
+ if (!addr.IsRoutable())
+ return false;
+
+ printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
+
+ {
+ LOCK(cs_mapLocalHost);
+ mapLocalHost[addr] = std::max(nScore, mapLocalHost[addr]) + (mapLocalHost.count(addr) ? 1 : 0);
+ }
+
+ AdvertizeLocal();
+
+ return true;
+}
+
+// vote for a local address
+bool SeenLocal(const CNetAddr& addr)
+{
+ {
+ LOCK(cs_mapLocalHost);
+ if (mapLocalHost.count(addr) == 0)
+ return false;
+ mapLocalHost[addr]++;
+ }
+
+ AdvertizeLocal();
+
+ return true;
+}
+
+// check whether a given address is potentially local
+bool IsLocal(const CNetAddr& addr)
+{
+ LOCK(cs_mapLocalHost);
+ return mapLocalHost.count(addr) > 0;
+}
bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
@@ -251,33 +355,11 @@ bool GetMyExternalIP(CNetAddr& ipRet)
void ThreadGetMyExternalIP(void* parg)
{
- // Wait for IRC to get it first
- if (GetBoolArg("-irc", false))
- {
- for (int i = 0; i < 2 * 60; i++)
- {
- Sleep(1000);
- if (fGotExternalIP || fShutdown)
- return;
- }
- }
-
- // Fallback in case IRC fails to get it
+ CNetAddr addrLocalHost;
if (GetMyExternalIP(addrLocalHost))
{
printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
- if (addrLocalHost.IsRoutable())
- {
- // If we already connected to a few before we had our IP, go back and addr them.
- // setAddrKnown automatically filters any duplicate sends.
- CAddress addr(addrLocalHost);
- addr.nTime = GetAdjustedTime();
- {
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- pnode->PushAddress(addr);
- }
- }
+ AddLocal(addrLocalHost, LOCAL_HTTP);
}
}
@@ -307,6 +389,15 @@ CNode* FindNode(const CNetAddr& ip)
return NULL;
}
+CNode* FindNode(std::string addrName)
+{
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ if (pnode->addrName == addrName)
+ return (pnode);
+ return NULL;
+}
+
CNode* FindNode(const CService& addr)
{
{
@@ -318,35 +409,38 @@ CNode* FindNode(const CService& addr)
return NULL;
}
-CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
+CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64 nTimeout)
{
- if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost)
- return NULL;
+ if (pszDest == NULL) {
+ if (IsLocal(addrConnect))
+ return NULL;
- // Look for an existing connection
- CNode* pnode = FindNode((CService)addrConnect);
- if (pnode)
- {
- if (nTimeout != 0)
- pnode->AddRef(nTimeout);
- else
- pnode->AddRef();
- return pnode;
+ // Look for an existing connection
+ CNode* pnode = FindNode((CService)addrConnect);
+ if (pnode)
+ {
+ if (nTimeout != 0)
+ pnode->AddRef(nTimeout);
+ else
+ pnode->AddRef();
+ return pnode;
+ }
}
+
/// debug print
printf("trying connection %s lastseen=%.1fhrs\n",
- addrConnect.ToString().c_str(),
- (double)(addrConnect.nTime - GetAdjustedTime())/3600.0);
-
- addrman.Attempt(addrConnect);
+ pszDest ? pszDest : addrConnect.ToString().c_str(),
+ pszDest ? 0 : (double)(addrConnect.nTime - GetAdjustedTime())/3600.0);
// Connect
SOCKET hSocket;
- if (ConnectSocket(addrConnect, hSocket))
+ if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
{
+ addrman.Attempt(addrConnect);
+
/// debug print
- printf("connected %s\n", addrConnect.ToString().c_str());
+ printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
// Set to nonblocking
#ifdef WIN32
@@ -359,11 +453,12 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
#endif
// Add node
- CNode* pnode = new CNode(hSocket, addrConnect, false);
+ CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
if (nTimeout != 0)
pnode->AddRef(nTimeout);
else
pnode->AddRef();
+
{
LOCK(cs_vNodes);
vNodes.push_back(pnode);
@@ -389,7 +484,7 @@ void CNode::CloseSocketDisconnect()
{
if (fDebug)
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
- printf("disconnecting node %s\n", addr.ToString().c_str());
+ printf("disconnecting node %s\n", addrName.c_str());
closesocket(hSocket);
hSocket = INVALID_SOCKET;
vRecv.clear();
@@ -406,7 +501,7 @@ void CNode::PushVersion()
/// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
CAddress addrYou = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addr);
- CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress(CService("0.0.0.0",0)) : addrLocalHost);
+ CAddress addrMe = GetLocalAddress(&addr);
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
@@ -444,7 +539,7 @@ bool CNode::Misbehaving(int howmuch)
{
if (addr.IsLocal())
{
- printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
+ printf("Warning: local node %s misbehaving\n", addrName.c_str());
return false;
}
@@ -458,7 +553,7 @@ bool CNode::Misbehaving(int howmuch)
setBanned[addr] = banTime;
}
CloseSocketDisconnect();
- printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
+ printf("Disconnected %s for misbehavior (score=%d)\n", addrName.c_str(), nMisbehavior);
return true;
}
return false;
@@ -621,7 +716,7 @@ void ThreadSocketHandler2(void* parg)
if (nSelect == SOCKET_ERROR)
{
int nErr = WSAGetLastError();
- if (hSocketMax > -1)
+ if (hSocketMax != INVALID_SOCKET)
{
printf("socket select error %d\n", nErr);
for (unsigned int i = 0; i <= hSocketMax; i++)
@@ -675,7 +770,7 @@ void ThreadSocketHandler2(void* parg)
else
{
printf("accepted connection %s\n", addr.ToString().c_str());
- CNode* pnode = new CNode(hSocket, addr, true);
+ CNode* pnode = new CNode(hSocket, addr, "", true);
pnode->AddRef();
{
LOCK(cs_vNodes);
@@ -878,8 +973,7 @@ void ThreadMapPort2(void* parg)
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
if (r == 1)
{
- if (!addrLocalHost.IsRoutable())
- {
+ if (GetBoolArg("-discover", true)) {
char externalIPAddress[40];
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS)
@@ -889,9 +983,7 @@ void ThreadMapPort2(void* parg)
if(externalIPAddress[0])
{
printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
- CAddress addrExternalFromUPnP(CService(externalIPAddress, 0), nLocalServices);
- if (addrExternalFromUPnP.IsRoutable())
- addrLocalHost = addrExternalFromUPnP;
+ AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
}
else
printf("UPnP: GetExternalIPAddress failed.\n");
@@ -1025,20 +1117,24 @@ void ThreadDNSAddressSeed2(void* parg)
printf("Loading addresses from DNS seeds (could take a while)\n");
for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
- vector<CNetAddr> vaddr;
- vector<CAddress> vAdd;
- if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
- {
- BOOST_FOREACH(CNetAddr& ip, vaddr)
+ if (fProxyNameLookup) {
+ AddOneShot(strDNSSeed[seed_idx][1]);
+ } else {
+ vector<CNetAddr> vaddr;
+ vector<CAddress> vAdd;
+ if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
{
- int nOneDay = 24*3600;
- CAddress addr = CAddress(CService(ip, GetDefaultPort()));
- addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
- vAdd.push_back(addr);
- found++;
+ BOOST_FOREACH(CNetAddr& ip, vaddr)
+ {
+ int nOneDay = 24*3600;
+ CAddress addr = CAddress(CService(ip, GetDefaultPort()));
+ addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
+ vAdd.push_back(addr);
+ found++;
+ }
}
+ addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
}
- addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
}
}
@@ -1188,6 +1284,21 @@ void ThreadOpenConnections(void* parg)
printf("ThreadOpenConnections exiting\n");
}
+void static ProcessOneShot()
+{
+ string strDest;
+ {
+ LOCK(cs_vOneShots);
+ if (vOneShots.empty())
+ return;
+ strDest = vOneShots.front();
+ vOneShots.pop_front();
+ }
+ CAddress addr;
+ if (!OpenNetworkConnection(addr, strDest.c_str(), true))
+ AddOneShot(strDest);
+}
+
void ThreadOpenConnections2(void* parg)
{
printf("ThreadOpenConnections started\n");
@@ -1197,11 +1308,11 @@ void ThreadOpenConnections2(void* parg)
{
for (int64 nLoop = 0;; nLoop++)
{
+ ProcessOneShot();
BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
{
- CAddress addr(CService(strAddr, GetDefaultPort(), fAllowDNS));
- if (addr.IsValid())
- OpenNetworkConnection(addr);
+ CAddress addr;
+ OpenNetworkConnection(addr, strAddr.c_str());
for (int i = 0; i < 10 && i < nLoop; i++)
{
Sleep(500);
@@ -1216,6 +1327,8 @@ void ThreadOpenConnections2(void* parg)
int64 nStart = GetTime();
loop
{
+ ProcessOneShot();
+
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(500);
vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
@@ -1277,7 +1390,7 @@ void ThreadOpenConnections2(void* parg)
CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
// if we selected an invalid address, restart
- if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()) || addr == addrLocalHost)
+ if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
break;
nTries++;
@@ -1325,11 +1438,25 @@ void ThreadOpenAddedConnections2(void* parg)
if (mapArgs.count("-addnode") == 0)
return;
+ if (fProxyNameLookup) {
+ while(!fShutdown) {
+ BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) {
+ CAddress addr;
+ OpenNetworkConnection(addr, strAddNode.c_str());
+ Sleep(500);
+ }
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
+ Sleep(120000); // Retry every 2 minutes
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
+ }
+ return;
+ }
+
vector<vector<CService> > vservAddressesToAdd(0);
BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])
{
vector<CService> vservNode(0);
- if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
+ if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
{
vservAddressesToAdd.push_back(vservNode);
{
@@ -1343,7 +1470,7 @@ void ThreadOpenAddedConnections2(void* parg)
{
vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
// Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
- // (keeping in mind that addnode entries can have many IPs if fAllowDNS)
+ // (keeping in mind that addnode entries can have many IPs if fNameLookup)
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
@@ -1373,25 +1500,31 @@ void ThreadOpenAddedConnections2(void* parg)
}
}
-bool OpenNetworkConnection(const CAddress& addrConnect)
+bool OpenNetworkConnection(const CAddress& addrConnect, const char *strDest, bool fOneShot)
{
//
// Initiate outbound network connection
//
if (fShutdown)
return false;
- if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost || !addrConnect.IsIPv4() ||
- FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
+ if (!strDest)
+ if (IsLocal(addrConnect) ||
+ FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
+ FindNode(addrConnect.ToStringIPPort().c_str()))
+ return false;
+ if (strDest && FindNode(strDest))
return false;
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
- CNode* pnode = ConnectNode(addrConnect);
+ CNode* pnode = ConnectNode(addrConnect, strDest);
vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown)
return false;
if (!pnode)
return false;
pnode->fNetworkNode = true;
+ if (fOneShot)
+ pnode->fOneShot = true;
return true;
}
@@ -1489,7 +1622,6 @@ bool BindListenPort(string& strError)
{
strError = "";
int nOne = 1;
- addrLocalHost.SetPort(GetListenPort());
#ifdef WIN32
// Initialize Windows Sockets
@@ -1565,18 +1697,10 @@ bool BindListenPort(string& strError)
return true;
}
-void StartNode(void* parg)
+void static Discover()
{
-#ifdef USE_UPNP
-#if USE_UPNP
- fUseUPnP = GetBoolArg("-upnp", true);
-#else
- fUseUPnP = GetBoolArg("-upnp", false);
-#endif
-#endif
-
- if (pnodeLocalHost == NULL)
- pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
+ if (!GetBoolArg("-discover", true))
+ return;
#ifdef WIN32
// Get local host ip
@@ -1588,11 +1712,7 @@ void StartNode(void* parg)
{
BOOST_FOREACH (const CNetAddr &addr, vaddr)
{
- if (!addr.IsLocal())
- {
- addrLocalHost.SetIP(addr);
- break;
- }
+ AddLocal(addr, LOCAL_IF);
}
}
}
@@ -1615,35 +1735,45 @@ void StartNode(void* parg)
printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
// Take the first IP that isn't loopback 127.x.x.x
- CAddress addr(CService(s4->sin_addr, GetListenPort()), nLocalServices);
- if (addr.IsValid() && !addr.IsLocal())
- {
- addrLocalHost = addr;
- break;
- }
+ CNetAddr addr(s4->sin_addr);
+ AddLocal(addr, LOCAL_IF);
}
else if (ifa->ifa_addr->sa_family == AF_INET6)
{
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
+
+#ifdef USE_IPV6
+ CNetAddr addr(s6->sin6_addr);
+ AddLocal(addr, LOCAL_IF);
+#endif
}
}
freeifaddrs(myaddrs);
}
#endif
- printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
- if (fUseProxy || mapArgs.count("-connect") || fNoListen)
- {
- // Proxies can't take incoming connections
- addrLocalHost.SetIP(CNetAddr("0.0.0.0"));
- printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
- }
- else
+ if (!fUseProxy && !mapArgs.count("-connect") && !fNoListen)
{
CreateThread(ThreadGetMyExternalIP, NULL);
}
+}
+
+void StartNode(void* parg)
+{
+#ifdef USE_UPNP
+#if USE_UPNP
+ fUseUPnP = GetBoolArg("-upnp", true);
+#else
+ fUseUPnP = GetBoolArg("-upnp", false);
+#endif
+#endif
+
+ if (pnodeLocalHost == NULL)
+ pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
+
+ Discover();
//
// Start threads
diff --git a/src/net.h b/src/net.h
index bad49a9f8f..a00dd1b8cc 100644
--- a/src/net.h
+++ b/src/net.h
@@ -30,12 +30,13 @@ extern int nBestHeight;
inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
+void AddOneShot(std::string strDest);
bool RecvLine(SOCKET hSocket, std::string& strLine);
bool GetMyExternalIP(CNetAddr& ipRet);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const CService& ip);
-CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
+CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTimeout=0);
void MapPort(bool fMapPort);
bool BindListenPort(std::string& strError=REF(std::string()));
void StartNode(void* parg);
@@ -43,6 +44,24 @@ bool StopNode();
enum
{
+ LOCAL_NONE,
+ LOCAL_IF,
+ LOCAL_UPNP,
+ LOCAL_IRC,
+ LOCAL_HTTP,
+ LOCAL_MANUAL,
+
+ LOCAL_MAX
+};
+
+bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
+bool SeenLocal(const CNetAddr& addr);
+bool IsLocal(const CNetAddr& addr);
+bool GetLocal(CNetAddr &addr, const CNetAddr *paddrPeer = NULL);
+CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
+
+enum
+{
MSG_TX = 1,
MSG_BLOCK,
};
@@ -83,9 +102,7 @@ enum threadId
};
extern bool fClient;
-extern bool fAllowDNS;
extern uint64 nLocalServices;
-extern CAddress addrLocalHost;
extern uint64 nLocalHostNonce;
extern boost::array<int, THREAD_MAX> vnThreadsRunning;
extern CAddrMan addrman;
@@ -120,8 +137,11 @@ public:
int nHeaderStart;
unsigned int nMessageStart;
CAddress addr;
+ std::string addrName;
+ CNetAddr addrLocal;
int nVersion;
std::string strSubVer;
+ bool fOneShot;
bool fClient;
bool fInbound;
bool fNetworkNode;
@@ -157,7 +177,7 @@ public:
CCriticalSection cs_inventory;
std::multimap<int64, CInv> mapAskFor;
- CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
+ CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
{
nServices = 0;
hSocket = hSocketIn;
@@ -168,8 +188,10 @@ public:
nHeaderStart = -1;
nMessageStart = -1;
addr = addrIn;
+ addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
nVersion = 0;
strSubVer = "";
+ fOneShot = false;
fClient = false; // set by version message
fInbound = fInboundIn;
fNetworkNode = false;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 8b30ffc140..48709dc5c6 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -15,7 +15,10 @@
using namespace std;
// Settings
+int nSocksVersion = 5;
int fUseProxy = false;
+bool fProxyNameLookup = false;
+bool fNameLookup = false;
CService addrProxy("127.0.0.1",9050);
int nConnectTimeout = 5000;
@@ -156,7 +159,149 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
return Lookup(pszName, addr, portDefault, false);
}
-bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
+bool static Socks4(const CService &addrDest, SOCKET& hSocket)
+{
+ printf("SOCKS4 connecting %s\n", addrDest.ToString().c_str());
+ if (!addrDest.IsIPv4())
+ {
+ closesocket(hSocket);
+ return error("Proxy destination is not IPv4");
+ }
+ char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
+ struct sockaddr_in addr;
+ addrDest.GetSockAddr(&addr);
+ memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
+ memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
+ char* pszSocks4 = pszSocks4IP;
+ int nSize = sizeof(pszSocks4IP);
+
+ int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
+ if (ret != nSize)
+ {
+ closesocket(hSocket);
+ return error("Error sending to proxy");
+ }
+ char pchRet[8];
+ if (recv(hSocket, pchRet, 8, 0) != 8)
+ {
+ closesocket(hSocket);
+ return error("Error reading proxy response");
+ }
+ if (pchRet[1] != 0x5a)
+ {
+ closesocket(hSocket);
+ if (pchRet[1] != 0x5b)
+ printf("ERROR: Proxy returned error %d\n", pchRet[1]);
+ return false;
+ }
+ printf("SOCKS4 connected %s\n", addrDest.ToString().c_str());
+ return true;
+}
+
+bool static Socks5(string strDest, int port, SOCKET& hSocket)
+{
+ printf("SOCKS5 connecting %s\n", strDest.c_str());
+ if (strDest.size() > 255)
+ {
+ closesocket(hSocket);
+ return error("Hostname too long");
+ }
+ char pszSocks5Init[] = "\5\1\0";
+ char *pszSocks5 = pszSocks5Init;
+ ssize_t nSize = sizeof(pszSocks5Init);
+
+ ssize_t ret = send(hSocket, pszSocks5, nSize, MSG_NOSIGNAL);
+ if (ret != nSize)
+ {
+ closesocket(hSocket);
+ return error("Error sending to proxy");
+ }
+ char pchRet1[2];
+ if (recv(hSocket, pchRet1, 2, 0) != 2)
+ {
+ closesocket(hSocket);
+ return error("Error reading proxy response");
+ }
+ if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00)
+ {
+ closesocket(hSocket);
+ return error("Proxy failed to initialize");
+ }
+ string strSocks5("\5\1");
+ strSocks5 += '\000'; strSocks5 += '\003';
+ strSocks5 += static_cast<char>(std::min((int)strDest.size(), 255));
+ strSocks5 += strDest;
+ strSocks5 += static_cast<char>((port >> 8) & 0xFF);
+ strSocks5 += static_cast<char>((port >> 0) & 0xFF);
+ ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL);
+ if (ret != (ssize_t)strSocks5.size())
+ {
+ closesocket(hSocket);
+ return error("Error sending to proxy");
+ }
+ char pchRet2[4];
+ if (recv(hSocket, pchRet2, 4, 0) != 4)
+ {
+ closesocket(hSocket);
+ return error("Error reading proxy response");
+ }
+ if (pchRet2[0] != 0x05)
+ {
+ closesocket(hSocket);
+ return error("Proxy failed to accept request");
+ }
+ if (pchRet2[1] != 0x00)
+ {
+ closesocket(hSocket);
+ switch (pchRet2[1])
+ {
+ case 0x01: return error("Proxy error: general failure");
+ case 0x02: return error("Proxy error: connection not allowed");
+ case 0x03: return error("Proxy error: network unreachable");
+ case 0x04: return error("Proxy error: host unreachable");
+ case 0x05: return error("Proxy error: connection refused");
+ case 0x06: return error("Proxy error: TTL expired");
+ case 0x07: return error("Proxy error: protocol error");
+ case 0x08: return error("Proxy error: address type not supported");
+ default: return error("Proxy error: unknown");
+ }
+ }
+ if (pchRet2[2] != 0x00)
+ {
+ closesocket(hSocket);
+ return error("Error: malformed proxy response");
+ }
+ char pchRet3[256];
+ switch (pchRet2[3])
+ {
+ case 0x01: ret = recv(hSocket, pchRet3, 4, 0) != 4; break;
+ case 0x04: ret = recv(hSocket, pchRet3, 16, 0) != 16; break;
+ case 0x03:
+ {
+ ret = recv(hSocket, pchRet3, 1, 0) != 1;
+ if (ret)
+ return error("Error reading from proxy");
+ int nRecv = pchRet3[0];
+ ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv;
+ break;
+ }
+ default: closesocket(hSocket); return error("Error: malformed proxy response");
+ }
+ if (ret)
+ {
+ closesocket(hSocket);
+ return error("Error reading from proxy");
+ }
+ if (recv(hSocket, pchRet3, 2, 0) != 2)
+ {
+ closesocket(hSocket);
+ return error("Error reading from proxy");
+ }
+ printf("SOCKS5 connected %s\n", strDest.c_str());
+ return true;
+}
+
+bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
{
hSocketRet = INVALID_SOCKET;
@@ -168,12 +313,12 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
#endif
- bool fProxy = (fUseProxy && addrDest.IsRoutable());
struct sockaddr_in sockaddr;
- if (fProxy)
- addrProxy.GetSockAddr(&sockaddr);
- else
- addrDest.GetSockAddr(&sockaddr);
+ if (!addrConnect.GetSockAddr(&sockaddr))
+ {
+ closesocket(hSocket);
+ return false;
+ }
#ifdef WIN32
u_long fNonblock = 1;
@@ -187,7 +332,6 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
return false;
}
-
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
{
// WSAEINVAL is here because some legacy version of winsock uses it
@@ -258,38 +402,76 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
return false;
}
+ hSocketRet = hSocket;
+ return true;
+}
+
+bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
+{
+ SOCKET hSocket = INVALID_SOCKET;
+ bool fProxy = (fUseProxy && addrDest.IsRoutable());
+
+ if (!ConnectSocketDirectly(fProxy ? addrProxy : addrDest, hSocket, nTimeout))
+ return false;
+
if (fProxy)
{
- printf("proxy connecting %s\n", addrDest.ToString().c_str());
- char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
- struct sockaddr_in addr;
- addrDest.GetSockAddr(&addr);
- memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
- memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
- char* pszSocks4 = pszSocks4IP;
- int nSize = sizeof(pszSocks4IP);
-
- int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
- if (ret != nSize)
- {
- closesocket(hSocket);
- return error("Error sending to proxy");
- }
- char pchRet[8];
- if (recv(hSocket, pchRet, 8, 0) != 8)
+ switch(nSocksVersion)
{
- closesocket(hSocket);
- return error("Error reading proxy response");
- }
- if (pchRet[1] != 0x5a)
+ case 4:
+ if (!Socks4(addrDest, hSocket))
+ return false;
+ break;
+
+ case 5:
+ default:
+ if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
+ return false;
+ break;
+ }
+ }
+
+ hSocketRet = hSocket;
+ return true;
+}
+
+bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout)
+{
+ string strDest(pszDest);
+ int port = portDefault;
+
+ size_t colon = strDest.find_last_of(':');
+ char *endp = NULL;
+ int n = strtol(pszDest + colon + 1, &endp, 10);
+ if (endp && *endp == 0 && n >= 0) {
+ strDest = strDest.substr(0, colon);
+ if (n > 0 && n < 0x10000)
+ port = n;
+ }
+ if (strDest[0] == '[' && strDest[strDest.size()-1] == ']')
+ strDest = strDest.substr(1, strDest.size()-2);
+
+ SOCKET hSocket = INVALID_SOCKET;
+ CService addrResolved(CNetAddr(strDest, fNameLookup && !fProxyNameLookup), port);
+ if (addrResolved.IsValid()) {
+ addr = addrResolved;
+ return ConnectSocket(addr, hSocketRet, nTimeout);
+ }
+ addr = CService("0.0.0.0:0");
+ if (!fNameLookup)
+ return false;
+ if (!ConnectSocketDirectly(addrProxy, hSocket, nTimeout))
+ return false;
+
+ switch(nSocksVersion)
{
- closesocket(hSocket);
- if (pchRet[1] != 0x5b)
- printf("ERROR: Proxy returned error %d\n", pchRet[1]);
- return false;
+ case 4: return false;
+ case 5:
+ default:
+ if (!Socks5(strDest, port, hSocket))
+ return false;
+ break;
}
- printf("proxy connected %s\n", addrDest.ToString().c_str());
- }
hSocketRet = hSocket;
return true;
@@ -590,6 +772,29 @@ void CNetAddr::print() const
printf("CNetAddr(%s)\n", ToString().c_str());
}
+// for IPv6 partners: for unknown/Teredo partners: for IPv4 partners:
+// 0 - unroutable // 0 - unroutable // 0 - unroutable
+// 1 - teredo // 1 - teredo // 1 - ipv4
+// 2 - tunneled ipv6 // 2 - tunneled ipv6
+// 3 - ipv4 // 3 - ipv6
+// 4 - ipv6 // 4 - ipv4
+int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
+{
+ if (!IsValid() || !IsRoutable())
+ return 0;
+ if (paddrPartner && paddrPartner->IsIPv4())
+ return IsIPv4() ? 1 : 0;
+ if (IsRFC4380())
+ return 1;
+ if (IsRFC3964() || IsRFC6052())
+ return 2;
+ bool fRealIPv6 = paddrPartner && !paddrPartner->IsRFC4380() && paddrPartner->IsValid() && paddrPartner->IsRoutable();
+ if (fRealIPv6)
+ return IsIPv4() ? 3 : 4;
+ else
+ return IsIPv4() ? 4 : 3;
+}
+
void CService::Init()
{
port = 0;
diff --git a/src/netbase.h b/src/netbase.h
index 00b6850b2a..e5c466e4f0 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -51,6 +51,7 @@ class CNetAddr
int64 GetHash() const;
bool GetInAddr(struct in_addr* pipv4Addr) const;
std::vector<unsigned char> GetGroup() const;
+ int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
void print() const;
#ifdef USE_IPV6
@@ -119,9 +120,13 @@ bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllo
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
+bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
// Settings
+extern int nSocksVersion;
extern int fUseProxy;
+extern bool fProxyNameLookup;
+extern bool fNameLookup;
extern CService addrProxy;
#endif
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 3e55c39e04..dfc85c66d6 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -58,25 +58,34 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
ui->signMessage->setVisible(true);
break;
}
- ui->tableView->setTabKeyNavigation(false);
- ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
// Context menu actions
- QAction *copyAddressAction = new QAction(tr("Copy address"), this);
- QAction *copyLabelAction = new QAction(tr("Copy label"), this);
- QAction *editAction = new QAction(tr("Edit"), this);
- deleteAction = new QAction(tr("Delete"), this);
-
+ QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
+ QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
+ QAction *editAction = new QAction(tr("&Edit"), this);
+ QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
+ QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
+ deleteAction = new QAction(ui->deleteButton->text(), this);
+
+ // Build context menu
contextMenu = new QMenu();
contextMenu->addAction(copyAddressAction);
contextMenu->addAction(copyLabelAction);
contextMenu->addAction(editAction);
- contextMenu->addAction(deleteAction);
-
+ if(tab == SendingTab)
+ contextMenu->addAction(deleteAction);
+ contextMenu->addSeparator();
+ contextMenu->addAction(showQRCodeAction);
+ if(tab == ReceivingTab)
+ contextMenu->addAction(signMessageAction);
+
+ // Connect signals for context menu actions
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));
+ connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
+ connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index e752269ca1..4a77bf9b70 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -282,6 +282,7 @@ int main(int argc, char *argv[])
#endif
app.exec();
+ window.hide();
window.setClientModel(0);
window.setWalletModel(0);
guiref = 0;
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index e631a65155..e696170312 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -38,11 +38,11 @@
<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>
+ <file alias="qrcode">res/icons/qrcode.png</file>
</qresource>
<qresource prefix="/images">
<file alias="about">res/images/about.png</file>
<file alias="splash">res/images/splash2.jpg</file>
- <file alias="qrcode">res/images/qrcode.png</file>
</qresource>
<qresource prefix="/movies">
<file alias="update_spinner">res/movies/update_spinner.mng</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index bcf90917ed..f750d29cd1 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -24,6 +24,7 @@
#include "askpassphrasedialog.h"
#include "notificator.h"
#include "guiutil.h"
+#include "rpcconsole.h"
#ifdef Q_WS_MAC
#include "macdockiconhandler.h"
@@ -64,7 +65,8 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
changePassphraseAction(0),
aboutQtAction(0),
trayIcon(0),
- notificator(0)
+ notificator(0),
+ rpcConsole(0)
{
resize(850, 550);
setWindowTitle(tr("Bitcoin Wallet"));
@@ -158,6 +160,9 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
// Doubleclicking on a transaction on the transaction history page shows details
connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));
+ rpcConsole = new RPCConsole(this);
+ connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
+
gotoOverviewPage();
}
@@ -204,7 +209,7 @@ void BitcoinGUI::createActions()
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
tabGroup->addAction(sendCoinsAction);
- messageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message"), this);
+ messageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
messageAction->setToolTip(tr("Prove you control an address"));
#ifdef FIRST_CLASS_MESSAGING
messageAction->setCheckable(true);
@@ -241,13 +246,15 @@ void BitcoinGUI::createActions()
toggleHideAction->setToolTip(tr("Show or hide the Bitcoin window"));
exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
exportAction->setToolTip(tr("Export the data in the current tab to a file"));
- encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet"), this);
+ 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 = 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 = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption"));
+ openRPCConsoleAction = new QAction(tr("&Debug window"), this);
+ openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console"));
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
@@ -286,6 +293,8 @@ void BitcoinGUI::createMenuBar()
settings->addAction(optionsAction);
QMenu *help = appMenuBar->addMenu(tr("&Help"));
+ help->addAction(openRPCConsoleAction);
+ help->addSeparator();
help->addAction(aboutAction);
help->addAction(aboutQtAction);
}
@@ -338,6 +347,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
// Report errors from network/worker thread
connect(clientModel, SIGNAL(error(QString,QString, bool)), this, SLOT(error(QString,QString,bool)));
+
+ rpcConsole->setClientModel(clientModel);
}
}
@@ -625,7 +636,7 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
"Do you want to pay the fee?").arg(
BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nFeeRequired));
QMessageBox::StandardButton retval = QMessageBox::question(
- this, tr("Sending..."), strMessage,
+ this, tr("Confirm transaction fee"), strMessage,
QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes);
*payFee = (retval == QMessageBox::Yes);
}
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 2cce8d3459..eb4f883496 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -13,6 +13,7 @@ class AddressBookPage;
class SendCoinsDialog;
class MessagePage;
class Notificator;
+class RPCConsole;
QT_BEGIN_NAMESPACE
class QLabel;
@@ -87,10 +88,12 @@ private:
QAction *backupWalletAction;
QAction *changePassphraseAction;
QAction *aboutQtAction;
+ QAction *openRPCConsoleAction;
QSystemTrayIcon *trayIcon;
Notificator *notificator;
TransactionView *transactionView;
+ RPCConsole *rpcConsole;
QMovie *syncIconMovie;
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index cb602ce327..d7172fd9cd 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -93,3 +93,8 @@ QString ClientModel::formatBuildDate() const
{
return QString::fromStdString(CLIENT_DATE);
}
+
+QString ClientModel::clientName() const
+{
+ return QString::fromStdString(CLIENT_NAME);
+}
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 8e7431a2f3..74e0c0688f 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -38,6 +38,7 @@ public:
QString formatFullVersion() const;
QString formatBuildDate() const;
+ QString clientName() const;
private:
OptionsModel *optionsModel;
diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui
index 6e342e5e8a..21fc7b2019 100644
--- a/src/qt/forms/aboutdialog.ui
+++ b/src/qt/forms/aboutdialog.ui
@@ -22,9 +22,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string/>
- </property>
<property name="pixmap">
<pixmap resource="../bitcoin.qrc">:/images/about</pixmap>
</property>
@@ -49,6 +46,9 @@
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>&lt;b&gt;Bitcoin&lt;/b&gt; version</string>
</property>
@@ -59,6 +59,9 @@
</item>
<item>
<widget class="QLabel" name="versionLabel">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string notr="true">0.3.666-beta</string>
</property>
@@ -87,6 +90,9 @@
</item>
<item>
<widget class="QLabel" name="label_2">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>Copyright © 2009-2012 Bitcoin Developers
diff --git a/src/qt/forms/addressbookpage.ui b/src/qt/forms/addressbookpage.ui
index b31a9ce997..bca0a8dcdb 100644
--- a/src/qt/forms/addressbookpage.ui
+++ b/src/qt/forms/addressbookpage.ui
@@ -29,9 +29,15 @@
</item>
<item>
<widget class="QTableView" name="tableView">
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
<property name="toolTip">
<string>Double-click to edit address or label</string>
</property>
+ <property name="tabKeyNavigation">
+ <bool>false</bool>
+ </property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
@@ -57,7 +63,7 @@
<string>Create a new address</string>
</property>
<property name="text">
- <string>&amp;New Address...</string>
+ <string>&amp;New Address</string>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
@@ -71,7 +77,7 @@
<string>Copy the currently selected address to the system clipboard</string>
</property>
<property name="text">
- <string>&amp;Copy to Clipboard</string>
+ <string>&amp;Copy Address</string>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
@@ -86,7 +92,7 @@
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
- <normaloff>:/images/qrcode</normaloff>:/images/qrcode</iconset>
+ <normaloff>:/icons/qrcode</normaloff>:/icons/qrcode</iconset>
</property>
</widget>
</item>
diff --git a/src/qt/forms/messagepage.ui b/src/qt/forms/messagepage.ui
index 3df5831db5..512e47ad6d 100644
--- a/src/qt/forms/messagepage.ui
+++ b/src/qt/forms/messagepage.ui
@@ -104,9 +104,6 @@
<property name="readOnly">
<bool>true</bool>
</property>
- <property name="placeholderText">
- <string>Click &quot;Sign Message&quot; to get signature</string>
- </property>
</widget>
</item>
<item>
@@ -131,7 +128,7 @@
<string>Copy the current signature to the system clipboard</string>
</property>
<property name="text">
- <string>&amp;Copy to Clipboard</string>
+ <string>&amp;Copy Signature</string>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
@@ -145,7 +142,7 @@
<string>Reset all sign message fields</string>
</property>
<property name="text">
- <string>Clear all</string>
+ <string>Clear &amp;All</string>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui
index 3cf7dd0ed3..aeace9f30d 100644
--- a/src/qt/forms/overviewpage.ui
+++ b/src/qt/forms/overviewpage.ui
@@ -43,8 +43,23 @@
</item>
<item row="2" column="1">
<widget class="QLabel" name="labelBalance">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Your current balance</string>
+ </property>
<property name="text">
- <string>123.456 BTC</string>
+ <string notr="true">123.456 BTC</string>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
@@ -57,6 +72,9 @@
</item>
<item row="4" column="1">
<widget class="QLabel" name="labelNumTransactions">
+ <property name="toolTip">
+ <string>Total number of transactions in wallet</string>
+ </property>
<property name="text">
<string>0</string>
</property>
@@ -71,8 +89,23 @@
</item>
<item row="3" column="1">
<widget class="QLabel" name="labelUnconfirmed">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</string>
+ </property>
<property name="text">
- <string>0 BTC</string>
+ <string notr="true">0 BTC</string>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
@@ -81,6 +114,7 @@
<property name="font">
<font>
<pointsize>11</pointsize>
+ <weight>75</weight>
<bold>true</bold>
</font>
</property>
@@ -127,6 +161,9 @@
</item>
<item>
<widget class="QListView" name="listTransactions">
+ <property name="styleSheet">
+ <string notr="true">QListView { background:transparent }</string>
+ </property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
@@ -136,6 +173,9 @@
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::NoSelection</enum>
+ </property>
</widget>
</item>
</layout>
diff --git a/src/qt/forms/qrcodedialog.ui b/src/qt/forms/qrcodedialog.ui
index 714b1d6cd8..ef21841c26 100644
--- a/src/qt/forms/qrcodedialog.ui
+++ b/src/qt/forms/qrcodedialog.ui
@@ -6,12 +6,12 @@
<rect>
<x>0</x>
<y>0</y>
- <width>320</width>
- <height>404</height>
+ <width>334</width>
+ <height>423</height>
</rect>
</property>
<property name="windowTitle">
- <string>Dialog</string>
+ <string>QR-Code Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
new file mode 100644
index 0000000000..7e496a5ce7
--- /dev/null
+++ b/src/qt/forms/rpcconsole.ui
@@ -0,0 +1,323 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RPCConsole</class>
+ <widget class="QDialog" name="RPCConsole">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>706</width>
+ <height>382</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Bitcoin debug window</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab_info">
+ <attribute name="title">
+ <string>&amp;Information</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
+ <property name="horizontalSpacing">
+ <number>12</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Client name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="clientName">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Client version</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="clientVersion">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Version</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Network</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Number of connections</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLabel" name="numberOfConnections">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>On testnet</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QCheckBox" name="isTestNet">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_10">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Block chain</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Current number of blocks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QLabel" name="numberOfBlocks">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Estimated total blocks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QLabel" name="totalBlocks">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Last block time</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="1">
+ <widget class="QLabel" name="lastBlockTime">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <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 row="3" column="0">
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>Build date</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="buildDate">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_console">
+ <attribute name="title">
+ <string>&amp;Console</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QTableWidget" name="messagesWidget">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="tabKeyNavigation">
+ <bool>false</bool>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="columnCount">
+ <number>2</number>
+ </property>
+ <attribute name="horizontalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ <column/>
+ <column/>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="clearButton">
+ <property name="maximumSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Clear console</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>
+ </property>
+ <property name="shortcut">
+ <string notr="true">Ctrl+L</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../bitcoin.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index 04cf404ae3..49b4580dcf 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -64,7 +64,7 @@
<string>Send to multiple recipients at once</string>
</property>
<property name="text">
- <string>&amp;Add recipient...</string>
+ <string>&amp;Add Recipient</string>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui
index da0273e9b1..22a3f8fdc6 100644
--- a/src/qt/forms/sendcoinsentry.ui
+++ b/src/qt/forms/sendcoinsentry.ui
@@ -65,9 +65,6 @@
<property name="toolTip">
<string>Enter a label for this address to add it to your address book</string>
</property>
- <property name="placeholderText">
- <string>Enter a label for this address to add it to your address book</string>
- </property>
</widget>
</item>
</layout>
@@ -98,9 +95,6 @@
<property name="maxLength">
<number>34</number>
</property>
- <property name="placeholderText">
- <string>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
- </property>
</widget>
</item>
<item>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 53ba23b11c..c48de170ad 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -15,7 +15,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/aboutdialog.ui" line="91"/>
+ <location filename="../forms/aboutdialog.ui" line="97"/>
<source>Copyright © 2009-2012 Bitcoin Developers
This is experimental software.
@@ -39,92 +39,82 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="33"/>
+ <location filename="../forms/addressbookpage.ui" line="36"/>
<source>Double-click to edit address or label</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="57"/>
+ <location filename="../forms/addressbookpage.ui" line="63"/>
<source>Create a new address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="60"/>
- <source>&amp;New Address...</source>
+ <location filename="../forms/addressbookpage.ui" line="77"/>
+ <source>Copy the currently selected address to the system clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="71"/>
- <source>Copy the currently selected address to the system clipboard</source>
+ <location filename="../forms/addressbookpage.ui" line="66"/>
+ <source>&amp;New Address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="74"/>
- <source>&amp;Copy to Clipboard</source>
+ <location filename="../forms/addressbookpage.ui" line="80"/>
+ <source>&amp;Copy Address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="85"/>
+ <location filename="../forms/addressbookpage.ui" line="91"/>
<source>Show &amp;QR Code</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="96"/>
+ <location filename="../forms/addressbookpage.ui" line="102"/>
<source>Sign a message to prove you own this address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="99"/>
+ <location filename="../forms/addressbookpage.ui" line="105"/>
<source>&amp;Sign Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="110"/>
+ <location filename="../forms/addressbookpage.ui" line="116"/>
<source>Delete the currently selected address from the list. Only sending addresses can be deleted.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/addressbookpage.ui" line="113"/>
+ <location filename="../forms/addressbookpage.ui" line="119"/>
<source>&amp;Delete</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="65"/>
- <source>Copy address</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../addressbookpage.cpp" line="66"/>
- <source>Copy label</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../addressbookpage.cpp" line="67"/>
- <source>Edit</source>
+ <location filename="../addressbookpage.cpp" line="63"/>
+ <source>Copy &amp;Label</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="68"/>
- <source>Delete</source>
+ <location filename="../addressbookpage.cpp" line="65"/>
+ <source>&amp;Edit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="288"/>
+ <location filename="../addressbookpage.cpp" line="297"/>
<source>Export Address Book Data</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="289"/>
+ <location filename="../addressbookpage.cpp" line="298"/>
<source>Comma separated file (*.csv)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="302"/>
+ <location filename="../addressbookpage.cpp" line="311"/>
<source>Error exporting</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="302"/>
+ <location filename="../addressbookpage.cpp" line="311"/>
<source>Could not write to file %1.</source>
<translation type="unfinished"></translation>
</message>
@@ -132,17 +122,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>AddressTableModel</name>
<message>
- <location filename="../addresstablemodel.cpp" line="77"/>
+ <location filename="../addresstablemodel.cpp" line="78"/>
<source>Label</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addresstablemodel.cpp" line="77"/>
+ <location filename="../addresstablemodel.cpp" line="78"/>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addresstablemodel.cpp" line="113"/>
+ <location filename="../addresstablemodel.cpp" line="114"/>
<source>(no label)</source>
<translation type="unfinished"></translation>
</message>
@@ -288,122 +278,137 @@ Are you sure you wish to encrypt your wallet?</source>
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="70"/>
+ <location filename="../bitcoingui.cpp" line="72"/>
<source>Bitcoin Wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="243"/>
+ <location filename="../bitcoingui.cpp" line="212"/>
+ <source>Sign &amp;message...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../bitcoingui.cpp" line="245"/>
<source>Show/Hide &amp;Bitcoin</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="499"/>
+ <location filename="../bitcoingui.cpp" line="507"/>
<source>Synchronizing with network...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="180"/>
+ <location filename="../bitcoingui.cpp" line="182"/>
<source>&amp;Overview</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="181"/>
+ <location filename="../bitcoingui.cpp" line="183"/>
<source>Show general overview of wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="186"/>
+ <location filename="../bitcoingui.cpp" line="188"/>
<source>&amp;Transactions</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="187"/>
+ <location filename="../bitcoingui.cpp" line="189"/>
<source>Browse transaction history</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="192"/>
+ <location filename="../bitcoingui.cpp" line="194"/>
<source>&amp;Address Book</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="193"/>
+ <location filename="../bitcoingui.cpp" line="195"/>
<source>Edit the list of stored addresses and labels</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="198"/>
+ <location filename="../bitcoingui.cpp" line="200"/>
<source>&amp;Receive coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="199"/>
+ <location filename="../bitcoingui.cpp" line="201"/>
<source>Show the list of addresses for receiving payments</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="204"/>
+ <location filename="../bitcoingui.cpp" line="206"/>
<source>&amp;Send coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="205"/>
+ <location filename="../bitcoingui.cpp" line="207"/>
<source>Send coins to a bitcoin address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="210"/>
- <source>Sign &amp;message</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../bitcoingui.cpp" line="211"/>
+ <location filename="../bitcoingui.cpp" line="213"/>
<source>Prove you control an address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="230"/>
+ <location filename="../bitcoingui.cpp" line="232"/>
<source>E&amp;xit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="231"/>
+ <location filename="../bitcoingui.cpp" line="233"/>
<source>Quit application</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="234"/>
+ <location filename="../bitcoingui.cpp" line="236"/>
<source>&amp;About %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="235"/>
+ <location filename="../bitcoingui.cpp" line="237"/>
<source>Show information about Bitcoin</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="237"/>
+ <location filename="../bitcoingui.cpp" line="239"/>
<source>About &amp;Qt</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="238"/>
+ <location filename="../bitcoingui.cpp" line="240"/>
<source>Show information about Qt</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="240"/>
+ <location filename="../bitcoingui.cpp" line="242"/>
<source>&amp;Options...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="241"/>
+ <location filename="../bitcoingui.cpp" line="243"/>
<source>Modify configuration options for bitcoin</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../bitcoingui.cpp" line="249"/>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../bitcoingui.cpp" line="252"/>
+ <source>&amp;Backup Wallet...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../bitcoingui.cpp" line="254"/>
+ <source>&amp;Change Passphrase...</source>
+ <translation type="unfinished"></translation>
+ </message>
<message numerus="yes">
- <location filename="../bitcoingui.cpp" line="501"/>
+ <location filename="../bitcoingui.cpp" line="509"/>
<source>~%n block(s) remaining</source>
<translation>
<numerusform>~%n block remaining</numerusform>
@@ -411,97 +416,92 @@ Are you sure you wish to encrypt your wallet?</source>
</translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="512"/>
+ <location filename="../bitcoingui.cpp" line="520"/>
<source>Downloaded %1 of %2 blocks of transaction history (%3% done).</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="245"/>
+ <location filename="../bitcoingui.cpp" line="247"/>
<source>&amp;Export...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="244"/>
+ <location filename="../bitcoingui.cpp" line="246"/>
<source>Show or hide the Bitcoin window</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="246"/>
+ <location filename="../bitcoingui.cpp" line="248"/>
<source>Export the data in the current tab to a file</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="247"/>
- <source>&amp;Encrypt Wallet</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../bitcoingui.cpp" line="248"/>
+ <location filename="../bitcoingui.cpp" line="250"/>
<source>Encrypt or decrypt wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="250"/>
- <source>&amp;Backup Wallet</source>
+ <location filename="../bitcoingui.cpp" line="253"/>
+ <source>Backup wallet to another location</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="251"/>
- <source>Backup wallet to another location</source>
+ <location filename="../bitcoingui.cpp" line="255"/>
+ <source>Change the passphrase used for wallet encryption</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="252"/>
- <source>&amp;Change Passphrase</source>
+ <location filename="../bitcoingui.cpp" line="256"/>
+ <source>&amp;Debug window</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="253"/>
- <source>Change the passphrase used for wallet encryption</source>
+ <location filename="../bitcoingui.cpp" line="257"/>
+ <source>Open debugging and diagnostic console</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="276"/>
+ <location filename="../bitcoingui.cpp" line="280"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="285"/>
+ <location filename="../bitcoingui.cpp" line="289"/>
<source>&amp;Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="291"/>
+ <location filename="../bitcoingui.cpp" line="295"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="298"/>
+ <location filename="../bitcoingui.cpp" line="304"/>
<source>Tabs toolbar</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="309"/>
+ <location filename="../bitcoingui.cpp" line="315"/>
<source>Actions toolbar</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="321"/>
+ <location filename="../bitcoingui.cpp" line="327"/>
<source>[testnet]</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="383"/>
+ <location filename="../bitcoingui.cpp" line="391"/>
<source>Bitcoin client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="411"/>
+ <location filename="../bitcoingui.cpp" line="419"/>
<source>bitcoin-qt</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location filename="../bitcoingui.cpp" line="475"/>
+ <location filename="../bitcoingui.cpp" line="483"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -509,12 +509,12 @@ Are you sure you wish to encrypt your wallet?</source>
</translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="524"/>
+ <location filename="../bitcoingui.cpp" line="532"/>
<source>Downloaded %1 blocks of transaction history.</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location filename="../bitcoingui.cpp" line="539"/>
+ <location filename="../bitcoingui.cpp" line="547"/>
<source>%n second(s) ago</source>
<translation>
<numerusform>%n second ago</numerusform>
@@ -522,7 +522,7 @@ Are you sure you wish to encrypt your wallet?</source>
</translation>
</message>
<message numerus="yes">
- <location filename="../bitcoingui.cpp" line="543"/>
+ <location filename="../bitcoingui.cpp" line="551"/>
<source>%n minute(s) ago</source>
<translation>
<numerusform>%n minute ago</numerusform>
@@ -530,7 +530,7 @@ Are you sure you wish to encrypt your wallet?</source>
</translation>
</message>
<message numerus="yes">
- <location filename="../bitcoingui.cpp" line="547"/>
+ <location filename="../bitcoingui.cpp" line="555"/>
<source>%n hour(s) ago</source>
<translation>
<numerusform>%n hour ago</numerusform>
@@ -538,7 +538,7 @@ Are you sure you wish to encrypt your wallet?</source>
</translation>
</message>
<message numerus="yes">
- <location filename="../bitcoingui.cpp" line="551"/>
+ <location filename="../bitcoingui.cpp" line="559"/>
<source>%n day(s) ago</source>
<translation>
<numerusform>%n day ago</numerusform>
@@ -546,42 +546,42 @@ Are you sure you wish to encrypt your wallet?</source>
</translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="557"/>
+ <location filename="../bitcoingui.cpp" line="565"/>
<source>Up to date</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="562"/>
+ <location filename="../bitcoingui.cpp" line="570"/>
<source>Catching up...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="570"/>
+ <location filename="../bitcoingui.cpp" line="578"/>
<source>Last received block was generated %1.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="626"/>
+ <location filename="../bitcoingui.cpp" line="634"/>
<source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="631"/>
- <source>Sending...</source>
+ <location filename="../bitcoingui.cpp" line="639"/>
+ <source>Confirm transaction fee</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="658"/>
+ <location filename="../bitcoingui.cpp" line="666"/>
<source>Sent transaction</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="659"/>
+ <location filename="../bitcoingui.cpp" line="667"/>
<source>Incoming transaction</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="660"/>
+ <location filename="../bitcoingui.cpp" line="668"/>
<source>Date: %1
Amount: %2
Type: %3
@@ -590,51 +590,61 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="785"/>
+ <location filename="../bitcoingui.cpp" line="793"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="793"/>
+ <location filename="../bitcoingui.cpp" line="801"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="816"/>
+ <location filename="../bitcoingui.cpp" line="824"/>
<source>Backup Wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="816"/>
+ <location filename="../bitcoingui.cpp" line="824"/>
<source>Wallet Data (*.dat)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="819"/>
+ <location filename="../bitcoingui.cpp" line="827"/>
<source>Backup Failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoingui.cpp" line="819"/>
+ <location filename="../bitcoingui.cpp" line="827"/>
<source>There was an error trying to save the wallet data to the new location.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../bitcoin.cpp" line="127"/>
+ <source>A fatal error occured. Bitcoin can no longer continue safely and will quit.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>DisplayOptionsPage</name>
<message>
- <location filename="../optionsdialog.cpp" line="268"/>
+ <location filename="../optionsdialog.cpp" line="273"/>
<source>&amp;Unit to show amounts in: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="272"/>
+ <location filename="../optionsdialog.cpp" line="277"/>
<source>Choose the default subdivision unit to show in the interface, and when sending coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="279"/>
- <source>Display addresses in transaction list</source>
+ <location filename="../optionsdialog.cpp" line="284"/>
+ <source>&amp;Display addresses in transaction list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../optionsdialog.cpp" line="285"/>
+ <source>Whether to show Bitcoin addresses in the transaction list</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -709,87 +719,92 @@ Address: %4
<context>
<name>MainOptionsPage</name>
<message>
- <location filename="../optionsdialog.cpp" line="170"/>
+ <location filename="../optionsdialog.cpp" line="171"/>
<source>&amp;Start Bitcoin on window system startup</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="171"/>
+ <location filename="../optionsdialog.cpp" line="172"/>
<source>Automatically start Bitcoin after the computer is turned on</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="175"/>
+ <location filename="../optionsdialog.cpp" line="176"/>
<source>&amp;Minimize to the tray instead of the taskbar</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="176"/>
+ <location filename="../optionsdialog.cpp" line="177"/>
<source>Show only a tray icon after minimizing the window</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="184"/>
+ <location filename="../optionsdialog.cpp" line="185"/>
<source>Map port using &amp;UPnP</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="185"/>
+ <location filename="../optionsdialog.cpp" line="186"/>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="179"/>
+ <location filename="../optionsdialog.cpp" line="180"/>
<source>M&amp;inimize on close</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="180"/>
+ <location filename="../optionsdialog.cpp" line="181"/>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="188"/>
+ <location filename="../optionsdialog.cpp" line="189"/>
<source>&amp;Connect through SOCKS4 proxy:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="189"/>
+ <location filename="../optionsdialog.cpp" line="190"/>
<source>Connect to the Bitcon network through a SOCKS4 proxy (e.g. when connecting through Tor)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="194"/>
+ <location filename="../optionsdialog.cpp" line="195"/>
<source>Proxy &amp;IP: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="200"/>
+ <location filename="../optionsdialog.cpp" line="201"/>
<source>IP address of the proxy (e.g. 127.0.0.1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="203"/>
+ <location filename="../optionsdialog.cpp" line="204"/>
<source>&amp;Port: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="209"/>
+ <location filename="../optionsdialog.cpp" line="210"/>
<source>Port of the proxy (e.g. 1234)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="215"/>
- <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended.</source>
+ <location filename="../optionsdialog.cpp" line="232"/>
+ <source>Detach databases at shutdown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../optionsdialog.cpp" line="233"/>
+ <source>Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="221"/>
+ <location filename="../optionsdialog.cpp" line="222"/>
<source>Pay transaction &amp;fee</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="224"/>
+ <location filename="../optionsdialog.cpp" line="216"/>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended.</source>
<translation type="unfinished"></translation>
</message>
@@ -837,49 +852,59 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/messagepage.ui" line="105"/>
- <source>Click &quot;Sign Message&quot; to get signature</source>
+ <location filename="../forms/messagepage.ui" line="128"/>
+ <source>Copy the current signature to the system clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/messagepage.ui" line="117"/>
- <source>Sign a message to prove you own this address</source>
+ <location filename="../forms/messagepage.ui" line="131"/>
+ <source>&amp;Copy Signature</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/messagepage.ui" line="120"/>
- <source>&amp;Sign Message</source>
+ <location filename="../forms/messagepage.ui" line="142"/>
+ <source>Reset all sign message fields</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/messagepage.ui" line="131"/>
- <source>Copy the currently selected address to the system clipboard</source>
+ <location filename="../forms/messagepage.ui" line="145"/>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../messagepage.cpp" line="30"/>
+ <source>Click &quot;Sign Message&quot; to get signature</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/messagepage.ui" line="114"/>
+ <source>Sign a message to prove you own this address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/messagepage.ui" line="134"/>
- <source>&amp;Copy to Clipboard</source>
+ <location filename="../forms/messagepage.ui" line="117"/>
+ <source>&amp;Sign Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../messagepage.cpp" line="74"/>
- <location filename="../messagepage.cpp" line="89"/>
- <location filename="../messagepage.cpp" line="101"/>
+ <location filename="../messagepage.cpp" line="79"/>
+ <location filename="../messagepage.cpp" line="94"/>
+ <location filename="../messagepage.cpp" line="106"/>
<source>Error signing</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../messagepage.cpp" line="74"/>
+ <location filename="../messagepage.cpp" line="79"/>
<source>%1 is not a valid address.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../messagepage.cpp" line="89"/>
+ <location filename="../messagepage.cpp" line="94"/>
<source>Private key for %1 is not available.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../messagepage.cpp" line="101"/>
+ <location filename="../messagepage.cpp" line="106"/>
<source>Sign failed</source>
<translation type="unfinished"></translation>
</message>
@@ -887,17 +912,17 @@ Address: %4
<context>
<name>OptionsDialog</name>
<message>
- <location filename="../optionsdialog.cpp" line="79"/>
+ <location filename="../optionsdialog.cpp" line="80"/>
<source>Main</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="84"/>
+ <location filename="../optionsdialog.cpp" line="85"/>
<source>Display</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="104"/>
+ <location filename="../optionsdialog.cpp" line="105"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
@@ -940,16 +965,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/overviewpage.ui" line="82"/>
- <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Ubuntu&apos;; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Wallet&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <location filename="../forms/overviewpage.ui" line="88"/>
+ <source>Wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/overviewpage.ui" line="122"/>
+ <location filename="../forms/overviewpage.ui" line="124"/>
<source>&lt;b&gt;Recent transactions&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
@@ -973,7 +994,7 @@ p, li { white-space: pre-wrap; }
<name>QRCodeDialog</name>
<message>
<location filename="../forms/qrcodedialog.ui" line="14"/>
- <source>Dialog</source>
+ <source>QR-Code Dialog</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1012,22 +1033,141 @@ p, li { white-space: pre-wrap; }
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../qrcodedialog.cpp" line="59"/>
+ <location filename="../qrcodedialog.cpp" line="46"/>
+ <source>Error encoding URI into QR Code.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qrcodedialog.cpp" line="64"/>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../qrcodedialog.cpp" line="116"/>
- <source>Save Image...</source>
+ <location filename="../qrcodedialog.cpp" line="121"/>
+ <source>Save QR Code</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../qrcodedialog.cpp" line="116"/>
+ <location filename="../qrcodedialog.cpp" line="121"/>
<source>PNG Images (*.png)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>RPCConsole</name>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="14"/>
+ <source>Bitcoin debug window</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="24"/>
+ <source>Information</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="33"/>
+ <source>Client name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="40"/>
+ <location filename="../forms/rpcconsole.ui" line="60"/>
+ <location filename="../forms/rpcconsole.ui" line="106"/>
+ <location filename="../forms/rpcconsole.ui" line="156"/>
+ <location filename="../forms/rpcconsole.ui" line="176"/>
+ <location filename="../forms/rpcconsole.ui" line="196"/>
+ <location filename="../forms/rpcconsole.ui" line="229"/>
+ <source>N/A</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="53"/>
+ <source>Client version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="79"/>
+ <source>Version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="92"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="99"/>
+ <source>Number of connections</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="119"/>
+ <source>On testnet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="142"/>
+ <source>Block chain</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="149"/>
+ <source>Current number of blocks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="169"/>
+ <source>Estimated total blocks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="189"/>
+ <source>Last block time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="222"/>
+ <source>Build date</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="237"/>
+ <source>Console</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="278"/>
+ <source>&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="294"/>
+ <source>Clear console</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../rpcconsole.cpp" line="97"/>
+ <source>&amp;Copy</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../rpcconsole.cpp" line="195"/>
+ <source>Welcome to the bitcoin RPC console.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../rpcconsole.cpp" line="196"/>
+ <source>Use up and down arrows to navigate history, and Ctrl-L to clear screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../rpcconsole.cpp" line="197"/>
+ <source>Type &quot;help&quot; for an overview of available commands.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="14"/>
@@ -1048,7 +1188,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="67"/>
- <source>&amp;Add recipient...</source>
+ <source>&amp;Add Recipient</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1156,7 +1296,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location filename="../forms/sendcoinsentry.ui" line="66"/>
- <location filename="../sendcoinsentry.cpp" line="26"/>
+ <location filename="../sendcoinsentry.cpp" line="25"/>
<source>Enter a label for this address to add it to your address book</source>
<translation type="unfinished"></translation>
</message>
@@ -1196,7 +1336,7 @@ p, li { white-space: pre-wrap; }
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../sendcoinsentry.cpp" line="25"/>
+ <location filename="../sendcoinsentry.cpp" line="26"/>
<source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
<translation type="unfinished"></translation>
</message>
@@ -1204,140 +1344,140 @@ p, li { white-space: pre-wrap; }
<context>
<name>TransactionDesc</name>
<message>
- <location filename="../transactiondesc.cpp" line="18"/>
+ <location filename="../transactiondesc.cpp" line="20"/>
<source>Open for %1 blocks</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="20"/>
+ <location filename="../transactiondesc.cpp" line="22"/>
<source>Open until %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="26"/>
+ <location filename="../transactiondesc.cpp" line="28"/>
<source>%1/offline?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="28"/>
+ <location filename="../transactiondesc.cpp" line="30"/>
<source>%1/unconfirmed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="30"/>
+ <location filename="../transactiondesc.cpp" line="32"/>
<source>%1 confirmations</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="48"/>
+ <location filename="../transactiondesc.cpp" line="50"/>
<source>&lt;b&gt;Status:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="53"/>
+ <location filename="../transactiondesc.cpp" line="55"/>
<source>, has not been successfully broadcast yet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="55"/>
+ <location filename="../transactiondesc.cpp" line="57"/>
<source>, broadcast through %1 node</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="57"/>
+ <location filename="../transactiondesc.cpp" line="59"/>
<source>, broadcast through %1 nodes</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="61"/>
+ <location filename="../transactiondesc.cpp" line="63"/>
<source>&lt;b&gt;Date:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="68"/>
+ <location filename="../transactiondesc.cpp" line="70"/>
<source>&lt;b&gt;Source:&lt;/b&gt; Generated&lt;br&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="74"/>
- <location filename="../transactiondesc.cpp" line="91"/>
+ <location filename="../transactiondesc.cpp" line="76"/>
+ <location filename="../transactiondesc.cpp" line="93"/>
<source>&lt;b&gt;From:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="91"/>
+ <location filename="../transactiondesc.cpp" line="93"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="92"/>
- <location filename="../transactiondesc.cpp" line="115"/>
- <location filename="../transactiondesc.cpp" line="174"/>
+ <location filename="../transactiondesc.cpp" line="94"/>
+ <location filename="../transactiondesc.cpp" line="117"/>
+ <location filename="../transactiondesc.cpp" line="176"/>
<source>&lt;b&gt;To:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="95"/>
+ <location filename="../transactiondesc.cpp" line="97"/>
<source> (yours, label: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="97"/>
+ <location filename="../transactiondesc.cpp" line="99"/>
<source> (yours)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="132"/>
- <location filename="../transactiondesc.cpp" line="146"/>
- <location filename="../transactiondesc.cpp" line="191"/>
- <location filename="../transactiondesc.cpp" line="208"/>
+ <location filename="../transactiondesc.cpp" line="134"/>
+ <location filename="../transactiondesc.cpp" line="148"/>
+ <location filename="../transactiondesc.cpp" line="193"/>
+ <location filename="../transactiondesc.cpp" line="210"/>
<source>&lt;b&gt;Credit:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="134"/>
+ <location filename="../transactiondesc.cpp" line="136"/>
<source>(%1 matures in %2 more blocks)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="138"/>
+ <location filename="../transactiondesc.cpp" line="140"/>
<source>(not accepted)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="182"/>
- <location filename="../transactiondesc.cpp" line="190"/>
- <location filename="../transactiondesc.cpp" line="205"/>
+ <location filename="../transactiondesc.cpp" line="184"/>
+ <location filename="../transactiondesc.cpp" line="192"/>
+ <location filename="../transactiondesc.cpp" line="207"/>
<source>&lt;b&gt;Debit:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="196"/>
+ <location filename="../transactiondesc.cpp" line="198"/>
<source>&lt;b&gt;Transaction fee:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="212"/>
+ <location filename="../transactiondesc.cpp" line="214"/>
<source>&lt;b&gt;Net amount:&lt;/b&gt; </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="218"/>
+ <location filename="../transactiondesc.cpp" line="220"/>
<source>Message:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="220"/>
+ <location filename="../transactiondesc.cpp" line="222"/>
<source>Comment:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="222"/>
+ <location filename="../transactiondesc.cpp" line="224"/>
<source>Transaction ID:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiondesc.cpp" line="225"/>
+ <location filename="../transactiondesc.cpp" line="227"/>
<source>Generated coins must wait 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, it will change to &quot;not accepted&quot; and not be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
<translation type="unfinished"></translation>
</message>
@@ -1358,27 +1498,27 @@ p, li { white-space: pre-wrap; }
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="213"/>
+ <location filename="../transactiontablemodel.cpp" line="214"/>
<source>Date</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="213"/>
+ <location filename="../transactiontablemodel.cpp" line="214"/>
<source>Type</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="213"/>
+ <location filename="../transactiontablemodel.cpp" line="214"/>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="213"/>
+ <location filename="../transactiontablemodel.cpp" line="214"/>
<source>Amount</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location filename="../transactiontablemodel.cpp" line="274"/>
+ <location filename="../transactiontablemodel.cpp" line="275"/>
<source>Open for %n block(s)</source>
<translation>
<numerusform>Open for %n block</numerusform>
@@ -1386,27 +1526,27 @@ p, li { white-space: pre-wrap; }
</translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="277"/>
+ <location filename="../transactiontablemodel.cpp" line="278"/>
<source>Open until %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="280"/>
+ <location filename="../transactiontablemodel.cpp" line="281"/>
<source>Offline (%1 confirmations)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="283"/>
+ <location filename="../transactiontablemodel.cpp" line="284"/>
<source>Unconfirmed (%1 of %2 confirmations)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="286"/>
+ <location filename="../transactiontablemodel.cpp" line="287"/>
<source>Confirmed (%1 confirmations)</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location filename="../transactiontablemodel.cpp" line="294"/>
+ <location filename="../transactiontablemodel.cpp" line="295"/>
<source>Mined balance will be available in %n more blocks</source>
<translation>
<numerusform>Mined balance will be available in %n more block</numerusform>
@@ -1414,67 +1554,67 @@ p, li { white-space: pre-wrap; }
</translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="300"/>
+ <location filename="../transactiontablemodel.cpp" line="301"/>
<source>This block was not received by any other nodes and will probably not be accepted!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="303"/>
+ <location filename="../transactiontablemodel.cpp" line="304"/>
<source>Generated but not accepted</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="346"/>
+ <location filename="../transactiontablemodel.cpp" line="347"/>
<source>Received with</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="348"/>
+ <location filename="../transactiontablemodel.cpp" line="349"/>
<source>Received from</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="351"/>
+ <location filename="../transactiontablemodel.cpp" line="352"/>
<source>Sent to</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="353"/>
+ <location filename="../transactiontablemodel.cpp" line="354"/>
<source>Payment to yourself</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="355"/>
+ <location filename="../transactiontablemodel.cpp" line="356"/>
<source>Mined</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="393"/>
+ <location filename="../transactiontablemodel.cpp" line="394"/>
<source>(n/a)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="592"/>
+ <location filename="../transactiontablemodel.cpp" line="593"/>
<source>Transaction status. Hover over this field to show number of confirmations.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="594"/>
+ <location filename="../transactiontablemodel.cpp" line="595"/>
<source>Date and time that the transaction was received.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="596"/>
+ <location filename="../transactiontablemodel.cpp" line="597"/>
<source>Type of transaction.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="598"/>
+ <location filename="../transactiontablemodel.cpp" line="599"/>
<source>Destination address of transaction.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../transactiontablemodel.cpp" line="600"/>
+ <location filename="../transactiontablemodel.cpp" line="601"/>
<source>Amount removed from or added to balance.</source>
<translation type="unfinished"></translation>
</message>
@@ -1574,7 +1714,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location filename="../transactionview.cpp" line="128"/>
- <source>Show details...</source>
+ <source>Show transaction details</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1646,7 +1786,7 @@ p, li { white-space: pre-wrap; }
<context>
<name>WalletModel</name>
<message>
- <location filename="../walletmodel.cpp" line="143"/>
+ <location filename="../walletmodel.cpp" line="142"/>
<source>Sending...</source>
<translation type="unfinished"></translation>
</message>
@@ -1654,448 +1794,448 @@ p, li { white-space: pre-wrap; }
<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="7"/>
+ <location filename="../bitcoinstrings.cpp" line="12"/>
<source>Bitcoin version</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="8"/>
+ <location filename="../bitcoinstrings.cpp" line="13"/>
<source>Usage:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="9"/>
+ <location filename="../bitcoinstrings.cpp" line="14"/>
<source>Send command to -server or bitcoind</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="10"/>
+ <location filename="../bitcoinstrings.cpp" line="15"/>
<source>List commands</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="11"/>
+ <location filename="../bitcoinstrings.cpp" line="16"/>
<source>Get help for a command</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="12"/>
+ <location filename="../bitcoinstrings.cpp" line="17"/>
<source>Options:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="13"/>
+ <location filename="../bitcoinstrings.cpp" line="18"/>
<source>Specify configuration file (default: bitcoin.conf)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="14"/>
+ <location filename="../bitcoinstrings.cpp" line="19"/>
<source>Specify pid file (default: bitcoind.pid)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="15"/>
+ <location filename="../bitcoinstrings.cpp" line="20"/>
<source>Generate coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="16"/>
+ <location filename="../bitcoinstrings.cpp" line="21"/>
<source>Don&apos;t generate coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="17"/>
+ <location filename="../bitcoinstrings.cpp" line="22"/>
<source>Start minimized</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="18"/>
+ <location filename="../bitcoinstrings.cpp" line="23"/>
<source>Show splash screen on startup (default: 1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="19"/>
+ <location filename="../bitcoinstrings.cpp" line="24"/>
<source>Specify data directory</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="20"/>
+ <location filename="../bitcoinstrings.cpp" line="25"/>
<source>Set database cache size in megabytes (default: 25)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="21"/>
+ <location filename="../bitcoinstrings.cpp" line="26"/>
<source>Set database disk log size in megabytes (default: 100)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="22"/>
+ <location filename="../bitcoinstrings.cpp" line="27"/>
<source>Specify connection timeout (in milliseconds)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="23"/>
+ <location filename="../bitcoinstrings.cpp" line="28"/>
<source>Connect through socks4 proxy</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="24"/>
+ <location filename="../bitcoinstrings.cpp" line="29"/>
<source>Allow DNS lookups for addnode and connect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="25"/>
+ <location filename="../bitcoinstrings.cpp" line="30"/>
<source>Listen for connections on &lt;port&gt; (default: 8333 or testnet: 18333)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="26"/>
+ <location filename="../bitcoinstrings.cpp" line="31"/>
<source>Maintain at most &lt;n&gt; connections to peers (default: 125)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="28"/>
+ <location filename="../bitcoinstrings.cpp" line="33"/>
<source>Connect only to the specified node</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="33"/>
+ <location filename="../bitcoinstrings.cpp" line="38"/>
<source>Threshold for disconnecting misbehaving peers (default: 100)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="34"/>
+ <location filename="../bitcoinstrings.cpp" line="39"/>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="37"/>
+ <location filename="../bitcoinstrings.cpp" line="42"/>
<source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: 10000)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="38"/>
+ <location filename="../bitcoinstrings.cpp" line="43"/>
<source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: 10000)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="42"/>
+ <location filename="../bitcoinstrings.cpp" line="47"/>
<source>Accept command line and JSON-RPC commands</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="43"/>
+ <location filename="../bitcoinstrings.cpp" line="48"/>
<source>Run in the background as a daemon and accept commands</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="44"/>
+ <location filename="../bitcoinstrings.cpp" line="49"/>
<source>Use the test network</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="45"/>
+ <location filename="../bitcoinstrings.cpp" line="50"/>
<source>Output extra debugging information</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="46"/>
+ <location filename="../bitcoinstrings.cpp" line="51"/>
<source>Prepend debug output with timestamp</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="47"/>
+ <location filename="../bitcoinstrings.cpp" line="52"/>
<source>Send trace/debug info to console instead of debug.log file</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="48"/>
+ <location filename="../bitcoinstrings.cpp" line="53"/>
<source>Send trace/debug info to debugger</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="49"/>
+ <location filename="../bitcoinstrings.cpp" line="54"/>
<source>Username for JSON-RPC connections</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="50"/>
+ <location filename="../bitcoinstrings.cpp" line="55"/>
<source>Password for JSON-RPC connections</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="51"/>
+ <location filename="../bitcoinstrings.cpp" line="56"/>
<source>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="52"/>
+ <location filename="../bitcoinstrings.cpp" line="57"/>
<source>Allow JSON-RPC connections from specified IP address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="53"/>
+ <location filename="../bitcoinstrings.cpp" line="58"/>
<source>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="54"/>
+ <location filename="../bitcoinstrings.cpp" line="59"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="57"/>
+ <location filename="../bitcoinstrings.cpp" line="62"/>
<source>Upgrade wallet to latest format</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="58"/>
+ <location filename="../bitcoinstrings.cpp" line="63"/>
<source>Set key pool size to &lt;n&gt; (default: 100)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="59"/>
+ <location filename="../bitcoinstrings.cpp" line="64"/>
<source>Rescan the block chain for missing wallet transactions</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="60"/>
+ <location filename="../bitcoinstrings.cpp" line="65"/>
<source>How many blocks to check at startup (default: 2500, 0 = all)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="61"/>
+ <location filename="../bitcoinstrings.cpp" line="66"/>
<source>How thorough the block verification is (0-6, default: 1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="62"/>
+ <location filename="../bitcoinstrings.cpp" line="67"/>
<source>
SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="65"/>
+ <location filename="../bitcoinstrings.cpp" line="70"/>
<source>Use OpenSSL (https) for JSON-RPC connections</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="66"/>
+ <location filename="../bitcoinstrings.cpp" line="71"/>
<source>Server certificate file (default: server.cert)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="67"/>
+ <location filename="../bitcoinstrings.cpp" line="72"/>
<source>Server private key (default: server.pem)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="68"/>
+ <location filename="../bitcoinstrings.cpp" line="73"/>
<source>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="71"/>
+ <location filename="../bitcoinstrings.cpp" line="76"/>
<source>This help message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="72"/>
+ <location filename="../bitcoinstrings.cpp" line="77"/>
<source>Usage</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="73"/>
+ <location filename="../bitcoinstrings.cpp" line="78"/>
<source>Cannot obtain a lock on data directory %s. Bitcoin is probably already running.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="76"/>
+ <location filename="../bitcoinstrings.cpp" line="81"/>
<source>Bitcoin</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="77"/>
+ <location filename="../bitcoinstrings.cpp" line="82"/>
<source>Loading addresses...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="78"/>
+ <location filename="../bitcoinstrings.cpp" line="83"/>
<source>Error loading addr.dat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="80"/>
+ <location filename="../bitcoinstrings.cpp" line="85"/>
<source>Error loading blkindex.dat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="82"/>
+ <location filename="../bitcoinstrings.cpp" line="87"/>
<source>Error loading wallet.dat: Wallet corrupted</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="83"/>
+ <location filename="../bitcoinstrings.cpp" line="88"/>
<source>Error loading wallet.dat: Wallet requires newer version of Bitcoin</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="84"/>
+ <location filename="../bitcoinstrings.cpp" line="89"/>
<source>Wallet needed to be rewritten: restart Bitcoin to complete</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="85"/>
+ <location filename="../bitcoinstrings.cpp" line="90"/>
<source>Error loading wallet.dat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="117"/>
+ <location filename="../bitcoinstrings.cpp" line="122"/>
<source>Error: Wallet locked, unable to create transaction </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="118"/>
+ <location filename="../bitcoinstrings.cpp" line="123"/>
<source>Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="121"/>
+ <location filename="../bitcoinstrings.cpp" line="126"/>
<source>Error: Transaction creation failed </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="122"/>
+ <location filename="../bitcoinstrings.cpp" line="127"/>
<source>Sending...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="123"/>
+ <location filename="../bitcoinstrings.cpp" line="128"/>
<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 type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="127"/>
+ <location filename="../bitcoinstrings.cpp" line="132"/>
<source>Invalid amount</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="128"/>
+ <location filename="../bitcoinstrings.cpp" line="133"/>
<source>Insufficient funds</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="79"/>
+ <location filename="../bitcoinstrings.cpp" line="84"/>
<source>Loading block index...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="27"/>
+ <location filename="../bitcoinstrings.cpp" line="32"/>
<source>Add a node to connect to and attempt to keep the connection open</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="29"/>
+ <location filename="../bitcoinstrings.cpp" line="34"/>
<source>Find peers using internet relay chat (default: 0)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="30"/>
+ <location filename="../bitcoinstrings.cpp" line="35"/>
<source>Accept connections from outside (default: 1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="31"/>
+ <location filename="../bitcoinstrings.cpp" line="36"/>
<source>Set language, for example &quot;de_DE&quot; (default: system locale)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="32"/>
+ <location filename="../bitcoinstrings.cpp" line="37"/>
<source>Find peers using DNS lookup (default: 1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="39"/>
+ <location filename="../bitcoinstrings.cpp" line="44"/>
<source>Use Universal Plug and Play to map the listening port (default: 1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="40"/>
+ <location filename="../bitcoinstrings.cpp" line="45"/>
<source>Use Universal Plug and Play to map the listening port (default: 0)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="41"/>
+ <location filename="../bitcoinstrings.cpp" line="46"/>
<source>Fee per KB to add to transactions you send</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="81"/>
+ <location filename="../bitcoinstrings.cpp" line="86"/>
<source>Loading wallet...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="86"/>
+ <location filename="../bitcoinstrings.cpp" line="91"/>
<source>Cannot downgrade wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="87"/>
+ <location filename="../bitcoinstrings.cpp" line="92"/>
<source>Cannot initialize keypool</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="88"/>
+ <location filename="../bitcoinstrings.cpp" line="93"/>
<source>Cannot write default address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="89"/>
+ <location filename="../bitcoinstrings.cpp" line="94"/>
<source>Rescanning...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="90"/>
+ <location filename="../bitcoinstrings.cpp" line="95"/>
<source>Done loading</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="91"/>
+ <location filename="../bitcoinstrings.cpp" line="96"/>
<source>Invalid -proxy address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="92"/>
+ <location filename="../bitcoinstrings.cpp" line="97"/>
<source>Invalid amount for -paytxfee=&lt;amount&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="93"/>
+ <location filename="../bitcoinstrings.cpp" line="98"/>
<source>Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="96"/>
+ <location filename="../bitcoinstrings.cpp" line="101"/>
<source>Error: CreateThread(StartNode) failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="6"/>
+ <location filename="../bitcoinstrings.cpp" line="11"/>
<source>Warning: Disk space is low </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="3"/>
+ <location filename="../bitcoinstrings.cpp" line="8"/>
<source>Unable to bind to port %d on this computer. Bitcoin is probably already running.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="97"/>
+ <location filename="../bitcoinstrings.cpp" line="102"/>
<source>To use the %s option</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="98"/>
+ <location filename="../bitcoinstrings.cpp" line="103"/>
<source>%s, you must set a rpcpassword in the configuration file:
%s
It is recommended you use the following random password:
@@ -2107,24 +2247,24 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="107"/>
+ <location filename="../bitcoinstrings.cpp" line="112"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="108"/>
+ <location filename="../bitcoinstrings.cpp" line="113"/>
<source>An error occured while setting up the RPC port %i for listening: %s</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="109"/>
+ <location filename="../bitcoinstrings.cpp" line="114"/>
<source>You must set rpcpassword=&lt;password&gt; in the configuration file:
%s
If the file does not exist, create it with owner-readable-only file permissions.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoinstrings.cpp" line="114"/>
+ <location filename="../bitcoinstrings.cpp" line="119"/>
<source>Warning: Please check that your computer&apos;s date and time are correct. If your clock is wrong Bitcoin will not work properly.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/src/qt/messagepage.cpp b/src/qt/messagepage.cpp
index aa7fdc5d91..236b67bf37 100644
--- a/src/qt/messagepage.cpp
+++ b/src/qt/messagepage.cpp
@@ -24,6 +24,11 @@ MessagePage::MessagePage(QWidget *parent) :
ui(new Ui::MessagePage)
{
ui->setupUi(this);
+
+#if (QT_VERSION >= 0x040700)
+ /* Do not move this to the XML file, Qt before 4.7 will choke on it */
+ ui->signature->setPlaceholderText(tr("Click \"Sign Message\" to get signature"));
+#endif
GUIUtil::setupAddressWidget(ui->signFrom, this);
ui->signature->installEventFilter(this);
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 59c44ac5f9..6b4e037cc5 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -19,73 +19,103 @@
#include <QDoubleValidator>
#include <QRegExpValidator>
#include <QDialogButtonBox>
+#include <QDir>
+#include <QMessageBox>
-/* First page of options */
-class MainOptionsPage : public QWidget
+class OptionsPage: public QWidget
+{
+ Q_OBJECT
+public:
+ explicit OptionsPage(QWidget *parent=0): QWidget(parent) {}
+
+ virtual void setMapper(MonitoredDataMapper *mapper) = 0;
+};
+
+class MainOptionsPage: public OptionsPage
{
Q_OBJECT
public:
explicit MainOptionsPage(QWidget *parent=0);
- void setMapper(MonitoredDataMapper *mapper);
+ virtual void setMapper(MonitoredDataMapper *mapper);
+private:
+ QCheckBox *detach_database;
+ BitcoinAmountField *fee_edit;
+};
+
+class WindowOptionsPage: public OptionsPage
+{
+ Q_OBJECT
+public:
+ explicit WindowOptionsPage(QWidget *parent=0);
+
+ virtual void setMapper(MonitoredDataMapper *mapper);
private:
QCheckBox *bitcoin_at_startup;
#ifndef Q_WS_MAC
QCheckBox *minimize_to_tray;
#endif
- QCheckBox *map_port_upnp;
#ifndef Q_WS_MAC
QCheckBox *minimize_on_close;
#endif
- QCheckBox *connect_socks4;
- QCheckBox *detach_database;
- QLineEdit *proxy_ip;
- QLineEdit *proxy_port;
- BitcoinAmountField *fee_edit;
-
-signals:
-
-public slots:
-
};
-class DisplayOptionsPage : public QWidget
+class DisplayOptionsPage: public OptionsPage
{
Q_OBJECT
public:
explicit DisplayOptionsPage(QWidget *parent=0);
- void setMapper(MonitoredDataMapper *mapper);
+ virtual void setMapper(MonitoredDataMapper *mapper);
private:
+ QValueComboBox *lang;
QValueComboBox *unit;
QCheckBox *display_addresses;
-signals:
+ bool restart_warning_displayed;
+private slots:
+ void showRestartWarning();
+};
-public slots:
+class NetworkOptionsPage: public OptionsPage
+{
+ Q_OBJECT
+public:
+ explicit NetworkOptionsPage(QWidget *parent=0);
+ virtual void setMapper(MonitoredDataMapper *mapper);
+private:
+ QCheckBox *map_port_upnp;
+ QCheckBox *connect_socks4;
+ QLineEdit *proxy_ip;
+ QLineEdit *proxy_port;
+ BitcoinAmountField *fee_edit;
};
+
#include "optionsdialog.moc"
OptionsDialog::OptionsDialog(QWidget *parent):
QDialog(parent), contents_widget(0), pages_widget(0),
- model(0), main_page(0), display_page(0)
+ model(0)
{
contents_widget = new QListWidget();
contents_widget->setMaximumWidth(128);
pages_widget = new QStackedWidget();
- pages_widget->setMinimumWidth(300);
+ pages_widget->setMinimumWidth(500);
+ pages_widget->setMinimumHeight(300);
- QListWidgetItem *item_main = new QListWidgetItem(tr("Main"));
- contents_widget->addItem(item_main);
- main_page = new MainOptionsPage(this);
- pages_widget->addWidget(main_page);
+ pages.append(new MainOptionsPage(this));
+ pages.append(new NetworkOptionsPage(this));
+ pages.append(new WindowOptionsPage(this));
+ pages.append(new DisplayOptionsPage(this));
- QListWidgetItem *item_display = new QListWidgetItem(tr("Display"));
- contents_widget->addItem(item_display);
- display_page = new DisplayOptionsPage(this);
- pages_widget->addWidget(display_page);
+ foreach(OptionsPage *page, pages)
+ {
+ QListWidgetItem *item = new QListWidgetItem(page->windowTitle());
+ contents_widget->addItem(item);
+ pages_widget->addWidget(page);
+ }
contents_widget->setCurrentRow(0);
@@ -125,8 +155,11 @@ void OptionsDialog::setModel(OptionsModel *model)
this->model = model;
mapper->setModel(model);
- main_page->setMapper(mapper);
- display_page->setMapper(mapper);
+
+ foreach(OptionsPage *page, pages)
+ {
+ page->setMapper(mapper);
+ }
mapper->toFirst();
}
@@ -163,10 +196,116 @@ void OptionsDialog::disableApply()
apply_button->setEnabled(false);
}
+/* Main options */
MainOptionsPage::MainOptionsPage(QWidget *parent):
- QWidget(parent)
+ OptionsPage(parent)
+{
+ QVBoxLayout *layout = new QVBoxLayout();
+ setWindowTitle(tr("Main"));
+
+ QLabel *fee_help = new QLabel(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
+ fee_help->setWordWrap(true);
+ layout->addWidget(fee_help);
+
+ QHBoxLayout *fee_hbox = new QHBoxLayout();
+ fee_hbox->addSpacing(18);
+ QLabel *fee_label = new QLabel(tr("Pay transaction &fee"));
+ fee_hbox->addWidget(fee_label);
+ fee_edit = new BitcoinAmountField();
+
+ fee_label->setBuddy(fee_edit);
+ fee_hbox->addWidget(fee_edit);
+ fee_hbox->addStretch(1);
+
+ layout->addLayout(fee_hbox);
+
+ detach_database = new QCheckBox(tr("Detach databases at shutdown"));
+ detach_database->setToolTip(tr("Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached."));
+ layout->addWidget(detach_database);
+
+ layout->addStretch(1); // Extra space at bottom
+ setLayout(layout);
+}
+
+void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
+{
+ // Map model to widgets
+ mapper->addMapping(fee_edit, OptionsModel::Fee);
+ mapper->addMapping(detach_database, OptionsModel::DetachDatabases);
+}
+
+/* Display options */
+DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
+ OptionsPage(parent), restart_warning_displayed(false)
+{
+ setWindowTitle(tr("Display"));
+
+ QVBoxLayout *layout = new QVBoxLayout();
+
+ QHBoxLayout *lang_hbox = new QHBoxLayout();
+ lang_hbox->addSpacing(18);
+ QLabel *lang_label = new QLabel(tr("User Interface &Language: "));
+ lang_hbox->addWidget(lang_label);
+ lang = new QValueComboBox(this);
+ // Make list of languages
+ QDir translations(":translations");
+ lang->addItem("(default)", QVariant(""));
+ foreach(const QString &langStr, translations.entryList())
+ {
+ lang->addItem(langStr, QVariant(langStr));
+ }
+
+ lang->setToolTip(tr("The user interface language can be set here. This setting will only take effect after restarting Bitcoin."));
+ connect(lang, SIGNAL(activated(int)), this, SLOT(showRestartWarning()));
+
+ lang_label->setBuddy(lang);
+ lang_hbox->addWidget(lang);
+
+ layout->addLayout(lang_hbox);
+
+ QHBoxLayout *unit_hbox = new QHBoxLayout();
+ unit_hbox->addSpacing(18);
+ QLabel *unit_label = new QLabel(tr("&Unit to show amounts in: "));
+ unit_hbox->addWidget(unit_label);
+ unit = new QValueComboBox(this);
+ unit->setModel(new BitcoinUnits(this));
+ unit->setToolTip(tr("Choose the default subdivision unit to show in the interface, and when sending coins"));
+
+ unit_label->setBuddy(unit);
+ unit_hbox->addWidget(unit);
+
+ layout->addLayout(unit_hbox);
+
+ display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
+ display_addresses->setToolTip(tr("Whether to show Bitcoin addresses in the transaction list"));
+ layout->addWidget(display_addresses);
+
+ layout->addStretch();
+ setLayout(layout);
+}
+
+void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper)
+{
+ mapper->addMapping(lang, OptionsModel::Language);
+ mapper->addMapping(unit, OptionsModel::DisplayUnit);
+ mapper->addMapping(display_addresses, OptionsModel::DisplayAddresses);
+}
+
+void DisplayOptionsPage::showRestartWarning()
+{
+ if(!restart_warning_displayed)
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting Bitcoin."), QMessageBox::Ok);
+ restart_warning_displayed = true;
+ }
+}
+
+/* Window options */
+WindowOptionsPage::WindowOptionsPage(QWidget *parent):
+ OptionsPage(parent)
{
QVBoxLayout *layout = new QVBoxLayout();
+ setWindowTitle(tr("Window"));
bitcoin_at_startup = new QCheckBox(tr("&Start Bitcoin on window system startup"));
bitcoin_at_startup->setToolTip(tr("Automatically start Bitcoin after the computer is turned on"));
@@ -182,6 +321,29 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
layout->addWidget(minimize_on_close);
#endif
+ layout->addStretch(1); // Extra space at bottom
+ setLayout(layout);
+}
+
+void WindowOptionsPage::setMapper(MonitoredDataMapper *mapper)
+{
+ // Map model to widgets
+ mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup);
+#ifndef Q_WS_MAC
+ mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray);
+#endif
+#ifndef Q_WS_MAC
+ mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose);
+#endif
+}
+
+/* Network options */
+NetworkOptionsPage::NetworkOptionsPage(QWidget *parent):
+ OptionsPage(parent)
+{
+ QVBoxLayout *layout = new QVBoxLayout();
+ setWindowTitle(tr("Network"));
+
map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled."));
layout->addWidget(map_port_upnp);
@@ -211,31 +373,9 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
proxy_port_label->setBuddy(proxy_port);
proxy_hbox->addWidget(proxy_port);
proxy_hbox->addStretch(1);
-
layout->addLayout(proxy_hbox);
- QLabel *fee_help = new QLabel(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
- fee_help->setWordWrap(true);
- layout->addWidget(fee_help);
-
- QHBoxLayout *fee_hbox = new QHBoxLayout();
- fee_hbox->addSpacing(18);
- QLabel *fee_label = new QLabel(tr("Pay transaction &fee"));
- fee_hbox->addWidget(fee_label);
- fee_edit = new BitcoinAmountField();
- fee_edit->setToolTip(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
-
- fee_label->setBuddy(fee_edit);
- fee_hbox->addWidget(fee_edit);
- fee_hbox->addStretch(1);
-
- layout->addLayout(fee_hbox);
-
- detach_database = new QCheckBox(tr("Detach databases at shutdown"));
- detach_database->setToolTip(tr("Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached."));
- layout->addWidget(detach_database);
layout->addStretch(1); // Extra space at bottom
-
setLayout(layout);
connect(connect_socks4, SIGNAL(toggled(bool)), proxy_ip, SLOT(setEnabled(bool)));
@@ -246,53 +386,11 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
#endif
}
-void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
+void NetworkOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
// Map model to widgets
- mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup);
-#ifndef Q_WS_MAC
- mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray);
-#endif
mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP);
-#ifndef Q_WS_MAC
- mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose);
-#endif
mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4);
mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
mapper->addMapping(proxy_port, OptionsModel::ProxyPort);
- mapper->addMapping(fee_edit, OptionsModel::Fee);
- mapper->addMapping(detach_database, OptionsModel::DetachDatabases);
-}
-
-DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
- QWidget(parent)
-{
- QVBoxLayout *layout = new QVBoxLayout();
-
- QHBoxLayout *unit_hbox = new QHBoxLayout();
- unit_hbox->addSpacing(18);
- QLabel *unit_label = new QLabel(tr("&Unit to show amounts in: "));
- unit_hbox->addWidget(unit_label);
- unit = new QValueComboBox(this);
- unit->setModel(new BitcoinUnits(this));
- unit->setToolTip(tr("Choose the default subdivision unit to show in the interface, and when sending coins"));
-
- unit_label->setBuddy(unit);
- unit_hbox->addWidget(unit);
-
- layout->addLayout(unit_hbox);
-
- display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
- display_addresses->setToolTip(tr("Whether to show Bitcoin addresses in the transaction list"));
- layout->addWidget(display_addresses);
-
- layout->addStretch();
-
- setLayout(layout);
-}
-
-void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper)
-{
- mapper->addMapping(unit, OptionsModel::DisplayUnit);
- mapper->addMapping(display_addresses, OptionsModel::DisplayAddresses);
}
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index 9e1f87c646..ea0cbb8bfc 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -2,6 +2,7 @@
#define OPTIONSDIALOG_H
#include <QDialog>
+#include <QList>
QT_BEGIN_NAMESPACE
class QStackedWidget;
@@ -10,8 +11,7 @@ class QListWidgetItem;
class QPushButton;
QT_END_NAMESPACE
class OptionsModel;
-class MainOptionsPage;
-class DisplayOptionsPage;
+class OptionsPage;
class MonitoredDataMapper;
/** Preferences dialog. */
@@ -43,11 +43,7 @@ private:
MonitoredDataMapper *mapper;
QPushButton *apply_button;
- // Pages
- MainOptionsPage *main_page;
- DisplayOptionsPage *display_page;
-
- void setupMainPage();
+ QList<OptionsPage*> pages;
};
#endif // OPTIONSDIALOG_H
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 5bba308cf2..78448d3ee1 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -21,6 +21,7 @@ void OptionsModel::Init()
fMinimizeToTray = settings.value("fMinimizeToTray", false).toBool();
fMinimizeOnClose = settings.value("fMinimizeOnClose", false).toBool();
nTransactionFee = settings.value("nTransactionFee").toLongLong();
+ language = settings.value("language", "").toString();
// These are shared with core bitcoin; we want
// command-line options to override the GUI settings:
@@ -30,6 +31,8 @@ void OptionsModel::Init()
SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString());
if (settings.contains("detachDB"))
SoftSetBoolArg("-detachdb", settings.value("detachDB").toBool());
+ if (!language.isEmpty())
+ SoftSetArg("-lang", language.toStdString());
}
bool OptionsModel::Upgrade()
@@ -125,6 +128,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return QVariant(bDisplayAddresses);
case DetachDatabases:
return QVariant(fDetachDB);
+ case Language:
+ return settings.value("language", "");
default:
return QVariant();
}
@@ -213,6 +218,10 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
settings.setValue("detachDB", fDetachDB);
}
break;
+ case Language: {
+ settings.setValue("language", value);
+ }
+ break;
default:
break;
}
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index da4e86f104..4315a33f8c 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -27,6 +27,7 @@ public:
DisplayUnit, // BitcoinUnits::Unit
DisplayAddresses, // bool
DetachDatabases, // bool
+ Language, // QString
OptionIDRowCount,
};
@@ -45,11 +46,13 @@ public:
bool getMinimizeOnClose();
int getDisplayUnit();
bool getDisplayAddresses();
+ QString getLanguage() { return language; }
private:
int nDisplayUnit;
bool bDisplayAddresses;
bool fMinimizeToTray;
bool fMinimizeOnClose;
+ QString language;
signals:
void displayUnitChanged(int unit);
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 5b5a8f5271..259f819deb 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -98,23 +98,9 @@ OverviewPage::OverviewPage(QWidget *parent) :
{
ui->setupUi(this);
- // Balance: <balance>
- ui->labelBalance->setFont(QFont("Monospace", -1, QFont::Bold));
- ui->labelBalance->setToolTip(tr("Your current balance"));
- ui->labelBalance->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
-
- // Unconfirmed balance: <balance>
- ui->labelUnconfirmed->setFont(QFont("Monospace", -1, QFont::Bold));
- ui->labelUnconfirmed->setToolTip(tr("Total of transactions that have yet to be confirmed, and do not yet count toward the current balance"));
- ui->labelUnconfirmed->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
-
- ui->labelNumTransactions->setToolTip(tr("Total number of transactions in wallet"));
-
// Recent transactions
- ui->listTransactions->setStyleSheet("QListView { background:transparent }");
ui->listTransactions->setItemDelegate(txdelegate);
ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
- ui->listTransactions->setSelectionMode(QAbstractItemView::NoSelection);
ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp
index 2a428fb79e..d8e2007a2f 100644
--- a/src/qt/qrcodedialog.cpp
+++ b/src/qt/qrcodedialog.cpp
@@ -118,7 +118,7 @@ void QRCodeDialog::on_lnMessage_textChanged(const QString &arg1)
void QRCodeDialog::on_btnSaveAs_clicked()
{
- QString fn = GUIUtil::getSaveFileName(this, tr("Save Image..."), QString(), tr("PNG Images (*.png)"));
+ QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Images (*.png)"));
if (!fn.isEmpty())
myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn);
}
diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp
index c0ad8c12e5..d7ce3d0130 100644
--- a/src/qt/qvaluecombobox.cpp
+++ b/src/qt/qvaluecombobox.cpp
@@ -6,12 +6,12 @@ QValueComboBox::QValueComboBox(QWidget *parent) :
connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(handleSelectionChanged(int)));
}
-int QValueComboBox::value() const
+QVariant QValueComboBox::value() const
{
- return itemData(currentIndex(), role).toInt();
+ return itemData(currentIndex(), role);
}
-void QValueComboBox::setValue(int value)
+void QValueComboBox::setValue(const QVariant &value)
{
setCurrentIndex(findData(value, role));
}
diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h
index 11f342d71c..1a47bb6565 100644
--- a/src/qt/qvaluecombobox.h
+++ b/src/qt/qvaluecombobox.h
@@ -2,19 +2,20 @@
#define QVALUECOMBOBOX_H
#include <QComboBox>
+#include <QVariant>
/* QComboBox that can be used with QDataWidgetMapper to select ordinal values from a model. */
class QValueComboBox : public QComboBox
{
Q_OBJECT
- Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged USER true)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged USER true)
public:
explicit QValueComboBox(QWidget *parent = 0);
- int value() const;
- void setValue(int value);
+ QVariant value() const;
+ void setValue(const QVariant &value);
- /** Specify model role to use as ordinal value */
+ /** Specify model role to use as ordinal value (defaults to Qt::UserRole) */
void setRole(int role);
signals:
diff --git a/src/qt/res/icons/qrcode.png b/src/qt/res/icons/qrcode.png
new file mode 100644
index 0000000000..a8d97174b3
--- /dev/null
+++ b/src/qt/res/icons/qrcode.png
Binary files differ
diff --git a/src/qt/res/images/qrcode.png b/src/qt/res/images/qrcode.png
deleted file mode 100644
index c89a49bbce..0000000000
--- a/src/qt/res/images/qrcode.png
+++ /dev/null
Binary files differ
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
new file mode 100644
index 0000000000..6d983989e9
--- /dev/null
+++ b/src/qt/rpcconsole.cpp
@@ -0,0 +1,312 @@
+#include "rpcconsole.h"
+#include "ui_rpcconsole.h"
+
+#include "clientmodel.h"
+#include "bitcoinrpc.h"
+#include "guiutil.h"
+
+#include <QTime>
+#include <QTimer>
+#include <QThread>
+#include <QTextEdit>
+#include <QKeyEvent>
+
+#include <boost/tokenizer.hpp>
+
+// TODO: make it possible to filter out categories (esp debug messages when implemented)
+// TODO: receive errors and debug messages through ClientModel
+
+const int CONSOLE_SCROLLBACK = 50;
+const int CONSOLE_HISTORY = 50;
+
+/* Object for executing console RPC commands in a separate thread.
+*/
+class RPCExecutor: public QObject
+{
+ Q_OBJECT
+public slots:
+ void start();
+ void request(const QString &command);
+signals:
+ void reply(int category, const QString &command);
+};
+
+#include "rpcconsole.moc"
+
+void RPCExecutor::start()
+{
+ // Nothing to do
+}
+
+void RPCExecutor::request(const QString &command)
+{
+ // Parse shell-like command line into separate arguments
+ boost::escaped_list_separator<char> els('\\',' ','\"');
+ std::string strCommand = command.toStdString();
+ boost::tokenizer<boost::escaped_list_separator<char> > tok(strCommand, els);
+
+ std::string strMethod;
+ std::vector<std::string> strParams;
+ int n = 0;
+ for(boost::tokenizer<boost::escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg,++n)
+ {
+ if(n == 0) // First parameter is the command
+ strMethod = *beg;
+ else
+ strParams.push_back(*beg);
+ }
+
+ try {
+ std::string strPrint;
+ json_spirit::Value result = tableRPC.execute(strMethod, RPCConvertValues(strMethod, strParams));
+
+ // Format result reply
+ if (result.type() == json_spirit::null_type)
+ strPrint = "";
+ else if (result.type() == json_spirit::str_type)
+ strPrint = result.get_str();
+ else
+ strPrint = write_string(result, true);
+
+ emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
+ }
+ catch (json_spirit::Object& objError)
+ {
+ emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
+ }
+ catch (std::exception& e)
+ {
+ emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
+ }
+}
+
+RPCConsole::RPCConsole(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::RPCConsole),
+ firstLayout(true),
+ historyPtr(0)
+{
+ ui->setupUi(this);
+ ui->messagesWidget->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
+ ui->messagesWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
+
+ // Install event filter for up and down arrow
+ ui->lineEdit->installEventFilter(this);
+
+ // Add "Copy message" to context menu explicitly
+ QAction *copyMessageAction = new QAction(tr("&Copy"), this);
+ copyMessageAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_C));
+ copyMessageAction->setShortcutContext(Qt::WidgetShortcut);
+ connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
+ ui->messagesWidget->addAction(copyMessageAction);
+
+ connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
+
+ startExecutor();
+
+ clear();
+}
+
+RPCConsole::~RPCConsole()
+{
+ emit stopExecutor();
+ delete ui;
+}
+
+bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
+{
+ if(obj == ui->lineEdit)
+ {
+ if(event->type() == QEvent::KeyPress)
+ {
+ QKeyEvent *key = static_cast<QKeyEvent*>(event);
+ switch(key->key())
+ {
+ case Qt::Key_Up: browseHistory(-1); return true;
+ case Qt::Key_Down: browseHistory(1); return true;
+ }
+ }
+ }
+ return QDialog::eventFilter(obj, event);
+}
+
+void RPCConsole::setClientModel(ClientModel *model)
+{
+ this->clientModel = model;
+ if(model)
+ {
+ // Subscribe to information, replies, messages, errors
+ connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
+ connect(model, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
+
+ // Provide initial values
+ ui->clientVersion->setText(model->formatFullVersion());
+ ui->clientName->setText(model->clientName());
+ ui->buildDate->setText(model->formatBuildDate());
+
+ setNumConnections(model->getNumConnections());
+ ui->isTestNet->setChecked(model->isTestNet());
+
+ setNumBlocks(model->getNumBlocks());
+ }
+}
+
+static QColor categoryColor(int category)
+{
+ switch(category)
+ {
+ case RPCConsole::MC_ERROR: return QColor(255,0,0); break;
+ case RPCConsole::MC_DEBUG: return QColor(192,192,192); break;
+ case RPCConsole::CMD_REQUEST: return QColor(128,128,128); break;
+ case RPCConsole::CMD_REPLY: return QColor(128,255,128); break;
+ case RPCConsole::CMD_ERROR: return QColor(255,128,128); break;
+ default: return QColor(0,0,0);
+ }
+}
+
+void RPCConsole::clear()
+{
+ ui->messagesWidget->clear();
+ ui->messagesWidget->setRowCount(0);
+ ui->lineEdit->clear();
+ ui->lineEdit->setFocus();
+
+ message(CMD_REPLY, tr("Welcome to the bitcoin RPC console.")+"\n"+
+ tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.")+"\n"+
+ tr("Type \"help\" for an overview of available commands."));
+}
+
+void RPCConsole::message(int category, const QString &message)
+{
+ // Add row to messages widget
+ int row = ui->messagesWidget->rowCount();
+ ui->messagesWidget->setRowCount(row+1);
+
+ QTime time = QTime::currentTime();
+ QTableWidgetItem *newTime = new QTableWidgetItem(time.toString());
+ newTime->setData(Qt::DecorationRole, categoryColor(category));
+ newTime->setForeground(QColor(128,128,128));
+ newTime->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); // make non-editable
+
+ int numLines = message.count("\n") + 1;
+ // As Qt doesn't like very tall cells (they break scrolling) keep only short messages in
+ // the cell text, longer messages trigger a display widget with scroll bar
+ if(numLines < 5)
+ {
+ QTableWidgetItem *newItem = new QTableWidgetItem(message);
+ newItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); // make non-editable
+ if(category == CMD_ERROR) // Coloring error messages in red
+ newItem->setForeground(QColor(255,16,16));
+ ui->messagesWidget->setItem(row, 1, newItem);
+ } else {
+ QTextEdit *newWidget = new QTextEdit;
+ newWidget->setText(message);
+ newWidget->setMaximumHeight(100);
+ newWidget->setReadOnly(true);
+ ui->messagesWidget->setCellWidget(row, 1, newWidget);
+ }
+
+ ui->messagesWidget->setItem(row, 0, newTime);
+ ui->messagesWidget->resizeRowToContents(row);
+ // Preserve only limited scrollback buffer
+ while(ui->messagesWidget->rowCount() > CONSOLE_SCROLLBACK)
+ ui->messagesWidget->removeRow(0);
+ // Scroll to bottom after table is updated
+ QTimer::singleShot(0, ui->messagesWidget, SLOT(scrollToBottom()));
+}
+
+void RPCConsole::setNumConnections(int count)
+{
+ ui->numberOfConnections->setText(QString::number(count));
+}
+
+void RPCConsole::setNumBlocks(int count)
+{
+ ui->numberOfBlocks->setText(QString::number(count));
+ if(clientModel)
+ {
+ ui->totalBlocks->setText(QString::number(clientModel->getNumBlocksOfPeers()));
+ ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
+ }
+}
+
+void RPCConsole::on_lineEdit_returnPressed()
+{
+ QString cmd = ui->lineEdit->text();
+ ui->lineEdit->clear();
+
+ if(!cmd.isEmpty())
+ {
+ message(CMD_REQUEST, cmd);
+ emit cmdRequest(cmd);
+ // Truncate history from current position
+ history.erase(history.begin() + historyPtr, history.end());
+ // Append command to history
+ history.append(cmd);
+ // Enforce maximum history size
+ while(history.size() > CONSOLE_HISTORY)
+ history.removeFirst();
+ // Set pointer to end of history
+ historyPtr = history.size();
+ }
+}
+
+void RPCConsole::browseHistory(int offset)
+{
+ historyPtr += offset;
+ if(historyPtr < 0)
+ historyPtr = 0;
+ if(historyPtr > history.size())
+ historyPtr = history.size();
+ QString cmd;
+ if(historyPtr < history.size())
+ cmd = history.at(historyPtr);
+ ui->lineEdit->setText(cmd);
+}
+
+void RPCConsole::startExecutor()
+{
+ QThread* thread = new QThread;
+ RPCExecutor *executor = new RPCExecutor();
+ executor->moveToThread(thread);
+
+ // Notify executor when thread started (in executor thread)
+ connect(thread, SIGNAL(started()), executor, SLOT(start()));
+ // Replies from executor object must go to this object
+ connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
+ // Requests from this object must go to executor
+ connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
+ // On stopExecutor signal
+ // - queue executor for deletion (in execution thread)
+ // - quit the Qt event loop in the execution thread
+ connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
+ connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
+ // Queue the thread for deletion (in this thread) when it is finished
+ connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
+
+ // Default implementation of QThread::run() simply spins up an event loop in the thread,
+ // which is what we want.
+ thread->start();
+}
+
+void RPCConsole::copyMessage()
+{
+ GUIUtil::copyEntryData(ui->messagesWidget, 1, Qt::EditRole);
+}
+
+void RPCConsole::on_tabWidget_currentChanged(int index)
+{
+ if(ui->tabWidget->widget(index) == ui->tab_console)
+ {
+ if(firstLayout)
+ {
+ // Work around QTableWidget issue:
+ // Call resizeRowsToContents on first Layout request with widget visible,
+ // to make sure multiline messages that were added before the console was shown
+ // have the right height.
+ firstLayout = false;
+ ui->messagesWidget->resizeRowsToContents();
+ }
+ ui->lineEdit->setFocus();
+ }
+}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
new file mode 100644
index 0000000000..2ec47b0cf8
--- /dev/null
+++ b/src/qt/rpcconsole.h
@@ -0,0 +1,65 @@
+#ifndef RPCCONSOLE_H
+#define RPCCONSOLE_H
+
+#include <QDialog>
+
+namespace Ui {
+ class RPCConsole;
+}
+class ClientModel;
+
+/** Local bitcoin RPC console. */
+class RPCConsole: public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit RPCConsole(QWidget *parent = 0);
+ ~RPCConsole();
+
+ void setClientModel(ClientModel *model);
+
+ enum MessageClass {
+ MC_ERROR,
+ MC_DEBUG,
+ CMD_REQUEST,
+ CMD_REPLY,
+ CMD_ERROR
+ };
+
+protected:
+ virtual bool eventFilter(QObject* obj, QEvent *event);
+
+private slots:
+ void on_lineEdit_returnPressed();
+
+ void on_tabWidget_currentChanged(int index);
+
+public slots:
+ void clear();
+ void message(int category, const QString &message);
+ /** Set number of connections shown in the UI */
+ void setNumConnections(int count);
+ /** Set number of blocks shown in the UI */
+ void setNumBlocks(int count);
+ /** Go forward or back in history */
+ void browseHistory(int offset);
+ /** Copy currently selected message to clipboard */
+ void copyMessage();
+
+signals:
+ // For RPC command executor
+ void stopExecutor();
+ void cmdRequest(const QString &command);
+
+private:
+ Ui::RPCConsole *ui;
+ ClientModel *clientModel;
+ bool firstLayout;
+ QStringList history;
+ int historyPtr;
+
+ void startExecutor();
+};
+
+#endif // RPCCONSOLE_H
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index d9b1daf679..5960597c77 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -20,7 +20,11 @@ SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
#ifdef Q_WS_MAC
ui->payToLayout->setSpacing(4);
#endif
-
+#if QT_VERSION >= 0x040700
+ /* Do not move this to the XML file, Qt before 4.7 will choke on it */
+ ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
+ ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
+#endif
setFocusPolicy(Qt::TabFocus);
setFocusProxy(ui->payTo);
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 90fc5b7da3..53cfb409ff 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -102,7 +102,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
//
int64 nTxFee = nDebit - wtx.GetValueOut();
- for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
+ for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
{
const CTxOut& txout = wtx.vout[nOut];
TransactionRecord sub(hash, nTime);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index eaed48bfdf..25d72b2742 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -125,7 +125,7 @@ TransactionView::TransactionView(QWidget *parent) :
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
QAction *editLabelAction = new QAction(tr("Edit label"), this);
- QAction *showDetailsAction = new QAction(tr("Show details..."), this);
+ QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);
contextMenu = new QMenu();
contextMenu->addAction(copyAddressAction);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index a915274da3..b9ccb06c09 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -150,14 +150,21 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
hex = QString::fromStdString(wtx.GetHash().GetHex());
}
- // Add addresses that we've sent to to the address book
+ // Add addresses / update labels that we've sent to to the address book
foreach(const SendCoinsRecipient &rcp, recipients)
{
std::string strAddress = rcp.address.toStdString();
+ std::string strLabel = rcp.label.toStdString();
{
LOCK(wallet->cs_wallet);
- if (!wallet->mapAddressBook.count(strAddress))
- wallet->SetAddressBookName(strAddress, rcp.label.toStdString());
+
+ std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(strAddress);
+
+ // Check if we have a new address or an updated label
+ if (mi == wallet->mapAddressBook.end() || mi->second != strLabel)
+ {
+ wallet->SetAddressBookName(strAddress, strLabel);
+ }
}
}
diff --git a/src/script.cpp b/src/script.cpp
index 65e9b7c9a2..0b103a80bc 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -940,7 +940,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
// ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
int i = 1;
- if (stack.size() < i)
+ if ((int)stack.size() < i)
return false;
int nKeysCount = CastToBigNum(stacktop(-i)).getint();
@@ -951,7 +951,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
return false;
int ikey = ++i;
i += nKeysCount;
- if (stack.size() < i)
+ if ((int)stack.size() < i)
return false;
int nSigsCount = CastToBigNum(stacktop(-i)).getint();
@@ -959,7 +959,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
return false;
int isig = ++i;
i += nSigsCount;
- if (stack.size() < i)
+ if ((int)stack.size() < i)
return false;
// Subset of script starting at the most recent codeseparator
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index e5a8b4f68b..04e2a95d70 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -31,13 +31,13 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
{
CNode::ClearBanned();
CAddress addr1(ip(0xa0b0c001));
- CNode dummyNode1(INVALID_SOCKET, addr1, true);
+ CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
dummyNode1.Misbehaving(100); // Should get banned
BOOST_CHECK(CNode::IsBanned(addr1));
BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different ip, not banned
CAddress addr2(ip(0xa0b0c002));
- CNode dummyNode2(INVALID_SOCKET, addr2, true);
+ CNode dummyNode2(INVALID_SOCKET, addr2, "", true);
dummyNode2.Misbehaving(50);
BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet...
BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be
@@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
CNode::ClearBanned();
mapArgs["-banscore"] = "111"; // because 11 is my favorite number
CAddress addr1(ip(0xa0b0c001));
- CNode dummyNode1(INVALID_SOCKET, addr1, true);
+ CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
dummyNode1.Misbehaving(100);
BOOST_CHECK(!CNode::IsBanned(addr1));
dummyNode1.Misbehaving(10);
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
SetMockTime(nStartTime); // Overrides future calls to GetTime()
CAddress addr(ip(0xa0b0c001));
- CNode dummyNode(INVALID_SOCKET, addr, true);
+ CNode dummyNode(INVALID_SOCKET, addr, "", true);
dummyNode.Misbehaving(100);
BOOST_CHECK(CNode::IsBanned(addr));
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index d52ac74982..de4096cd39 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -67,7 +67,7 @@ const char *vstrOut[] = {
BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
- for (int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
{
BOOST_CHECK_EQUAL(EncodeBase58(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size), vstrOut[i]);
}
@@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
{
std::vector<unsigned char> result;
- for (int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
{
std::vector<unsigned char> expected(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size);
BOOST_CHECK(DecodeBase58(vstrOut[i], result));
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index fff30ef5eb..c5a053e2eb 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -10,7 +10,7 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
{
static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"};
static const std::string vstrOut[] = {"","Zg==","Zm8=","Zm9v","Zm9vYg==","Zm9vYmE=","Zm9vYmFy"};
- for (int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
{
std::string strEnc = EncodeBase64(vstrIn[i]);
BOOST_CHECK(strEnc == vstrOut[i]);
diff --git a/src/util.cpp b/src/util.cpp
index 3d301d21e3..1a57cc6621 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -53,7 +53,6 @@ namespace boost {
#endif
using namespace std;
-using namespace boost;
map<string, string> mapArgs;
map<string, vector<string> > mapMultiArgs;
@@ -328,7 +327,7 @@ bool error(const char *format, ...)
va_end(arg_ptr);
if (ret < 0 || ret >= limit)
{
- buffer[limit-1] = 0;
+ buffer[limit - 1] = 0;
}
printf("ERROR: %s\n", buffer);
return false;
@@ -494,7 +493,7 @@ static void InterpretNegativeSetting(string name, map<string, string>& mapSettin
}
}
-void ParseParameters(int argc, const char*const argv[])
+void ParseParameters(int argc, const char* const argv[])
{
mapArgs.clear();
mapMultiArgs.clear();
@@ -761,8 +760,7 @@ bool WildcardMatch(const string& str, const string& mask)
void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
{
#ifdef WIN32
- char pszModule[MAX_PATH];
- pszModule[0] = '\0';
+ char pszModule[MAX_PATH] = "";
GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
#else
const char* pszModule = "bitcoin";
@@ -801,38 +799,16 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread)
strMiscWarning = pszMessage;
}
-#ifdef WIN32
-boost::filesystem::path MyGetSpecialFolderPath(int nFolder, bool fCreate)
-{
- namespace fs = boost::filesystem;
-
- char pszPath[MAX_PATH] = "";
- if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
- {
- return fs::path(pszPath);
- }
- else if (nFolder == CSIDL_STARTUP)
- {
- return fs::path(getenv("USERPROFILE")) / "Start Menu" / "Programs" / "Startup";
- }
- else if (nFolder == CSIDL_APPDATA)
- {
- return fs::path(getenv("APPDATA"));
- }
- return fs::path("");
-}
-#endif
-
boost::filesystem::path GetDefaultDataDir()
{
namespace fs = boost::filesystem;
-
- // Windows: C:\Documents and Settings\username\Application Data\Bitcoin
+ // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
+ // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
// Mac: ~/Library/Application Support/Bitcoin
// Unix: ~/.bitcoin
#ifdef WIN32
// Windows
- return MyGetSpecialFolderPath(CSIDL_APPDATA, true) / "Bitcoin";
+ return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
#else
fs::path pathRet;
char* pszHome = getenv("HOME");
@@ -843,7 +819,7 @@ boost::filesystem::path GetDefaultDataDir()
#ifdef MAC_OSX
// Mac
pathRet /= "Library/Application Support";
- filesystem::create_directory(pathRet);
+ fs::create_directory(pathRet);
return pathRet / "Bitcoin";
#else
// Unix
@@ -889,9 +865,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
boost::filesystem::path GetConfigFile()
{
- namespace fs = boost::filesystem;
-
- fs::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
+ boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile;
return pathConfigFile;
}
@@ -899,24 +873,21 @@ boost::filesystem::path GetConfigFile()
void ReadConfigFile(map<string, string>& mapSettingsRet,
map<string, vector<string> >& mapMultiSettingsRet)
{
- namespace fs = boost::filesystem;
- namespace pod = boost::program_options::detail;
-
- fs::ifstream streamConfig(GetConfigFile());
+ boost::filesystem::ifstream streamConfig(GetConfigFile());
if (!streamConfig.good())
return; // No bitcoin.conf file is OK
set<string> setOptions;
setOptions.insert("*");
- for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
+ for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
{
// 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)
+ // 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]);
@@ -925,9 +896,7 @@ void ReadConfigFile(map<string, string>& mapSettingsRet,
boost::filesystem::path GetPidFile()
{
- namespace fs = boost::filesystem;
-
- fs::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
+ boost::filesystem::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
return pathPidFile;
}
@@ -1095,14 +1064,30 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const
}
#ifdef WIN32
+boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
+{
+ namespace fs = boost::filesystem;
+
+ char pszPath[MAX_PATH] = "";
+
+ if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
+ {
+ return fs::path(pszPath);
+ }
+
+ printf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
+ return fs::path("");
+}
+
boost::filesystem::path static StartupShortcutPath()
{
- return MyGetSpecialFolderPath(CSIDL_STARTUP, true) / "Bitcoin.lnk";
+ return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
}
bool GetStartOnSystemStartup()
{
- return filesystem::exists(StartupShortcutPath());
+ // check for Bitcoin.lnk
+ return boost::filesystem::exists(StartupShortcutPath());
}
bool SetStartOnSystemStartup(bool fAutoStart)
diff --git a/src/util.h b/src/util.h
index 5f8d0375da..ebd574f896 100644
--- a/src/util.h
+++ b/src/util.h
@@ -163,6 +163,9 @@ boost::filesystem::path GetConfigFile();
boost::filesystem::path GetPidFile();
void CreatePidFile(const boost::filesystem::path &path, pid_t pid);
void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
+#ifdef WIN32
+boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
+#endif
bool GetStartOnSystemStartup();
bool SetStartOnSystemStartup(bool fAutoStart);
void ShrinkDebugFile();
@@ -217,9 +220,11 @@ public:
{
printf("LOCKCONTENTION: %s\n", pszName);
printf("Locker: %s:%d\n", pszFile, nLine);
- }
#endif
lock.lock();
+#ifdef DEBUG_LOCKCONTENTION
+ }
+#endif
}
}
diff --git a/src/version.h b/src/version.h
index 9b92bd618e..423e885f93 100644
--- a/src/version.h
+++ b/src/version.h
@@ -12,8 +12,8 @@
static const int CLIENT_VERSION_MAJOR = 0;
static const int CLIENT_VERSION_MINOR = 6;
-static const int CLIENT_VERSION_REVISION = 1;
-static const int CLIENT_VERSION_BUILD = 3;
+static const int CLIENT_VERSION_REVISION = 99;
+static const int CLIENT_VERSION_BUILD = 0;
static const int CLIENT_VERSION =
1000000 * CLIENT_VERSION_MAJOR
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 709ecac184..e5d57288e8 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -189,7 +189,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
//// debug print
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
- //printf(" %12I64d %s %s %s\n",
+ //printf(" %12"PRI64d" %s %s %s\n",
// wtx.vout[0].nValue,
// DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(),
// wtx.hashBlock.ToString().substr(0,20).c_str(),