aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build-windows.md66
-rwxr-xr-xqa/rpc-tests/multi_rpc.py2
-rw-r--r--qa/rpc-tests/test_framework/util.py6
-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/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.cpp86
-rw-r--r--src/init.h25
-rw-r--r--src/main.cpp8
-rw-r--r--src/main.h2
-rw-r--r--src/net.cpp29
-rw-r--r--src/net.h3
-rw-r--r--src/qt/bitcoin.cpp17
-rw-r--r--src/qt/optionsmodel.h2
-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/torcontrol.cpp2
-rw-r--r--src/txmempool.h2
-rw-r--r--src/util.cpp1
-rw-r--r--src/util.h1
29 files changed, 348 insertions, 142 deletions
diff --git a/doc/build-windows.md b/doc/build-windows.md
index 044356830a..b6a047b9c3 100644
--- a/doc/build-windows.md
+++ b/doc/build-windows.md
@@ -7,16 +7,18 @@ Most developers use cross-compilation from Ubuntu to build executables for
Windows. This is also used to build the release binaries.
While there are potentially a number of ways to build on Windows (for example using msys / mingw-w64),
-using the Windows Subsystem For Linux is the most straight forward. If you are building with
-an alternative method, please contribute the instructions here for others who are running versions
+using the Windows Subsystem For Linux is the most straightforward. If you are building with
+another method, please contribute the instructions here for others who are running versions
of Windows that are not compatible with the Windows Subsystem for Linux.
-Compiling with the Windows Subsystem For Linux
--------------------
+Compiling with Windows Subsystem For Linux
+-------------------------------------------
-With Windows 10, Microsoft has released a new feature named the
-[Windows Subsystem for Linux](https://msdn.microsoft.com/commandline/wsl/about). This feature allows you to run a bash shell directly on Windows in an Ubuntu based
-environment. Within this environment you can cross compile for Windows without the need for a separate Linux VM or Server.
+With Windows 10, Microsoft has released a new feature named the [Windows
+Subsystem for Linux](https://msdn.microsoft.com/commandline/wsl/about). This
+feature allows you to run a bash shell directly on Windows in an Ubuntu based
+environment. Within this environment you can cross compile for Windows without
+the need for a separate Linux VM or Server.
This feature is not supported in versions of Windows prior to Windows 10 or on Windows Server SKUs.
@@ -37,9 +39,6 @@ To get the bash shell, you must first activate the feature in Windows.
* Create a new UNIX user account (this is a separate account from your Windows account)
After the bash shell is active, you can follow the instructions below for Windows 64-bit Cross-compilation.
-When building dependencies within the 'depends' folder, you may encounter an error building
-the protobuf dependency. If this occurs, re-run the command with sudo. This is likely
-a bug with the Windows Subsystem for Linux feature and may be fixed with a future update.
Cross-compilation
-------------------
@@ -48,28 +47,55 @@ These steps can be performed on, for example, an Ubuntu VM. The depends system
will also work on other Linux distributions, however the commands for
installing the toolchain will be different.
-Make sure you install the build requirements mentioned in
-[build-unix.md](/doc/build-unix.md).
-Then, install the toolchains and curl:
+First, install the general dependencies:
+
+ sudo apt-get install build-essential libtool autotools-dev automake pkg-config bsdmainutils curl
+
+A host toolchain (`build-essential`) is necessary because some dependency
+packages (such as `protobuf`) need to build host utilities that are used in the
+build process.
+
+## Building for 64-bit Windows
+
+To build executables for Windows 64-bit, install the following dependencies:
- sudo apt-get install g++-mingw-w64-i686 mingw-w64-i686-dev g++-mingw-w64-x86-64 mingw-w64-x86-64-dev curl
+ sudo apt-get install g++-mingw-w64-x86-64 mingw-w64-x86-64-dev
-To build executables for Windows 32-bit:
+Then build using:
cd depends
- make HOST=i686-w64-mingw32 -j4
+ make HOST=x86_64-w64-mingw32 -j4
cd ..
./autogen.sh # not required when building from tarball
- ./configure --prefix=`pwd`/depends/i686-w64-mingw32
+ CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site ./configure --prefix=/
make
-To build executables for Windows 64-bit:
+## Building for 32-bit Windows
+
+To build executables for Windows 32-bit, install the following dependencies:
+
+ sudo apt-get install g++-mingw-w64-i686 mingw-w64-i686-dev
+
+Then build using:
cd depends
- make HOST=x86_64-w64-mingw32 -j4
+ make HOST=i686-w64-mingw32 -j4
cd ..
./autogen.sh # not required when building from tarball
- ./configure --prefix=`pwd`/depends/x86_64-w64-mingw32
+ CONFIG_SITE=$PWD/depends/i686-w64-mingw32/share/config.site ./configure --prefix=/
make
+## Depends system
+
For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
+
+Installation
+-------------
+
+After building using the Windows subsystem it can be useful to copy the compiled
+executables to a directory on the windows drive in the same directory structure
+as they appear in the release `.zip` archive. This can be done in the following
+way. This will install to `c:\workspace\bitcoin`, for example:
+
+ make install DESTDIR=/mnt/c/workspace/bitcoin
+
diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py
index cdeb94caa0..95d9090ce2 100755
--- a/qa/rpc-tests/multi_rpc.py
+++ b/qa/rpc-tests/multi_rpc.py
@@ -4,7 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-# Test mulitple rpc user config option rpcauth
+# Test multiple rpc user config option rpcauth
#
from test_framework.test_framework import BitcoinTestFramework
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index 24a9d434af..99c30f7651 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -223,7 +223,7 @@ def wait_for_bitcoind_start(process, url, i):
raise # unknown IO error
except JSONRPCException as e: # Initialization phase
if e.error['code'] != -28: # RPC in warmup?
- raise # unkown JSON RPC exception
+ raise # unknown JSON RPC exception
time.sleep(0.25)
def initialize_chain(test_dir, num_nodes, cachedir):
@@ -257,7 +257,7 @@ def initialize_chain(test_dir, num_nodes, cachedir):
print("initialize_chain: bitcoind started, waiting for RPC to come up")
wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
if os.getenv("PYTHON_DEBUG", ""):
- print("initialize_chain: RPC succesfully started")
+ print("initialize_chain: RPC successfully started")
rpcs = []
for i in range(MAX_NODES):
@@ -344,7 +344,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
url = rpc_url(i, rpchost)
wait_for_bitcoind_start(bitcoind_processes[i], url, i)
if os.getenv("PYTHON_DEBUG", ""):
- print("start_node: RPC succesfully started")
+ print("start_node: RPC successfully started")
proxy = get_rpc_proxy(url, i, timeout=timewait)
if COVERAGE_DIR:
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/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..63ec744812 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()
@@ -849,12 +860,12 @@ 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);
+ 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 +923,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 +978,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 +1026,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 +1040,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 +1092,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 +1111,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..274bf6fdda 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;
@@ -4974,7 +4974,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 +5242,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;
}
diff --git a/src/main.h b/src/main.h
index 43c62f6de6..c98ed05726 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;
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/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/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/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/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 a1f87a2645..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;
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;