aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/allocators.h165
-rw-r--r--src/bitcoinrpc.cpp5
-rw-r--r--src/bitcoinrpc.h1
-rw-r--r--src/checkpoints.cpp2
-rw-r--r--src/crypter.cpp12
-rw-r--r--src/crypter.h11
-rw-r--r--src/init.cpp8
-rw-r--r--src/irc.cpp21
-rw-r--r--src/main.cpp55
-rw-r--r--src/main.h2
-rw-r--r--src/makefile.linux-mingw22
-rw-r--r--src/makefile.mingw30
-rw-r--r--src/makefile.osx12
-rw-r--r--src/makefile.unix7
-rw-r--r--src/net.cpp4
-rw-r--r--src/qt/bitcoin.cpp53
-rw-r--r--src/qt/bitcoingui.cpp17
-rw-r--r--src/qt/bitcoinstrings.cpp1
-rw-r--r--src/qt/forms/aboutdialog.ui19
-rw-r--r--src/qt/locale/bitcoin_cs.ts186
-rw-r--r--src/qt/locale/bitcoin_en.ts142
-rw-r--r--src/qt/qtipcserver.cpp54
-rw-r--r--src/qt/qtipcserver.h3
-rw-r--r--src/qt/rpcconsole.cpp126
-rw-r--r--src/qt/transactionrecord.cpp12
-rw-r--r--src/qt/transactiontablemodel.cpp4
-rw-r--r--src/rpcmining.cpp4
-rw-r--r--src/rpcrawtransaction.cpp42
-rw-r--r--src/rpcwallet.cpp92
-rw-r--r--src/script.cpp3
-rw-r--r--src/test/allocator_tests.cpp115
-rw-r--r--src/util.cpp2
-rw-r--r--src/version.h4
-rw-r--r--src/wallet.cpp147
-rw-r--r--src/wallet.h15
35 files changed, 999 insertions, 399 deletions
diff --git a/src/allocators.h b/src/allocators.h
index ddeabc48c5..99afa10c25 100644
--- a/src/allocators.h
+++ b/src/allocators.h
@@ -7,6 +7,8 @@
#include <string.h>
#include <string>
+#include <boost/thread/mutex.hpp>
+#include <map>
#ifdef WIN32
#ifdef _WIN32_WINNT
@@ -22,23 +24,156 @@
// Note that VirtualLock does not provide this as a guarantee on Windows,
// but, in practice, memory that has been VirtualLock'd almost never gets written to
// the pagefile except in rare circumstances where memory is extremely low.
-#define mlock(p, n) VirtualLock((p), (n));
-#define munlock(p, n) VirtualUnlock((p), (n));
#else
#include <sys/mman.h>
-#include <limits.h>
-/* This comes from limits.h if it's not defined there set a sane default */
-#ifndef PAGESIZE
-#include <unistd.h>
-#define PAGESIZE sysconf(_SC_PAGESIZE)
+#include <limits.h> // for PAGESIZE
+#include <unistd.h> // for sysconf
#endif
-#define mlock(a,b) \
- mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
- (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
-#define munlock(a,b) \
- munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
- (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
+
+/**
+ * Thread-safe class to keep track of locked (ie, non-swappable) memory pages.
+ *
+ * Memory locks do not stack, that is, pages which have been locked several times by calls to mlock()
+ * will be unlocked by a single call to munlock(). This can result in keying material ending up in swap when
+ * those functions are used naively. This class simulates stacking memory locks by keeping a counter per page.
+ *
+ * @note By using a map from each page base address to lock count, this class is optimized for
+ * small objects that span up to a few pages, mostly smaller than a page. To support large allocations,
+ * something like an interval tree would be the preferred data structure.
+ */
+template <class Locker> class LockedPageManagerBase
+{
+public:
+ LockedPageManagerBase(size_t page_size):
+ page_size(page_size)
+ {
+ // Determine bitmask for extracting page from address
+ assert(!(page_size & (page_size-1))); // size must be power of two
+ page_mask = ~(page_size - 1);
+ }
+
+ // For all pages in affected range, increase lock count
+ void LockRange(void *p, size_t size)
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ if(!size) return;
+ const size_t base_addr = reinterpret_cast<size_t>(p);
+ const size_t start_page = base_addr & page_mask;
+ const size_t end_page = (base_addr + size - 1) & page_mask;
+ for(size_t page = start_page; page <= end_page; page += page_size)
+ {
+ Histogram::iterator it = histogram.find(page);
+ if(it == histogram.end()) // Newly locked page
+ {
+ locker.Lock(reinterpret_cast<void*>(page), page_size);
+ histogram.insert(std::make_pair(page, 1));
+ }
+ else // Page was already locked; increase counter
+ {
+ it->second += 1;
+ }
+ }
+ }
+
+ // For all pages in affected range, decrease lock count
+ void UnlockRange(void *p, size_t size)
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ if(!size) return;
+ const size_t base_addr = reinterpret_cast<size_t>(p);
+ const size_t start_page = base_addr & page_mask;
+ const size_t end_page = (base_addr + size - 1) & page_mask;
+ for(size_t page = start_page; page <= end_page; page += page_size)
+ {
+ Histogram::iterator it = histogram.find(page);
+ assert(it != histogram.end()); // Cannot unlock an area that was not locked
+ // Decrease counter for page, when it is zero, the page will be unlocked
+ it->second -= 1;
+ if(it->second == 0) // Nothing on the page anymore that keeps it locked
+ {
+ // Unlock page and remove the count from histogram
+ locker.Unlock(reinterpret_cast<void*>(page), page_size);
+ histogram.erase(it);
+ }
+ }
+ }
+
+ // Get number of locked pages for diagnostics
+ int GetLockedPageCount()
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ return histogram.size();
+ }
+
+private:
+ Locker locker;
+ boost::mutex mutex;
+ size_t page_size, page_mask;
+ // map of page base address to lock count
+ typedef std::map<size_t,int> Histogram;
+ Histogram histogram;
+};
+
+/** Determine system page size in bytes */
+static inline size_t GetSystemPageSize()
+{
+ size_t page_size;
+#if defined(WIN32)
+ SYSTEM_INFO sSysInfo;
+ GetSystemInfo(&sSysInfo);
+ page_size = sSysInfo.dwPageSize;
+#elif defined(PAGESIZE) // defined in limits.h
+ page_size = PAGESIZE;
+#else // assume some POSIX OS
+ page_size = sysconf(_SC_PAGESIZE);
+#endif
+ return page_size;
+}
+
+/**
+ * OS-dependent memory page locking/unlocking.
+ * Defined as policy class to make stubbing for test possible.
+ */
+class MemoryPageLocker
+{
+public:
+ /** Lock memory pages.
+ * addr and len must be a multiple of the system page size
+ */
+ bool Lock(const void *addr, size_t len)
+ {
+#ifdef WIN32
+ return VirtualLock(const_cast<void*>(addr), len);
+#else
+ return mlock(addr, len) == 0;
+#endif
+ }
+ /** Unlock memory pages.
+ * addr and len must be a multiple of the system page size
+ */
+ bool Unlock(const void *addr, size_t len)
+ {
+#ifdef WIN32
+ return VirtualUnlock(const_cast<void*>(addr), len);
+#else
+ return munlock(addr, len) == 0;
#endif
+ }
+};
+
+/**
+ * Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in
+ * std::allocator templates.
+ */
+class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker>
+{
+public:
+ static LockedPageManager instance; // instantiated in util.cpp
+private:
+ LockedPageManager():
+ LockedPageManagerBase<MemoryPageLocker>(GetSystemPageSize())
+ {}
+};
//
// Allocator that locks its contents from being paged
@@ -69,7 +204,7 @@ struct secure_allocator : public std::allocator<T>
T *p;
p = std::allocator<T>::allocate(n, hint);
if (p != NULL)
- mlock(p, sizeof(T) * n);
+ LockedPageManager::instance.LockRange(p, sizeof(T) * n);
return p;
}
@@ -78,7 +213,7 @@ struct secure_allocator : public std::allocator<T>
if (p != NULL)
{
memset(p, 0, sizeof(T) * n);
- munlock(p, sizeof(T) * n);
+ LockedPageManager::instance.UnlockRange(p, sizeof(T) * n);
}
std::allocator<T>::deallocate(p, n);
}
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 5537eb4815..2271ff07c4 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -104,8 +104,7 @@ Value ValueFromAmount(int64 amount)
return (double)amount / (double)COIN;
}
-std::string
-HexBits(unsigned int nBits)
+std::string HexBits(unsigned int nBits)
{
union {
int32_t nBits;
@@ -231,6 +230,7 @@ static const CRPCCommand vRPCCommands[] =
{ "getblockhash", &getblockhash, false, false },
{ "gettransaction", &gettransaction, false, false },
{ "listtransactions", &listtransactions, false, false },
+ { "listaddressgroupings", &listaddressgroupings, false, false },
{ "signmessage", &signmessage, false, false },
{ "verifymessage", &verifymessage, false, false },
{ "getwork", &getwork, true, false },
@@ -1139,6 +1139,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "addmultisigaddress" && n > 1) ConvertTo<Array>(params[1]);
if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]);
if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]);
if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
index 6a1857cb44..94446c36bb 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -114,6 +114,7 @@ extern json_spirit::Value addmultisigaddress(const json_spirit::Array& params, b
extern json_spirit::Value listreceivedbyaddress(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value listreceivedbyaccount(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value listtransactions(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value listaddressgroupings(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value listaccounts(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value listsinceblock(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gettransaction(const json_spirit::Array& params, bool fHelp);
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 2df647e83d..8208854962 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -29,7 +29,7 @@ namespace Checkpoints
(105000, uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97"))
(134444, uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"))
(168000, uint256("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763"))
- (185333, uint256("0x00000000000002334c71b8706940c20348af897a9cfc0f1a6dab0d14d4ceb815"))
+ (193000, uint256("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317"))
;
static MapCheckpoints mapCheckpointsTestnet =
diff --git a/src/crypter.cpp b/src/crypter.cpp
index 411a1ee4c1..181b8fa00a 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -17,12 +17,6 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v
if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
return false;
- // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
- // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
- // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
- mlock(&chKey[0], sizeof chKey);
- mlock(&chIV[0], sizeof chIV);
-
int i = 0;
if (nDerivationMethod == 0)
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
@@ -44,12 +38,6 @@ bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigne
if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE)
return false;
- // Try to keep the key data out of swap
- // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
- // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
- mlock(&chKey[0], sizeof chKey);
- mlock(&chIV[0], sizeof chIV);
-
memcpy(&chKey[0], &chNewKey[0], sizeof chKey);
memcpy(&chIV[0], &chNewIV[0], sizeof chIV);
diff --git a/src/crypter.h b/src/crypter.h
index d1bdb92c91..04538a3fa5 100644
--- a/src/crypter.h
+++ b/src/crypter.h
@@ -78,19 +78,26 @@ public:
{
memset(&chKey, 0, sizeof chKey);
memset(&chIV, 0, sizeof chIV);
- munlock(&chKey, sizeof chKey);
- munlock(&chIV, sizeof chIV);
fKeySet = false;
}
CCrypter()
{
fKeySet = false;
+
+ // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
+ // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
+ // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
+ LockedPageManager::instance.LockRange(&chKey[0], sizeof chKey);
+ LockedPageManager::instance.LockRange(&chIV[0], sizeof chIV);
}
~CCrypter()
{
CleanKey();
+
+ LockedPageManager::instance.UnlockRange(&chKey[0], sizeof chKey);
+ LockedPageManager::instance.UnlockRange(&chIV[0], sizeof chIV);
}
};
diff --git a/src/init.cpp b/src/init.cpp
index 1a1e31c2f3..b085a23d60 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -225,7 +225,7 @@ std::string HelpMessage()
" -datadir=<dir> " + _("Specify data directory") + "\n" +
" -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n" +
" -dblogsize=<n> " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
- " -timeout=<n> " + _("Specify connection timeout (in milliseconds)") + "\n" +
+ " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000))") + "\n" +
" -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" +
" -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n" +
" -tor=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n"
@@ -500,6 +500,12 @@ bool AppInit2()
SetLimited(net);
}
}
+#if defined(USE_IPV6)
+#if ! USE_IPV6
+ else
+ SetLimited(NET_IPV6);
+#endif
+#endif
CService addrProxy;
bool fProxy = false;
diff --git a/src/irc.cpp b/src/irc.cpp
index 50c6a5b4db..6991e6ee7e 100644
--- a/src/irc.cpp
+++ b/src/irc.cpp
@@ -207,16 +207,22 @@ void ThreadIRCSeed(void* parg)
void ThreadIRCSeed2(void* parg)
{
- /* Don't advertise on IRC if we don't allow incoming connections */
- if (mapArgs.count("-connect") || fNoListen)
+ // Don't connect to IRC if we won't use IPv4 connections.
+ if (IsLimited(NET_IPV4))
return;
+ // ... or if we won't make outbound connections and won't accept inbound ones.
+ if (mapArgs.count("-connect") && fNoListen)
+ return;
+
+ // ... or if IRC is not enabled.
if (!GetBoolArg("-irc", false))
return;
printf("ThreadIRCSeed started\n");
int nErrorWait = 10;
int nRetryWait = 10;
+ int nNameRetry = 0;
while (!fShutdown)
{
@@ -251,7 +257,9 @@ void ThreadIRCSeed2(void* parg)
CNetAddr addrIPv4("1.2.3.4"); // arbitrary IPv4 address to make GetLocal prefer IPv4 addresses
CService addrLocal;
string strMyName;
- if (GetLocal(addrLocal, &addrIPv4))
+ // Don't use our IP as our nick if we're not listening
+ // or if it keeps failing because the nick is already in use.
+ if (!fNoListen && GetLocal(addrLocal, &addrIPv4) && nNameRetry<3)
strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
if (strMyName == "")
strMyName = strprintf("x%u", GetRand(1000000000));
@@ -267,6 +275,7 @@ void ThreadIRCSeed2(void* parg)
if (nRet == 2)
{
printf("IRC name already in use\n");
+ nNameRetry++;
Wait(10);
continue;
}
@@ -276,6 +285,7 @@ void ThreadIRCSeed2(void* parg)
else
return;
}
+ nNameRetry = 0;
Sleep(500);
// Get our external IP from the IRC server and re-nick before joining the channel
@@ -283,7 +293,8 @@ void ThreadIRCSeed2(void* parg)
if (GetIPFromIRC(hSocket, strMyName, addrFromIRC))
{
printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str());
- if (addrFromIRC.IsRoutable())
+ // Don't use our IP as our nick if we're not listening
+ if (!fNoListen && addrFromIRC.IsRoutable())
{
// IRC lets you to re-nick
AddLocal(addrFromIRC, LOCAL_IRC);
@@ -291,7 +302,7 @@ void ThreadIRCSeed2(void* parg)
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
}
}
-
+
if (fTestNet) {
Send(hSocket, "JOIN #bitcoinTEST3\r");
Send(hSocket, "WHO #bitcoinTEST3\r");
diff --git a/src/main.cpp b/src/main.cpp
index 91aba149bc..71d425e15f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -281,9 +281,12 @@ bool CTransaction::IsStandard() const
if (!txin.scriptSig.IsPushOnly())
return false;
}
- BOOST_FOREACH(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, vout) {
if (!::IsStandard(txout.scriptPubKey))
return false;
+ if (txout.nValue == 0)
+ return false;
+ }
return true;
}
@@ -653,8 +656,7 @@ bool CTxMemPool::remove(CTransaction &tx)
return true;
}
-void
-CTxMemPool::clear()
+void CTxMemPool::clear()
{
LOCK(cs);
mapTx.clear();
@@ -2320,6 +2322,28 @@ bool CAlert::ProcessAlert()
if (!IsInEffect())
return false;
+ // alert.nID=max is reserved for if the alert key is
+ // compromised. It must have a pre-defined message,
+ // must never expire, must apply to all versions,
+ // and must cancel all previous
+ // alerts or it will be ignored (so an attacker can't
+ // send an "everything is OK, don't panic" version that
+ // cannot be overridden):
+ int maxInt = std::numeric_limits<int>::max();
+ if (nID == maxInt)
+ {
+ if (!(
+ nExpiration == maxInt &&
+ nCancel == (maxInt-1) &&
+ nMinVer == 0 &&
+ nMaxVer == maxInt &&
+ setSubVer.empty() &&
+ nPriority == maxInt &&
+ strStatusBar == "URGENT: Alert key compromised, upgrade required"
+ ))
+ return false;
+ }
+
{
LOCK(cs_mapAlerts);
// Cancel previous alerts
@@ -2995,14 +3019,27 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CAlert alert;
vRecv >> alert;
- if (alert.ProcessAlert())
+ uint256 alertHash = alert.GetHash();
+ if (pfrom->setKnown.count(alertHash) == 0)
{
- // Relay
- pfrom->setKnown.insert(alert.GetHash());
+ if (alert.ProcessAlert())
{
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- alert.RelayTo(pnode);
+ // Relay
+ pfrom->setKnown.insert(alertHash);
+ {
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ alert.RelayTo(pnode);
+ }
+ }
+ else {
+ // Small DoS penalty so peers that send us lots of
+ // duplicate/expired/invalid-signature/whatever alerts
+ // eventually get banned.
+ // This isn't a Misbehaving(100) (immediate ban) because the
+ // peer might be an older or different implementation with
+ // a different signature key, etc.
+ pfrom->Misbehaving(10);
}
}
}
diff --git a/src/main.h b/src/main.h
index cbc48e05c0..dc9f9ee74a 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1535,7 +1535,7 @@ public:
uint256 GetHash() const
{
- return SerializeHash(*this);
+ return Hash(this->vchMsg.begin(), this->vchMsg.end());
}
bool IsInEffect() const
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index e22a9f38ea..828ddfe588 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -5,17 +5,18 @@
DEPSDIR:=/usr/i586-mingw32msvc
USE_UPNP:=0
+USE_IPV6:=1
INCLUDEPATHS= \
-I"$(CURDIR)" \
-I"$(CURDIR)"/obj \
- -I"$(DEPSDIR)/boost_1_49_0" \
+ -I"$(DEPSDIR)/boost_1_50_0" \
-I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
-I"$(DEPSDIR)/openssl-1.0.1b/include" \
-I"$(DEPSDIR)"
LIBPATHS= \
- -L"$(DEPSDIR)/boost_1_49_0/stage/lib" \
+ -L"$(DEPSDIR)/boost_1_50_0/stage/lib" \
-L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
-L"$(DEPSDIR)/openssl-1.0.1b"
@@ -24,22 +25,31 @@ LIBS= \
-l boost_filesystem-mt-s \
-l boost_program_options-mt-s \
-l boost_thread_win32-mt-s \
+ -l boost_chrono-mt-s \
-l db_cxx \
-l ssl \
-l crypto
-DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE -DUSE_IPV6
+DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
DEBUGFLAGS=-g
CFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
+LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
-ifdef USE_UPNP
+ifndef USE_UPNP
+ override USE_UPNP = -
+endif
+ifneq (${USE_UPNP}, -)
LIBPATHS += -L"$(DEPSDIR)/miniupnpc"
LIBS += -l miniupnpc -l iphlpapi
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
endif
+ifneq (${USE_IPV6}, -)
+ DEFS += -DUSE_IPV6=$(USE_IPV6)
+endif
+
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
@@ -84,7 +94,7 @@ obj/%.o: %.cpp $(HEADERS)
i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
bitcoind.exe: $(OBJS:obj/%=obj/%)
- i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
+ i586-mingw32msvc-g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
@@ -92,7 +102,7 @@ obj-test/%.o: test/%.cpp $(HEADERS)
i586-mingw32msvc-g++ -c $(TESTDEFS) $(CFLAGS) -o $@ $<
test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
- i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS)
+ i586-mingw32msvc-g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS)
clean:
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 74897656a9..5d46797766 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -3,39 +3,49 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
USE_UPNP:=0
+USE_IPV6:=1
INCLUDEPATHS= \
- -I"C:\boost-1.49.0-mgw" \
+ -I"C:\boost-1.50.0-mgw" \
-I"C:\db-4.8.30.NC-mgw\build_unix" \
-I"C:\openssl-1.0.1b-mgw\include"
LIBPATHS= \
- -L"C:\boost-1.49.0-mgw\stage\lib" \
+ -L"C:\boost-1.50.0-mgw\stage\lib" \
-L"C:\db-4.8.30.NC-mgw\build_unix" \
-L"C:\openssl-1.0.1b-mgw"
LIBS= \
- -l boost_system-mgw45-mt-s-1_49 \
- -l boost_filesystem-mgw45-mt-s-1_49 \
- -l boost_program_options-mgw45-mt-s-1_49 \
- -l boost_thread-mgw45-mt-s-1_49 \
+ -l boost_system-mgw45-mt-s-1_50 \
+ -l boost_filesystem-mgw45-mt-s-1_50 \
+ -l boost_program_options-mgw45-mt-s-1_50 \
+ -l boost_thread-mgw45-mt-s-1_50 \
+ -l boost_chrono-mgw45-mt-s-1_50 \
-l db_cxx \
-l ssl \
-l crypto
-DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE -DUSE_IPV6
+DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
DEBUGFLAGS=-g
CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
+LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
-ifdef USE_UPNP
+ifndef USE_UPNP
+ override USE_UPNP = -
+endif
+ifneq (${USE_UPNP}, -)
INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw"
LIBPATHS += -L"C:\miniupnpc-1.6-mgw"
LIBS += -l miniupnpc -l iphlpapi
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
endif
+ifneq (${USE_IPV6}, -)
+ DEFS += -DUSE_IPV6=$(USE_IPV6)
+endif
+
LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
@@ -76,7 +86,7 @@ obj/%.o: %.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
bitcoind.exe: $(OBJS:obj/%=obj/%)
- g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
+ g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
@@ -84,7 +94,7 @@ obj-test/%.o: test/%.cpp $(HEADERS)
g++ -c $(TESTDEFS) $(CFLAGS) -o $@ $<
test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
- g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework $(LIBS)
+ g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework $(LIBS)
clean:
-del /Q bitcoind test_bitcoin
diff --git a/src/makefile.osx b/src/makefile.osx
index 977878398c..de829b9eb1 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -20,6 +20,7 @@ LIBPATHS= \
-L"$(DEPSDIR)/lib/db48"
USE_UPNP:=1
+USE_IPV6:=1
LIBS= -dead_strip
@@ -53,7 +54,7 @@ LIBS += \
TESTDEFS += -DBOOST_TEST_DYN_LINK
endif
-DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE -DUSE_IPV6
+DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE
ifdef RELEASE
# Compile for maximum compatibility and smallest size.
@@ -96,7 +97,10 @@ OBJS= \
obj/walletdb.o \
obj/noui.o
-ifdef USE_UPNP
+ifndef USE_UPNP
+ override USE_UPNP = -
+endif
+ifneq (${USE_UPNP}, -)
DEFS += -DUSE_UPNP=$(USE_UPNP)
ifdef STATIC
LIBS += $(DEPSDIR)/lib/libminiupnpc.a
@@ -105,6 +109,10 @@ else
endif
endif
+ifneq (${USE_IPV6}, -)
+ DEFS += -DUSE_IPV6=$(USE_IPV6)
+endif
+
all: bitcoind
# auto-generated dependencies:
diff --git a/src/makefile.unix b/src/makefile.unix
index c9a09ad020..ac42743d8e 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -3,10 +3,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
USE_UPNP:=0
+USE_IPV6:=1
LINK:=$(CXX)
-DEFS=-DUSE_IPV6 -DBOOST_SPIRIT_THREADSAFE
+DEFS=-DBOOST_SPIRIT_THREADSAFE
DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
@@ -43,6 +44,10 @@ ifneq (${USE_UPNP}, -)
DEFS += -DUSE_UPNP=$(USE_UPNP)
endif
+ifneq (${USE_IPV6}, -)
+ DEFS += -DUSE_IPV6=$(USE_IPV6)
+endif
+
LIBS+= \
-Wl,-B$(LMODE2) \
-l z \
diff --git a/src/net.cpp b/src/net.cpp
index aaf7883e51..dc55fae5c5 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -233,8 +233,8 @@ bool AddLocal(const CService& addr, int nScore)
bool fAlready = mapLocalHost.count(addr) > 0;
LocalServiceInfo &info = mapLocalHost[addr];
if (!fAlready || nScore >= info.nScore) {
- info.nScore = nScore;
- info.nPort = addr.GetPort() + (fAlready ? 1 : 0);
+ info.nScore = nScore + (fAlready ? 1 : 0);
+ info.nPort = addr.GetPort();
}
SetReachable(addr.GetNetwork());
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 42bfcfd0b2..ad145fdf9d 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -20,9 +20,6 @@
#include <QSplashScreen>
#include <QLibraryInfo>
-#include <boost/interprocess/ipc/message_queue.hpp>
-#include <boost/algorithm/string/predicate.hpp>
-
#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
#define _BITCOIN_QT_PLUGINS_INCLUDED
#define __INSURE__
@@ -116,35 +113,8 @@ static void handleRunawayException(std::exception *e)
#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
-// TODO: implement URI support on the Mac.
-#if !defined(MAC_OSX)
// Do this early as we don't want to bother initializing if we are just calling IPC
- for (int i = 1; i < argc; i++)
- {
- if (boost::algorithm::istarts_with(argv[i], "bitcoin:"))
- {
- const char *strURI = argv[i];
- try {
- boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
- if (mq.try_send(strURI, strlen(strURI), 0))
- // if URI could be sent to the message queue exit here
- exit(0);
- else
- // if URI could not be sent to the message queue do a normal Bitcoin-Qt startup
- break;
- }
- catch (boost::interprocess::interprocess_exception &ex) {
- // don't log the "file not found" exception, because that's normal for
- // the first start of the first instance
- if (ex.get_error_code() != boost::interprocess::not_found_error)
- {
- printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
- break;
- }
- }
- }
- }
-#endif
+ ipcScanRelay(argc, argv);
// Internal string conversion is all UTF-8
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
@@ -269,29 +239,10 @@ int main(int argc, char *argv[])
{
window.show();
}
-// TODO: implement URI support on the Mac.
-#if !defined(MAC_OSX)
// Place this here as guiref has to be defined if we don't want to lose URIs
- ipcInit();
+ ipcInit(argc, argv);
- // Check for URI in argv
- for (int i = 1; i < argc; i++)
- {
- if (boost::algorithm::istarts_with(argv[i], "bitcoin:"))
- {
- const char *strURI = argv[i];
- try {
- boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
- mq.try_send(strURI, strlen(strURI), 0);
- }
- catch (boost::interprocess::interprocess_exception &ex) {
- printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
- break;
- }
- }
- }
-#endif
app.exec();
window.hide();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 7e6ad15d6a..27b974b5c6 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -53,6 +53,7 @@
#include <QTimer>
#include <QDragEnterEvent>
#include <QUrl>
+#include <QStyle>
#include <iostream>
@@ -148,6 +149,15 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
progressBar->setAlignment(Qt::AlignCenter);
progressBar->setVisible(false);
+ // Override style sheet for progress bar for styles that have a segmented progress bar,
+ // as they make the text unreadable (workaround for issue #1071)
+ // See https://qt-project.org/doc/qt-4.8/gallery.html
+ QString curStyle = qApp->style()->metaObject()->className();
+ if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
+ {
+ progressBar->setStyleSheet("QProgressBar { background-color: #e8e8e8; border: 1px solid grey; border-radius: 7px; padding: 1px; text-align: center; } QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: 7px; margin: 0px; }");
+ }
+
statusBar()->addWidget(progressBarLabel);
statusBar()->addWidget(progressBar);
statusBar()->addPermanentWidget(frameBlocks);
@@ -257,14 +267,13 @@ void BitcoinGUI::createActions()
aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin"), this);
aboutAction->setToolTip(tr("Show information about Bitcoin"));
aboutAction->setMenuRole(QAction::AboutRole);
- aboutQtAction = new QAction(tr("About &Qt"), this);
+ aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
aboutQtAction->setToolTip(tr("Show information about Qt"));
aboutQtAction->setMenuRole(QAction::AboutQtRole);
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
optionsAction->setToolTip(tr("Modify configuration options for Bitcoin"));
optionsAction->setMenuRole(QAction::PreferencesRole);
- toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("Show/Hide &Bitcoin"), this);
- toggleHideAction->setToolTip(tr("Show or hide the Bitcoin window"));
+ toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
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);
@@ -453,7 +462,7 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
if(reason == QSystemTrayIcon::Trigger)
{
- // Click on system tray icon triggers "show/hide Bitcoin"
+ // Click on system tray icon triggers show/hide of the main window
toggleHideAction->trigger();
}
}
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 5fe9e5218a..92b3352866 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -92,6 +92,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins"),
QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"),
QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 2500, 0 = all)"),
QT_TRANSLATE_NOOP("bitcoin-core", "How thorough the block verification is (0-6, default: 1)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Importing blocks..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000?.dat file"),
QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"),
diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui
index 6632e311d0..b59c2445de 100644
--- a/src/qt/forms/aboutdialog.ui
+++ b/src/qt/forms/aboutdialog.ui
@@ -65,9 +65,6 @@
<property name="text">
<string notr="true">0.3.666-beta</string>
</property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
@@ -89,13 +86,25 @@
</layout>
</item>
<item>
+ <widget class="QLabel" name="copyrightLabel">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>Copyright © 2009-2012 The Bitcoin developers</string>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="label_2">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
- <string>Copyright © 2009-2012 Bitcoin Developers
-
+ <string>
This is experimental software.
Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts
index 81f94e388e..edc7e52aa4 100644
--- a/src/qt/locale/bitcoin_cs.ts
+++ b/src/qt/locale/bitcoin_cs.ts
@@ -21,7 +21,13 @@ This is experimental software.
Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</source>
- <translation type="unfinished"/>
+ <translation>Copyright © 2009-2012 Vývojáři Bitcoinu
+
+Tohle je experimentální program.
+
+Šířen pod licencí MIT/X11, viz přiložený soubor COPYING nebo http://www.opensource.org/licenses/mit-license.php.
+
+Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v OpenSSL Toolkitu (http://www.openssl.org/) a kryptografický program od Erika Younga (eay@cryptsoft.com) a program UPnP od Thomase Bernarda.</translation>
</message>
</context>
<context>
@@ -215,18 +221,18 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+1"/>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished"/>
+ <translation>Varování: Pokud si zašifruješ peněženku a ztratíš či zapomeneš heslo, &lt;b&gt;PŘIJDEŠ O VŠECHNY BITCOINY&lt;/b&gt;!</translation>
</message>
<message>
<location line="+0"/>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished"/>
+ <translation>Jsi si jistý, že chceš peněženku zašifrovat?</translation>
</message>
<message>
<location line="+106"/>
<location line="+24"/>
<source>Warning: The Caps Lock key is on!</source>
- <translation type="unfinished"/>
+ <translation>Upozornění: Caps Lock je zapnutý!</translation>
</message>
<message>
<location line="-121"/>
@@ -278,7 +284,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+14"/>
<source>Wallet passphrase was successfully changed.</source>
- <translation type="unfinished"/>
+ <translation>Heslo k peněžence bylo v pořádku změněno.</translation>
</message>
</context>
<context>
@@ -456,12 +462,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+1"/>
<source>&amp;Debug window</source>
- <translation>&amp;Ladící okno</translation>
+ <translation>&amp;Ladicí okno</translation>
</message>
<message>
<location line="+1"/>
<source>Open debugging and diagnostic console</source>
- <translation>Otevři ladící a diagnostickou konzoli</translation>
+ <translation>Otevři ladicí a diagnostickou konzoli</translation>
</message>
<message>
<location line="-56"/>
@@ -481,7 +487,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+186"/>
<source>&amp;About Bitcoin</source>
- <translation type="unfinished"/>
+ <translation>O &amp;Bitcoinu</translation>
</message>
<message>
<location line="+44"/>
@@ -643,7 +649,7 @@ Adresa: %4
<message>
<location filename="../bitcoin.cpp" line="+112"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation type="unfinished"/>
+ <translation>Stala se fatální chyba. Bitcoin nemůže bezpečně pokračovat v činnosti, a proto skončí.</translation>
</message>
</context>
<context>
@@ -728,7 +734,7 @@ Adresa: %4
<location filename="../guiutil.cpp" line="+425"/>
<location line="+12"/>
<source>Bitcoin-Qt</source>
- <translation type="unfinished"/>
+ <translation>Bitcoin-Qt</translation>
</message>
<message>
<location line="-12"/>
@@ -997,12 +1003,12 @@ Adresa: %4
<message>
<location line="+124"/>
<source>Immature:</source>
- <translation type="unfinished"/>
+ <translation>Nedozráno:</translation>
</message>
<message>
<location line="+13"/>
<source>Mined balance that has not yet matured</source>
- <translation type="unfinished"/>
+ <translation>Vytěžené mince, které ještě nejsou zralé</translation>
</message>
<message>
<location line="+46"/>
@@ -1178,7 +1184,7 @@ Adresa: %4
<message>
<location line="+7"/>
<source>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</source>
- <translation type="unfinished"/>
+ <translation>Seznam parametrů Bitcoinu pro příkazovou řádku získáš v nápovědě Bitcoinu Qt.</translation>
</message>
<message>
<location line="+3"/>
@@ -1198,22 +1204,22 @@ Adresa: %4
<message>
<location line="-104"/>
<source>Bitcoin - Debug window</source>
- <translation type="unfinished"/>
+ <translation>Bitcoin - ladicí okno</translation>
</message>
<message>
<location line="+25"/>
<source>Bitcoin Core</source>
- <translation type="unfinished"/>
+ <translation>Jádro Bitcoinu</translation>
</message>
<message>
<location line="+279"/>
<source>Debug log file</source>
- <translation type="unfinished"/>
+ <translation>Soubor s ladicími záznamy</translation>
</message>
<message>
<location line="+7"/>
<source>Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files.</source>
- <translation type="unfinished"/>
+ <translation>Otevři soubor s ladicími záznamy Bitcoinu z aktuálního datového adresáře. U velkých logů to může pár vteřin zabrat.</translation>
</message>
<message>
<location line="+102"/>
@@ -1313,7 +1319,7 @@ Adresa: %4
<message>
<location line="+23"/>
<source>The recipient address is not valid, please recheck.</source>
- <translation type="unfinished"/>
+ <translation>Adresa příjemce je neplatná, překontroluj ji prosím.</translation>
</message>
<message>
<location line="+5"/>
@@ -1415,7 +1421,7 @@ Adresa: %4
<message>
<location filename="../forms/signverifymessagedialog.ui" line="+14"/>
<source>Signatures - Sign / Verify a Message</source>
- <translation type="unfinished"/>
+ <translation>Podpisy - podepsat/ověřit zprávu</translation>
</message>
<message>
<location line="+13"/>
@@ -1443,7 +1449,7 @@ Adresa: %4
<location line="-193"/>
<location line="+203"/>
<source>Alt+A</source>
- <translation type="unfinished"/>
+ <translation>Alt+A</translation>
</message>
<message>
<location line="-193"/>
@@ -1453,7 +1459,7 @@ Adresa: %4
<message>
<location line="+10"/>
<source>Alt+P</source>
- <translation type="unfinished"/>
+ <translation>Alt+P</translation>
</message>
<message>
<location line="+12"/>
@@ -1490,17 +1496,17 @@ Adresa: %4
<message>
<location line="-64"/>
<source>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</source>
- <translation type="unfinished"/>
+ <translation>K ověření podpisu zprávy zadej podepisující adresu, zprávu (ověř si, že správně kopíruješ zalomení řádků, mezery, tabulátory apod.) a podpis. Dávej pozor na to, abys nezkopíroval do podpisu víc, než co je v samotné podepsané zprávě, abys nebyl napálen man-in-the-middle útokem.</translation>
</message>
<message>
<location line="+21"/>
<source>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
- <translation type="unfinished"/>
+ <translation>Adresa, kterou je zpráva podepsána (např. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
</message>
<message>
<location line="+40"/>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation type="unfinished"/>
+ <translation>Ověř zprávu, aby ses ujistil, že byla podepsána danou Bitcoinovou adresou</translation>
</message>
<message>
<location line="+17"/>
@@ -1535,18 +1541,18 @@ Adresa: %4
<location line="+73"/>
<location line="+8"/>
<source>Please check the address and try again.</source>
- <translation type="unfinished"/>
+ <translation>Zkontroluj ji prosím a zkus to pak znovu.</translation>
</message>
<message>
<location line="-81"/>
<location line="+81"/>
<source>The entered address does not refer to a key.</source>
- <translation type="unfinished"/>
+ <translation>Zadaná adresa nepasuje ke klíči.</translation>
</message>
<message>
<location line="-73"/>
<source>Wallet unlock was cancelled.</source>
- <translation type="unfinished"/>
+ <translation>Odemčení peněženky bylo zrušeno.</translation>
</message>
<message>
<location line="+8"/>
@@ -1556,23 +1562,23 @@ Adresa: %4
<message>
<location line="+12"/>
<source>Message signing failed.</source>
- <translation type="unfinished"/>
+ <translation>Podepisování zprávy selhalo.</translation>
</message>
<message>
<location line="+5"/>
<source>Message signed.</source>
- <translation type="unfinished"/>
+ <translation>Zpráv podepsána.</translation>
</message>
<message>
<location line="+59"/>
<source>The signature could not be decoded.</source>
- <translation type="unfinished"/>
+ <translation>Podpis nejde dekódovat.</translation>
</message>
<message>
<location line="+0"/>
<location line="+13"/>
<source>Please check the signature and try again.</source>
- <translation type="unfinished"/>
+ <translation>Zkontroluj ho prosím a zkus to pak znovu.</translation>
</message>
<message>
<location line="+0"/>
@@ -1582,12 +1588,12 @@ Adresa: %4
<message>
<location line="+7"/>
<source>Message verification failed.</source>
- <translation type="unfinished"/>
+ <translation>Ověřování zprávy selhalo.</translation>
</message>
<message>
<location line="+5"/>
<source>Message verified.</source>
- <translation type="unfinished"/>
+ <translation>Zpráva ověřena.</translation>
</message>
</context>
<context>
@@ -1600,12 +1606,12 @@ Adresa: %4
<message numerus="yes">
<location line="-2"/>
<source>Open for %n block(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>Otevřeno pro 1 blok</numerusform><numerusform>Otevřeno pro %n bloky</numerusform><numerusform>Otevřeno pro %n bloků</numerusform></translation>
</message>
<message>
<location line="+8"/>
<source>%1/offline</source>
- <translation type="unfinished"/>
+ <translation>%1/offline</translation>
</message>
<message>
<location line="+2"/>
@@ -1620,12 +1626,12 @@ Adresa: %4
<message>
<location line="+18"/>
<source>Status</source>
- <translation type="unfinished"/>
+ <translation>Stav</translation>
</message>
<message numerus="yes">
<location line="+7"/>
<source>, broadcast through %n node(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>, rozesláno přes 1 uzel</numerusform><numerusform>, rozesláno přes %n uzly</numerusform><numerusform>, rozesláno přes %n uzlů</numerusform></translation>
</message>
<message>
<location line="+4"/>
@@ -1635,36 +1641,36 @@ Adresa: %4
<message>
<location line="+7"/>
<source>Source</source>
- <translation type="unfinished"/>
+ <translation>Zdroj</translation>
</message>
<message>
<location line="+0"/>
<source>Generated</source>
- <translation type="unfinished"/>
+ <translation>Vygenerováno</translation>
</message>
<message>
<location line="+6"/>
<location line="+17"/>
<source>From</source>
- <translation type="unfinished"/>
+ <translation>Od</translation>
</message>
<message>
<location line="+1"/>
<location line="+22"/>
<location line="+58"/>
<source>To</source>
- <translation type="unfinished"/>
+ <translation>Pro</translation>
</message>
<message>
<location line="-77"/>
<location line="+2"/>
<source>own address</source>
- <translation type="unfinished"/>
+ <translation>vlastní adresa</translation>
</message>
<message>
<location line="-2"/>
<source>label</source>
- <translation type="unfinished"/>
+ <translation>označení</translation>
</message>
<message>
<location line="+37"/>
@@ -1673,17 +1679,17 @@ Adresa: %4
<location line="+17"/>
<location line="+30"/>
<source>Credit</source>
- <translation type="unfinished"/>
+ <translation>Příjem</translation>
</message>
<message numerus="yes">
<location line="-102"/>
<source>matures in %n more block(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>dozraje po jednom bloku</numerusform><numerusform>dozraje po %n blocích</numerusform><numerusform>dozraje po %n blocích</numerusform></translation>
</message>
<message>
<location line="+2"/>
<source>not accepted</source>
- <translation type="unfinished"/>
+ <translation>neakceptováno</translation>
</message>
<message>
<location line="+44"/>
@@ -1691,67 +1697,67 @@ Adresa: %4
<location line="+15"/>
<location line="+30"/>
<source>Debit</source>
- <translation type="unfinished"/>
+ <translation>Výdaj</translation>
</message>
<message>
<location line="-39"/>
<source>Transaction fee</source>
- <translation type="unfinished"/>
+ <translation>Transakční poplatek</translation>
</message>
<message>
<location line="+16"/>
<source>Net amount</source>
- <translation type="unfinished"/>
+ <translation>Čistá částka</translation>
</message>
<message>
<location line="+6"/>
<source>Message</source>
- <translation type="unfinished"/>
+ <translation>Zpráva</translation>
</message>
<message>
<location line="+2"/>
<source>Comment</source>
- <translation type="unfinished"/>
+ <translation>Komentář</translation>
</message>
<message>
<location line="+2"/>
<source>Transaction ID</source>
- <translation type="unfinished"/>
+ <translation>ID transakce</translation>
</message>
<message>
<location line="+3"/>
<source>Generated coins must mature 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, its state will change to &quot;not accepted&quot; and it won&apos;t be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation type="unfinished"/>
+ <translation>Vygenerované mince musí čekat 120 bloků, než mohou být utraceny. Když jsi vygeneroval tenhle blok, tak byl rozposlán do sítě, aby byl přidán do řetězce bloků. Pokud se mu nepodaří dostat se do řetězce, změní se na &quot;neakceptovaný&quot; a nepůjde utratit. To se občas může stát, pokud jiný uzel vygeneruje blok zhruba ve stejném okamžiku jako ty.</translation>
</message>
<message>
<location line="+7"/>
<source>Debug information</source>
- <translation type="unfinished"/>
+ <translation>Ladicí informace</translation>
</message>
<message>
<location line="+8"/>
<source>Transaction</source>
- <translation type="unfinished"/>
+ <translation>Transakce</translation>
</message>
<message>
<location line="+5"/>
<source>Inputs</source>
- <translation type="unfinished"/>
+ <translation>Vstupy</translation>
</message>
<message>
<location line="+23"/>
<source>Amount</source>
- <translation>Množství</translation>
+ <translation>Částka</translation>
</message>
<message>
<location line="+1"/>
<source>true</source>
- <translation type="unfinished"/>
+ <translation>true</translation>
</message>
<message>
<location line="+0"/>
<source>false</source>
- <translation type="unfinished"/>
+ <translation>false</translation>
</message>
<message>
<location line="-212"/>
@@ -2197,142 +2203,142 @@ Adresa: %4
<message>
<location line="-92"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation type="unfinished"/>
+ <translation>Přijímat spojení zvenčí (výchozí: 1, pokud není zadáno -proxy nebo -connect)</translation>
</message>
<message>
<location line="-20"/>
<source>Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)</source>
- <translation type="unfinished"/>
+ <translation>Nastavit maximální velikost prioritních/nízkopoplatkových transakcí v bajtech (výchozí: 27000)</translation>
</message>
<message>
<location line="+5"/>
<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>Upozornění: -paytxfee je nastaveno velmi vysoko! Toto je transakční poplatek, který zaplatíš za každou poslanou transakci.</translation>
</message>
<message>
<location line="+3"/>
<source>Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.</source>
- <translation type="unfinished"/>
+ <translation>Upozornění: Zobrazené transakce nemusí být správné! Možná potřebuješ aktualizovat nebo ostatní uzly potřebují aktualizovat.</translation>
</message>
<message>
<location line="+3"/>
<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>Upozornění: Zkontroluj, že máš v počítači správně nastavený datum a čas! Pokud jsou nastaveny špatně, Bitcoin nebude fungovat správně.</translation>
</message>
<message>
<location line="+13"/>
<source>An error occurred while setting up the RPC port %i for listening: %s</source>
- <translation type="unfinished"/>
+ <translation>Při nastavování naslouchacího RPC portu %i nastala chyba: %s</translation>
</message>
<message>
<location line="+4"/>
<source>Block creation options:</source>
- <translation type="unfinished"/>
+ <translation>Možnosti vytvoření bloku:</translation>
</message>
<message>
<location line="+6"/>
<source>Connect only to the specified node(s)</source>
- <translation type="unfinished"/>
+ <translation>Připojovat se pouze k zadaným uzlům</translation>
</message>
<message>
<location line="+3"/>
<source>Discover own IP address (default: 1 when listening and no -externalip)</source>
- <translation type="unfinished"/>
+ <translation>Zjistit vlastní IP adresu (výchozí: 1, pokud naslouchá a není zadáno -externalip)</translation>
</message>
<message>
<location line="+11"/>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation type="unfinished"/>
+ <translation>Nepodařilo se naslouchat na žádném portu. Použij -listen=0, pokud to byl tvůj záměr.</translation>
</message>
<message>
<location line="+2"/>
<source>Find peers using DNS lookup (default: 1 unless -connect)</source>
- <translation type="unfinished"/>
+ <translation>Hledat uzly přes DNS (výchozí: 1, pokud není zadáno -connect)</translation>
</message>
<message>
<location line="+9"/>
<source>Invalid -tor address: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Neplatná -tor adresa: &apos;%s&apos;</translation>
</message>
<message>
<location line="+10"/>
<source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: 5000)</source>
- <translation type="unfinished"/>
+ <translation>Maximální velikost přijímacího bufferu pro každé spojení, &lt;n&gt;*1000 bajtů (výchozí: 5000)</translation>
</message>
<message>
<location line="+1"/>
<source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: 1000)</source>
- <translation type="unfinished"/>
+ <translation>Maximální velikost odesílacího bufferu pro každé spojení, &lt;n&gt;*1000 bajtů (výchozí: 1000)</translation>
</message>
<message>
<location line="+1"/>
<source>Only connect to nodes in network &lt;net&gt; (IPv4, IPv6 or Tor)</source>
- <translation type="unfinished"/>
+ <translation>Připojovat se pouze k uzlům v &lt;net&gt; síti (IPv4, IPv6 nebo Tor)</translation>
</message>
<message>
<location line="+2"/>
<source>Output extra debugging information. Implies all other -debug* options</source>
- <translation type="unfinished"/>
+ <translation>Tisknout speciální ladicí informace. Implikuje použití všechny -debug* voleb</translation>
</message>
<message>
<location line="+1"/>
<source>Output extra network debugging information</source>
- <translation type="unfinished"/>
+ <translation>Tisknout speciální ladicí informace o síti</translation>
</message>
<message>
<location line="+2"/>
<source>Prepend debug output with timestamp</source>
- <translation>Připojit před ladící výstup časové razítko</translation>
+ <translation>Připojit před ladicí výstup časové razítko</translation>
</message>
<message>
<location line="+4"/>
<source>SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source>
- <translation type="unfinished"/>
+ <translation>Možnosti SSL: (viz instrukce nastavení SSL v Bitcoin Wiki)</translation>
</message>
<message>
<location line="+1"/>
<source>Select the version of socks proxy to use (4-5, default: 5)</source>
- <translation type="unfinished"/>
+ <translation>Zvol verzi socks proxy (4-5, výchozí: 5)</translation>
</message>
<message>
<location line="+3"/>
<source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Posílat stopovací/ladící informace do konzole místo do souboru debug.log</translation>
+ <translation>Posílat stopovací/ladicí informace do konzole místo do souboru debug.log</translation>
</message>
<message>
<location line="+1"/>
<source>Send trace/debug info to debugger</source>
- <translation>Posílat stopovací/ladící informace do debuggeru</translation>
+ <translation>Posílat stopovací/ladicí informace do debuggeru</translation>
</message>
<message>
<location line="+7"/>
<source>Set maximum block size in bytes (default: 250000)</source>
- <translation type="unfinished"/>
+ <translation>Nastavit maximální velikost bloku v bajtech (výchozí: 250000)</translation>
</message>
<message>
<location line="+1"/>
<source>Set minimum block size in bytes (default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Nastavit minimální velikost bloku v bajtech (výchozí: 0)</translation>
</message>
<message>
<location line="+1"/>
<source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation type="unfinished"/>
+ <translation>Při spuštění klienta zmenšit soubor debug.log (výchozí: 1, pokud není zadáno -debug)</translation>
</message>
<message>
<location line="+15"/>
<source>Use UPnP to map the listening port (default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Použít UPnP k namapování naslouchacího portu (výchozí: 0)</translation>
</message>
<message>
<location line="+1"/>
<source>Use UPnP to map the listening port (default: 1 when listening)</source>
- <translation type="unfinished"/>
+ <translation>Použít UPnP k namapování naslouchacího portu (výchozí: 1, pokud naslouchá)</translation>
</message>
<message>
<location line="+1"/>
<source>Use proxy to reach tor hidden services (default: same as -proxy)</source>
- <translation type="unfinished"/>
+ <translation>Použít proxy k připojení ke skryté služby (výchozí: stejné jako -proxy)</translation>
</message>
<message>
<location line="+2"/>
@@ -2342,12 +2348,12 @@ Adresa: %4
<message>
<location line="+2"/>
<source>Warning: Disk space is low!</source>
- <translation type="unfinished"/>
+ <translation>Upozornění: Na disku je málo místa!</translation>
</message>
<message>
<location line="+1"/>
<source>Warning: This version is obsolete, upgrade required!</source>
- <translation type="unfinished"/>
+ <translation>Upozornění: tahle verze je zastaralá, měl bys ji aktualizovat!</translation>
</message>
<message>
<location line="-41"/>
@@ -2567,7 +2573,7 @@ Adresa: %4
<message>
<location line="-18"/>
<source>Unable to bind to %s on this computer. Bitcoin is probably already running.</source>
- <translation type="unfinished"/>
+ <translation>Nedaří se mi připojit na %s na tomhle počítači. Bitcoin už pravděpodobně jednou běží.</translation>
</message>
<message>
<location line="+48"/>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 849ff47a52..2ac97a532b 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -15,9 +15,13 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+44"/>
- <source>Copyright © 2009-2012 Bitcoin Developers
-
+ <location line="+41"/>
+ <source>Copyright © 2009-2012 The Bitcoin developers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>
This is experimental software.
Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -286,22 +290,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+218"/>
+ <location filename="../bitcoingui.cpp" line="+228"/>
<source>Sign &amp;message...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+48"/>
- <source>Show/Hide &amp;Bitcoin</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+248"/>
+ <location line="+295"/>
<source>Synchronizing with network...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-326"/>
+ <location line="-325"/>
<source>&amp;Overview</source>
<translation type="unfinished"></translation>
</message>
@@ -376,7 +375,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+6"/>
<source>&amp;Encrypt Wallet...</source>
<translation type="unfinished"></translation>
</message>
@@ -409,7 +408,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-55"/>
+ <location line="-54"/>
<source>Send coins to a Bitcoin address</source>
<translation type="unfinished"></translation>
</message>
@@ -434,12 +433,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Show or hide the Bitcoin window</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
+ <location line="+4"/>
<source>Export the data in the current tab to a file</source>
<translation type="unfinished"></translation>
</message>
@@ -469,12 +463,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-56"/>
+ <location line="-55"/>
<source>&amp;Verify message...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-151"/>
+ <location line="-160"/>
<source>Bitcoin</source>
<translation type="unfinished"></translation>
</message>
@@ -484,12 +478,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+186"/>
+ <location line="+195"/>
<source>&amp;About Bitcoin</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+44"/>
+ <location line="+9"/>
+ <source>&amp;Show / Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+34"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
@@ -657,7 +656,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+112"/>
+ <location filename="../bitcoin.cpp" line="+109"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
<translation type="unfinished"></translation>
</message>
@@ -741,7 +740,7 @@ Address: %4
<context>
<name>GUIUtil::HelpMessageBox</name>
<message>
- <location filename="../guiutil.cpp" line="+425"/>
+ <location filename="../guiutil.cpp" line="+419"/>
<location line="+12"/>
<source>Bitcoin-Qt</source>
<translation type="unfinished"></translation>
@@ -960,7 +959,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+134"/>
+ <location line="+147"/>
<location line="+9"/>
<source>Warning</source>
<translation type="unfinished"></translation>
@@ -1256,7 +1255,7 @@ Address: %4
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+123"/>
+ <location filename="../sendcoinsdialog.cpp" line="+124"/>
<location line="+5"/>
<location line="+5"/>
<location line="+5"/>
@@ -2106,7 +2105,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+81"/>
+ <location line="+82"/>
<source>Usage:</source>
<translation type="unfinished"></translation>
</message>
@@ -2121,12 +2120,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-9"/>
+ <location line="-10"/>
<source>Get help for a command</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+20"/>
<source>Options:</source>
<translation type="unfinished"></translation>
</message>
@@ -2141,7 +2140,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-46"/>
+ <location line="-47"/>
<source>Generate coins</source>
<translation type="unfinished"></translation>
</message>
@@ -2151,7 +2150,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+59"/>
+ <location line="+60"/>
<source>Specify data directory</source>
<translation type="unfinished"></translation>
</message>
@@ -2181,27 +2180,27 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-32"/>
+ <location line="-33"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+63"/>
+ <location line="+64"/>
<source>Specify your own public address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-74"/>
+ <location line="-75"/>
<source>Bind to given address. Use [host]:port notation for IPv6</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+76"/>
+ <location line="+77"/>
<source>Threshold for disconnecting misbehaving peers (default: 100)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-104"/>
+ <location line="-105"/>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
<translation type="unfinished"></translation>
</message>
@@ -2216,7 +2215,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+60"/>
+ <location line="+61"/>
<source>Run in the background as a daemon and accept commands</source>
<translation type="unfinished"></translation>
</message>
@@ -2226,7 +2225,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-92"/>
+ <location line="-93"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
<translation type="unfinished"></translation>
</message>
@@ -2281,7 +2280,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+6"/>
+ <source>Importing blocks...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Invalid -tor address: &apos;%s&apos;</source>
<translation type="unfinished"></translation>
</message>
@@ -2391,22 +2395,22 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-40"/>
+ <location line="-41"/>
<source>Allow JSON-RPC connections from specified IP address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+60"/>
+ <location line="+61"/>
<source>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-89"/>
+ <location line="-90"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+112"/>
+ <location line="+113"/>
<source>Upgrade wallet to latest format</source>
<translation type="unfinished"></translation>
</message>
@@ -2421,7 +2425,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-23"/>
+ <location line="-24"/>
<source>How many blocks to check at startup (default: 2500, 0 = all)</source>
<translation type="unfinished"></translation>
</message>
@@ -2431,7 +2435,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Imports blocks from external blk000?.dat file</source>
<translation type="unfinished"></translation>
</message>
@@ -2451,17 +2455,17 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-109"/>
+ <location line="-110"/>
<source>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+121"/>
+ <location line="+122"/>
<source>This help message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-118"/>
+ <location line="-119"/>
<source>Cannot obtain a lock on data directory %s. Bitcoin is probably already running.</source>
<translation type="unfinished"></translation>
</message>
@@ -2471,12 +2475,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+76"/>
+ <location line="+77"/>
<source>Unable to bind to %s on this computer (bind returned error %d, %s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-68"/>
+ <location line="-69"/>
<source>Connect through socks proxy</source>
<translation type="unfinished"></translation>
</message>
@@ -2486,12 +2490,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+43"/>
+ <location line="+44"/>
<source>Loading addresses...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-25"/>
+ <location line="-26"/>
<source>Error loading blkindex.dat</source>
<translation type="unfinished"></translation>
</message>
@@ -2506,17 +2510,17 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+71"/>
+ <location line="+72"/>
<source>Wallet needed to be rewritten: restart Bitcoin to complete</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-73"/>
+ <location line="-74"/>
<source>Error loading wallet.dat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+18"/>
<source>Invalid -proxy address: &apos;%s&apos;</source>
<translation type="unfinished"></translation>
</message>
@@ -2531,7 +2535,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-73"/>
+ <location line="-74"/>
<source>Cannot resolve -bind address: &apos;%s&apos;</source>
<translation type="unfinished"></translation>
</message>
@@ -2541,12 +2545,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+28"/>
+ <location line="+29"/>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-13"/>
+ <location line="-14"/>
<source>Error: could not start node</source>
<translation type="unfinished"></translation>
</message>
@@ -2566,17 +2570,17 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+41"/>
+ <location line="+42"/>
<source>Sending...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-99"/>
+ <location line="-100"/>
<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 line="+74"/>
+ <location line="+75"/>
<source>Invalid amount</source>
<translation type="unfinished"></translation>
</message>
@@ -2591,7 +2595,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-45"/>
+ <location line="-46"/>
<source>Add a node to connect to and attempt to keep the connection open</source>
<translation type="unfinished"></translation>
</message>
@@ -2611,12 +2615,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+19"/>
<source>Loading wallet...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-38"/>
+ <location line="-39"/>
<source>Cannot downgrade wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -2631,22 +2635,22 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+45"/>
+ <location line="+46"/>
<source>Rescanning...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-39"/>
+ <location line="-40"/>
<source>Done loading</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+63"/>
+ <location line="+64"/>
<source>To use the %s option</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-132"/>
+ <location line="-133"/>
<source>%s, you must set a rpcpassword in the configuration file:
%s
It is recommended you use the following random password:
diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp
index ccdfc66bad..a2fe866e29 100644
--- a/src/qt/qtipcserver.cpp
+++ b/src/qt/qtipcserver.cpp
@@ -2,11 +2,18 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <boost/version.hpp>
+#if defined(WIN32) && BOOST_VERSION == 104900
+#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
+#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+#endif
+
#include "qtipcserver.h"
#include "guiconstants.h"
#include "ui_interface.h"
#include "util.h"
+#include <boost/algorithm/string/predicate.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/version.hpp>
@@ -19,15 +26,52 @@ using namespace boost;
using namespace boost::interprocess;
using namespace boost::posix_time;
-static void ipcThread2(void* pArg);
-
#ifdef MAC_OSX
// URI handling not implemented on OSX yet
-void ipcInit() { }
+void ipcScanRelay(int argc, char *argv[]) { }
+void ipcInit(int argc, char *argv[]) { }
#else
+static void ipcThread2(void* pArg);
+
+static bool ipcScanCmd(int argc, char *argv[], bool fRelay)
+{
+ // Check for URI in argv
+ bool fSent = false;
+ for (int i = 1; i < argc; i++)
+ {
+ if (boost::algorithm::istarts_with(argv[i], "bitcoin:"))
+ {
+ const char *strURI = argv[i];
+ try {
+ boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
+ if (mq.try_send(strURI, strlen(strURI), 0))
+ fSent = true;
+ else if (fRelay)
+ break;
+ }
+ catch (boost::interprocess::interprocess_exception &ex) {
+ // don't log the "file not found" exception, because that's normal for
+ // the first start of the first instance
+ if (ex.get_error_code() != boost::interprocess::not_found_error || !fRelay)
+ {
+ printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
+ break;
+ }
+ }
+ }
+ }
+ return fSent;
+}
+
+void ipcScanRelay(int argc, char *argv[])
+{
+ if (ipcScanCmd(argc, argv, true))
+ exit(0);
+}
+
static void ipcThread(void* pArg)
{
IMPLEMENT_RANDOMIZE_STACK(ipcThread(pArg));
@@ -75,7 +119,7 @@ static void ipcThread2(void* pArg)
delete mq;
}
-void ipcInit()
+void ipcInit(int argc, char *argv[])
{
message_queue* mq = NULL;
char buffer[MAX_URI_LENGTH + 1] = "";
@@ -113,6 +157,8 @@ void ipcInit()
delete mq;
return;
}
+
+ ipcScanCmd(argc, argv, false);
}
#endif
diff --git a/src/qt/qtipcserver.h b/src/qt/qtipcserver.h
index 484b6222eb..cccf200b2d 100644
--- a/src/qt/qtipcserver.h
+++ b/src/qt/qtipcserver.h
@@ -4,6 +4,7 @@
// Define Bitcoin-Qt message queue name
#define BITCOINURI_QUEUE_NAME "BitcoinURI"
-void ipcInit();
+void ipcScanRelay(int argc, char *argv[]);
+void ipcInit(int argc, char *argv[]);
#endif // QTIPCSERVER_H
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 08f936e719..7d5b6fed53 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -13,7 +13,6 @@
#include <QUrl>
#include <QScrollBar>
-#include <boost/tokenizer.hpp>
#include <openssl/crypto.h>
// TODO: make it possible to filter out categories (esp debug messages when implemented)
@@ -54,34 +53,108 @@ void RPCExecutor::start()
// Nothing to do
}
-void RPCExecutor::request(const QString &command)
+/**
+ * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
+ *
+ * - Arguments are delimited with whitespace
+ * - Extra whitespace at the beginning and end and between arguments will be ignored
+ * - Text can be "double" or 'single' quoted
+ * - The backslash \c \ is used as escape character
+ * - Outside quotes, any character can be escaped
+ * - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
+ * - Within single quotes, no escaping is possible and no special interpretation takes place
+ *
+ * @param[out] args Parsed arguments will be appended to this list
+ * @param[in] strCommand Command line to split
+ */
+bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
- // Parse shell-like command line into separate arguments
- std::string strMethod;
- std::vector<std::string> strParams;
- try {
- boost::escaped_list_separator<char> els('\\',' ','\"');
- std::string strCommand = command.toStdString();
- boost::tokenizer<boost::escaped_list_separator<char> > tok(strCommand, els);
-
- int n = 0;
- for(boost::tokenizer<boost::escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg,++n)
+ enum CmdParseState
+ {
+ STATE_EATING_SPACES,
+ STATE_ARGUMENT,
+ STATE_SINGLEQUOTED,
+ STATE_DOUBLEQUOTED,
+ STATE_ESCAPE_OUTER,
+ STATE_ESCAPE_DOUBLEQUOTED
+ } state = STATE_EATING_SPACES;
+ std::string curarg;
+ foreach(char ch, strCommand)
+ {
+ switch(state)
{
- if(n == 0) // First parameter is the command
- strMethod = *beg;
- else
- strParams.push_back(*beg);
+ case STATE_ARGUMENT: // In or after argument
+ case STATE_EATING_SPACES: // Handle runs of whitespace
+ switch(ch)
+ {
+ case '"': state = STATE_DOUBLEQUOTED; break;
+ case '\'': state = STATE_SINGLEQUOTED; break;
+ case '\\': state = STATE_ESCAPE_OUTER; break;
+ case ' ': case '\n': case '\t':
+ if(state == STATE_ARGUMENT) // Space ends argument
+ {
+ args.push_back(curarg);
+ curarg.clear();
+ }
+ state = STATE_EATING_SPACES;
+ break;
+ default: curarg += ch; state = STATE_ARGUMENT;
+ }
+ break;
+ case STATE_SINGLEQUOTED: // Single-quoted string
+ switch(ch)
+ {
+ case '\'': state = STATE_ARGUMENT; break;
+ default: curarg += ch;
+ }
+ break;
+ case STATE_DOUBLEQUOTED: // Double-quoted string
+ switch(ch)
+ {
+ case '"': state = STATE_ARGUMENT; break;
+ case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
+ default: curarg += ch;
+ }
+ break;
+ case STATE_ESCAPE_OUTER: // '\' outside quotes
+ curarg += ch; state = STATE_ARGUMENT;
+ break;
+ case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
+ if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
+ curarg += ch; state = STATE_DOUBLEQUOTED;
+ break;
}
}
- catch(boost::escaped_list_error &e)
+ switch(state) // final state
{
- emit reply(RPCConsole::CMD_ERROR, QString("Parse error"));
- return;
+ case STATE_EATING_SPACES:
+ return true;
+ case STATE_ARGUMENT:
+ args.push_back(curarg);
+ return true;
+ default: // ERROR to end in one of the other states
+ return false;
}
+}
- try {
+void RPCExecutor::request(const QString &command)
+{
+ std::vector<std::string> args;
+ if(!parseCommandLine(args, command.toStdString()))
+ {
+ emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
+ return;
+ }
+ if(args.empty())
+ return; // Nothing to do
+ try
+ {
std::string strPrint;
- json_spirit::Value result = tableRPC.execute(strMethod, RPCConvertValues(strMethod, strParams));
+ // Convert argument list to JSON objects in method-dependent way,
+ // and pass it along with the method name to the dispatcher.
+ json_spirit::Value result = tableRPC.execute(
+ args[0],
+ RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));
// Format result reply
if (result.type() == json_spirit::null_type)
@@ -95,7 +168,16 @@ void RPCExecutor::request(const QString &command)
}
catch (json_spirit::Object& objError)
{
- emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
+ try // Nice formatting for standard-format error
+ {
+ int code = find_value(objError, "code").get_int();
+ std::string message = find_value(objError, "message").get_str();
+ emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
+ }
+ catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
+ { // Show raw JSON object
+ emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
+ }
}
catch (std::exception& e)
{
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 160973638d..cc60e2732b 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -54,12 +54,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
CTxDestination address;
sub.idx = parts.size(); // sequence number
sub.credit = txout.nValue;
- if (wtx.IsCoinBase())
- {
- // Generated
- sub.type = TransactionRecord::Generated;
- }
- else if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
+ if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
{
// Received by Bitcoin Address
sub.type = TransactionRecord::RecvWithAddress;
@@ -71,6 +66,11 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
sub.type = TransactionRecord::RecvFromOther;
sub.address = mapValue["from"];
}
+ if (wtx.IsCoinBase())
+ {
+ // Generated
+ sub.type = TransactionRecord::Generated;
+ }
parts.append(sub);
}
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index b3e001ea1d..847c9e9733 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -392,11 +392,11 @@ QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, b
return QString::fromStdString(wtx->address);
case TransactionRecord::RecvWithAddress:
case TransactionRecord::SendToAddress:
+ case TransactionRecord::Generated:
return lookupAddress(wtx->address, tooltip);
case TransactionRecord::SendToOther:
return QString::fromStdString(wtx->address);
case TransactionRecord::SendToSelf:
- case TransactionRecord::Generated:
default:
return tr("(n/a)");
}
@@ -409,13 +409,13 @@ QVariant TransactionTableModel::addressColor(const TransactionRecord *wtx) const
{
case TransactionRecord::RecvWithAddress:
case TransactionRecord::SendToAddress:
+ case TransactionRecord::Generated:
{
QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
if(label.isEmpty())
return COLOR_BAREADDRESS;
} break;
case TransactionRecord::SendToSelf:
- case TransactionRecord::Generated:
return COLOR_BAREADDRESS;
default:
break;
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index d2cb31f51d..2954b9ee57 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -225,6 +225,10 @@ Value getblocktemplate(const Array& params, bool fHelp)
const Value& modeval = find_value(oparam, "mode");
if (modeval.type() == str_type)
strMode = modeval.get_str();
+ else if (modeval.type() == null_type)
+ {
+ /* Do nothing */
+ }
else
throw JSONRPCError(-8, "Invalid mode");
}
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index fefefc7d62..08b0049b08 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -18,8 +18,7 @@ using namespace boost;
using namespace boost::assign;
using namespace json_spirit;
-void
-ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
+void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
{
txnouttype type;
vector<CTxDestination> addresses;
@@ -43,8 +42,7 @@ ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
out.push_back(Pair("addresses", a));
}
-void
-TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
+void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
{
entry.push_back(Pair("txid", tx.GetHash().GetHex()));
entry.push_back(Pair("version", tx.nVersion));
@@ -138,24 +136,40 @@ Value getrawtransaction(const Array& params, bool fHelp)
Value listunspent(const Array& params, bool fHelp)
{
- if (fHelp || params.size() > 2)
+ if (fHelp || params.size() > 3)
throw runtime_error(
- "listunspent [minconf=1] [maxconf=999999]\n"
+ "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n"
"Returns array of unspent transaction outputs\n"
"with between minconf and maxconf (inclusive) confirmations.\n"
+ "Optionally filtered to only include txouts paid to specified addresses.\n"
"Results are an array of Objects, each of which has:\n"
"{txid, vout, scriptPubKey, amount, confirmations}");
- RPCTypeCheck(params, list_of(int_type)(int_type));
+ RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
int nMinDepth = 1;
if (params.size() > 0)
nMinDepth = params[0].get_int();
- int nMaxDepth = 999999;
+ int nMaxDepth = 9999999;
if (params.size() > 1)
nMaxDepth = params[1].get_int();
+ set<CBitcoinAddress> setAddress;
+ if (params.size() > 2)
+ {
+ Array inputs = params[2].get_array();
+ BOOST_FOREACH(Value& input, inputs)
+ {
+ CBitcoinAddress address(input.get_str());
+ if (!address.IsValid())
+ throw JSONRPCError(-5, string("Invalid Bitcoin address: ")+input.get_str());
+ if (setAddress.count(address))
+ throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+input.get_str());
+ setAddress.insert(address);
+ }
+ }
+
Array results;
vector<COutput> vecOutputs;
pwalletMain->AvailableCoins(vecOutputs, false);
@@ -164,6 +178,16 @@ Value listunspent(const Array& params, bool fHelp)
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
continue;
+ if(setAddress.size())
+ {
+ CTxDestination address;
+ if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
+ continue;
+
+ if (!setAddress.count(address))
+ continue;
+ }
+
int64 nValue = out.tx->vout[out.i].nValue;
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
Object entry;
@@ -224,7 +248,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
{
CBitcoinAddress address(s.name_);
if (!address.IsValid())
- throw JSONRPCError(-5, string("Invalid Bitcoin address:")+s.name_);
+ throw JSONRPCError(-5, string("Invalid Bitcoin address: ")+s.name_);
if (setAddress.count(address))
throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 20df4c0a68..b8e6a4467a 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -15,16 +15,14 @@ using namespace std;
int64 nWalletUnlockTime;
static CCriticalSection cs_nWalletUnlockTime;
-std::string
-HelpRequiringPassphrase()
+std::string HelpRequiringPassphrase()
{
return pwalletMain->IsCrypted()
? "\nrequires wallet passphrase to be set with walletpassphrase first"
: "";
}
-void
-EnsureWalletIsUnlocked()
+void EnsureWalletIsUnlocked()
{
if (pwalletMain->IsLocked())
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
@@ -34,6 +32,8 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
{
int confirms = wtx.GetDepthInMainChain();
entry.push_back(Pair("confirmations", confirms));
+ if (wtx.IsCoinBase())
+ entry.push_back(Pair("generated", true));
if (confirms)
{
entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
@@ -274,6 +274,37 @@ Value sendtoaddress(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
+Value listaddressgroupings(const Array& params, bool fHelp)
+{
+ if (fHelp)
+ throw runtime_error(
+ "listaddressgroupings\n"
+ "Lists groups of addresses which have had their common ownership\n"
+ "made public by common use as inputs or as the resulting change\n"
+ "in past transactions");
+
+ Array jsonGroupings;
+ map<CTxDestination, int64> balances = pwalletMain->GetAddressBalances();
+ BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
+ {
+ Array jsonGrouping;
+ BOOST_FOREACH(CTxDestination address, grouping)
+ {
+ Array addressInfo;
+ addressInfo.push_back(CBitcoinAddress(address).ToString());
+ addressInfo.push_back(ValueFromAmount(balances[address]));
+ {
+ LOCK(pwalletMain->cs_wallet);
+ if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
+ addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second);
+ }
+ jsonGrouping.push_back(addressInfo);
+ }
+ jsonGroupings.push_back(jsonGrouping);
+ }
+ return jsonGroupings;
+}
+
Value signmessage(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 2)
@@ -445,12 +476,12 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
if (!wtx.IsFinal())
continue;
- int64 nGenerated, nReceived, nSent, nFee;
- wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
+ int64 nReceived, nSent, nFee;
+ wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee);
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
nBalance += nReceived;
- nBalance += nGenerated - nSent - nFee;
+ nBalance -= nSent + nFee;
}
// Tally internal accounting entries
@@ -492,12 +523,11 @@ Value getbalance(const Array& params, bool fHelp)
if (!wtx.IsFinal())
continue;
- int64 allGeneratedImmature, allGeneratedMature, allFee;
- allGeneratedImmature = allGeneratedMature = allFee = 0;
+ int64 allFee;
string strSentAccount;
list<pair<CTxDestination, int64> > listReceived;
list<pair<CTxDestination, int64> > listSent;
- wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
+ wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount);
if (wtx.GetDepthInMainChain() >= nMinDepth)
{
BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listReceived)
@@ -506,7 +536,6 @@ Value getbalance(const Array& params, bool fHelp)
BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listSent)
nBalance -= r.second;
nBalance -= allFee;
- nBalance += allGeneratedMature;
}
return ValueFromAmount(nBalance);
}
@@ -877,35 +906,15 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
{
- int64 nGeneratedImmature, nGeneratedMature, nFee;
+ int64 nFee;
string strSentAccount;
list<pair<CTxDestination, int64> > listReceived;
list<pair<CTxDestination, int64> > listSent;
- wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
+ wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount);
bool fAllAccounts = (strAccount == string("*"));
- // Generated blocks assigned to account ""
- if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
- {
- Object entry;
- entry.push_back(Pair("account", string("")));
- if (nGeneratedImmature)
- {
- entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
- entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
- }
- else
- {
- entry.push_back(Pair("category", "generate"));
- entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
- }
- if (fLong)
- WalletTxToJSON(wtx, entry);
- ret.push_back(entry);
- }
-
// Sent
if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
{
@@ -936,7 +945,17 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
Object entry;
entry.push_back(Pair("account", account));
entry.push_back(Pair("address", CBitcoinAddress(r.first).ToString()));
- entry.push_back(Pair("category", "receive"));
+ if (wtx.IsCoinBase())
+ {
+ if (wtx.GetDepthInMainChain() < 1)
+ entry.push_back(Pair("category", "orphan"));
+ else if (wtx.GetBlocksToMaturity() > 0)
+ entry.push_back(Pair("category", "immature"));
+ else
+ entry.push_back(Pair("category", "generate"));
+ }
+ else
+ entry.push_back(Pair("category", "receive"));
entry.push_back(Pair("amount", ValueFromAmount(r.second)));
if (fLong)
WalletTxToJSON(wtx, entry);
@@ -1041,17 +1060,16 @@ Value listaccounts(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- int64 nGeneratedImmature, nGeneratedMature, nFee;
+ int64 nFee;
string strSentAccount;
list<pair<CTxDestination, int64> > listReceived;
list<pair<CTxDestination, int64> > listSent;
- wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
+ wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount);
mapAccountBalances[strSentAccount] -= nFee;
BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& s, listSent)
mapAccountBalances[strSentAccount] -= s.second;
if (wtx.GetDepthInMainChain() >= nMinDepth)
{
- mapAccountBalances[""] += nGeneratedMature;
BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& r, listReceived)
if (pwalletMain->mapAddressBook.count(r.first))
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
diff --git a/src/script.cpp b/src/script.cpp
index 8c35f0eed5..c34fbec82d 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -1127,8 +1127,7 @@ public:
return false;
}
- void
- Set(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
+ void Set(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
{
// DoS prevention: limit cache size to less than 10MB
// (~200 bytes per cache entry times 50,000 entries)
diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp
new file mode 100644
index 0000000000..d5cb8e8101
--- /dev/null
+++ b/src/test/allocator_tests.cpp
@@ -0,0 +1,115 @@
+#include <boost/test/unit_test.hpp>
+
+#include "init.h"
+#include "main.h"
+#include "util.h"
+
+BOOST_AUTO_TEST_SUITE(allocator_tests)
+
+// Dummy memory page locker for platform independent tests
+static const void *last_lock_addr, *last_unlock_addr;
+static size_t last_lock_len, last_unlock_len;
+class TestLocker
+{
+public:
+ bool Lock(const void *addr, size_t len)
+ {
+ last_lock_addr = addr;
+ last_lock_len = len;
+ return true;
+ }
+ bool Unlock(const void *addr, size_t len)
+ {
+ last_unlock_addr = addr;
+ last_unlock_len = len;
+ return true;
+ }
+};
+
+BOOST_AUTO_TEST_CASE(test_LockedPageManagerBase)
+{
+ const size_t test_page_size = 4096;
+ LockedPageManagerBase<TestLocker> lpm(test_page_size);
+ size_t addr;
+ last_lock_addr = last_unlock_addr = 0;
+ last_lock_len = last_unlock_len = 0;
+
+ /* Try large number of small objects */
+ addr = 0;
+ for(int i=0; i<1000; ++i)
+ {
+ lpm.LockRange(reinterpret_cast<void*>(addr), 33);
+ addr += 33;
+ }
+ /* Try small number of page-sized objects, straddling two pages */
+ addr = test_page_size*100 + 53;
+ for(int i=0; i<100; ++i)
+ {
+ lpm.LockRange(reinterpret_cast<void*>(addr), test_page_size);
+ addr += test_page_size;
+ }
+ /* Try small number of page-sized objects aligned to exactly one page */
+ addr = test_page_size*300;
+ for(int i=0; i<100; ++i)
+ {
+ lpm.LockRange(reinterpret_cast<void*>(addr), test_page_size);
+ addr += test_page_size;
+ }
+ /* one very large object, straddling pages */
+ lpm.LockRange(reinterpret_cast<void*>(test_page_size*600+1), test_page_size*500);
+ BOOST_CHECK(last_lock_addr == reinterpret_cast<void*>(test_page_size*(600+500)));
+ /* one very large object, page aligned */
+ lpm.LockRange(reinterpret_cast<void*>(test_page_size*1200), test_page_size*500-1);
+ BOOST_CHECK(last_lock_addr == reinterpret_cast<void*>(test_page_size*(1200+500-1)));
+
+ BOOST_CHECK(lpm.GetLockedPageCount() == (
+ (1000*33+test_page_size-1)/test_page_size + // small objects
+ 101 + 100 + // page-sized objects
+ 501 + 500)); // large objects
+ BOOST_CHECK((last_lock_len & (test_page_size-1)) == 0); // always lock entire pages
+ BOOST_CHECK(last_unlock_len == 0); // nothing unlocked yet
+
+ /* And unlock again */
+ addr = 0;
+ for(int i=0; i<1000; ++i)
+ {
+ lpm.UnlockRange(reinterpret_cast<void*>(addr), 33);
+ addr += 33;
+ }
+ addr = test_page_size*100 + 53;
+ for(int i=0; i<100; ++i)
+ {
+ lpm.UnlockRange(reinterpret_cast<void*>(addr), test_page_size);
+ addr += test_page_size;
+ }
+ addr = test_page_size*300;
+ for(int i=0; i<100; ++i)
+ {
+ lpm.UnlockRange(reinterpret_cast<void*>(addr), test_page_size);
+ addr += test_page_size;
+ }
+ lpm.UnlockRange(reinterpret_cast<void*>(test_page_size*600+1), test_page_size*500);
+ lpm.UnlockRange(reinterpret_cast<void*>(test_page_size*1200), test_page_size*500-1);
+
+ /* Check that everything is released */
+ BOOST_CHECK(lpm.GetLockedPageCount() == 0);
+
+ /* A few and unlocks of size zero (should have no effect) */
+ addr = 0;
+ for(int i=0; i<1000; ++i)
+ {
+ lpm.LockRange(reinterpret_cast<void*>(addr), 0);
+ addr += 1;
+ }
+ BOOST_CHECK(lpm.GetLockedPageCount() == 0);
+ addr = 0;
+ for(int i=0; i<1000; ++i)
+ {
+ lpm.UnlockRange(reinterpret_cast<void*>(addr), 0);
+ addr += 1;
+ }
+ BOOST_CHECK(lpm.GetLockedPageCount() == 0);
+ BOOST_CHECK((last_unlock_len & (test_page_size-1)) == 0); // always unlock entire pages
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/util.cpp b/src/util.cpp
index d6d9a368f0..461f42d177 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -86,6 +86,8 @@ void locking_callback(int mode, int i, const char* file, int line)
}
}
+LockedPageManager LockedPageManager::instance;
+
// Init
class CInit
{
diff --git a/src/version.h b/src/version.h
index 8546ab85b6..a26c9e42ef 100644
--- a/src/version.h
+++ b/src/version.h
@@ -12,8 +12,8 @@
// These need to be macros, as version.cpp's voodoo requires it
#define CLIENT_VERSION_MAJOR 0
-#define CLIENT_VERSION_MINOR 6
-#define CLIENT_VERSION_REVISION 99
+#define CLIENT_VERSION_MINOR 7
+#define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_BUILD 0
static const int CLIENT_VERSION =
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 3af9fdaeae..6538ca9713 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -601,23 +601,14 @@ int CWalletTx::GetRequestCount() const
return nRequests;
}
-void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CTxDestination, int64> >& listReceived,
+void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
list<pair<CTxDestination, int64> >& listSent, int64& nFee, string& strSentAccount) const
{
- nGeneratedImmature = nGeneratedMature = nFee = 0;
+ nFee = 0;
listReceived.clear();
listSent.clear();
strSentAccount = strFromAccount;
- if (IsCoinBase())
- {
- if (GetBlocksToMaturity() > 0)
- nGeneratedImmature = pwallet->GetCredit(*this);
- else
- nGeneratedMature = GetCredit();
- return;
- }
-
// Compute fee:
int64 nDebit = GetDebit();
if (nDebit > 0) // debit>0 means we signed/sent this transaction
@@ -650,20 +641,17 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
}
-void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived,
+void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nReceived,
int64& nSent, int64& nFee) const
{
- nGenerated = nReceived = nSent = nFee = 0;
+ nReceived = nSent = nFee = 0;
- int64 allGeneratedImmature, allGeneratedMature, allFee;
- allGeneratedImmature = allGeneratedMature = allFee = 0;
+ int64 allFee;
string strSentAccount;
list<pair<CTxDestination, int64> > listReceived;
list<pair<CTxDestination, int64> > listSent;
- GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
+ GetAmounts(listReceived, listSent, allFee, strSentAccount);
- if (strAccount == "")
- nGenerated = allGeneratedMature;
if (strAccount == strSentAccount)
{
BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& s, listSent)
@@ -1620,6 +1608,129 @@ int64 CWallet::GetOldestKeyPoolTime()
return keypool.nTime;
}
+std::map<CTxDestination, int64> CWallet::GetAddressBalances()
+{
+ map<CTxDestination, int64> balances;
+
+ {
+ LOCK(cs_wallet);
+ BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
+ {
+ CWalletTx *pcoin = &walletEntry.second;
+
+ if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
+ continue;
+
+ if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+ continue;
+
+ int nDepth = pcoin->GetDepthInMainChain();
+ if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
+ continue;
+
+ for (unsigned int i = 0; i < pcoin->vout.size(); i++)
+ {
+ CTxDestination addr;
+ if (!IsMine(pcoin->vout[i]))
+ continue;
+ if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
+ continue;
+
+ int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
+
+ if (!balances.count(addr))
+ balances[addr] = 0;
+ balances[addr] += n;
+ }
+ }
+ }
+
+ return balances;
+}
+
+set< set<CTxDestination> > CWallet::GetAddressGroupings()
+{
+ set< set<CTxDestination> > groupings;
+ set<CTxDestination> grouping;
+
+ BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
+ {
+ CWalletTx *pcoin = &walletEntry.second;
+
+ if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0]))
+ {
+ // group all input addresses with each other
+ BOOST_FOREACH(CTxIn txin, pcoin->vin)
+ {
+ CTxDestination address;
+ if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
+ continue;
+ grouping.insert(address);
+ }
+
+ // group change with input addresses
+ BOOST_FOREACH(CTxOut txout, pcoin->vout)
+ if (IsChange(txout))
+ {
+ CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash];
+ CTxDestination txoutAddr;
+ if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
+ continue;
+ grouping.insert(txoutAddr);
+ }
+ groupings.insert(grouping);
+ grouping.clear();
+ }
+
+ // group lone addrs by themselves
+ for (unsigned int i = 0; i < pcoin->vout.size(); i++)
+ if (IsMine(pcoin->vout[i]))
+ {
+ CTxDestination address;
+ if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
+ continue;
+ grouping.insert(address);
+ groupings.insert(grouping);
+ grouping.clear();
+ }
+ }
+
+ set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
+ map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
+ BOOST_FOREACH(set<CTxDestination> grouping, groupings)
+ {
+ // make a set of all the groups hit by this new group
+ set< set<CTxDestination>* > hits;
+ map< CTxDestination, set<CTxDestination>* >::iterator it;
+ BOOST_FOREACH(CTxDestination address, grouping)
+ if ((it = setmap.find(address)) != setmap.end())
+ hits.insert((*it).second);
+
+ // merge all hit groups into a new single group and delete old groups
+ set<CTxDestination>* merged = new set<CTxDestination>(grouping);
+ BOOST_FOREACH(set<CTxDestination>* hit, hits)
+ {
+ merged->insert(hit->begin(), hit->end());
+ uniqueGroupings.erase(hit);
+ delete hit;
+ }
+ uniqueGroupings.insert(merged);
+
+ // update setmap
+ BOOST_FOREACH(CTxDestination element, *merged)
+ setmap[element] = merged;
+ }
+
+ set< set<CTxDestination> > ret;
+ BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
+ {
+ ret.insert(*uniqueGrouping);
+ delete uniqueGrouping;
+ }
+
+ return ret;
+}
+
CPubKey CReserveKey::GetReservedKey()
{
if (nIndex == -1)
diff --git a/src/wallet.h b/src/wallet.h
index 65d3448212..7fd33629fe 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -181,6 +181,9 @@ public:
int64 GetOldestKeyPoolTime();
void GetAllReserveKeys(std::set<CKeyID>& setAddress);
+ std::set< std::set<CTxDestination> > GetAddressGroupings();
+ std::map<CTxDestination, int64> GetAddressBalances();
+
bool IsMine(const CTxIn& txin) const;
int64 GetDebit(const CTxIn& txin) const;
bool IsMine(const CTxOut& txout) const
@@ -324,9 +327,7 @@ public:
typedef std::map<std::string, std::string> mapValue_t;
-static
-void
-ReadOrderPos(int64& nOrderPos, mapValue_t& mapValue)
+static void ReadOrderPos(int64& nOrderPos, mapValue_t& mapValue)
{
if (!mapValue.count("n"))
{
@@ -337,9 +338,7 @@ ReadOrderPos(int64& nOrderPos, mapValue_t& mapValue)
}
-static
-void
-WriteOrderPos(const int64& nOrderPos, mapValue_t& mapValue)
+static void WriteOrderPos(const int64& nOrderPos, mapValue_t& mapValue)
{
if (nOrderPos == -1)
return;
@@ -594,10 +593,10 @@ public:
return nChangeCached;
}
- void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<CTxDestination, int64> >& listReceived,
+ void GetAmounts(std::list<std::pair<CTxDestination, int64> >& listReceived,
std::list<std::pair<CTxDestination, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
- void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived,
+ void GetAccountAmounts(const std::string& strAccount, int64& nReceived,
int64& nSent, int64& nFee) const;
bool IsFromMe() const