aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.bench.include4
-rw-r--r--src/addrman.h53
-rw-r--r--src/bench/bench.cpp22
-rw-r--r--src/bench/bench.h10
-rw-r--r--src/bench/perf.cpp53
-rw-r--r--src/bench/perf.h37
-rw-r--r--src/bitcoin-cli.cpp2
-rw-r--r--src/bitcoind.cpp26
-rw-r--r--src/blockencodings.cpp2
-rw-r--r--src/compat.h1
-rw-r--r--src/core_io.h22
-rw-r--r--src/crypto/ctaes/test.c2
-rw-r--r--src/init.cpp90
-rw-r--r--src/init.h25
-rw-r--r--src/main.cpp73
-rw-r--r--src/main.h17
-rw-r--r--src/net.cpp29
-rw-r--r--src/net.h3
-rw-r--r--src/netbase.cpp48
-rw-r--r--src/policy/fees.cpp7
-rw-r--r--src/qt/bitcoin.cpp17
-rw-r--r--src/qt/forms/sendcoinsdialog.ui2
-rw-r--r--src/qt/optionsmodel.h2
-rw-r--r--src/qt/sendcoinsdialog.cpp8
-rw-r--r--src/rpc/mining.cpp2
-rw-r--r--src/support/lockedpool.h2
-rwxr-xr-xsrc/test/bitcoin-util-test.py2
-rw-r--r--src/test/limitedmap_tests.cpp2
-rw-r--r--src/test/policyestimator_tests.cpp22
-rw-r--r--src/torcontrol.cpp2
-rw-r--r--src/txmempool.h2
-rw-r--r--src/util.cpp5
-rw-r--r--src/util.h1
-rw-r--r--src/utiltime.cpp3
34 files changed, 396 insertions, 202 deletions
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 246797a1b2..e58bd9dfbf 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -22,7 +22,9 @@ bench_bench_bitcoin_SOURCES = \
bench/mempool_eviction.cpp \
bench/verify_script.cpp \
bench/base58.cpp \
- bench/lockedpool.cpp
+ bench/lockedpool.cpp \
+ bench/perf.cpp \
+ bench/perf.h
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
diff --git a/src/addrman.h b/src/addrman.h
index cabacbbea9..76e7b210f7 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -482,6 +482,7 @@ public:
//! Return the number of (unique) addresses in all tables.
size_t size() const
{
+ LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
return vRandom.size();
}
@@ -501,13 +502,11 @@ public:
//! Add a single address.
bool Add(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty = 0)
{
+ LOCK(cs);
bool fRet = false;
- {
- LOCK(cs);
- Check();
- fRet |= Add_(addr, source, nTimePenalty);
- Check();
- }
+ Check();
+ fRet |= Add_(addr, source, nTimePenalty);
+ Check();
if (fRet)
LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort(), source.ToString(), nTried, nNew);
return fRet;
@@ -516,14 +515,12 @@ public:
//! Add multiple addresses.
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0)
{
+ LOCK(cs);
int nAdd = 0;
- {
- LOCK(cs);
- Check();
- for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
- nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
- Check();
- }
+ Check();
+ for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
+ nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
+ Check();
if (nAdd)
LogPrint("addrman", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew);
return nAdd > 0;
@@ -532,23 +529,19 @@ public:
//! Mark an entry as accessible.
void Good(const CService &addr, int64_t nTime = GetAdjustedTime())
{
- {
- LOCK(cs);
- Check();
- Good_(addr, nTime);
- Check();
- }
+ LOCK(cs);
+ Check();
+ Good_(addr, nTime);
+ Check();
}
//! Mark an entry as connection attempted to.
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime = GetAdjustedTime())
{
- {
- LOCK(cs);
- Check();
- Attempt_(addr, fCountFailure, nTime);
- Check();
- }
+ LOCK(cs);
+ Check();
+ Attempt_(addr, fCountFailure, nTime);
+ Check();
}
/**
@@ -582,12 +575,10 @@ public:
//! Mark an entry as currently-connected-to.
void Connected(const CService &addr, int64_t nTime = GetAdjustedTime())
{
- {
- LOCK(cs);
- Check();
- Connected_(addr, nTime);
- Check();
- }
+ LOCK(cs);
+ Check();
+ Connected_(addr, nTime);
+ Check();
}
void SetServices(const CService &addr, ServiceFlags nServices)
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 8942da8c74..af3d152c9a 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "bench.h"
+#include "perf.h"
#include <iostream>
#include <iomanip>
@@ -26,7 +27,9 @@ BenchRunner::BenchRunner(std::string name, BenchFunction func)
void
BenchRunner::RunAll(double elapsedTimeForOne)
{
- std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n";
+ perf_init();
+ std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << ","
+ << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n";
for (std::map<std::string,BenchFunction>::iterator it = benchmarks.begin();
it != benchmarks.end(); ++it) {
@@ -35,6 +38,7 @@ BenchRunner::RunAll(double elapsedTimeForOne)
BenchFunction& func = it->second;
func(state);
}
+ perf_fini();
}
bool State::KeepRunning()
@@ -44,8 +48,10 @@ bool State::KeepRunning()
return true;
}
double now;
+ uint64_t nowCycles;
if (count == 0) {
lastTime = beginTime = now = gettimedouble();
+ lastCycles = beginCycles = nowCycles = perf_cpucycles();
}
else {
now = gettimedouble();
@@ -53,6 +59,13 @@ bool State::KeepRunning()
double elapsedOne = elapsed * countMaskInv;
if (elapsedOne < minTime) minTime = elapsedOne;
if (elapsedOne > maxTime) maxTime = elapsedOne;
+
+ // We only use relative values, so don't have to handle 64-bit wrap-around specially
+ nowCycles = perf_cpucycles();
+ uint64_t elapsedOneCycles = (nowCycles - lastCycles) * countMaskInv;
+ if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles;
+ if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles;
+
if (elapsed*128 < maxElapsed) {
// If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
// The restart avoids including the overhead of this code in the measurement.
@@ -61,6 +74,8 @@ bool State::KeepRunning()
count = 0;
minTime = std::numeric_limits<double>::max();
maxTime = std::numeric_limits<double>::min();
+ minCycles = std::numeric_limits<uint64_t>::max();
+ maxCycles = std::numeric_limits<uint64_t>::min();
return true;
}
if (elapsed*16 < maxElapsed) {
@@ -72,6 +87,7 @@ bool State::KeepRunning()
}
}
lastTime = now;
+ lastCycles = nowCycles;
++count;
if (now - beginTime < maxElapsed) return true; // Keep going
@@ -80,7 +96,9 @@ bool State::KeepRunning()
// Output results
double average = (now-beginTime)/count;
- std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n";
+ int64_t averageCycles = (nowCycles-beginCycles)/count;
+ std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << ","
+ << minCycles << "," << maxCycles << "," << averageCycles << "\n";
return false;
}
diff --git a/src/bench/bench.h b/src/bench/bench.h
index f13b145aaf..caf73e949b 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -41,12 +41,18 @@ namespace benchmark {
double maxElapsed;
double beginTime;
double lastTime, minTime, maxTime, countMaskInv;
- int64_t count;
- int64_t countMask;
+ uint64_t count;
+ uint64_t countMask;
+ uint64_t beginCycles;
+ uint64_t lastCycles;
+ uint64_t minCycles;
+ uint64_t maxCycles;
public:
State(std::string _name, double _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) {
minTime = std::numeric_limits<double>::max();
maxTime = std::numeric_limits<double>::min();
+ minCycles = std::numeric_limits<uint64_t>::max();
+ maxCycles = std::numeric_limits<uint64_t>::min();
countMask = 1;
countMaskInv = 1./(countMask + 1);
}
diff --git a/src/bench/perf.cpp b/src/bench/perf.cpp
new file mode 100644
index 0000000000..1f43e5d3ac
--- /dev/null
+++ b/src/bench/perf.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "perf.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/* These architectures support quering the cycle counter
+ * from user space, no need for any syscall overhead.
+ */
+void perf_init(void) { }
+void perf_fini(void) { }
+
+#elif defined(__linux__)
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <linux/perf_event.h>
+
+static int fd = -1;
+static struct perf_event_attr attr;
+
+void perf_init(void)
+{
+ attr.type = PERF_TYPE_HARDWARE;
+ attr.config = PERF_COUNT_HW_CPU_CYCLES;
+ fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
+}
+
+void perf_fini(void)
+{
+ if (fd != -1) {
+ close(fd);
+ }
+}
+
+uint64_t perf_cpucycles(void)
+{
+ uint64_t result = 0;
+ if (fd == -1 || read(fd, &result, sizeof(result)) < (ssize_t)sizeof(result)) {
+ return 0;
+ }
+ return result;
+}
+
+#else /* Unhandled platform */
+
+void perf_init(void) { }
+void perf_fini(void) { }
+uint64_t perf_cpucycles(void) { return 0; }
+
+#endif
diff --git a/src/bench/perf.h b/src/bench/perf.h
new file mode 100644
index 0000000000..681bd0c8a2
--- /dev/null
+++ b/src/bench/perf.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+/** Functions for measurement of CPU cycles */
+#ifndef H_PERF
+#define H_PERF
+
+#include <stdint.h>
+
+#if defined(__i386__)
+
+static inline uint64_t perf_cpucycles(void)
+{
+ uint64_t x;
+ __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
+ return x;
+}
+
+#elif defined(__x86_64__)
+
+static inline uint64_t perf_cpucycles(void)
+{
+ uint32_t hi, lo;
+ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((uint64_t)lo)|(((uint64_t)hi)<<32);
+}
+#else
+
+uint64_t perf_cpucycles(void);
+
+#endif
+
+void perf_init(void);
+void perf_fini(void);
+
+#endif // H_PERF
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index b272640819..596cc8eada 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -247,7 +247,7 @@ UniValue CallRPC(const std::string& strMethod, const UniValue& params)
event_base_free(base);
if (response.status == 0)
- throw CConnectionFailed(strprintf("couldn't connect to server\n(make sure server is running and you are connecting to the correct RPC port: %d %s)", response.error, http_errorstring(response.error)));
+ throw CConnectionFailed(strprintf("couldn't connect to server: %s (code %d)\n(make sure server is running and you are connecting to the correct RPC port)", http_errorstring(response.error), response.error));
else if (response.status == HTTP_UNAUTHORIZED)
throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 3352a76de6..ba3ccac615 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -128,6 +128,26 @@ bool AppInit(int argc, char* argv[])
fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n");
exit(EXIT_FAILURE);
}
+ // -server defaults to true for bitcoind but not for the GUI so do this here
+ SoftSetBoolArg("-server", true);
+ // Set this early so that parameter interactions go to console
+ InitLogging();
+ InitParameterInteraction();
+ if (!AppInitBasicSetup())
+ {
+ // InitError will have been called with detailed error, which ends up on console
+ exit(1);
+ }
+ if (!AppInitParameterInteraction())
+ {
+ // InitError will have been called with detailed error, which ends up on console
+ exit(1);
+ }
+ if (!AppInitSanityChecks())
+ {
+ // InitError will have been called with detailed error, which ends up on console
+ exit(1);
+ }
if (GetBoolArg("-daemon", false))
{
#if HAVE_DECL_DAEMON
@@ -143,12 +163,8 @@ bool AppInit(int argc, char* argv[])
return false;
#endif // HAVE_DECL_DAEMON
}
- SoftSetBoolArg("-server", true);
- // Set this early so that parameter interactions go to console
- InitLogging();
- InitParameterInteraction();
- fRet = AppInit2(threadGroup, scheduler);
+ fRet = AppInitMain(threadGroup, scheduler);
}
catch (const std::exception& e) {
PrintExceptionContinue(&e, "AppInit()");
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index f14ae1c412..2efeda9cc6 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -62,7 +62,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
if (cmpctblock.prefilledtxn[i].tx->IsNull())
return READ_STATUS_INVALID;
- lastprefilledindex += cmpctblock.prefilledtxn[i].index + 1; //index is a uint16_t, so cant overflow here
+ lastprefilledindex += cmpctblock.prefilledtxn[i].index + 1; //index is a uint16_t, so can't overflow here
if (lastprefilledindex > std::numeric_limits<uint16_t>::max())
return READ_STATUS_INVALID;
if ((uint32_t)lastprefilledindex > cmpctblock.shorttxids.size() + i) {
diff --git a/src/compat.h b/src/compat.h
index 79a297e5e4..2578d6d344 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -34,6 +34,7 @@
#else
#include <sys/fcntl.h>
#include <sys/mman.h>
+#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
diff --git a/src/core_io.h b/src/core_io.h
index b559d44bf5..5aecbc4489 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -15,18 +15,18 @@ class uint256;
class UniValue;
// core_read.cpp
-extern CScript ParseScript(const std::string& s);
-extern std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
-extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false);
-extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
-extern uint256 ParseHashUV(const UniValue& v, const std::string& strName);
-extern uint256 ParseHashStr(const std::string&, const std::string& strName);
-extern std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
+CScript ParseScript(const std::string& s);
+std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
+bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false);
+bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
+uint256 ParseHashUV(const UniValue& v, const std::string& strName);
+uint256 ParseHashStr(const std::string&, const std::string& strName);
+std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
// core_write.cpp
-extern std::string FormatScript(const CScript& script);
-extern std::string EncodeHexTx(const CTransaction& tx);
-extern void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
-extern void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry);
+std::string FormatScript(const CScript& script);
+std::string EncodeHexTx(const CTransaction& tx);
+void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry);
#endif // BITCOIN_CORE_IO_H
diff --git a/src/crypto/ctaes/test.c b/src/crypto/ctaes/test.c
index fce1696acd..21439a16f1 100644
--- a/src/crypto/ctaes/test.c
+++ b/src/crypto/ctaes/test.c
@@ -102,7 +102,7 @@ int main(void) {
}
}
if (fail == 0) {
- fprintf(stderr, "All tests succesful\n");
+ fprintf(stderr, "All tests successful\n");
} else {
fprintf(stderr, "%i tests failed\n", fail);
}
diff --git a/src/init.cpp b/src/init.cpp
index ca5437fb91..377d196f2b 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -780,10 +780,17 @@ void InitLogging()
LogPrintf("Bitcoin version %s\n", FormatFullVersion());
}
-/** Initialize bitcoin.
- * @pre Parameters should be parsed and config file should be read.
- */
-bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
+namespace { // Variables internal to initialization process only
+
+ServiceFlags nRelevantServices = NODE_NETWORK;
+int nMaxConnections;
+int nUserMaxConnections;
+int nFD;
+ServiceFlags nLocalServices = NODE_NETWORK;
+
+}
+
+bool AppInitBasicSetup()
{
// ********************************************************* Step 1: setup
#ifdef _MSC_VER
@@ -835,9 +842,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
signal(SIGPIPE, SIG_IGN);
#endif
+ return true;
+}
- // ********************************************************* Step 2: parameter interactions
+bool AppInitParameterInteraction()
+{
const CChainParams& chainparams = Params();
+ // ********************************************************* Step 2: parameter interactions
// also see: InitParameterInteraction()
@@ -848,13 +859,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
// Make sure enough file descriptors are available
- int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
- int nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
- int nMaxConnections = std::max(nUserMaxConnections, 0);
+ int nBind = std::max(
+ (mapMultiArgs.count("-bind") ? mapMultiArgs.at("-bind").size() : 0) +
+ (mapMultiArgs.count("-whitebind") ? mapMultiArgs.at("-whitebind").size() : 0), size_t(1));
+ nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
+ nMaxConnections = std::max(nUserMaxConnections, 0);
// Trim requested connection counts, to fit into system limitations
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
- int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
+ nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available."));
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS, nMaxConnections);
@@ -912,8 +925,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
- fServer = GetBoolArg("-server", false);
-
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
int64_t nSignedPruneTarget = GetArg("-prune", 0) * 1024 * 1024;
if (nSignedPruneTarget < 0) {
@@ -969,9 +980,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Option to startup with mocktime set (used for regression testing):
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
- ServiceFlags nLocalServices = NODE_NETWORK;
- ServiceFlags nRelevantServices = NODE_NETWORK;
-
if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
@@ -1020,17 +1028,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
}
}
+ return true;
+}
- // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
-
- // Initialize elliptic curve code
- ECC_Start();
- globalVerifyHandle.reset(new ECCVerifyHandle());
-
- // Sanity check
- if (!InitSanityCheck())
- return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME)));
-
+static bool LockDataDirectory(bool probeOnly)
+{
std::string strDataDir = GetDataDir().string();
// Make sure only a single Bitcoin process is using the data directory.
@@ -1040,11 +1042,45 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
try {
static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
- if (!lock.try_lock())
+ if (!lock.try_lock()) {
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), strDataDir, _(PACKAGE_NAME)));
+ }
+ if (probeOnly) {
+ lock.unlock();
+ }
} catch(const boost::interprocess::interprocess_exception& e) {
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.", strDataDir, _(PACKAGE_NAME), e.what()));
}
+ return true;
+}
+
+bool AppInitSanityChecks()
+{
+ // ********************************************************* Step 4: sanity checks
+
+ // Initialize elliptic curve code
+ ECC_Start();
+ globalVerifyHandle.reset(new ECCVerifyHandle());
+
+ // Sanity check
+ if (!InitSanityCheck())
+ return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME)));
+
+ // Probe the data directory lock to give an early error message, if possible
+ return LockDataDirectory(true);
+}
+
+bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
+{
+ const CChainParams& chainparams = Params();
+ // ********************************************************* Step 4a: application initialization
+ // After daemonization get the data directory lock again and hold on to it until exit
+ // This creates a slight window for a race condition to happen, however this condition is harmless: it
+ // will at most make us exit without printing a message to console.
+ if (!LockDataDirectory(false)) {
+ // Detailed error printed inside LockDataDirectory
+ return false;
+ }
#ifndef WIN32
CreatePidFile(GetPidFile(), getpid());
@@ -1058,7 +1094,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!fLogTimestamps)
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
- LogPrintf("Using data directory %s\n", strDataDir);
+ LogPrintf("Using data directory %s\n", GetDataDir().string());
LogPrintf("Using config file %s\n", GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
@@ -1077,7 +1113,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
* that the server is there and will be ready later). Warmup mode will
* be disabled when initialisation is finished.
*/
- if (fServer)
+ if (GetBoolArg("-server", false))
{
uiInterface.InitMessage.connect(SetRPCWarmupStatus);
if (!AppInitServers(threadGroup))
diff --git a/src/init.h b/src/init.h
index 63e07ccb3c..1b87e0ec52 100644
--- a/src/init.h
+++ b/src/init.h
@@ -25,7 +25,30 @@ void Shutdown();
void InitLogging();
//!Parameter interaction: change current parameters depending on various rules
void InitParameterInteraction();
-bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler);
+
+/** Initialize bitcoin core: Basic context setup.
+ * @note This can be done before daemonization.
+ * @pre Parameters should be parsed and config file should be read.
+ */
+bool AppInitBasicSetup();
+/**
+ * Initialization: parameter interaction.
+ * @note This can be done before daemonization.
+ * @pre Parameters should be parsed and config file should be read, AppInitBasicSetup should have been called.
+ */
+bool AppInitParameterInteraction();
+/**
+ * Initialization sanity checks: ecc init, sanity checks, dir lock.
+ * @note This can be done before daemonization.
+ * @pre Parameters should be parsed and config file should be read, AppInitParameterInteraction should have been called.
+ */
+bool AppInitSanityChecks();
+/**
+ * Bitcoin core main initialization.
+ * @note This should only be done after daemonization.
+ * @pre Parameters should be parsed and config file should be read, AppInitSanityChecks should have been called.
+ */
+bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler);
/** The help message mode determines what help message to show */
enum HelpMessageMode {
diff --git a/src/main.cpp b/src/main.cpp
index 6bb81fab24..e2a1f31228 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -69,7 +69,7 @@ int64_t nTimeBestReceived = 0; // Used only to inform the wallet of when we last
CWaitableCriticalSection csBestBlock;
CConditionVariable cvBlockChange;
int nScriptCheckThreads = 0;
-bool fImporting = false;
+std::atomic_bool fImporting(false);
bool fReindex = false;
bool fTxIndex = false;
bool fHavePruned = false;
@@ -3643,7 +3643,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
return true;
}
-static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex=NULL)
+static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
{
AssertLockHeld(cs_main);
// Check for duplicate
@@ -3692,6 +3692,21 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
return true;
}
+// Exposed wrapper for AcceptBlockHeader
+bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
+{
+ {
+ LOCK(cs_main);
+ for (const CBlockHeader& header : headers) {
+ if (!AcceptBlockHeader(header, state, chainparams, ppindex)) {
+ return false;
+ }
+ }
+ }
+ NotifyHeaderTip();
+ return true;
+}
+
/** Store block on disk. If dbp is non-NULL, the file is known to already reside on disk */
static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock)
{
@@ -4974,7 +4989,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
else if (inv.type == MSG_CMPCT_BLOCK)
{
// If a peer is asking for old blocks, we're almost guaranteed
- // they wont have a useful mempool to match against a compact block,
+ // they won't have a useful mempool to match against a compact block,
// and we don't feel like constructing the object for them, so
// instead we respond with the full, non-compact block.
bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
@@ -5242,8 +5257,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
- // Mark this node as currently connected, so we update its timestamp later.
- if (pfrom->fNetworkNode) {
+ if (!pfrom->fInbound) {
+ // Mark this node as currently connected, so we update its timestamp later.
LOCK(cs_main);
State(pfrom->GetId())->fCurrentlyConnected = true;
}
@@ -5690,8 +5705,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
if (!fRejectedParents) {
+ uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
- CInv _inv(MSG_TX, txin.prevout.hash);
+ CInv _inv(MSG_TX | nFetchFlags, txin.prevout.hash);
pfrom->AddInventoryKnown(_inv);
if (!AlreadyHave(_inv)) pfrom->AskFor(_inv);
}
@@ -5753,6 +5769,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CBlockHeaderAndShortTxIDs cmpctblock;
vRecv >> cmpctblock;
+ {
LOCK(cs_main);
if (mapBlockIndex.find(cmpctblock.header.hashPrevBlock) == mapBlockIndex.end()) {
@@ -5761,19 +5778,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
return true;
}
+ }
CBlockIndex *pindex = NULL;
CValidationState state;
- if (!AcceptBlockHeader(cmpctblock.header, state, chainparams, &pindex)) {
+ if (!ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) {
int nDoS;
if (state.IsInvalid(nDoS)) {
- if (nDoS > 0)
+ if (nDoS > 0) {
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), nDoS);
+ }
LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->id);
return true;
}
}
+ LOCK(cs_main);
// If AcceptBlockHeader returned true, it set pindex
assert(pindex);
UpdateBlockAvailability(pfrom->GetId(), pindex->GetBlockHash());
@@ -5967,14 +5988,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
}
- {
- LOCK(cs_main);
-
if (nCount == 0) {
// Nothing interesting. Stop asking this peers for more headers.
return true;
}
+ CBlockIndex *pindexLast = NULL;
+ {
+ LOCK(cs_main);
CNodeState *nodestate = State(pfrom->GetId());
// If this looks like it could be a block announcement (nCount <
@@ -6004,23 +6025,31 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
- CBlockIndex *pindexLast = NULL;
- BOOST_FOREACH(const CBlockHeader& header, headers) {
- CValidationState state;
- if (pindexLast != NULL && header.hashPrevBlock != pindexLast->GetBlockHash()) {
+ uint256 hashLastBlock;
+ for (const CBlockHeader& header : headers) {
+ if (!hashLastBlock.IsNull() && header.hashPrevBlock != hashLastBlock) {
Misbehaving(pfrom->GetId(), 20);
return error("non-continuous headers sequence");
}
- if (!AcceptBlockHeader(header, state, chainparams, &pindexLast)) {
- int nDoS;
- if (state.IsInvalid(nDoS)) {
- if (nDoS > 0)
- Misbehaving(pfrom->GetId(), nDoS);
- return error("invalid header received");
+ hashLastBlock = header.GetHash();
+ }
+ }
+
+ CValidationState state;
+ if (!ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast)) {
+ int nDoS;
+ if (state.IsInvalid(nDoS)) {
+ if (nDoS > 0) {
+ LOCK(cs_main);
+ Misbehaving(pfrom->GetId(), nDoS);
}
+ return error("invalid header received");
}
}
+ {
+ LOCK(cs_main);
+ CNodeState *nodestate = State(pfrom->GetId());
if (nodestate->nUnconnectingHeaders > 0) {
LogPrint("net", "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders);
}
@@ -6092,8 +6121,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
}
-
- NotifyHeaderTip();
}
else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
diff --git a/src/main.h b/src/main.h
index 43c62f6de6..6b2668e568 100644
--- a/src/main.h
+++ b/src/main.h
@@ -165,7 +165,7 @@ extern uint64_t nLastBlockWeight;
extern const std::string strMessageMagic;
extern CWaitableCriticalSection csBestBlock;
extern CConditionVariable cvBlockChange;
-extern bool fImporting;
+extern std::atomic_bool fImporting;
extern bool fReindex;
extern int nScriptCheckThreads;
extern bool fTxIndex;
@@ -223,6 +223,8 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
* Note that we guarantee that either the proof-of-work is valid on pblock, or
* (and possibly also) BlockChecked will have been called.
*
+ * Call without cs_main held.
+ *
* @param[in] pblock The block we want to process.
* @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers.
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
@@ -230,6 +232,19 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
* @return True if state.IsValid()
*/
bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool* fNewBlock);
+
+/**
+ * Process incoming block headers.
+ *
+ * Call without cs_main held.
+ *
+ * @param[in] block The block headers themselves
+ * @param[out] state This may be set to an Error state if any error occurred processing them
+ * @param[in] chainparams The params for the chain we want to connect to
+ * @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
+ */
+bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex=NULL);
+
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
diff --git a/src/net.cpp b/src/net.cpp
index ce87150ae3..27b200b3f0 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -74,7 +74,6 @@ bool fRelayTxes = true;
CCriticalSection cs_mapLocalHost;
std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfLimited[NET_MAX] = {};
-static CNode* pnodeLocalHost = NULL;
std::string strSubVersion;
limitedmap<uint256, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
@@ -1067,8 +1066,7 @@ void CConnman::ThreadSocketHandler()
pnode->CloseSocketDisconnect();
// hold in disconnected pool until all refs are released
- if (pnode->fNetworkNode || pnode->fInbound)
- pnode->Release();
+ pnode->Release();
vNodesDisconnected.push_back(pnode);
}
}
@@ -1103,8 +1101,13 @@ void CConnman::ThreadSocketHandler()
}
}
}
- if(vNodes.size() != nPrevNodeCount) {
- nPrevNodeCount = vNodes.size();
+ size_t vNodesSize;
+ {
+ LOCK(cs_vNodes);
+ vNodesSize = vNodes.size();
+ }
+ if(vNodesSize != nPrevNodeCount) {
+ nPrevNodeCount = vNodesSize;
if(clientInterface)
clientInterface->NotifyNumConnectionsChanged(nPrevNodeCount);
}
@@ -1808,7 +1811,6 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
return false;
if (grantOutbound)
grantOutbound->MoveTo(pnode->grantOutbound);
- pnode->fNetworkNode = true;
if (fOneShot)
pnode->fOneShot = true;
if (fFeeler)
@@ -2139,17 +2141,6 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st
semOutbound = new CSemaphore(std::min((nMaxOutbound + nMaxFeeler), nMaxConnections));
}
- if (pnodeLocalHost == NULL) {
- CNetAddr local;
- LookupHost("127.0.0.1", local, false);
-
- NodeId id = GetNewNodeId();
- uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
-
- pnodeLocalHost = new CNode(id, nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices), 0, nonce);
- GetNodeSignals().InitializeNode(pnodeLocalHost, *this);
- }
-
//
// Start threads
//
@@ -2227,9 +2218,6 @@ void CConnman::Stop()
vhListenSocket.clear();
delete semOutbound;
semOutbound = NULL;
- if(pnodeLocalHost)
- DeleteNode(pnodeLocalHost);
- pnodeLocalHost = NULL;
}
void CConnman::DeleteNode(CNode* pnode)
@@ -2531,7 +2519,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
fOneShot = false;
fClient = false; // set by version message
fFeeler = false;
- fNetworkNode = false;
fSuccessfullyConnected = false;
fDisconnect = false;
nRefCount = 0;
diff --git a/src/net.h b/src/net.h
index a4a9fb676a..a7c0ecf324 100644
--- a/src/net.h
+++ b/src/net.h
@@ -613,9 +613,8 @@ public:
bool fOneShot;
bool fClient;
const bool fInbound;
- bool fNetworkNode;
bool fSuccessfullyConnected;
- bool fDisconnect;
+ std::atomic_bool fDisconnect;
// We use fRelayTxes for two purposes -
// a) it allows us to not relay tx invs before receiving the peer's version message
// b) the peer may tell us in its version message that we should not relay tx invs
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 9fe34108f5..9118584b80 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -94,30 +94,9 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
}
}
-#ifdef HAVE_GETADDRINFO_A
- struct in_addr ipv4_addr;
-#ifdef HAVE_INET_PTON
- if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) {
- vIP.push_back(CNetAddr(ipv4_addr));
- return true;
- }
-
- struct in6_addr ipv6_addr;
- if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) {
- vIP.push_back(CNetAddr(ipv6_addr));
- return true;
- }
-#else
- ipv4_addr.s_addr = inet_addr(pszName);
- if (ipv4_addr.s_addr != INADDR_NONE) {
- vIP.push_back(CNetAddr(ipv4_addr));
- return true;
- }
-#endif
-#endif
-
struct addrinfo aiHint;
memset(&aiHint, 0, sizeof(struct addrinfo));
+
aiHint.ai_socktype = SOCK_STREAM;
aiHint.ai_protocol = IPPROTO_TCP;
aiHint.ai_family = AF_UNSPEC;
@@ -126,33 +105,8 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
#else
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
#endif
-
struct addrinfo *aiRes = NULL;
-#ifdef HAVE_GETADDRINFO_A
- struct gaicb gcb, *query = &gcb;
- memset(query, 0, sizeof(struct gaicb));
- gcb.ar_name = pszName;
- gcb.ar_request = &aiHint;
- int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL);
- if (nErr)
- return false;
-
- do {
- // Should set the timeout limit to a reasonable value to avoid
- // generating unnecessary checking call during the polling loop,
- // while it can still response to stop request quick enough.
- // 2 seconds looks fine in our situation.
- struct timespec ts = { 2, 0 };
- gai_suspend(&query, 1, &ts);
- boost::this_thread::interruption_point();
-
- nErr = gai_error(query);
- if (0 == nErr)
- aiRes = query->ar_result;
- } while (nErr == EAI_INPROGRESS);
-#else
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
-#endif
if (nErr)
return false;
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 7113390cdf..9eb831bc17 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -404,7 +404,8 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight,
CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget)
{
// Return failure if trying to analyze a target we're not tracking
- if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms())
+ // It's not possible to get reasonable estimates for confTarget of 1
+ if (confTarget <= 1 || (unsigned int)confTarget > feeStats.GetMaxConfirms())
return CFeeRate(0);
double median = feeStats.EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
@@ -423,6 +424,10 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun
if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms())
return CFeeRate(0);
+ // It's not possible to get reasonable estimates for confTarget of 1
+ if (confTarget == 1)
+ confTarget = 2;
+
double median = -1;
while (median < 0 && (unsigned int)confTarget <= feeStats.GetMaxConfirms()) {
median = feeStats.EstimateMedianVal(confTarget++, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index d7452f308e..4f48e21a22 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -268,7 +268,22 @@ void BitcoinCore::initialize()
try
{
qDebug() << __func__ << ": Running AppInit2 in thread";
- int rv = AppInit2(threadGroup, scheduler);
+ if (!AppInitBasicSetup())
+ {
+ Q_EMIT initializeResult(false);
+ return;
+ }
+ if (!AppInitParameterInteraction())
+ {
+ Q_EMIT initializeResult(false);
+ return;
+ }
+ if (!AppInitSanityChecks())
+ {
+ Q_EMIT initializeResult(false);
+ return;
+ }
+ int rv = AppInitMain(threadGroup, scheduler);
Q_EMIT initializeResult(rv);
} catch (const std::exception& e) {
handleRunawayException(&e);
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index 33db9f8938..0a8afa2e76 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -1064,7 +1064,7 @@
<number>0</number>
</property>
<property name="maximum">
- <number>24</number>
+ <number>23</number>
</property>
<property name="pageStep">
<number>1</number>
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index b23b5f2607..d2e1fb23a3 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -81,7 +81,7 @@ private:
int nDisplayUnit;
QString strThirdPartyTxUrls;
bool fCoinControlFeatures;
- /* settings that were overriden by command-line */
+ /* settings that were overridden by command-line */
QString strOverriddenByCommandLine;
// Add option to list of GUI options overridden through command line/config file
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 57b2179435..bd3f20e9dc 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -175,7 +175,7 @@ void SendCoinsDialog::setModel(WalletModel *_model)
// set the smartfee-sliders default value (wallets default conf.target or last stored value)
QSettings settings;
if (settings.value("nSmartFeeSliderPosition").toInt() == 0)
- ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 1);
+ ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 2);
else
ui->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt());
}
@@ -241,7 +241,7 @@ void SendCoinsDialog::on_sendButton_clicked()
if (model->getOptionsModel()->getCoinControlFeatures())
ctrl = *CoinControlDialog::coinControl;
if (ui->radioSmartFee->isChecked())
- ctrl.nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 1;
+ ctrl.nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2;
else
ctrl.nConfirmTarget = 0;
@@ -601,7 +601,7 @@ void SendCoinsDialog::updateGlobalFeeVariables()
{
if (ui->radioSmartFee->isChecked())
{
- int nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 1;
+ int nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2;
payTxFee = CFeeRate(0);
// set nMinimumTotalFee to 0 to not accidentally pay a custom fee
@@ -646,7 +646,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
if(!model || !model->getOptionsModel())
return;
- int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 1;
+ int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2;
int estimateFoundAtBlocks = nBlocksToConfirm;
CFeeRate feeRate = mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks);
if (feeRate <= CFeeRate(0)) // not enough data => minfee
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index f3cd1fbf0b..c2e5791572 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -785,6 +785,8 @@ UniValue estimatefee(const JSONRPCRequest& request)
"\n"
"A negative value is returned if not enough transactions and blocks\n"
"have been observed to make an estimate.\n"
+ "-1 is always returned for nblocks == 1 as it is impossible to calculate\n"
+ "a fee that is high enough to get reliably included in the next block.\n"
"\nExample:\n"
+ HelpExampleCli("estimatefee", "6")
);
diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h
index 3403415436..f5212bc266 100644
--- a/src/support/lockedpool.h
+++ b/src/support/lockedpool.h
@@ -109,7 +109,7 @@ private:
* An arena manages a contiguous region of memory. The pool starts out with one arena
* but can grow to multiple arenas if the need arises.
*
- * Unlike a normal C heap, the administrative structures are seperate from the managed
+ * Unlike a normal C heap, the administrative structures are separate from the managed
* memory. This has been done as the sizes and bases of objects are not in themselves sensitive
* information, as to conserve precious locked memory. In some operating systems
* the amount of memory that can be locked is small.
diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py
index 4301b93b7c..1c090b3f3f 100755
--- a/src/test/bitcoin-util-test.py
+++ b/src/test/bitcoin-util-test.py
@@ -15,7 +15,7 @@ help_text="""Test framework for bitcoin utils.
Runs automatically during `make check`.
-Can also be run manually from the src directory by specifiying the source directory:
+Can also be run manually from the src directory by specifying the source directory:
test/bitcoin-util-test.py --srcdir='srcdir' [--verbose]
"""
diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp
index faaddffad8..e3531486aa 100644
--- a/src/test/limitedmap_tests.cpp
+++ b/src/test/limitedmap_tests.cpp
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(limitedmap_test)
// make sure the item is present
BOOST_CHECK(map.count(i) == 1);
- // use the iterator to check for the expected key adn value
+ // use the iterator to check for the expected key and value
BOOST_CHECK(it->first == i);
BOOST_CHECK(it->second == i + 1);
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 7dc8f226c9..c57feaec90 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -95,17 +95,22 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
// Highest feerate is 10*baseRate and gets in all blocks,
// second highest feerate is 9*baseRate and gets in 9/10 blocks = 90%,
// third highest feerate is 8*base rate, and gets in 8/10 blocks = 80%,
- // so estimateFee(1) should return 10*baseRate.
+ // so estimateFee(1) would return 10*baseRate but is hardcoded to return failure
// Second highest feerate has 100% chance of being included by 2 blocks,
// so estimateFee(2) should return 9*baseRate etc...
for (int i = 1; i < 10;i++) {
origFeeEst.push_back(mpool.estimateFee(i).GetFeePerK());
- if (i > 1) { // Fee estimates should be monotonically decreasing
+ if (i > 2) { // Fee estimates should be monotonically decreasing
BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]);
}
int mult = 11-i;
- BOOST_CHECK(origFeeEst[i-1] < mult*baseRate.GetFeePerK() + deltaFee);
- BOOST_CHECK(origFeeEst[i-1] > mult*baseRate.GetFeePerK() - deltaFee);
+ if (i > 1) {
+ BOOST_CHECK(origFeeEst[i-1] < mult*baseRate.GetFeePerK() + deltaFee);
+ BOOST_CHECK(origFeeEst[i-1] > mult*baseRate.GetFeePerK() - deltaFee);
+ }
+ else {
+ BOOST_CHECK(origFeeEst[i-1] == CFeeRate(0).GetFeePerK());
+ }
}
// Mine 50 more blocks with no transactions happening, estimates shouldn't change
@@ -113,7 +118,8 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
while (blocknum < 250)
mpool.removeForBlock(block, ++blocknum);
- for (int i = 1; i < 10;i++) {
+ BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0));
+ for (int i = 2; i < 10;i++) {
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee);
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
}
@@ -151,7 +157,8 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
}
mpool.removeForBlock(block, 265);
block.clear();
- for (int i = 1; i < 10;i++) {
+ BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0));
+ for (int i = 2; i < 10;i++) {
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
}
@@ -172,7 +179,8 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
mpool.removeForBlock(block, ++blocknum);
block.clear();
}
- for (int i = 1; i < 10; i++) {
+ BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0));
+ for (int i = 2; i < 10; i++) {
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee);
}
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 1ca6b46566..ffb9993f90 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -470,7 +470,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
// Finally - now create the service
if (private_key.empty()) // No private key, generate one
- private_key = "NEW:BEST";
+ private_key = "NEW:RSA1024"; // Explicitly request RSA1024 - see issue #9214
// Request hidden service, redirect port.
// Note that the 'virtual' port doesn't have to be the same as our internal port, but this is just a convenient
// choice. TODO; refactor the shutdown sequence some day.
diff --git a/src/txmempool.h b/src/txmempool.h
index 29b59363a2..23fe5a7abe 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -62,7 +62,7 @@ class CTxMemPool;
/** \class CTxMemPoolEntry
*
- * CTxMemPoolEntry stores data about the correponding transaction, as well
+ * CTxMemPoolEntry stores data about the corresponding transaction, as well
* as data about all in-mempool transactions that depend on the transaction
* ("descendant" transactions).
*
diff --git a/src/util.cpp b/src/util.cpp
index c20ede6221..014013d214 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -107,7 +107,6 @@ map<string, vector<string> > mapMultiArgs;
bool fDebug = false;
bool fPrintToConsole = false;
bool fPrintToDebugLog = true;
-bool fServer = false;
string strMiscWarning;
bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
@@ -259,7 +258,7 @@ bool LogAcceptCategory(const char* category)
* suppress printing of the timestamp when multiple calls are made that don't
* end in a newline. Initialize it to true, and hold it, in the calling context.
*/
-static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
+static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fStartedNewLine)
{
string strStamped;
@@ -286,7 +285,7 @@ static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine
int LogPrintStr(const std::string &str)
{
int ret = 0; // Returns total number of characters written
- static bool fStartedNewLine = true;
+ static std::atomic_bool fStartedNewLine(true);
string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
diff --git a/src/util.h b/src/util.h
index bbb9b5db82..e8aa266f28 100644
--- a/src/util.h
+++ b/src/util.h
@@ -46,7 +46,6 @@ extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
extern bool fDebug;
extern bool fPrintToConsole;
extern bool fPrintToDebugLog;
-extern bool fServer;
extern std::string strMiscWarning;
extern bool fLogTimestamps;
extern bool fLogTimeMicros;
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index da590f8889..51d545ef8a 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.cpp
@@ -74,8 +74,9 @@ void MilliSleep(int64_t n)
std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
{
+ static std::locale classic(std::locale::classic());
// std::locale takes ownership of the pointer
- std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
+ std::locale loc(classic, new boost::posix_time::time_facet(pszFormat));
std::stringstream ss;
ss.imbue(loc);
ss << boost::posix_time::from_time_t(nTime);