aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chainparams.cpp1
-rw-r--r--src/init.cpp66
-rw-r--r--src/leveldbwrapper.cpp5
-rw-r--r--src/main.cpp24
-rw-r--r--src/main.h2
-rw-r--r--src/miner.cpp3
-rw-r--r--src/net.cpp60
-rw-r--r--src/net.h13
-rw-r--r--src/qt/bitcoingui.cpp25
-rw-r--r--src/qt/rpcconsole.cpp29
-rw-r--r--src/qt/rpcconsole.h2
-rw-r--r--src/rpcblockchain.cpp4
-rw-r--r--src/rpcmining.cpp60
-rw-r--r--src/rpcnet.cpp1
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/rpcserver.cpp49
-rw-r--r--src/rpcserver.h2
-rw-r--r--src/rpcwallet.cpp2
-rw-r--r--src/sync.h3
-rw-r--r--src/ui_interface.h2
-rw-r--r--src/wallet.cpp12
21 files changed, 275 insertions, 92 deletions
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 50977dc06b..fb1d05f833 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -152,6 +152,7 @@ public:
vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org"));
vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com"));
vSeeds.push_back(CDNSSeedData("bitnodes.io", "seed.bitnodes.io"));
+ vSeeds.push_back(CDNSSeedData("open-nodes.org", "seeds.bitcoin.open-nodes.org"));
vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org"));
base58Prefixes[PUBKEY_ADDRESS] = list_of(0);
diff --git a/src/init.cpp b/src/init.cpp
index f9e568a207..99df237b2a 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -38,8 +38,8 @@
#include <boost/interprocess/sync/file_lock.hpp>
#include <openssl/crypto.h>
-using namespace std;
using namespace boost;
+using namespace std;
#ifdef ENABLE_WALLET
CWallet* pwalletMain;
@@ -58,7 +58,8 @@ CWallet* pwalletMain;
enum BindFlags {
BF_NONE = 0,
BF_EXPLICIT = (1U << 0),
- BF_REPORT_ERROR = (1U << 1)
+ BF_REPORT_ERROR = (1U << 1),
+ BF_WHITELIST = (1U << 2),
};
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
@@ -109,10 +110,11 @@ static CCoinsViewDB *pcoinsdbview;
void Shutdown()
{
- LogPrintf("Shutdown : In progress...\n");
+ LogPrintf("%s: In progress...\n", __func__);
static CCriticalSection cs_Shutdown;
TRY_LOCK(cs_Shutdown, lockShutdown);
- if (!lockShutdown) return;
+ if (!lockShutdown)
+ return;
RenameThread("bitcoin-shutoff");
mempool.AddTransactionsUpdated(1);
@@ -130,7 +132,7 @@ void Shutdown()
if (est_fileout)
mempool.WriteFeeEstimates(est_fileout);
else
- LogPrintf("failed to write fee estimates");
+ LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
{
LOCK(cs_main);
@@ -142,9 +144,12 @@ void Shutdown()
pblocktree->Flush();
if (pcoinsTip)
pcoinsTip->Flush();
- delete pcoinsTip; pcoinsTip = NULL;
- delete pcoinsdbview; pcoinsdbview = NULL;
- delete pblocktree; pblocktree = NULL;
+ delete pcoinsTip;
+ pcoinsTip = NULL;
+ delete pcoinsdbview;
+ pcoinsdbview = NULL;
+ delete pblocktree;
+ pblocktree = NULL;
}
#ifdef ENABLE_WALLET
if (pwalletMain)
@@ -156,7 +161,7 @@ void Shutdown()
if (pwalletMain)
delete pwalletMain;
#endif
- LogPrintf("Shutdown : done\n");
+ LogPrintf("%s: done\n", __func__);
}
//
@@ -174,13 +179,13 @@ void HandleSIGHUP(int)
bool static InitError(const std::string &str)
{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR | CClientUIInterface::NOSHOWGUI);
+ uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
return false;
}
bool static InitWarning(const std::string &str)
{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING | CClientUIInterface::NOSHOWGUI);
+ uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
return true;
}
@@ -188,7 +193,7 @@ bool static Bind(const CService &addr, unsigned int flags) {
if (!(flags & BF_EXPLICIT) && IsLimited(addr))
return false;
std::string strError;
- if (!BindListenPort(addr, strError)) {
+ if (!BindListenPort(addr, strError, flags & BF_WHITELIST)) {
if (flags & BF_REPORT_ERROR)
return InitError(strError);
return false;
@@ -214,7 +219,6 @@ std::string HelpMessage(HelpMessageMode mode)
}
strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n";
- strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n";
strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n";
strUsage += " -maxorphanblocks=<n> " + strprintf(_("Keep at most <n> unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n";
strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n";
@@ -249,10 +253,13 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n";
#endif
#endif
+ strUsage += " -whitebind=<addr> " + _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6") + "\n";
+ strUsage += " -whitelist=<netmask> " + _("Whitelist peers connecting from the given netmask or ip. Can be specified multiple times.") + "\n";
#ifdef ENABLE_WALLET
strUsage += "\n" + _("Wallet options:") + "\n";
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
+ strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n";
if (GetBoolArg("-help-debug", false))
strUsage += " -mintxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CWallet::minTxFee.GetFeePerK())) + "\n";
strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n";
@@ -288,8 +295,10 @@ std::string HelpMessage(HelpMessageMode mode)
if (mode == HMM_BITCOIN_QT)
strUsage += ", qt";
strUsage += ".\n";
+#ifdef ENABLE_WALLET
strUsage += " -gen " + _("Generate coins (default: 0)") + "\n";
strUsage += " -genproclimit=<n> " + _("Set the processor limit for when generation is on (-1 = unlimited, default: -1)") + "\n";
+#endif
strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n";
strUsage += " -logips " + _("Include IP addresses in debug output (default: 0)") + "\n";
strUsage += " -logtimestamps " + _("Prepend debug output with timestamp (default: 1)") + "\n";
@@ -315,6 +324,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += "\n" + _("Node relay options:") + "\n";
strUsage += " -datacarrier " + _("Relay and mine data carrier transactions (default: 1)") + "\n";
+
strUsage += "\n" + _("Block creation options:") + "\n";
strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n";
strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n";
@@ -499,11 +509,11 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 2: parameter interactions
- if (mapArgs.count("-bind")) {
+ if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
// when specifying an explicit binding address, you want to listen on it
// even when -connect or -proxy is specified
if (SoftSetBoolArg("-listen", true))
- LogPrintf("AppInit2 : parameter interaction: -bind set -> setting -listen=1\n");
+ LogPrintf("AppInit2 : parameter interaction: -bind or -whitebind set -> setting -listen=1\n");
}
if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) {
@@ -547,7 +557,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
// Make sure enough file descriptors are available
- int nBind = std::max((int)mapArgs.count("-bind"), 1);
+ int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
nMaxConnections = GetArg("-maxconnections", 125);
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
@@ -564,9 +574,9 @@ bool AppInit2(boost::thread_group& threadGroup)
if (GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), string("0")) != categories.end())
fDebug = false;
- // Check for -debugnet (deprecated)
+ // Check for -debugnet
if (GetBoolArg("-debugnet", false))
- InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net"));
+ InitWarning(_("Warning: Unsupported argument -debugnet ignored, use -debug=net."));
// Check for -socks - as this is a privacy risk to continue, exit here
if (mapArgs.count("-socks"))
return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
@@ -764,6 +774,15 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
+ if (mapArgs.count("-whitelist")) {
+ BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) {
+ CSubNet subnet(net);
+ if (!subnet.IsValid())
+ return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net));
+ CNode::AddWhitelistedRange(subnet);
+ }
+ }
+
CService addrProxy;
bool fProxy = false;
if (mapArgs.count("-proxy")) {
@@ -800,13 +819,21 @@ bool AppInit2(boost::thread_group& threadGroup)
bool fBound = false;
if (fListen) {
- if (mapArgs.count("-bind")) {
+ if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind));
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
}
+ BOOST_FOREACH(std::string strBind, mapMultiArgs["-whitebind"]) {
+ CService addrBind;
+ if (!Lookup(strBind.c_str(), addrBind, 0, false))
+ return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind));
+ if (addrBind.GetPort() == 0)
+ return InitError(strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind));
+ fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST));
+ }
}
else {
struct in_addr inaddr_any;
@@ -994,6 +1021,7 @@ bool AppInit2(boost::thread_group& threadGroup)
boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
CAutoFile est_filein = CAutoFile(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION);
+ // Allowed to fail as this file IS missing on first startup.
if (est_filein)
mempool.ReadFeeEstimates(est_filein);
diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp
index 5b4a9c147b..9e849696a8 100644
--- a/src/leveldbwrapper.cpp
+++ b/src/leveldbwrapper.cpp
@@ -32,6 +32,11 @@ static leveldb::Options GetOptions(size_t nCacheSize) {
options.filter_policy = leveldb::NewBloomFilterPolicy(10);
options.compression = leveldb::kNoCompression;
options.max_open_files = 64;
+ if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
+ // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
+ // on corruption in later versions.
+ options.paranoid_checks = true;
+ }
return options;
}
diff --git a/src/main.cpp b/src/main.cpp
index 8225d73d8d..4f6b442f3a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -41,6 +41,8 @@ CCriticalSection cs_main;
map<uint256, CBlockIndex*> mapBlockIndex;
CChain chainActive;
int64_t nTimeBestReceived = 0;
+CWaitableCriticalSection csBestBlock;
+CConditionVariable cvBlockChange;
int nScriptCheckThreads = 0;
bool fImporting = false;
bool fReindex = false;
@@ -210,7 +212,7 @@ struct CBlockReject {
struct CNodeState {
// Accumulated misbehaviour score for this peer.
int nMisbehavior;
- // Whether this peer should be disconnected and banned.
+ // Whether this peer should be disconnected and banned (unless whitelisted).
bool fShouldBan;
// String name of this peer (debugging/logging purposes).
std::string name;
@@ -1425,7 +1427,8 @@ void Misbehaving(NodeId pnode, int howmuch)
return;
state->nMisbehavior += howmuch;
- if (state->nMisbehavior >= GetArg("-banscore", 100))
+ int banscore = GetArg("-banscore", 100);
+ if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore)
{
LogPrintf("Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", state->name, state->nMisbehavior-howmuch, state->nMisbehavior);
state->fShouldBan = true;
@@ -1944,11 +1947,14 @@ void static UpdateTip(CBlockIndex *pindexNew) {
// New best block
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
+
LogPrintf("UpdateTip: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainActive.Tip()));
+ cvBlockChange.notify_all();
+
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
{
@@ -3947,6 +3953,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS);
if (nEvicted > 0)
LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
+ } else if (pfrom->fWhitelisted) {
+ // Always relay transactions received from whitelisted peers, even
+ // if they are already in the mempool (allowing the node to function
+ // as a gateway for nodes hidden behind it).
+ RelayTransaction(tx);
}
int nDoS = 0;
if (state.IsInvalid(nDoS))
@@ -4440,11 +4451,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
CNodeState &state = *State(pto->GetId());
if (state.fShouldBan) {
- if (pto->addr.IsLocal())
- LogPrintf("Warning: not banning local node %s!\n", pto->addr.ToString());
+ if (pto->fWhitelisted)
+ LogPrintf("Warning: not punishing whitelisted peer %s!\n", pto->addr.ToString());
else {
pto->fDisconnect = true;
- CNode::Ban(pto->addr);
+ if (pto->addr.IsLocal())
+ LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
+ else
+ CNode::Ban(pto->addr);
}
state.fShouldBan = false;
}
diff --git a/src/main.h b/src/main.h
index f6bac889be..a683412571 100644
--- a/src/main.h
+++ b/src/main.h
@@ -87,6 +87,8 @@ extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
extern const std::string strMessageMagic;
extern int64_t nTimeBestReceived;
+extern CWaitableCriticalSection csBestBlock;
+extern CConditionVariable cvBlockChange;
extern bool fImporting;
extern bool fReindex;
extern bool fBenchmark;
diff --git a/src/miner.cpp b/src/miner.cpp
index 17918a1280..ec56c71192 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -467,7 +467,10 @@ void static BitcoinMiner(CWallet *pwallet)
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
if (!pblocktemplate.get())
+ {
+ LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
return;
+ }
CBlock *pblock = &pblocktemplate->block;
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
diff --git a/src/net.cpp b/src/net.cpp
index 0e663aea83..3b3d91d652 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -50,7 +50,16 @@
using namespace std;
using namespace boost;
-static const int MAX_OUTBOUND_CONNECTIONS = 8;
+namespace {
+ const int MAX_OUTBOUND_CONNECTIONS = 8;
+
+ struct ListenSocket {
+ SOCKET socket;
+ bool whitelisted;
+
+ ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {}
+ };
+}
//
// Global state variables
@@ -65,7 +74,7 @@ static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
static CNode* pnodeSync = NULL;
uint64_t nLocalHostNonce = 0;
-static std::vector<SOCKET> vhListenSocket;
+static std::vector<ListenSocket> vhListenSocket;
CAddrMan addrman;
int nMaxConnections = 125;
@@ -593,6 +602,24 @@ bool CNode::Ban(const CNetAddr &addr) {
return true;
}
+
+std::vector<CSubNet> CNode::vWhitelistedRange;
+CCriticalSection CNode::cs_vWhitelistedRange;
+
+bool CNode::IsWhitelistedRange(const CNetAddr &addr) {
+ LOCK(cs_vWhitelistedRange);
+ BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) {
+ if (subnet.Match(addr))
+ return true;
+ }
+ return false;
+}
+
+void CNode::AddWhitelistedRange(const CSubNet &subnet) {
+ LOCK(cs_vWhitelistedRange);
+ vWhitelistedRange.push_back(subnet);
+}
+
#undef X
#define X(name) stats.name = name
void CNode::copyStats(CNodeStats &stats)
@@ -609,6 +636,7 @@ void CNode::copyStats(CNodeStats &stats)
X(nStartingHeight);
X(nSendBytes);
X(nRecvBytes);
+ X(fWhitelisted);
stats.fSyncNode = (this == pnodeSync);
// It is common for nodes with good ping times to suddenly become lagged,
@@ -848,9 +876,9 @@ void ThreadSocketHandler()
SOCKET hSocketMax = 0;
bool have_fds = false;
- BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
- FD_SET(hListenSocket, &fdsetRecv);
- hSocketMax = max(hSocketMax, hListenSocket);
+ BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) {
+ FD_SET(hListenSocket.socket, &fdsetRecv);
+ hSocketMax = max(hSocketMax, hListenSocket.socket);
have_fds = true;
}
@@ -917,13 +945,13 @@ void ThreadSocketHandler()
//
// Accept new connections
//
- BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
+ BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket)
{
- if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
+ if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
{
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
- SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
+ SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
CAddress addr;
int nInbound = 0;
@@ -931,6 +959,7 @@ void ThreadSocketHandler()
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
LogPrintf("Warning: Unknown socket family\n");
+ bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr);
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
@@ -948,7 +977,7 @@ void ThreadSocketHandler()
{
closesocket(hSocket);
}
- else if (CNode::IsBanned(addr))
+ else if (CNode::IsBanned(addr) && !whitelisted)
{
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
closesocket(hSocket);
@@ -957,6 +986,7 @@ void ThreadSocketHandler()
{
CNode* pnode = new CNode(hSocket, addr, "", true);
pnode->AddRef();
+ pnode->fWhitelisted = whitelisted;
{
LOCK(cs_vNodes);
@@ -1580,7 +1610,7 @@ void ThreadMessageHandler()
-bool BindListenPort(const CService &addrBind, string& strError)
+bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted)
{
strError = "";
int nOne = 1;
@@ -1661,9 +1691,9 @@ bool BindListenPort(const CService &addrBind, string& strError)
return false;
}
- vhListenSocket.push_back(hListenSocket);
+ vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted));
- if (addrBind.IsRoutable() && fDiscover)
+ if (addrBind.IsRoutable() && fDiscover && !fWhitelisted)
AddLocal(addrBind, LOCAL_BIND);
return true;
@@ -1788,9 +1818,9 @@ public:
BOOST_FOREACH(CNode* pnode, vNodes)
if (pnode->hSocket != INVALID_SOCKET)
closesocket(pnode->hSocket);
- BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
- if (hListenSocket != INVALID_SOCKET)
- if (closesocket(hListenSocket) == SOCKET_ERROR)
+ BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket)
+ if (hListenSocket.socket != INVALID_SOCKET)
+ if (closesocket(hListenSocket.socket) == SOCKET_ERROR)
LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
// clean up some globals (to help leak detection)
diff --git a/src/net.h b/src/net.h
index 21a2919f4a..866c9ae783 100644
--- a/src/net.h
+++ b/src/net.h
@@ -64,7 +64,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL);
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
void MapPort(bool fUseUPnP);
unsigned short GetListenPort();
-bool BindListenPort(const CService &bindAddr, std::string& strError);
+bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
void StartNode(boost::thread_group& threadGroup);
bool StopNode();
void SocketSendData(CNode *pnode);
@@ -154,6 +154,7 @@ public:
uint64_t nSendBytes;
uint64_t nRecvBytes;
bool fSyncNode;
+ bool fWhitelisted;
double dPingTime;
double dPingWait;
std::string addrLocal;
@@ -236,6 +237,7 @@ public:
// store the sanitized version in cleanSubVer. The original should be used when dealing with
// the network or wire types and the cleaned string used when displayed or logged.
std::string strSubVer, cleanSubVer;
+ bool fWhitelisted; // This peer can bypass DoS banning.
bool fOneShot;
bool fClient;
bool fInbound;
@@ -259,6 +261,11 @@ protected:
static std::map<CNetAddr, int64_t> setBanned;
static CCriticalSection cs_setBanned;
+ // Whitelisted ranges. Any node connecting from these is automatically
+ // whitelisted (as well as those connecting to whitelisted binds).
+ static std::vector<CSubNet> vWhitelistedRange;
+ static CCriticalSection cs_vWhitelistedRange;
+
// Basic fuzz-testing
void Fuzz(int nChance); // modifies ssSend
@@ -305,6 +312,7 @@ public:
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
nVersion = 0;
strSubVer = "";
+ fWhitelisted = false;
fOneShot = false;
fClient = false; // set by version message
fInbound = fInboundIn;
@@ -720,6 +728,9 @@ public:
static bool Ban(const CNetAddr &ip);
void copyStats(CNodeStats &stats);
+ static bool IsWhitelistedRange(const CNetAddr &ip);
+ static void AddWhitelistedRange(const CSubNet &subnet);
+
// Network stats
static void RecordBytesRecv(uint64_t bytes);
static void RecordBytesSent(uint64_t bytes);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 6b3aa2a2df..5fc2f500b5 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -159,10 +159,13 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
labelEncryptionIcon = new QLabel();
labelConnectionsIcon = new QLabel();
labelBlocksIcon = new QLabel();
- frameBlocksLayout->addStretch();
- frameBlocksLayout->addWidget(unitDisplayControl);
- frameBlocksLayout->addStretch();
- frameBlocksLayout->addWidget(labelEncryptionIcon);
+ if(enableWallet)
+ {
+ frameBlocksLayout->addStretch();
+ frameBlocksLayout->addWidget(unitDisplayControl);
+ frameBlocksLayout->addStretch();
+ frameBlocksLayout->addWidget(labelEncryptionIcon);
+ }
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelConnectionsIcon);
frameBlocksLayout->addStretch();
@@ -780,11 +783,7 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
buttons = QMessageBox::Ok;
- // Ensure we get users attention, but only if main window is visible
- // as we don't want to pop up the main window for messages that happen before
- // initialization is finished.
- if(!(style & CClientUIInterface::NOSHOWGUI))
- showNormalIfMinimized();
+ showNormalIfMinimized();
QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
int r = mBox.exec();
if (ret != NULL)
@@ -921,6 +920,8 @@ void BitcoinGUI::setEncryptionStatus(int status)
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
{
+ if(!clientModel)
+ return;
// activateWindow() (sometimes) helps with keyboard focus on Windows
if (isHidden())
{
@@ -1012,7 +1013,7 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl():QLabel()
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
}
-/** So that it responds to left-button clicks */
+/** So that it responds to button clicks */
void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
{
onDisplayUnitsClicked(event->pos());
@@ -1029,10 +1030,6 @@ void UnitDisplayStatusBarControl::createContextMenu()
menu->addAction(menuAction);
}
connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
-
- // what happens on right click.
- setContextMenuPolicy(Qt::CustomContextMenu);
- connect(this,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(onDisplayUnitsClicked(const QPoint&)));
}
/** Lets the control know about the Options Model (and its signals) */
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index e1f40ddd09..9b67f8125f 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -473,6 +473,10 @@ void RPCConsole::on_tabWidget_currentChanged(int index)
{
ui->lineEdit->setFocus();
}
+ else if(ui->tabWidget->widget(index) == ui->tab_peers)
+ {
+ initPeerTable();
+ }
}
void RPCConsole::on_openDebugLogfileButton_clicked()
@@ -648,11 +652,27 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *combinedStats)
ui->peerBanScore->setText(tr("Fetching..."));
}
+void RPCConsole::initPeerTable()
+{
+ if (!clientModel)
+ return;
+
+ // peerWidget needs a resize in case the dialog has non-default geometry
+ columnResizingFixer->stretchColumnWidth(PeerTableModel::Address);
+
+ // start PeerTableModel auto refresh
+ clientModel->getPeerTableModel()->startAutoRefresh(1000);
+}
+
// We override the virtual resizeEvent of the QWidget to adjust tables column
// sizes as the tables width is proportional to the dialogs width.
void RPCConsole::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
+
+ if (!clientModel)
+ return;
+
columnResizingFixer->stretchColumnWidth(PeerTableModel::Address);
}
@@ -660,17 +680,16 @@ void RPCConsole::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
- // peerWidget needs a resize in case the dialog has non-default geometry
- columnResizingFixer->stretchColumnWidth(PeerTableModel::Address);
-
- // start PeerTableModel auto refresh
- clientModel->getPeerTableModel()->startAutoRefresh(1000);
+ initPeerTable();
}
void RPCConsole::hideEvent(QHideEvent *event)
{
QWidget::hideEvent(event);
+ if (!clientModel)
+ return;
+
// stop PeerTableModel auto refresh
clientModel->getPeerTableModel()->stopAutoRefresh();
}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 3aeff3eace..94672b30cc 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -47,6 +47,8 @@ protected:
private:
/** show detailed information on ui about selected node */
void updateNodeDetail(const CNodeCombinedStats *combinedStats);
+ /** initialize peer table */
+ void initPeerTable();
enum ColumnWidths
{
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index a67f266a13..253693e624 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -276,7 +276,9 @@ Value getblock(const Array& params, bool fHelp)
CBlock block;
CBlockIndex* pblockindex = mapBlockIndex[hash];
- ReadBlockFromDisk(block, pblockindex);
+
+ if(!ReadBlockFromDisk(block, pblockindex))
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
if (!fVerbose)
{
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index c7621dc137..6f72ea7404 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -324,6 +324,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
);
std::string strMode = "template";
+ Value lpval = Value::null;
if (params.size() > 0)
{
const Object& oparam = params[0].get_obj();
@@ -336,6 +337,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
}
else
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
+ lpval = find_value(oparam, "longpollid");
}
if (strMode != "template")
@@ -347,8 +349,63 @@ Value getblocktemplate(const Array& params, bool fHelp)
if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
- // Update block
static unsigned int nTransactionsUpdatedLast;
+
+ if (lpval.type() != null_type)
+ {
+ // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
+ uint256 hashWatchedChain;
+ boost::system_time checktxtime;
+ unsigned int nTransactionsUpdatedLastLP;
+
+ if (lpval.type() == str_type)
+ {
+ // Format: <hashBestChain><nTransactionsUpdatedLast>
+ std::string lpstr = lpval.get_str();
+
+ hashWatchedChain.SetHex(lpstr.substr(0, 64));
+ nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
+ }
+ else
+ {
+ // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
+ hashWatchedChain = chainActive.Tip()->GetBlockHash();
+ nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
+ }
+
+ // Release the wallet and main lock while waiting
+#ifdef ENABLE_WALLET
+ if(pwalletMain)
+ LEAVE_CRITICAL_SECTION(pwalletMain->cs_wallet);
+#endif
+ LEAVE_CRITICAL_SECTION(cs_main);
+ {
+ checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
+
+ boost::unique_lock<boost::mutex> lock(csBestBlock);
+ while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
+ {
+ if (!cvBlockChange.timed_wait(lock, checktxtime))
+ {
+ // Timeout: Check transactions for update
+ if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
+ break;
+ checktxtime += boost::posix_time::seconds(10);
+ }
+ }
+ }
+ ENTER_CRITICAL_SECTION(cs_main);
+#ifdef ENABLE_WALLET
+ if(pwalletMain)
+ ENTER_CRITICAL_SECTION(pwalletMain->cs_wallet);
+#endif
+
+ if (!IsRPCRunning())
+ throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
+ // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
+ }
+
+ // Update block
static CBlockIndex* pindexPrev;
static int64_t nStart;
static CBlockTemplate* pblocktemplate;
@@ -436,6 +493,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
result.push_back(Pair("transactions", transactions));
result.push_back(Pair("coinbaseaux", aux));
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
+ result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
result.push_back(Pair("target", hashTarget.GetHex()));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index cf2c293caf..680717930b 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -137,6 +137,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("syncheight", statestats.nSyncHeight));
}
obj.push_back(Pair("syncnode", stats.fSyncNode));
+ obj.push_back(Pair("whitelisted", stats.fWhitelisted));
ret.push_back(obj);
}
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 2306b1b883..1efe38e830 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -523,7 +523,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
" \"txid\":\"id\", (string, required) The transaction id\n"
" \"vout\":n, (numeric, required) The output number\n"
" \"scriptPubKey\": \"hex\", (string, required) script key\n"
- " \"redeemScript\": \"hex\" (string, required) redeem script\n"
+ " \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n"
" }\n"
" ,...\n"
" ]\n"
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index e0c96d88fa..5deb6a4e08 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -32,6 +32,7 @@ using namespace std;
static std::string strRPCUserColonPass;
+static bool fRPCRunning = false;
// These are created by StartRPCThreads, destroyed in StopRPCThreads
static asio::io_service* rpc_io_service = NULL;
static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
@@ -232,8 +233,8 @@ static const CRPCCommand vRPCCommands[] =
{ "getblockchaininfo", &getblockchaininfo, true, false, false },
{ "getbestblockhash", &getbestblockhash, true, false, false },
{ "getblockcount", &getblockcount, true, false, false },
- { "getblock", &getblock, false, false, false },
- { "getblockhash", &getblockhash, false, false, false },
+ { "getblock", &getblock, true, false, false },
+ { "getblockhash", &getblockhash, true, false, false },
{ "getdifficulty", &getdifficulty, true, false, false },
{ "getrawmempool", &getrawmempool, true, false, false },
{ "gettxout", &gettxout, true, false, false },
@@ -245,32 +246,32 @@ static const CRPCCommand vRPCCommands[] =
{ "getmininginfo", &getmininginfo, true, false, false },
{ "getnetworkhashps", &getnetworkhashps, true, false, false },
{ "prioritisetransaction", &prioritisetransaction, true, false, false },
- { "submitblock", &submitblock, false, true, false },
+ { "submitblock", &submitblock, true, true, false },
/* Raw transactions */
- { "createrawtransaction", &createrawtransaction, false, false, false },
- { "decoderawtransaction", &decoderawtransaction, false, false, false },
- { "decodescript", &decodescript, false, false, false },
- { "getrawtransaction", &getrawtransaction, false, false, false },
+ { "createrawtransaction", &createrawtransaction, true, false, false },
+ { "decoderawtransaction", &decoderawtransaction, true, false, false },
+ { "decodescript", &decodescript, true, false, false },
+ { "getrawtransaction", &getrawtransaction, true, false, false },
{ "sendrawtransaction", &sendrawtransaction, false, false, false },
{ "signrawtransaction", &signrawtransaction, false, false, false }, /* uses wallet if enabled */
/* Utility functions */
{ "createmultisig", &createmultisig, true, true , false },
{ "validateaddress", &validateaddress, true, false, false }, /* uses wallet if enabled */
- { "verifymessage", &verifymessage, false, false, false },
+ { "verifymessage", &verifymessage, true, false, false },
{ "estimatefee", &estimatefee, true, true, false },
{ "estimatepriority", &estimatepriority, true, true, false },
#ifdef ENABLE_WALLET
/* Wallet */
- { "addmultisigaddress", &addmultisigaddress, false, false, true },
+ { "addmultisigaddress", &addmultisigaddress, true, false, true },
{ "backupwallet", &backupwallet, true, false, true },
{ "dumpprivkey", &dumpprivkey, true, false, true },
{ "dumpwallet", &dumpwallet, true, false, true },
- { "encryptwallet", &encryptwallet, false, false, true },
+ { "encryptwallet", &encryptwallet, true, false, true },
{ "getaccountaddress", &getaccountaddress, true, false, true },
- { "getaccount", &getaccount, false, false, true },
+ { "getaccount", &getaccount, true, false, true },
{ "getaddressesbyaccount", &getaddressesbyaccount, true, false, true },
{ "getbalance", &getbalance, false, false, true },
{ "getnewaddress", &getnewaddress, true, false, true },
@@ -279,10 +280,10 @@ static const CRPCCommand vRPCCommands[] =
{ "getreceivedbyaddress", &getreceivedbyaddress, false, false, true },
{ "gettransaction", &gettransaction, false, false, true },
{ "getunconfirmedbalance", &getunconfirmedbalance, false, false, true },
- { "getwalletinfo", &getwalletinfo, true, false, true },
- { "importprivkey", &importprivkey, false, false, true },
- { "importwallet", &importwallet, false, false, true },
- { "importaddress", &importaddress, false, false, true },
+ { "getwalletinfo", &getwalletinfo, false, false, true },
+ { "importprivkey", &importprivkey, true, false, true },
+ { "importwallet", &importwallet, true, false, true },
+ { "importaddress", &importaddress, true, false, true },
{ "keypoolrefill", &keypoolrefill, true, false, true },
{ "listaccounts", &listaccounts, false, false, true },
{ "listaddressgroupings", &listaddressgroupings, false, false, true },
@@ -292,16 +293,16 @@ static const CRPCCommand vRPCCommands[] =
{ "listsinceblock", &listsinceblock, false, false, true },
{ "listtransactions", &listtransactions, false, false, true },
{ "listunspent", &listunspent, false, false, true },
- { "lockunspent", &lockunspent, false, false, true },
+ { "lockunspent", &lockunspent, true, false, true },
{ "move", &movecmd, false, false, true },
{ "sendfrom", &sendfrom, false, false, true },
{ "sendmany", &sendmany, false, false, true },
{ "sendtoaddress", &sendtoaddress, false, false, true },
{ "setaccount", &setaccount, true, false, true },
- { "settxfee", &settxfee, false, false, true },
- { "signmessage", &signmessage, false, false, true },
+ { "settxfee", &settxfee, true, false, true },
+ { "signmessage", &signmessage, true, false, true },
{ "walletlock", &walletlock, true, false, true },
- { "walletpassphrasechange", &walletpassphrasechange, false, false, true },
+ { "walletpassphrasechange", &walletpassphrasechange, true, false, true },
{ "walletpassphrase", &walletpassphrase, true, false, true },
/* Wallet-enabled mining */
@@ -659,6 +660,7 @@ void StartRPCThreads()
rpc_worker_group = new boost::thread_group();
for (int i = 0; i < GetArg("-rpcthreads", 4); i++)
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
+ fRPCRunning = true;
}
void StartDummyRPCThread()
@@ -671,12 +673,15 @@ void StartDummyRPCThread()
rpc_dummy_work = new asio::io_service::work(*rpc_io_service);
rpc_worker_group = new boost::thread_group();
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
+ fRPCRunning = true;
}
}
void StopRPCThreads()
{
if (rpc_io_service == NULL) return;
+ // Set this to false first, so that longpolling loops will exit when woken up
+ fRPCRunning = false;
// First, cancel all timers and acceptors
// This is not done automatically by ->stop(), and in some cases the destructor of
@@ -698,6 +703,7 @@ void StopRPCThreads()
deadlineTimers.clear();
rpc_io_service->stop();
+ cvBlockChange.notify_all();
if (rpc_worker_group != NULL)
rpc_worker_group->join_all();
delete rpc_dummy_work; rpc_dummy_work = NULL;
@@ -706,6 +712,11 @@ void StopRPCThreads()
delete rpc_io_service; rpc_io_service = NULL;
}
+bool IsRPCRunning()
+{
+ return fRPCRunning;
+}
+
void RPCRunHandler(const boost::system::error_code& err, boost::function<void(void)> func)
{
if (!err)
diff --git a/src/rpcserver.h b/src/rpcserver.h
index e32eb975a1..31badadd6d 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -40,6 +40,8 @@ void StartRPCThreads();
void StartDummyRPCThread();
/* Stop RPC threads */
void StopRPCThreads();
+/* Query whether RPC is running */
+bool IsRPCRunning();
/*
Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 1e46129065..e8c62fd37b 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -201,7 +201,7 @@ Value getrawchangeaddress(const Array& params, bool fHelp)
CReserveKey reservekey(pwalletMain);
CPubKey vchPubKey;
if (!reservekey.GetReservedKey(vchPubKey))
- throw JSONRPCError(RPC_WALLET_ERROR, "Error: Unable to obtain key for change");
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
reservekey.KeepKey();
diff --git a/src/sync.h b/src/sync.h
index 077ed59b89..cd319e0171 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -84,6 +84,9 @@ typedef AnnotatedMixin<boost::recursive_mutex> CCriticalSection;
/** Wrapped boost mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;
+/** Just a typedef for boost::condition_variable, can be wrapped later if desired */
+typedef boost::condition_variable CConditionVariable;
+
#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
diff --git a/src/ui_interface.h b/src/ui_interface.h
index e9fcd91d41..a48ba237d2 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -63,8 +63,6 @@ public:
/** Force blocking, modal message box dialog (not just OS notification) */
MODAL = 0x10000000U,
- /** Don't bring GUI to foreground. Use for messages during initialization */
- NOSHOWGUI = 0x20000000U,
/** Predefined combinations for certain default usage cases */
MSG_INFORMATION = ICON_INFORMATION,
diff --git a/src/wallet.cpp b/src/wallet.cpp
index d61f01d096..8d27da9d40 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -1076,7 +1076,7 @@ int64_t CWallet::GetWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
@@ -1092,7 +1092,7 @@ int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
@@ -1107,7 +1107,7 @@ int64_t CWallet::GetImmatureWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
@@ -2011,11 +2011,7 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey)
if (nIndex != -1)
vchPubKey = keypool.vchPubKey;
else {
- if (pwallet->vchDefaultKey.IsValid()) {
- LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
- vchPubKey = pwallet->vchDefaultKey;
- } else
- return false;
+ return false;
}
}
assert(vchPubKey.IsValid());