From a49f4123e508948ff3f9632c2384bdac2b3fda8a Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Thu, 3 Jan 2019 03:18:47 -0600 Subject: [PATCH] Backports 0.15 pr1 (#2590) * Merge #9744: Remove unused module from rpc-tests a432aa0 Remove unused module from rpc-tests (Takashi Mitsuta) * Merge #9696: [trivial] Fix recently introduced typos in comments 0c9b9b7 [trivial] Fix recently introduced typos in comments (practicalswift) * Merge #9657: Improve rpc-tests.py a6a3e58 Various review markups for rpc-tests.py improvements (John Newbery) 3de3ccd Refactor rpc-tests.py (John Newbery) afd38e7 Improve rpc-tests.py arguments (John Newbery) 91bffff Use argparse in rpc_tests.py (John Newbery) 1581ecb Use configparser in rpc-tests.py (John Newbery) * Merge #9724: Qt/Intro: Add explanation of IBD process f6d18f5 Qt/Intro: Explain a bit more what will happen first time (Luke Dashjr) 50c5657 Qt/Intro: Storage shouldn't grow significantly with pruning enabled (Luke Dashjr) 9adb694 Qt/Intro: Move sizeWarningLabel text into C++ code (Luke Dashjr) * Merge #9794: Minor update to qrencode package builder 1bfe6b4 Use package name variable inside $(package)_file_name variable (Mitchell Cash) * Merge #9726: netbase: Do not print an error on connection timeouts through proxy 3ddfe29 netbase: Do not print an error on connection timeouts through proxy (Wladimir J. van der Laan) 13f6085 netbase: Make InterruptibleRecv return an error code instead of bool (Wladimir J. van der Laan) * Merge #9727: Remove fallbacks for boost_filesystem < v3 056aba2 Remove fallbacks for boost_filesystem < v3 (Wladimir J. van der Laan) * Merge #9485: ZMQ example using python3 and asyncio b471daf Adddress nits, use asyncio signal handling, create_task (Bob McElrath) 4bb7d1b Add python version checks and 3.4 example (Bob McElrath) 5406d51 Rewrite to not use Polling wrapper for asyncio, link to python2.7 example (Bob McElrath) 5ea5368 ZMQ example using python3 and asyncio (Bob McElrath) * Merge #9807: RPC doc fix-ups. 851f6a3 [qa][doc] Correct rpc test options in readme (fanquake) 41e7219 [trivial] Add tests_config.ini to .gitignore (fanquake) * Dashify Co-Authored-By: PastaPastaPasta * Change file permissions * update travis.yml -parallel -> --jobs --- .gitignore | 1 + .travis.yml | 2 +- Makefile.am | 3 - configure.ac | 2 +- contrib/zmq/zmq_sub.py | 109 ++++++++---- contrib/zmq/zmq_sub3.4.py | 121 ++++++++++++++ depends/packages/qrencode.mk | 2 +- qa/README.md | 8 +- qa/pull-tester/rpc-tests.py | 258 +++++++++++++++-------------- qa/pull-tester/tests_config.ini.in | 18 ++ qa/pull-tester/tests_config.py.in | 14 -- qa/rpc-tests/bip68-112-113-p2p.py | 2 +- qa/rpc-tests/bip68-sequence.py | 2 - qa/rpc-tests/p2p-compactblocks.py | 1 - qa/rpc-tests/rpcnamedargs.py | 6 - qa/rpc-tests/wallet-accounts.py | 2 - src/init.cpp | 2 +- src/netbase.cpp | 52 ++++-- src/qt/forms/intro.ui | 35 +++- src/qt/guiutil.cpp | 17 -- src/qt/intro.cpp | 20 ++- src/rpc/client.cpp | 2 +- src/rpc/misc.cpp | 2 +- src/test/testutil.cpp | 18 -- src/utiltime.h | 2 +- src/validation.cpp | 10 +- src/validationinterface.h | 2 +- src/wallet/wallet.cpp | 6 +- 28 files changed, 451 insertions(+), 268 deletions(-) create mode 100755 contrib/zmq/zmq_sub3.4.py create mode 100644 qa/pull-tester/tests_config.ini.in delete mode 100644 qa/pull-tester/tests_config.py.in diff --git a/.gitignore b/.gitignore index 204c463e74..d34b5eb02a 100644 --- a/.gitignore +++ b/.gitignore @@ -109,6 +109,7 @@ linux-coverage-build linux-build win32-build qa/pull-tester/tests_config.py +qa/pull-tester/tests_config.ini qa/cache/* !src/leveldb*/Makefile diff --git a/.travis.yml b/.travis.yml index 3a57c00eb2..9b2bb2043f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,7 +73,7 @@ script: - if [ $SECONDS -gt 1200 ]; then export DEPENDS_TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 - test "$DEPENDS_TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh - test "$DEPENDS_TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_unittests.sh - - test "$DEPENDS_TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh -parallel=3 + - test "$DEPENDS_TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 - test "$DEPENDS_TIMEOUT" != "true" && if [ "$DOCKER_BUILD" = "true" ]; then BUILD_DIR=build-ci/dashcore-$BUILD_TARGET ./docker/build-docker.sh; fi after_script: - echo $TRAVIS_COMMIT_RANGE diff --git a/Makefile.am b/Makefile.am index 81b90f2c46..ce09ef59ea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -224,9 +224,6 @@ EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc- CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) -# This file is problematic for out-of-tree builds if it exists. -DISTCLEANFILES = qa/pull-tester/tests_config.pyc - .INTERMEDIATE: $(COVERAGE_INFO) DISTCHECK_CONFIGURE_FLAGS = --enable-man diff --git a/configure.ac b/configure.ac index 92f731c0c6..0e75c13802 100644 --- a/configure.ac +++ b/configure.ac @@ -1113,7 +1113,7 @@ AC_SUBST(ZMQ_LIBS) AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) -AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) +AC_CONFIG_FILES([qa/pull-tester/tests_config.ini],[chmod +x qa/pull-tester/tests_config.ini]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) AC_CONFIG_LINKS([qa/pull-tester/rpc-tests.py:qa/pull-tester/rpc-tests.py]) diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index fa15f1285c..035a39765a 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -1,34 +1,64 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright (c) 2014-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. +""" + ZMQ example using python3's asyncio + + Dash should be started with the command line arguments: + dashd-testnet -daemon \ + -zmqpubhashblock=tcp://127.0.0.1:28332 \ + -zmqpubrawtx=tcp://127.0.0.1:28332 \ + -zmqpubhashtx=tcp://127.0.0.1:28332 \ + -zmqpubhashblock=tcp://127.0.0.1:28332 + + We use the asyncio library here. `self.handle()` installs itself as a + future at the end of the function. Since it never returns with the event + loop having an empty stack of futures, this creates an infinite loop. An + alternative is to wrap the contents of `handle` inside `while True`. + + A blocking example using python 2.7 can be obtained from the git history: + https://github.com/bitcoin/bitcoin/blob/37a7fe9e440b83e2364d5498931253937abe9294/contrib/zmq/zmq_sub.py +""" + import binascii +import asyncio import zmq +import zmq.asyncio +import signal import struct +import sys + +if not (sys.version_info.major >= 3 and sys.version_info.minor >= 5): + print("This example only works with Python 3.5 and greater") + exit(1) port = 28332 -zmqContext = zmq.Context() -zmqSubSocket = zmqContext.socket(zmq.SUB) -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtxlock") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashgovernancevote") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashgovernanceobject") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashinstantsenddoublespend") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawblock") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawtx") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawtxlock") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawgovernancevote") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawgovernanceobject") -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawinstantsenddoublespend") -zmqSubSocket.connect("tcp://127.0.0.1:%i" % port) +class ZMQHandler(): + def __init__(self): + self.loop = zmq.asyncio.install() + self.zmqContext = zmq.asyncio.Context() -try: - while True: - msg = zmqSubSocket.recv_multipart() - topic = str(msg[0].decode("utf-8")) + self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashblock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtx") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtxlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashgovernancevote") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashgovernanceobject") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashinstantsenddoublespend") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtxlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernancevote") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernanceobject") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawinstantsenddoublespend") + self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % port) + + async def handle(self) : + msg = await self.zmqSubSocket.recv_multipart() + topic = msg[0] body = msg[1] sequence = "Unknown" @@ -36,42 +66,53 @@ try: msgSequence = struct.unpack('= 3 and sys.version_info.minor >= 4): + print("This example only works with Python 3.4 and greater") + exit(1) + +port = 28332 + +class ZMQHandler(): + def __init__(self): + self.loop = zmq.asyncio.install() + self.zmqContext = zmq.asyncio.Context() + + self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashblock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtx") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtxlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashgovernancevote") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashgovernanceobject") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashinstantsenddoublespend") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtxlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernancevote") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernanceobject") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawinstantsenddoublespend") + self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % port) + + @asyncio.coroutine + def handle(self) : + msg = yield from self.zmqSubSocket.recv_multipart() + topic = msg[0] + body = msg[1] + sequence = "Unknown"; + if len(msg[-1]) == 4: + msgSequence = struct.unpack(' 1 and run_parallel > 1: + if len(test_list) > 1 and jobs > 1: # Populate cache - subprocess.check_output([RPC_TESTS_DIR + 'create_cache.py'] + flags) + subprocess.check_output([tests_dir + 'create_cache.py'] + flags) #Run Tests - max_len_name = len(max(test_list, key=len)) + all_passed = True time_sum = 0 time0 = time.time() - job_queue = RPCTestHandler(run_parallel, test_list, flags) + + job_queue = RPCTestHandler(jobs, tests_dir, test_list, flags) + + max_len_name = len(max(test_list, key=len)) results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "PASSED", "DURATION") + BOLD[0] - all_passed = True for _ in range(len(test_list)): (name, stdout, stderr, passed, duration) = job_queue.get_next() all_passed = all_passed and passed @@ -250,8 +256,10 @@ def runtests(): print('\n' + BOLD[1] + name + BOLD[0] + ":") print('' if passed else stdout + '\n', end='') print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='') - results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration) print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration)) + + results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration) + results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0] print(results) print("\nRuntime: %s s" % (int(time.time() - time0))) @@ -264,15 +272,15 @@ def runtests(): sys.exit(not all_passed) - class RPCTestHandler: """ Trigger the testscrips passed in via the list. """ - def __init__(self, num_tests_parallel, test_list=None, flags=None): + def __init__(self, num_tests_parallel, tests_dir, test_list=None, flags=None): assert(num_tests_parallel >= 1) self.num_jobs = num_tests_parallel + self.tests_dir = tests_dir self.test_list = test_list self.flags = flags self.num_running = 0 @@ -292,7 +300,7 @@ class RPCTestHandler: log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) self.jobs.append((t, time.time(), - subprocess.Popen((RPC_TESTS_DIR + t).split() + self.flags + port_seed, + subprocess.Popen((self.tests_dir + t).split() + self.flags + port_seed, universal_newlines=True, stdout=log_stdout, stderr=log_stderr), @@ -357,10 +365,10 @@ class RPCCoverage(object): """ # This is shared from `qa/rpc-tests/test-framework/coverage.py` - REFERENCE_FILENAME = 'rpc_interface.txt' - COVERAGE_FILE_PREFIX = 'coverage.' + reference_filename = 'rpc_interface.txt' + coverage_file_prefix = 'coverage.' - coverage_ref_filename = os.path.join(self.dir, REFERENCE_FILENAME) + coverage_ref_filename = os.path.join(self.dir, reference_filename) coverage_filenames = set() all_cmds = set() covered_cmds = set() @@ -373,7 +381,7 @@ class RPCCoverage(object): for root, dirs, files in os.walk(self.dir): for filename in files: - if filename.startswith(COVERAGE_FILE_PREFIX): + if filename.startswith(coverage_file_prefix): coverage_filenames.add(os.path.join(root, filename)) for filename in coverage_filenames: @@ -384,4 +392,4 @@ class RPCCoverage(object): if __name__ == '__main__': - runtests() + main() diff --git a/qa/pull-tester/tests_config.ini.in b/qa/pull-tester/tests_config.ini.in new file mode 100644 index 0000000000..e3e457d0b1 --- /dev/null +++ b/qa/pull-tester/tests_config.ini.in @@ -0,0 +1,18 @@ +# Copyright (c) 2013-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. + +# These environment variables are set by the build process and read by +# rpc-tests.py + +[environment] +SRCDIR=@abs_top_srcdir@ +BUILDDIR=@abs_top_builddir@ +EXEEXT=@EXEEXT@ + +[components] +# Which components are enabled. These are commented out by `configure` if they were disabled when running config. +@ENABLE_WALLET_TRUE@ENABLE_WALLET=true +@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=true +@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true +@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true diff --git a/qa/pull-tester/tests_config.py.in b/qa/pull-tester/tests_config.py.in deleted file mode 100644 index a0d0a3d98a..0000000000 --- a/qa/pull-tester/tests_config.py.in +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2013-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. - -SRCDIR="@abs_top_srcdir@" -BUILDDIR="@abs_top_builddir@" -EXEEXT="@EXEEXT@" - -# These will turn into comments if they were disabled when configuring. -@ENABLE_WALLET_TRUE@ENABLE_WALLET=1 -@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=1 -@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=1 -@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=1 diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index 2915029d0b..131ada5a4f 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -5,7 +5,7 @@ from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * -from test_framework.mininode import ToHex, CTransaction, NetworkThread +from test_framework.mininode import ToHex, NetworkThread from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager from test_framework.script import * diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py index 5e5fff8a78..d7718dfb09 100755 --- a/qa/rpc-tests/bip68-sequence.py +++ b/qa/rpc-tests/bip68-sequence.py @@ -9,8 +9,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.script import * -from test_framework.mininode import * from test_framework.blocktools import * SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index da257b1580..d14ebc1ef6 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -7,7 +7,6 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.blocktools import create_block, create_coinbase -from test_framework.siphash import siphash256 from test_framework.script import CScript, OP_TRUE ''' diff --git a/qa/rpc-tests/rpcnamedargs.py b/qa/rpc-tests/rpcnamedargs.py index da2d8f040f..f9a40955c0 100755 --- a/qa/rpc-tests/rpcnamedargs.py +++ b/qa/rpc-tests/rpcnamedargs.py @@ -3,17 +3,11 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -from decimal import Decimal - from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException from test_framework.util import ( assert_equal, assert_raises_jsonrpc, - assert_is_hex_string, - assert_is_hash_string, start_nodes, - connect_nodes_bi, ) diff --git a/qa/rpc-tests/wallet-accounts.py b/qa/rpc-tests/wallet-accounts.py index cf2e3fc60b..3ba1caccbe 100755 --- a/qa/rpc-tests/wallet-accounts.py +++ b/qa/rpc-tests/wallet-accounts.py @@ -6,9 +6,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( start_nodes, - start_node, assert_equal, - connect_nodes_bi, ) diff --git a/src/init.cpp b/src/init.cpp index 1cda57b89e..829cf75e5f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1174,7 +1174,7 @@ bool AppInitParameterInteraction() int64_t nMempoolSizeMin = GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40; if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(nMempoolSizeMin / 1000000.0))); - // incremental relay fee sets the minimimum feerate increase necessary for BIP 125 replacement in the mempool + // incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting. if (IsArgSet("-incrementalrelayfee")) { diff --git a/src/netbase.cpp b/src/netbase.cpp index c48e4edd0c..03e336c3de 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -198,6 +198,14 @@ struct timeval MillisToTimeval(int64_t nTimeout) return timeout; } +enum class IntrRecvError { + OK, + Timeout, + Disconnected, + NetworkError, + Interrupted +}; + /** * Read bytes from socket. This will either read the full number of bytes requested * or return False on error or timeout. @@ -209,7 +217,7 @@ struct timeval MillisToTimeval(int64_t nTimeout) * * @note This function requires that hSocket is in non-blocking mode. */ -bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket) +static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket) { int64_t curTime = GetTimeMillis(); int64_t endTime = curTime + timeout; @@ -222,12 +230,12 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock len -= ret; data += ret; } else if (ret == 0) { // Unexpected disconnection - return false; + return IntrRecvError::Disconnected; } else { // Other error or blocking int nErr = WSAGetLastError(); if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { if (!IsSelectableSocket(hSocket)) { - return false; + return IntrRecvError::NetworkError; } struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait)); fd_set fdset; @@ -235,17 +243,17 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock FD_SET(hSocket, &fdset); int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval); if (nRet == SOCKET_ERROR) { - return false; + return IntrRecvError::NetworkError; } } else { - return false; + return IntrRecvError::NetworkError; } } if (interruptSocks5Recv) - return false; + return IntrRecvError::Interrupted; curTime = GetTimeMillis(); } - return len == 0; + return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout; } struct ProxyCredentials @@ -272,6 +280,7 @@ std::string Socks5ErrorString(int err) /** Connect using SOCKS5 (as described in RFC1928) */ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket) { + IntrRecvError recvr; LogPrint("net", "SOCKS5 connecting %s\n", strDest); if (strDest.size() > 255) { CloseSocket(hSocket); @@ -294,7 +303,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials return error("Error sending to proxy"); } char pchRet1[2]; - if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) { + if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port); return false; @@ -320,7 +329,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials } LogPrint("proxy", "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); char pchRetA[2]; - if (!InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) { + if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); return error("Error reading proxy authentication response"); } @@ -349,9 +358,16 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials return error("Error sending to proxy"); } char pchRet2[4]; - if (!InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) { + if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); - return error("Error reading proxy response"); + if (recvr == IntrRecvError::Timeout) { + /* If a timeout happens here, this effectively means we timed out while connecting + * to the remote node. This is very common for Tor, so do not print an + * error message. */ + return false; + } else { + return error("Error while reading proxy response"); + } } if (pchRet2[0] != 0x05) { CloseSocket(hSocket); @@ -370,26 +386,26 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials char pchRet3[256]; switch (pchRet2[3]) { - case 0x01: ret = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break; - case 0x04: ret = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break; + case 0x01: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break; + case 0x04: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break; case 0x03: { - ret = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket); - if (!ret) { + recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket); + if (recvr != IntrRecvError::OK) { CloseSocket(hSocket); return error("Error reading from proxy"); } int nRecv = pchRet3[0]; - ret = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket); + recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket); break; } default: CloseSocket(hSocket); return error("Error: malformed proxy response"); } - if (!ret) { + if (recvr != IntrRecvError::OK) { CloseSocket(hSocket); return error("Error reading from proxy"); } - if (!InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) { + if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); return error("Error reading from proxy"); } diff --git a/src/qt/forms/intro.ui b/src/qt/forms/intro.ui index 19b90f705f..91d4553ce7 100644 --- a/src/qt/forms/intro.ui +++ b/src/qt/forms/intro.ui @@ -7,7 +7,7 @@ 0 0 674 - 363 + 415 @@ -55,9 +55,6 @@ - - %1 will download and store a copy of the Dash block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - true @@ -203,6 +200,36 @@ + + + + When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched. + + + true + + + + + + + This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off. + + + true + + + + + + + If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low. + + + true + + + diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 31aab8ff2d..877e8e8e32 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -38,9 +38,7 @@ #include #include -#if BOOST_FILESYSTEM_VERSION >= 3 #include -#endif #include #include @@ -68,9 +66,7 @@ #include #endif -#if BOOST_FILESYSTEM_VERSION >= 3 static boost::filesystem::detail::utf8_codecvt_facet utf8; -#endif #if defined(Q_OS_MAC) extern double NSAppKitVersionNumber; @@ -952,7 +948,6 @@ void setClipboard(const QString& str) QApplication::clipboard()->setText(str, QClipboard::Selection); } -#if BOOST_FILESYSTEM_VERSION >= 3 boost::filesystem::path qstringToBoostPath(const QString &path) { return boost::filesystem::path(path.toStdString(), utf8); @@ -962,18 +957,6 @@ QString boostPathToQString(const boost::filesystem::path &path) { return QString::fromStdString(path.string(utf8)); } -#else -#warning Conversion between boost path and QString can use invalid character encoding with boost_filesystem v2 and older -boost::filesystem::path qstringToBoostPath(const QString &path) -{ - return boost::filesystem::path(path.toStdString()); -} - -QString boostPathToQString(const boost::filesystem::path &path) -{ - return QString::fromStdString(path.string()); -} -#endif QString formatDurationStr(int secs) { diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index d752072b48..117d4424c3 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -125,16 +125,34 @@ Intro::Intro(QWidget *parent) : ui->setupUi(this); ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME))); ui->storageLabel->setText(ui->storageLabel->text().arg(tr(PACKAGE_NAME))); + + ui->lblExplanation1->setText(ui->lblExplanation1->text() + .arg(tr(PACKAGE_NAME)) + .arg(BLOCK_CHAIN_SIZE) + .arg(2014) + .arg(tr("Dash")) + ); + ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME))); + uint64_t pruneTarget = std::max(0, GetArg("-prune", 0)); requiredSpace = BLOCK_CHAIN_SIZE; + QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); if (pruneTarget) { uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES); if (prunedGBs <= requiredSpace) { requiredSpace = prunedGBs; + storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); } + ui->lblExplanation3->setVisible(true); + } else { + ui->lblExplanation3->setVisible(false); } requiredSpace += CHAIN_STATE_SIZE; - ui->sizeWarningLabel->setText(ui->sizeWarningLabel->text().arg(tr(PACKAGE_NAME)).arg(requiredSpace)); + ui->sizeWarningLabel->setText( + tr("%1 will download and store a copy of the Bitcoin block chain.").arg(tr(PACKAGE_NAME)) + " " + + storageRequiresMsg.arg(requiredSpace) + " " + + tr("The wallet will also be stored in this directory.") + ); startThread(); } diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 643beb54e7..8242ffcaba 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -22,7 +22,7 @@ public: std::string paramName; //!< parameter name }; /** - * Specifiy a (method, idx, name) here if the argument is a non-string RPC + * Specify a (method, idx, name) here if the argument is a non-string RPC * argument and needs to be converted from JSON. * * @note Parameter indexes start from 0. diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 8799a7959f..c3605f834a 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -595,7 +595,7 @@ UniValue setmocktime(const JSONRPCRequest& request) // this could have an effect on mempool time-based eviction, as well as // IsCurrentForFeeEstimation() and IsInitialBlockDownload(). // TODO: figure out the right way to synchronize around mocktime, and - // ensure all callsites of GetTime() are accessing this safely. + // ensure all call sites of GetTime() are accessing this safely. LOCK(cs_main); RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); diff --git a/src/test/testutil.cpp b/src/test/testutil.cpp index 304cffb798..e6d8622979 100644 --- a/src/test/testutil.cpp +++ b/src/test/testutil.cpp @@ -11,23 +11,5 @@ #include boost::filesystem::path GetTempPath() { -#if BOOST_FILESYSTEM_VERSION == 3 return boost::filesystem::temp_directory_path(); -#else - // TODO: remove when we don't support filesystem v2 anymore - boost::filesystem::path path; -#ifdef WIN32 - char pszPath[MAX_PATH] = ""; - - if (GetTempPathA(MAX_PATH, pszPath)) - path = boost::filesystem::path(pszPath); -#else - path = boost::filesystem::path("/tmp"); -#endif - if (path.empty() || !boost::filesystem::is_directory(path)) { - LogPrintf("GetTempPath(): failed to find temp path\n"); - return boost::filesystem::path(""); - } - return path; -#endif } diff --git a/src/utiltime.h b/src/utiltime.h index e37ee32813..cb2c0afb1e 100644 --- a/src/utiltime.h +++ b/src/utiltime.h @@ -11,7 +11,7 @@ /** * GetTimeMicros() and GetTimeMillis() both return the system time, but in - * different units. GetTime() returns the sytem time in seconds, but also + * different units. GetTime() returns the system time in seconds, but also * supports mocktime, where the time can be specified by the user, eg for * testing (eg with the setmocktime rpc, or -mocktime argument). * diff --git a/src/validation.cpp b/src/validation.cpp index e51e3034cd..d79218fcd2 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1444,7 +1444,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // Helps prevent CPU exhaustion attacks. // Skip script verification when connecting blocks under the - // assumedvalid block. Assuming the assumedvalid block is valid this + // assumevalid block. Assuming the assumevalid block is valid this // is safe because block merkle hashes are still computed and checked, // Of course, if an assumed valid block is invalid due to false scriptSigs // this optimization would allow an invalid chain to be accepted. @@ -1932,7 +1932,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd pindexBestHeader->GetAncestor(pindex->nHeight) == pindex && pindexBestHeader->nChainWork >= UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) { // This block is a member of the assumed verified chain and an ancestor of the best header. - // The equivalent time check discourages hashpower from extorting the network via DOS attack + // The equivalent time check discourages hash power from extorting the network via DOS attack // into accepting an invalid block through telling users they must manually set assumevalid. // Requiring a software change or burying the invalid block, regardless of the setting, makes // it hard to hide the implication of the demand. This also avoids having release candidates @@ -2831,12 +2831,12 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, bool fInitialDownload; { LOCK(cs_main); - { // TODO: Tempoarily ensure that mempool removals are notified before + { // TODO: Temporarily ensure that mempool removals are notified before // connected transactions. This shouldn't matter, but the abandoned // state of transactions in our wallet is currently cleared when we // receive another notification and there is a race condition where // notification of a connected conflict might cause an outside process - // to abandon a transaction and then have it inadvertantly cleared by + // to abandon a transaction and then have it inadvertently cleared by // the notification that the conflicted transaction was evicted. MemPoolConflictRemovalTracker mrt(mempool); CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -2865,7 +2865,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, } // MemPoolConflictRemovalTracker destroyed and conflict evictions are notified - // Transactions in the connnected block are notified + // Transactions in the connected block are notified for (const auto& pair : connectTrace.blocksConnected) { assert(pair.second); const CBlock& block = *(pair.second); diff --git a/src/validationinterface.h b/src/validationinterface.h index 78dafba43a..f28144ed97 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -63,7 +63,7 @@ struct CMainSignals { boost::signals2::signal NotifyHeaderTip; /** Notifies listeners of updated block chain tip */ boost::signals2::signal UpdatedBlockTip; - /** A posInBlock value for SyncTransaction calls for tranactions not + /** A posInBlock value for SyncTransaction calls for transactions not * included in connected blocks such as transactions removed from mempool, * accepted to mempool or appearing in disconnected blocks.*/ static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d0982ba94a..fd0ec54858 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1219,7 +1219,7 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn) * TODO: One exception to this is that the abandoned state is cleared under the * assumption that any further notification of a transaction that was considered * abandoned is an indication that it is not safe to be considered abandoned. - * Abandoned state should probably be more carefuly tracked via different + * Abandoned state should probably be more carefully tracked via different * posInBlock signals or by checking mempool presence when necessary. */ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) @@ -5221,11 +5221,7 @@ bool CWallet::BackupWallet(const std::string& strDest) pathDest /= strWalletFile; try { -#if BOOST_VERSION >= 104000 boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists); -#else - boost::filesystem::copy_file(pathSrc, pathDest); -#endif LogPrintf("copied %s to %s\n", strWalletFile, pathDest.string()); return true; } catch (const boost::filesystem::filesystem_error& e) {