diff options
90 files changed, 1249 insertions, 629 deletions
diff --git a/.travis.yml b/.travis.yml index e08e78dabf..9c18729b42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ env: global: - MAKEJOBS=-j3 - RUN_TESTS=false + - BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID - CCACHE_SIZE=100M - CCACHE_TEMPDIR=/tmp/.ccache-temp - CCACHE_COMPRESS=1 diff --git a/configure.ac b/configure.ac index f5bc1e3122..2c918218bb 100644 --- a/configure.ac +++ b/configure.ac @@ -350,8 +350,8 @@ if test x$use_lcov = xyes; then [AC_MSG_ERROR("lcov testing requested but --coverage flag does not work")]) fi -dnl Require little endian -AC_C_BIGENDIAN([AC_MSG_ERROR("Big Endian not supported")]) +dnl Check for endianness +AC_C_BIGENDIAN dnl Check for pthread compile/link requirements AX_PTHREAD @@ -438,17 +438,22 @@ if test x$TARGET_OS = xdarwin; then AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) fi -AC_CHECK_HEADERS([endian.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h]) +AC_CHECK_HEADERS([endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h]) AC_SEARCH_LIBS([getaddrinfo_a], [anl], [AC_DEFINE(HAVE_GETADDRINFO_A, 1, [Define this symbol if you have getaddrinfo_a])]) AC_SEARCH_LIBS([inet_pton], [nsl resolv], [AC_DEFINE(HAVE_INET_PTON, 1, [Define this symbol if you have inet_pton])]) AC_CHECK_DECLS([strnlen]) -AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,, +AC_CHECK_DECLS([le16toh, le32toh, le64toh, htole16, htole32, htole64, be16toh, be32toh, be64toh, htobe16, htobe32, htobe64],,, [#if HAVE_ENDIAN_H #include <endian.h> #endif]) +AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64],,, + [#if HAVE_BYTESWAP_H + #include <byteswap.h> + #endif]) + dnl Check for MSG_NOSIGNAL AC_MSG_CHECKING(for MSG_NOSIGNAL) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], diff --git a/contrib/init/bitcoind.openrc b/contrib/init/bitcoind.openrc index 1f7758c920..b0ac5e31e1 100644 --- a/contrib/init/bitcoind.openrc +++ b/contrib/init/bitcoind.openrc @@ -12,9 +12,11 @@ BITCOIND_CONFIGFILE=${BITCOIND_CONFIGFILE:-/etc/bitcoin/bitcoin.conf} BITCOIND_PIDDIR=${BITCOIND_PIDDIR:-/var/run/bitcoind} BITCOIND_PIDFILE=${BITCOIND_PIDFILE:-${BITCOIND_PIDDIR}/bitcoind.pid} BITCOIND_DATADIR=${BITCOIND_DATADIR:-${BITCOIND_DEFAULT_DATADIR}} -BITCOIND_USER=${BITCOIND_USER:-bitcoin} +BITCOIND_USER=${BITCOIND_USER:-${BITCOIN_USER:-bitcoin}} BITCOIND_GROUP=${BITCOIND_GROUP:-bitcoin} BITCOIND_BIN=${BITCOIND_BIN:-/usr/bin/bitcoind} +BITCOIND_NICE=${BITCOIND_NICE:-${NICELEVEL:-0}} +BITCOIND_OPTS="${BITCOIND_OPTS:-${BITCOIN_OPTS}}" name="Bitcoin Core Daemon" description="Bitcoin crypto-currency p2p network daemon" @@ -28,7 +30,7 @@ command_args="-pid=\"${BITCOIND_PIDFILE}\" \ required_files="${BITCOIND_CONFIGFILE}" start_stop_daemon_args="-u ${BITCOIND_USER} \ - -N ${BITCOIND_NICE:-0} -w 2000" + -N ${BITCOIND_NICE} -w 2000" pidfile="${BITCOIND_PIDFILE}" retry=60 diff --git a/qa/rpc-tests/invalidateblock.py b/qa/rpc-tests/invalidateblock.py new file mode 100755 index 0000000000..a8bfbe6e6c --- /dev/null +++ b/qa/rpc-tests/invalidateblock.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test InvalidateBlock code +# + +from test_framework import BitcoinTestFramework +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * + +class InvalidateTest(BitcoinTestFramework): + + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 2) + + def setup_network(self): + self.nodes = [] + self.is_network_split = False + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug"])) + + def run_test(self): + print "Mine 4 blocks on Node 0" + self.nodes[0].setgenerate(True, 4) + assert(self.nodes[0].getblockcount() == 4) + besthash = self.nodes[0].getbestblockhash() + + print "Mine competing 6 blocks on Node 1" + self.nodes[1].setgenerate(True, 6) + assert(self.nodes[1].getblockcount() == 6) + + print "Connect nodes to force a reorg" + connect_nodes_bi(self.nodes,0,1) + sync_blocks(self.nodes) + assert(self.nodes[0].getblockcount() == 6) + badhash = self.nodes[1].getblockhash(2) + + print "Invalidate block 2 on node 0 and verify we reorg to node 0's original chain" + self.nodes[0].invalidateblock(badhash) + newheight = self.nodes[0].getblockcount() + newhash = self.nodes[0].getbestblockhash() + if (newheight != 4 or newhash != besthash): + raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight)) + +if __name__ == '__main__': + InvalidateTest().main() diff --git a/src/Makefile.am b/src/Makefile.am index e1d467ff85..da65efa713 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -141,6 +141,8 @@ BITCOIN_CORE_H = \ walletdb.h \ wallet.h \ wallet_ismine.h \ + compat/byteswap.h \ + compat/endian.h \ compat/sanity.h JSON_H = \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 90494439fa..e9d99323c5 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -55,6 +55,7 @@ BITCOIN_TESTS =\ test/multisig_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ + test/pow_tests.cpp \ test/rpc_tests.cpp \ test/sanity_tests.cpp \ test/script_P2SH_tests.cpp \ @@ -65,6 +66,7 @@ BITCOIN_TESTS =\ test/sigopcount_tests.cpp \ test/skiplist_tests.cpp \ test/test_bitcoin.cpp \ + test/test_bitcoin.h \ test/timedata_tests.cpp \ test/transaction_tests.cpp \ test/uint256_tests.cpp \ diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 1243823da5..2e61363576 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -7,6 +7,7 @@ #include "uint256.h" #include "utilstrencodings.h" +#include "crypto/common.h" #include <stdio.h> #include <string.h> @@ -246,14 +247,14 @@ uint32_t arith_uint256::GetCompact(bool fNegative) const uint256 ArithToUint256(const arith_uint256 &a) { uint256 b; - // TODO: needs bswap32 on big-endian - memcpy(b.begin(), a.pn, a.size()); + for(int x=0; x<a.WIDTH; ++x) + WriteLE32(b.begin() + x*4, a.pn[x]); return b; } arith_uint256 UintToArith256(const uint256 &a) { arith_uint256 b; - // TODO: needs bswap32 on big-endian - memcpy(b.pn, a.begin(), a.size()); + for(int x=0; x<b.WIDTH; ++x) + b.pn[x] = ReadLE32(a.begin() + x*4); return b; } diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index f273a15713..2fa8de6fd8 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -20,21 +20,21 @@ using namespace json_spirit; std::string HelpMessageCli() { string strUsage; - strUsage += _("Options:") + "\n"; - strUsage += " -? " + _("This help message") + "\n"; - strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n"; - strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n"; - strUsage += " -testnet " + _("Use the test network") + "\n"; - strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be " - "solved instantly. This is intended for regression testing tools and app development.") + "\n"; - strUsage += " -rpcconnect=<ip> " + strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1") + "\n"; - strUsage += " -rpcport=<port> " + strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n"; - strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n"; - strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; - strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; - - strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; - strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; + strUsage += HelpMessageGroup(_("Options:")); + strUsage += HelpMessageOpt("-?", _("This help message")); + strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf")); + strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory")); + strUsage += HelpMessageOpt("-testnet", _("Use the test network")); + strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be " + "solved instantly. This is intended for regression testing tools and app development.")); + strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1")); + strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332)); + strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start")); + strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections")); + strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections")); + + strUsage += HelpMessageGroup(_("SSL options: (see the Bitcoin Wiki for SSL setup instructions)")); + strUsage += HelpMessageOpt("-rpcssl", _("Use OpenSSL (https) for JSON-RPC connections")); return strUsage; } diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index c1622cf5d3..78f5c2c4b6 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -54,38 +54,34 @@ static bool AppInitRawTx(int argc, char* argv[]) fprintf(stdout, "%s", strUsage.c_str()); - strUsage = _("Options:") + "\n"; - strUsage += " -? " + _("This help message") + "\n"; - strUsage += " -create " + _("Create new, empty TX.") + "\n"; - strUsage += " -json " + _("Select JSON output") + "\n"; - strUsage += " -txid " + _("Output only the hex-encoded transaction id of the resultant transaction.") + "\n"; - strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; - strUsage += " -testnet " + _("Use the test network") + "\n"; - strUsage += "\n"; + strUsage = HelpMessageGroup(_("Options:")); + strUsage += HelpMessageOpt("-?", _("This help message")); + strUsage += HelpMessageOpt("-create", _("Create new, empty TX.")); + strUsage += HelpMessageOpt("-json", _("Select JSON output")); + strUsage += HelpMessageOpt("-txid", _("Output only the hex-encoded transaction id of the resultant transaction.")); + strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.")); + strUsage += HelpMessageOpt("-testnet", _("Use the test network")); fprintf(stdout, "%s", strUsage.c_str()); - - strUsage = _("Commands:") + "\n"; - strUsage += " delin=N " + _("Delete input N from TX") + "\n"; - strUsage += " delout=N " + _("Delete output N from TX") + "\n"; - strUsage += " in=TXID:VOUT " + _("Add input to TX") + "\n"; - strUsage += " locktime=N " + _("Set TX lock time to N") + "\n"; - strUsage += " nversion=N " + _("Set TX version to N") + "\n"; - strUsage += " outaddr=VALUE:ADDRESS " + _("Add address-based output to TX") + "\n"; - strUsage += " outscript=VALUE:SCRIPT " + _("Add raw script output to TX") + "\n"; - strUsage += " sign=SIGHASH-FLAGS " + _("Add zero or more signatures to transaction") + "\n"; - strUsage += " This command requires JSON registers:\n"; - strUsage += " prevtxs=JSON object\n"; - strUsage += " privatekeys=JSON object\n"; - strUsage += " See signrawtransaction docs for format of sighash flags, JSON objects.\n"; - strUsage += "\n"; + strUsage = HelpMessageGroup(_("Commands:")); + strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX")); + strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX")); + strUsage += HelpMessageOpt("in=TXID:VOUT", _("Add input to TX")); + strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); + strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); + strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); + strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX")); + strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " + + _("This command requires JSON registers:") + + _("prevtxs=JSON object") + ", " + + _("privatekeys=JSON object") + ". " + + _("See signrawtransaction docs for format of sighash flags, JSON objects.")); fprintf(stdout, "%s", strUsage.c_str()); - strUsage = _("Register Commands:") + "\n"; - strUsage += " load=NAME:FILENAME " + _("Load JSON file FILENAME into register NAME") + "\n"; - strUsage += " set=NAME:JSON-STRING " + _("Set register NAME to given JSON-STRING") + "\n"; - strUsage += "\n"; + strUsage = HelpMessageGroup(_("Register Commands:")); + strUsage += HelpMessageOpt("load=NAME:FILENAME", _("Load JSON file FILENAME into register NAME")); + strUsage += HelpMessageOpt("set=NAME:JSON-STRING", _("Set register NAME to given JSON-STRING")); fprintf(stdout, "%s", strUsage.c_str()); return false; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1fd3b01681..2bc8976510 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -170,7 +170,6 @@ public: fAllowMinDifficultyBlocks = false; fRequireStandard = true; fMineBlocksOnDemand = false; - fSkipProofOfWorkCheck = false; fTestnetToBeDeprecatedFieldRPC = false; } @@ -281,51 +280,8 @@ public: }; static CRegTestParams regTestParams; -/** - * Unit test - */ -class CUnitTestParams : public CMainParams, public CModifiableParams { -public: - CUnitTestParams() { - strNetworkID = "unittest"; - nDefaultPort = 18445; - vFixedSeeds.clear(); //! Unit test mode doesn't have any fixed seeds. - vSeeds.clear(); //! Unit test mode doesn't have any DNS seeds. - - fRequireRPCPassword = false; - fMiningRequiresPeers = false; - fDefaultCheckMemPool = true; - fAllowMinDifficultyBlocks = false; - fMineBlocksOnDemand = true; - } - - const Checkpoints::CCheckpointData& Checkpoints() const - { - // UnitTest share the same checkpoints as MAIN - return data; - } - - //! Published setters to allow changing values in unit test cases - virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) { nSubsidyHalvingInterval=anSubsidyHalvingInterval; } - virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority) { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; } - virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority) { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; } - virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority) { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; } - virtual void setDefaultCheckMemPool(bool afDefaultCheckMemPool) { fDefaultCheckMemPool=afDefaultCheckMemPool; } - virtual void setAllowMinDifficultyBlocks(bool afAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=afAllowMinDifficultyBlocks; } - virtual void setSkipProofOfWorkCheck(bool afSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = afSkipProofOfWorkCheck; } -}; -static CUnitTestParams unitTestParams; - - static CChainParams *pCurrentParams = 0; -CModifiableParams *ModifiableParams() -{ - assert(pCurrentParams); - assert(pCurrentParams==&unitTestParams); - return (CModifiableParams*)&unitTestParams; -} - const CChainParams &Params() { assert(pCurrentParams); return *pCurrentParams; @@ -339,8 +295,6 @@ CChainParams &Params(CBaseChainParams::Network network) { return testNetParams; case CBaseChainParams::REGTEST: return regTestParams; - case CBaseChainParams::UNITTEST: - return unitTestParams; default: assert(false && "Unimplemented network"); return mainParams; diff --git a/src/chainparams.h b/src/chainparams.h index 86b84df667..134dcd6558 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -14,8 +14,6 @@ #include <vector> -typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; - struct CDNSSeedData { std::string name, host; CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {} @@ -42,7 +40,7 @@ public: }; const uint256& HashGenesisBlock() const { return hashGenesisBlock; } - const MessageStartChars& MessageStart() const { return pchMessageStart; } + const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } const arith_uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } @@ -62,8 +60,6 @@ public: bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; } /** Allow mining of a min-difficulty block */ bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } - /** Skip proof-of-work check: allow mining of any difficulty block */ - bool SkipProofOfWorkCheck() const { return fSkipProofOfWorkCheck; } /** Make standard checks */ bool RequireStandard() const { return fRequireStandard; } int64_t TargetTimespan() const { return nTargetTimespan; } @@ -83,7 +79,7 @@ protected: CChainParams() {} uint256 hashGenesisBlock; - MessageStartChars pchMessageStart; + CMessageHeader::MessageStartChars pchMessageStart; //! Raw pub key bytes for the broadcast alert signing key. std::vector<unsigned char> vAlertPubKey; int nDefaultPort; @@ -106,29 +102,9 @@ protected: bool fAllowMinDifficultyBlocks; bool fRequireStandard; bool fMineBlocksOnDemand; - bool fSkipProofOfWorkCheck; bool fTestnetToBeDeprecatedFieldRPC; }; -/** - * Modifiable parameters interface is used by test cases to adapt the parameters in order - * to test specific features more easily. Test cases should always restore the previous - * values after finalization. - */ - -class CModifiableParams { -public: - //! Published setters to allow changing values in unit test cases - virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) =0; - virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority)=0; - virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority)=0; - virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority)=0; - virtual void setDefaultCheckMemPool(bool aDefaultCheckMemPool)=0; - virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks)=0; - virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck)=0; -}; - - /** * Return the currently selected parameters. This won't change after app startup * outside of the unit tests. @@ -138,9 +114,6 @@ const CChainParams &Params(); /** Return parameters for the given network. */ CChainParams &Params(CBaseChainParams::Network network); -/** Get modifiable network parameters (UNITTEST only) */ -CModifiableParams *ModifiableParams(); - /** Sets the params returned by Params() to those for the given network. */ void SelectParams(CBaseChainParams::Network network); diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index c42fd106be..7d82d689ec 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -82,9 +82,6 @@ void SelectBaseParams(CBaseChainParams::Network network) case CBaseChainParams::REGTEST: pCurrentBaseParams = ®TestParams; break; - case CBaseChainParams::UNITTEST: - pCurrentBaseParams = &unitTestParams; - break; default: assert(false && "Unimplemented network"); return; diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index cebe7aa01a..421a3a06ff 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -19,7 +19,6 @@ public: MAIN, TESTNET, REGTEST, - UNITTEST, MAX_NETWORK_TYPES }; diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h new file mode 100644 index 0000000000..899220bdc5 --- /dev/null +++ b/src/compat/byteswap.h @@ -0,0 +1,47 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_COMPAT_BYTESWAP_H +#define BITCOIN_COMPAT_BYTESWAP_H + +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" +#endif + +#include <stdint.h> + +#if defined(HAVE_BYTESWAP_H) +#include <byteswap.h> +#endif + +#if HAVE_DECL_BSWAP_16 == 0 +inline uint16_t bswap_16(uint16_t x) +{ + return (x >> 8) | ((x & 0x00ff) << 8); +} +#endif // HAVE_DECL_BSWAP16 + +#if HAVE_DECL_BSWAP_32 == 0 +inline uint32_t bswap_32(uint32_t x) +{ + return (((x & 0xff000000U) >> 24) | ((x & 0x00ff0000U) >> 8) | + ((x & 0x0000ff00U) << 8) | ((x & 0x000000ffU) << 24)); +} +#endif // HAVE_DECL_BSWAP32 + +#if HAVE_DECL_BSWAP_64 == 0 +inline uint64_t bswap_64(uint64_t x) +{ + return (((x & 0xff00000000000000ull) >> 56) + | ((x & 0x00ff000000000000ull) >> 40) + | ((x & 0x0000ff0000000000ull) >> 24) + | ((x & 0x000000ff00000000ull) >> 8) + | ((x & 0x00000000ff000000ull) << 8) + | ((x & 0x0000000000ff0000ull) << 24) + | ((x & 0x000000000000ff00ull) << 40) + | ((x & 0x00000000000000ffull) << 56)); +} +#endif // HAVE_DECL_BSWAP64 + +#endif // BITCOIN_COMPAT_BYTESWAP_H diff --git a/src/compat/endian.h b/src/compat/endian.h new file mode 100644 index 0000000000..4d041d6554 --- /dev/null +++ b/src/compat/endian.h @@ -0,0 +1,194 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_COMPAT_ENDIAN_H +#define BITCOIN_COMPAT_ENDIAN_H + +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" +#endif + +#include <stdint.h> + +#include "compat/byteswap.h" + +#if defined(HAVE_ENDIAN_H) +#include <endian.h> +#endif + +#if defined(WORDS_BIGENDIAN) + +#if HAVE_DECL_HTOBE16 == 0 +inline uint16_t htobe16(uint16_t host_16bits) +{ + return host_16bits; +} +#endif // HAVE_DECL_HTOBE16 + +#if HAVE_DECL_HTOLE16 == 0 +inline uint16_t htole16(uint16_t host_16bits) +{ + return bswap_16(host_16bits); +} +#endif // HAVE_DECL_HTOLE16 + +#if HAVE_DECL_BE16TOH == 0 +inline uint16_t be16toh(uint16_t big_endian_16bits) +{ + return big_endian_16bits; +} +#endif // HAVE_DECL_BE16TOH + +#if HAVE_DECL_LE16TOH == 0 +inline uint16_t le16toh(uint16_t little_endian_16bits) +{ + return bswap_16(little_endian_16bits); +} +#endif // HAVE_DECL_LE16TOH + +#if HAVE_DECL_HTOBE32 == 0 +inline uint32_t htobe32(uint32_t host_32bits) +{ + return host_32bits; +} +#endif // HAVE_DECL_HTOBE32 + +#if HAVE_DECL_HTOLE32 == 0 +inline uint32_t htole32(uint32_t host_32bits) +{ + return bswap_32(host_32bits); +} +#endif // HAVE_DECL_HTOLE32 + +#if HAVE_DECL_BE32TOH == 0 +inline uint32_t be32toh(uint32_t big_endian_32bits) +{ + return big_endian_32bits; +} +#endif // HAVE_DECL_BE32TOH + +#if HAVE_DECL_LE32TOH == 0 +inline uint32_t le32toh(uint32_t little_endian_32bits) +{ + return bswap_32(little_endian_32bits); +} +#endif // HAVE_DECL_LE32TOH + +#if HAVE_DECL_HTOBE64 == 0 +inline uint64_t htobe64(uint64_t host_64bits) +{ + return host_64bits; +} +#endif // HAVE_DECL_HTOBE64 + +#if HAVE_DECL_HTOLE64 == 0 +inline uint64_t htole64(uint64_t host_64bits) +{ + return bswap_64(host_64bits); +} +#endif // HAVE_DECL_HTOLE64 + +#if HAVE_DECL_BE64TOH == 0 +inline uint64_t be64toh(uint64_t big_endian_64bits) +{ + return big_endian_64bits; +} +#endif // HAVE_DECL_BE64TOH + +#if HAVE_DECL_LE64TOH == 0 +inline uint64_t le64toh(uint64_t little_endian_64bits) +{ + return bswap_64(little_endian_64bits); +} +#endif // HAVE_DECL_LE64TOH + +#else // WORDS_BIGENDIAN + +#if HAVE_DECL_HTOBE16 == 0 +inline uint16_t htobe16(uint16_t host_16bits) +{ + return bswap_16(host_16bits); +} +#endif // HAVE_DECL_HTOBE16 + +#if HAVE_DECL_HTOLE16 == 0 +inline uint16_t htole16(uint16_t host_16bits) +{ + return host_16bits; +} +#endif // HAVE_DECL_HTOLE16 + +#if HAVE_DECL_BE16TOH == 0 +inline uint16_t be16toh(uint16_t big_endian_16bits) +{ + return bswap_16(big_endian_16bits); +} +#endif // HAVE_DECL_BE16TOH + +#if HAVE_DECL_LE16TOH == 0 +inline uint16_t le16toh(uint16_t little_endian_16bits) +{ + return little_endian_16bits; +} +#endif // HAVE_DECL_LE16TOH + +#if HAVE_DECL_HTOBE32 == 0 +inline uint32_t htobe32(uint32_t host_32bits) +{ + return bswap_32(host_32bits); +} +#endif // HAVE_DECL_HTOBE32 + +#if HAVE_DECL_HTOLE32 == 0 +inline uint32_t htole32(uint32_t host_32bits) +{ + return host_32bits; +} +#endif // HAVE_DECL_HTOLE32 + +#if HAVE_DECL_BE32TOH == 0 +inline uint32_t be32toh(uint32_t big_endian_32bits) +{ + return bswap_32(big_endian_32bits); +} +#endif // HAVE_DECL_BE32TOH + +#if HAVE_DECL_LE32TOH == 0 +inline uint32_t le32toh(uint32_t little_endian_32bits) +{ + return little_endian_32bits; +} +#endif // HAVE_DECL_LE32TOH + +#if HAVE_DECL_HTOBE64 == 0 +inline uint64_t htobe64(uint64_t host_64bits) +{ + return bswap_64(host_64bits); +} +#endif // HAVE_DECL_HTOBE64 + +#if HAVE_DECL_HTOLE64 == 0 +inline uint64_t htole64(uint64_t host_64bits) +{ + return host_64bits; +} +#endif // HAVE_DECL_HTOLE64 + +#if HAVE_DECL_BE64TOH == 0 +inline uint64_t be64toh(uint64_t big_endian_64bits) +{ + return bswap_64(big_endian_64bits); +} +#endif // HAVE_DECL_BE64TOH + +#if HAVE_DECL_LE64TOH == 0 +inline uint64_t le64toh(uint64_t little_endian_64bits) +{ + return little_endian_64bits; +} +#endif // HAVE_DECL_LE64TOH + +#endif // WORDS_BIGENDIAN + +#endif // BITCOIN_COMPAT_ENDIAN_H diff --git a/src/crypto/common.h b/src/crypto/common.h index 8b04b1f728..580c72f5a6 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -11,110 +11,56 @@ #include <stdint.h> -#if defined(HAVE_ENDIAN_H) -#include <endian.h> -#endif +#include "compat/endian.h" + +uint16_t static inline ReadLE16(const unsigned char* ptr) +{ + return le16toh(*((uint16_t*)ptr)); +} uint32_t static inline ReadLE32(const unsigned char* ptr) { -#if HAVE_DECL_LE32TOH == 1 return le32toh(*((uint32_t*)ptr)); -#elif !defined(WORDS_BIGENDIAN) - return *((uint32_t*)ptr); -#else - return ((uint32_t)ptr[3] << 24 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[0]); -#endif } uint64_t static inline ReadLE64(const unsigned char* ptr) { -#if HAVE_DECL_LE64TOH == 1 return le64toh(*((uint64_t*)ptr)); -#elif !defined(WORDS_BIGENDIAN) - return *((uint64_t*)ptr); -#else - return ((uint64_t)ptr[7] << 56 | (uint64_t)ptr[6] << 48 | (uint64_t)ptr[5] << 40 | (uint64_t)ptr[4] << 32 | - (uint64_t)ptr[3] << 24 | (uint64_t)ptr[2] << 16 | (uint64_t)ptr[1] << 8 | (uint64_t)ptr[0]); -#endif +} + +void static inline WriteLE16(unsigned char* ptr, uint16_t x) +{ + *((uint16_t*)ptr) = htole16(x); } void static inline WriteLE32(unsigned char* ptr, uint32_t x) { -#if HAVE_DECL_HTOLE32 == 1 *((uint32_t*)ptr) = htole32(x); -#elif !defined(WORDS_BIGENDIAN) - *((uint32_t*)ptr) = x; -#else - ptr[3] = x >> 24; - ptr[2] = x >> 16; - ptr[1] = x >> 8; - ptr[0] = x; -#endif } void static inline WriteLE64(unsigned char* ptr, uint64_t x) { -#if HAVE_DECL_HTOLE64 == 1 *((uint64_t*)ptr) = htole64(x); -#elif !defined(WORDS_BIGENDIAN) - *((uint64_t*)ptr) = x; -#else - ptr[7] = x >> 56; - ptr[6] = x >> 48; - ptr[5] = x >> 40; - ptr[4] = x >> 32; - ptr[3] = x >> 24; - ptr[2] = x >> 16; - ptr[1] = x >> 8; - ptr[0] = x; -#endif } uint32_t static inline ReadBE32(const unsigned char* ptr) { -#if HAVE_DECL_BE32TOH == 1 return be32toh(*((uint32_t*)ptr)); -#else - return ((uint32_t)ptr[0] << 24 | (uint32_t)ptr[1] << 16 | (uint32_t)ptr[2] << 8 | (uint32_t)ptr[3]); -#endif } uint64_t static inline ReadBE64(const unsigned char* ptr) { -#if HAVE_DECL_BE64TOH == 1 return be64toh(*((uint64_t*)ptr)); -#else - return ((uint64_t)ptr[0] << 56 | (uint64_t)ptr[1] << 48 | (uint64_t)ptr[2] << 40 | (uint64_t)ptr[3] << 32 | - (uint64_t)ptr[4] << 24 | (uint64_t)ptr[5] << 16 | (uint64_t)ptr[6] << 8 | (uint64_t)ptr[7]); -#endif } void static inline WriteBE32(unsigned char* ptr, uint32_t x) { -#if HAVE_DECL_HTOBE32 == 1 *((uint32_t*)ptr) = htobe32(x); -#else - ptr[0] = x >> 24; - ptr[1] = x >> 16; - ptr[2] = x >> 8; - ptr[3] = x; -#endif } void static inline WriteBE64(unsigned char* ptr, uint64_t x) { -#if HAVE_DECL_HTOBE64 == 1 *((uint64_t*)ptr) = htobe64(x); -#else - ptr[0] = x >> 56; - ptr[1] = x >> 48; - ptr[2] = x >> 40; - ptr[3] = x >> 32; - ptr[4] = x >> 24; - ptr[5] = x >> 16; - ptr[6] = x >> 8; - ptr[7] = x; -#endif } #endif // BITCOIN_CRYPTO_COMMON_H diff --git a/src/db.cpp b/src/db.cpp index 3246e4b67a..36946b7dcc 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -39,22 +39,31 @@ void CDBEnv::EnvShutdown() return; fDbEnvInit = false; - int ret = dbenv.close(0); + int ret = dbenv->close(0); if (ret != 0) LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret)); if (!fMockDb) DbEnv(0).remove(path.string().c_str(), 0); } -CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS) +void CDBEnv::Reset() { + delete dbenv; + dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS); fDbEnvInit = false; fMockDb = false; } +CDBEnv::CDBEnv() : dbenv(NULL) +{ + Reset(); +} + CDBEnv::~CDBEnv() { EnvShutdown(); + delete dbenv; + dbenv = NULL; } void CDBEnv::Close() @@ -79,17 +88,17 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) if (GetBoolArg("-privdb", true)) nEnvFlags |= DB_PRIVATE; - dbenv.set_lg_dir(pathLogDir.string().c_str()); - dbenv.set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet - dbenv.set_lg_bsize(0x10000); - dbenv.set_lg_max(1048576); - dbenv.set_lk_max_locks(40000); - dbenv.set_lk_max_objects(40000); - dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug - dbenv.set_flags(DB_AUTO_COMMIT, 1); - dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1); - dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); - int ret = dbenv.open(path.string().c_str(), + dbenv->set_lg_dir(pathLogDir.string().c_str()); + dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet + dbenv->set_lg_bsize(0x10000); + dbenv->set_lg_max(1048576); + dbenv->set_lk_max_locks(40000); + dbenv->set_lk_max_objects(40000); + dbenv->set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug + dbenv->set_flags(DB_AUTO_COMMIT, 1); + dbenv->set_flags(DB_TXN_WRITE_NOSYNC, 1); + dbenv->log_set_config(DB_LOG_AUTO_REMOVE, 1); + int ret = dbenv->open(path.string().c_str(), DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | @@ -116,14 +125,14 @@ void CDBEnv::MakeMock() LogPrint("db", "CDBEnv::MakeMock\n"); - dbenv.set_cachesize(1, 0, 1); - dbenv.set_lg_bsize(10485760 * 4); - dbenv.set_lg_max(10485760); - dbenv.set_lk_max_locks(10000); - dbenv.set_lk_max_objects(10000); - dbenv.set_flags(DB_AUTO_COMMIT, 1); - dbenv.log_set_config(DB_LOG_IN_MEMORY, 1); - int ret = dbenv.open(NULL, + dbenv->set_cachesize(1, 0, 1); + dbenv->set_lg_bsize(10485760 * 4); + dbenv->set_lg_max(10485760); + dbenv->set_lk_max_locks(10000); + dbenv->set_lk_max_objects(10000); + dbenv->set_flags(DB_AUTO_COMMIT, 1); + dbenv->log_set_config(DB_LOG_IN_MEMORY, 1); + int ret = dbenv->open(NULL, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | @@ -144,7 +153,7 @@ CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDB LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); - Db db(&dbenv, 0); + Db db(dbenv, 0); int result = db.verify(strFile.c_str(), NULL, NULL, 0); if (result == 0) return VERIFY_OK; @@ -167,7 +176,7 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vector<CDBEnv:: stringstream strDump; - Db db(&dbenv, 0); + Db db(dbenv, 0); int result = db.verify(strFile.c_str(), NULL, &strDump, flags); if (result == DB_VERIFY_BAD) { LogPrintf("CDBEnv::Salvage: Database salvage found errors, all data may not be recoverable.\n"); @@ -208,10 +217,10 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vector<CDBEnv:: void CDBEnv::CheckpointLSN(const std::string& strFile) { - dbenv.txn_checkpoint(0, 0, 0); + dbenv->txn_checkpoint(0, 0, 0); if (fMockDb) return; - dbenv.lsn_reset(strFile.c_str(), 0); + dbenv->lsn_reset(strFile.c_str(), 0); } @@ -237,7 +246,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose ++bitdb.mapFileUseCount[strFile]; pdb = bitdb.mapDb[strFile]; if (pdb == NULL) { - pdb = new Db(&bitdb.dbenv, 0); + pdb = new Db(bitdb.dbenv, 0); bool fMockDb = bitdb.IsMock(); if (fMockDb) { @@ -284,7 +293,7 @@ void CDB::Flush() if (fReadOnly) nMinutes = 1; - bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); + bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); } void CDB::Close() @@ -324,7 +333,7 @@ bool CDBEnv::RemoveDb(const string& strFile) this->CloseDb(strFile); LOCK(cs_db); - int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT); + int rc = dbenv->dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT); return (rc == 0); } @@ -344,7 +353,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} CDB db(strFile.c_str(), "r"); - Db* pdbCopy = new Db(&bitdb.dbenv, 0); + Db* pdbCopy = new Db(bitdb.dbenv, 0); int ret = pdbCopy->open(NULL, // Txn pointer strFileRes.c_str(), // Filename @@ -394,10 +403,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) } } if (fSuccess) { - Db dbA(&bitdb.dbenv, 0); + Db dbA(bitdb.dbenv, 0); if (dbA.remove(strFile.c_str(), NULL, 0)) fSuccess = false; - Db dbB(&bitdb.dbenv, 0); + Db dbB(bitdb.dbenv, 0); if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) fSuccess = false; } @@ -430,10 +439,10 @@ void CDBEnv::Flush(bool fShutdown) // Move log data to the dat file CloseDb(strFile); LogPrint("db", "CDBEnv::Flush: %s checkpoint\n", strFile); - dbenv.txn_checkpoint(0, 0, 0); + dbenv->txn_checkpoint(0, 0, 0); LogPrint("db", "CDBEnv::Flush: %s detach\n", strFile); if (!fMockDb) - dbenv.lsn_reset(strFile.c_str(), 0); + dbenv->lsn_reset(strFile.c_str(), 0); LogPrint("db", "CDBEnv::Flush: %s closed\n", strFile); mapFileUseCount.erase(mi++); } else @@ -443,7 +452,7 @@ void CDBEnv::Flush(bool fShutdown) if (fShutdown) { char** listp; if (mapFileUseCount.empty()) { - dbenv.log_archive(&listp, DB_ARCH_REMOVE); + dbenv->log_archive(&listp, DB_ARCH_REMOVE); Close(); if (!fMockDb) boost::filesystem::remove_all(path / "database"); @@ -39,12 +39,14 @@ private: public: mutable CCriticalSection cs_db; - DbEnv dbenv; + DbEnv *dbenv; std::map<std::string, int> mapFileUseCount; std::map<std::string, Db*> mapDb; CDBEnv(); ~CDBEnv(); + void Reset(); + void MakeMock(); bool IsMock() { return fMockDb; } @@ -79,7 +81,7 @@ public: DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) { DbTxn* ptxn = NULL; - int ret = dbenv.txn_begin(NULL, &ptxn, flags); + int ret = dbenv->txn_begin(NULL, &ptxn, flags); if (!ptxn || ret != 0) return NULL; return ptxn; diff --git a/src/hash.cpp b/src/hash.cpp index a7eb5a2a0b..20d5d21777 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -3,8 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "hash.h" +#include "crypto/common.h" #include "crypto/hmac_sha512.h" + inline uint32_t ROTL32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); @@ -23,10 +25,10 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char //---------- // body - const uint32_t* blocks = (const uint32_t*)(&vDataToHash[0] + nblocks * 4); + const uint8_t* blocks = &vDataToHash[0] + nblocks * 4; for (int i = -nblocks; i; i++) { - uint32_t k1 = blocks[i]; + uint32_t k1 = ReadLE32(blocks + i*4); k1 *= c1; k1 = ROTL32(k1, 15); diff --git a/src/init.cpp b/src/init.cpp index c8f32d8bfd..1e3cc1d899 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -256,157 +256,174 @@ void OnRPCPreCommand(const CRPCCommand& cmd) std::string HelpMessage(HelpMessageMode mode) { + // When adding new options to the categories, please keep and ensure alphabetical ordering. - string strUsage = _("Options:") + "\n"; - strUsage += " -? " + _("This help message") + "\n"; - strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n"; - strUsage += " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n"; - strUsage += " -checkblocks=<n> " + strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288) + "\n"; - strUsage += " -checklevel=<n> " + strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3) + "\n"; - strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n"; + string strUsage = HelpMessageGroup(_("Options:")); + strUsage += HelpMessageOpt("-?", _("This help message")); + strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)")); + strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)")); + strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288)); + strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3)); + strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf")); if (mode == HMM_BITCOIND) { #if !defined(WIN32) - strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n"; + strUsage += HelpMessageOpt("-daemon", _("Run in the background as a daemon and accept commands")); #endif } - strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n"; - strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n"; - strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n"; - strUsage += " -maxorphantx=<n> " + strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS) + "\n"; - strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n"; + strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory")); + strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache)); + strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file") + " " + _("on startup")); + strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); + strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), + -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS)); #ifndef WIN32 - strUsage += " -pid=<file> " + strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid") + "\n"; + strUsage += HelpMessageOpt("-pid=<file>", strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid")); #endif - strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n"; + strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup")); #if !defined(WIN32) - strUsage += " -sysperms " + _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)") + "\n"; + strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)")); #endif - strUsage += " -txindex " + strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0) + "\n"; - - strUsage += "\n" + _("Connection options:") + "\n"; - strUsage += " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n"; - strUsage += " -banscore=<n> " + strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100) + "\n"; - strUsage += " -bantime=<n> " + strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), 86400) + "\n"; - strUsage += " -bind=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n"; - strUsage += " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n"; - strUsage += " -discover " + _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)") + "\n"; - strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)") + "\n"; - strUsage += " -dnsseed " + _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)") + "\n"; - strUsage += " -externalip=<ip> " + _("Specify your own public address") + "\n"; - strUsage += " -forcednsseed " + strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0) + "\n"; - strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n"; - strUsage += " -maxconnections=<n> " + strprintf(_("Maintain at most <n> connections to peers (default: %u)"), 125) + "\n"; - strUsage += " -maxreceivebuffer=<n> " + strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000) + "\n"; - strUsage += " -maxsendbuffer=<n> " + strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000) + "\n"; - strUsage += " -onion=<ip:port> " + strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy") + "\n"; - strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)") + "\n"; - strUsage += " -permitbaremultisig " + strprintf(_("Relay non-P2SH multisig (default: %u)"), 1) + "\n"; - strUsage += " -port=<port> " + strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), 8333, 18333) + "\n"; - strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS5 proxy") + "\n"; - strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n"; - strUsage += " -timeout=<n> " + strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT) + "\n"; + strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0)); + + strUsage += HelpMessageGroup(_("Connection options:")); + strUsage += HelpMessageOpt("-addnode=<ip>", _("Add a node to connect to and attempt to keep the connection open")); + strUsage += HelpMessageOpt("-banscore=<n>", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100)); + strUsage += HelpMessageOpt("-bantime=<n>", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), 86400)); + strUsage += HelpMessageOpt("-bind=<addr>", _("Bind to given address and always listen on it. Use [host]:port notation for IPv6")); + strUsage += HelpMessageOpt("-connect=<ip>", _("Connect only to the specified node(s)")); + strUsage += HelpMessageOpt("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)")); + strUsage += HelpMessageOpt("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)")); + strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)")); + strUsage += HelpMessageOpt("-externalip=<ip>", _("Specify your own public address")); + strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0)); + strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)")); + strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), 125)); + strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000)); + strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000)); + strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); + strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)")); + strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1)); + strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), 8333, 18333)); + strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy")); + strUsage += HelpMessageOpt("-seednode=<ip>", _("Connect to a node to retrieve peer addresses, and disconnect")); + strUsage += HelpMessageOpt("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT)); #ifdef USE_UPNP #if USE_UPNP - strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n"; + strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening)")); #else - strUsage += " -upnp " + strprintf(_("Use UPnP to map the listening port (default: %u)"), 0) + "\n"; + strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0)); #endif #endif - strUsage += " -whitebind=<addr> " + _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6") + "\n"; - strUsage += " -whitelist=<netmask> " + _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + "\n"; - strUsage += " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway") + "\n"; + strUsage += HelpMessageOpt("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); + strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); + #ifdef ENABLE_WALLET - strUsage += "\n" + _("Wallet options:") + "\n"; - strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; - strUsage += " -keypool=<n> " + strprintf(_("Set key pool size to <n> (default: %u)"), 100) + "\n"; + strUsage += HelpMessageGroup(_("Wallet options:")); + strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); + strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), 100)); if (GetBoolArg("-help-debug", false)) - strUsage += " -mintxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CWallet::minTxFee.GetFeePerK())) + "\n"; - strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n"; - strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; - strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; - strUsage += " -sendfreetransactions " + strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0) + "\n"; - strUsage += " -spendzeroconfchange " + strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1) + "\n"; - strUsage += " -txconfirmtarget=<n> " + strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1) + "\n"; - strUsage += " -maxtxfee=<amt> " + strprintf(_("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)"), FormatMoney(maxTxFee)) + "\n"; - strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; - strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat") + "\n"; - strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; - strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + "\n"; - strUsage += " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; + strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), + FormatMoney(CWallet::minTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup")); + strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup")); + strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); + strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); + strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1)); + strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)"), + FormatMoney(maxTxFee))); + strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup")); + strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat")); + strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); + strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + + " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)")); + #endif - strUsage += "\n" + _("Debugging/Testing options:") + "\n"; + strUsage += HelpMessageGroup(_("Debugging/Testing options:")); if (GetBoolArg("-help-debug", false)) { - strUsage += " -checkpoints " + strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1) + "\n"; - strUsage += " -dblogsize=<n> " + strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100) + "\n"; - strUsage += " -disablesafemode " + strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0) + "\n"; - strUsage += " -testsafemode " + strprintf(_("Force safe mode (default: %u)"), 0) + "\n"; - strUsage += " -dropmessagestest=<n> " + _("Randomly drop 1 of every <n> network messages") + "\n"; - strUsage += " -fuzzmessagestest=<n> " + _("Randomly fuzz 1 of every <n> network messages") + "\n"; - strUsage += " -flushwallet " + strprintf(_("Run a thread to flush wallet periodically (default: %u)"), 1) + "\n"; - strUsage += " -stopafterblockimport " + strprintf(_("Stop running after importing blocks from disk (default: %u)"), 0) + "\n"; + strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1)); + strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100)); + strUsage += HelpMessageOpt("-disablesafemode", strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0)); + strUsage += HelpMessageOpt("-testsafemode", strprintf(_("Force safe mode (default: %u)"), 0)); + strUsage += HelpMessageOpt("-dropmessagestest=<n>", _("Randomly drop 1 of every <n> network messages")); + strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", _("Randomly fuzz 1 of every <n> network messages")); + strUsage += HelpMessageOpt("-flushwallet", strprintf(_("Run a thread to flush wallet periodically (default: %u)"), 1)); + strUsage += HelpMessageOpt("-stopafterblockimport", strprintf(_("Stop running after importing blocks from disk (default: %u)"), 0)); } - strUsage += " -debug=<category> " + strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + "\n"; - strUsage += " " + _("If <category> is not supplied, output all debugging information.") + "\n"; - strUsage += " " + _("<category> can be:"); - strUsage += " addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below + string debugCategories = "addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below if (mode == HMM_BITCOIN_QT) - strUsage += ", qt"; - strUsage += ".\n"; + debugCategories += ", qt"; + strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " + + _("If <category> is not supplied, output all debugging information.") + _("<category> can be:") + " " + debugCategories + "."); #ifdef ENABLE_WALLET - strUsage += " -gen " + strprintf(_("Generate coins (default: %u)"), 0) + "\n"; - strUsage += " -genproclimit=<n> " + strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1) + "\n"; + strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0)); + strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1)); #endif - strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n"; - strUsage += " -logips " + strprintf(_("Include IP addresses in debug output (default: %u)"), 0) + "\n"; - strUsage += " -logtimestamps " + strprintf(_("Prepend debug output with timestamp (default: %u)"), 1) + "\n"; + strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)")); + strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), 0)); + strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1)); if (GetBoolArg("-help-debug", false)) { - strUsage += " -limitfreerelay=<n> " + strprintf(_("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)"), 15) + "\n"; - strUsage += " -relaypriority " + strprintf(_("Require high priority for relaying free or low-fee transactions (default:%u)"), 1) + "\n"; - strUsage += " -maxsigcachesize=<n> " + strprintf(_("Limit size of signature cache to <n> entries (default: %u)"), 50000) + "\n"; + strUsage += HelpMessageOpt("-limitfreerelay=<n>", strprintf(_("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)"), 15)); + strUsage += HelpMessageOpt("-relaypriority", strprintf(_("Require high priority for relaying free or low-fee transactions (default:%u)"), 1)); + strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf(_("Limit size of signature cache to <n> entries (default: %u)"), 50000)); } - strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n"; - strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; + strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file")); if (GetBoolArg("-help-debug", false)) { - strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n"; - strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n"; - strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; - strUsage += " " + _("This is intended for regression testing tools and app development.") + "\n"; - strUsage += " " + _("In this mode -genproclimit controls how many blocks are generated immediately.") + "\n"; + strUsage += HelpMessageOpt("-printpriority", strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0)); + strUsage += HelpMessageOpt("-privdb", strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1)); + strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + " " + + _("This is intended for regression testing tools and app development.") + " " + + _("In this mode -genproclimit controls how many blocks are generated immediately.")); + } + strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); + strUsage += HelpMessageOpt("-testnet", _("Use the test network")); + + strUsage += HelpMessageGroup(_("Node relay options:")); + strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1)); + strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY)); + + strUsage += HelpMessageGroup(_("Block creation options:")); + strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), 0)); + strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); + strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); + + strUsage += HelpMessageGroup(_("RPC server options:")); + strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands")); + strUsage += HelpMessageOpt("-rest", strprintf(_("Accept public REST requests (default: %u)"), 0)); + strUsage += HelpMessageOpt("-rpcbind=<addr>", _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)")); + strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections")); + strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections")); + strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332)); + strUsage += HelpMessageOpt("-rpcallowip=<ip>", _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times")); + strUsage += HelpMessageOpt("-rpcthreads=<n>", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4)); + strUsage += HelpMessageOpt("-rpckeepalive", strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1)); + + strUsage += HelpMessageGroup(_("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)")); + strUsage += HelpMessageOpt("-rpcssl", _("Use OpenSSL (https) for JSON-RPC connections")); + strUsage += HelpMessageOpt("-rpcsslcertificatechainfile=<file.cert>", strprintf(_("Server certificate file (default: %s)"), "server.cert")); + strUsage += HelpMessageOpt("-rpcsslprivatekeyfile=<file.pem>", strprintf(_("Server private key (default: %s)"), "server.pem")); + strUsage += HelpMessageOpt("-rpcsslciphers=<ciphers>", strprintf(_("Acceptable ciphers (default: %s)"), "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH")); + + if (mode == HMM_BITCOIN_QT) + { + strUsage += HelpMessageGroup(_("UI Options:")); + if (GetBoolArg("-help-debug", false)) { + strUsage += HelpMessageOpt("-allowselfsignedrootcertificates", _("Allow self signed root certificates (default: 0)")); + } + strUsage += HelpMessageOpt("-choosedatadir", _("Choose data directory on startup (default: 0)")); + strUsage += HelpMessageOpt("-lang=<lang>", _("Set language, for example \"de_DE\" (default: system locale)")); + strUsage += HelpMessageOpt("-min", _("Start minimized")); + strUsage += HelpMessageOpt("-rootcertificates=<file>", _("Set SSL root certificates for payment request (default: -system-)")); + strUsage += HelpMessageOpt("-splash", _("Show splash screen on startup (default: 1)")); } - strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n"; - strUsage += " -testnet " + _("Use the test network") + "\n"; - - strUsage += "\n" + _("Node relay options:") + "\n"; - strUsage += " -datacarrier " + strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1) + "\n"; - strUsage += " -datacarriersize " + strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY) + "\n"; - - strUsage += "\n" + _("Block creation options:") + "\n"; - strUsage += " -blockminsize=<n> " + strprintf(_("Set minimum block size in bytes (default: %u)"), 0) + "\n"; - strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n"; - strUsage += " -blockprioritysize=<n> " + strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE) + "\n"; - - strUsage += "\n" + _("RPC server options:") + "\n"; - strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; - strUsage += " -rest " + strprintf(_("Accept public REST requests (default: %u)"), 0) + "\n"; - strUsage += " -rpcbind=<addr> " + _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)") + "\n"; - strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; - strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; - strUsage += " -rpcport=<port> " + strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n"; - strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times") + "\n"; - strUsage += " -rpcthreads=<n> " + strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4) + "\n"; - strUsage += " -rpckeepalive " + strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1) + "\n"; - - strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; - strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; - strUsage += " -rpcsslcertificatechainfile=<file.cert> " + strprintf(_("Server certificate file (default: %s)"), "server.cert") + "\n"; - strUsage += " -rpcsslprivatekeyfile=<file.pem> " + strprintf(_("Server private key (default: %s)"), "server.pem") + "\n"; - strUsage += " -rpcsslciphers=<ciphers> " + strprintf(_("Acceptable ciphers (default: %s)"), "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH") + "\n"; return strUsage; } diff --git a/src/main.cpp b/src/main.cpp index b6a61f7da1..9b4bb43128 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,7 +54,6 @@ bool fTxIndex = false; bool fIsBareMultisigStd = true; unsigned int nCoinCacheSize = 5000; - /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ CFeeRate minRelayTxFee = CFeeRate(1000); @@ -2312,7 +2311,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { BlockMap::iterator it = mapBlockIndex.begin(); while (it != mapBlockIndex.end()) { if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) { - setBlockIndexCandidates.insert(pindex); + setBlockIndexCandidates.insert(it->second); } it++; } @@ -2455,8 +2454,11 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd } nLastBlockFile = nFile; - vinfoBlockFile[nFile].nSize += nAddSize; vinfoBlockFile[nFile].AddBlock(nHeight, nTime); + if (fKnown) + vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize); + else + vinfoBlockFile[nFile].nSize += nAddSize; if (!fKnown) { unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; @@ -2594,8 +2596,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta int nHeight = pindexPrev->nHeight+1; // Check proof of work - if ((!Params().SkipProofOfWorkCheck()) && - (block.nBits != GetNextWorkRequired(pindexPrev, &block))) + if ((block.nBits != GetNextWorkRequired(pindexPrev, &block))) return state.DoS(100, error("%s: incorrect proof of work", __func__), REJECT_INVALID, "bad-diffbits"); @@ -3085,10 +3086,31 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth void UnloadBlockIndex() { - mapBlockIndex.clear(); + LOCK(cs_main); setBlockIndexCandidates.clear(); chainActive.SetTip(NULL); pindexBestInvalid = NULL; + pindexBestHeader = NULL; + mempool.clear(); + mapOrphanTransactions.clear(); + mapOrphanTransactionsByPrev.clear(); + nSyncStarted = 0; + mapBlocksUnlinked.clear(); + vinfoBlockFile.clear(); + nLastBlockFile = 0; + nBlockSequenceId = 1; + mapBlockSource.clear(); + mapBlocksInFlight.clear(); + nQueuedValidatedHeaders = 0; + nPreferredDownload = 0; + setDirtyBlockIndex.clear(); + setDirtyFileInfo.clear(); + mapNodeState.clear(); + + BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) { + delete entry.second; + } + mapBlockIndex.clear(); } bool LoadBlockIndex() @@ -4021,7 +4043,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (strCommand == "getaddr") + // This asymmetric behavior for inbound and outbound connections was introduced + // to prevent a fingerprinting attack: an attacker can send specific fake addresses + // to users' AddrMan and later request them by sending getaddr messages. + // Making users (which are behind NAT and can only make outgoing connections) ignore + // getaddr message mitigates the attack. + else if ((strCommand == "getaddr") && (pfrom->fInbound)) { pfrom->vAddrToSend.clear(); vector<CAddress> vAddr = addrman.GetAddr(); @@ -4305,7 +4332,7 @@ bool ProcessMessages(CNode* pfrom) // Read header CMessageHeader& hdr = msg.hdr; - if (!hdr.IsValid()) + if (!hdr.IsValid(Params().MessageStart())) { LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); continue; @@ -4318,8 +4345,7 @@ bool ProcessMessages(CNode* pfrom) // Checksum CDataStream& vRecv = msg.vRecv; uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize); - unsigned int nChecksum = 0; - memcpy(&nChecksum, &hash, sizeof(nChecksum)); + unsigned int nChecksum = ReadLE32((unsigned char*)&hash); if (nChecksum != hdr.nChecksum) { LogPrintf("ProcessMessages(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", diff --git a/src/net.cpp b/src/net.cpp index 3c3666615e..0723ee218a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -14,6 +14,7 @@ #include "clientversion.h" #include "primitives/transaction.h" #include "ui_interface.h" +#include "crypto/common.h" #ifdef WIN32 #include <string.h> @@ -509,7 +510,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) // get current incomplete message, or create a new one if (vRecvMsg.empty() || vRecvMsg.back().complete()) - vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); + vRecvMsg.push_back(CNetMessage(Params().MessageStart(), SER_NETWORK, nRecvVersion)); CNetMessage& msg = vRecvMsg.back(); @@ -523,6 +524,11 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) if (handled < 0) return false; + if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) { + LogPrint("net", "Oversized message from peer=%i, disconnecting", GetId()); + return false; + } + pch += handled; nBytes -= handled; @@ -1970,7 +1976,7 @@ void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSen { ENTER_CRITICAL_SECTION(cs_vSend); assert(ssSend.size() == 0); - ssSend << CMessageHeader(pszCommand, 0); + ssSend << CMessageHeader(Params().MessageStart(), pszCommand, 0); LogPrint("net", "sending: %s ", SanitizeString(pszCommand)); } @@ -2002,7 +2008,7 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend) // Set the size unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE; - memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize)); + WriteLE32((uint8_t*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], nSize); // Set the checksum uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end()); @@ -46,6 +46,8 @@ static const int TIMEOUT_INTERVAL = 20 * 60; static const unsigned int MAX_INV_SZ = 50000; /** The maximum number of new addresses to accumulate before announcing. */ static const unsigned int MAX_ADDR_TO_SEND = 1000; +/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */ +static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024; /** -listen default */ static const bool DEFAULT_LISTEN = true; /** -upnp default */ @@ -76,12 +78,27 @@ void SocketSendData(CNode *pnode); typedef int NodeId; +struct CombinerAll +{ + typedef bool result_type; + + template<typename I> + bool operator()(I first, I last) const + { + while (first != last) { + if (!(*first)) return false; + ++first; + } + return true; + } +}; + // Signals for message handling struct CNodeSignals { boost::signals2::signal<int ()> GetHeight; - boost::signals2::signal<bool (CNode*)> ProcessMessages; - boost::signals2::signal<bool (CNode*, bool)> SendMessages; + boost::signals2::signal<bool (CNode*), CombinerAll> ProcessMessages; + boost::signals2::signal<bool (CNode*, bool), CombinerAll> SendMessages; boost::signals2::signal<void (NodeId, const CNode*)> InitializeNode; boost::signals2::signal<void (NodeId)> FinalizeNode; }; @@ -183,7 +200,7 @@ public: int64_t nTime; // time (in microseconds) of message receipt. - CNetMessage(int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn) { + CNetMessage(const CMessageHeader::MessageStartChars& pchMessageStartIn, int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), hdr(pchMessageStartIn), vRecv(nTypeIn, nVersionIn) { hdrbuf.resize(24); in_data = false; nHdrPos = 0; diff --git a/src/netbase.h b/src/netbase.h index 5bf13a673f..b42c2dffa4 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -162,7 +162,7 @@ class CService : public CNetAddr inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(FLATDATA(ip)); unsigned short portN = htons(port); - READWRITE(portN); + READWRITE(FLATDATA(portN)); if (ser_action.ForRead()) port = ntohs(portN); } diff --git a/src/pow.cpp b/src/pow.cpp index 6dd5c4c12c..eb899ffc94 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -48,8 +48,13 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead pindexFirst = pindexFirst->pprev; assert(pindexFirst); + return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime()); +} + +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime) +{ // Limit adjustment step - int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); + int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); if (nActualTimespan < Params().TargetTimespan()/4) nActualTimespan = Params().TargetTimespan()/4; @@ -82,9 +87,6 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) bool fOverflow; arith_uint256 bnTarget; - if (Params().SkipProofOfWorkCheck()) - return true; - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range @@ -14,6 +14,7 @@ class uint256; class arith_uint256; unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits); diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 3b4a360395..5b9c13d870 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -8,10 +8,11 @@ #include "hash.h" #include "tinyformat.h" #include "utilstrencodings.h" +#include "crypto/common.h" uint256 CBlockHeader::GetHash() const { - return Hash(BEGIN(nVersion), END(nNonce)); + return SerializeHash(*this); } uint256 CBlock::BuildMerkleTree(bool* fMutated) const diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index fdb8c50a46..6cfd93a9a1 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -25,7 +25,8 @@ public: template <typename Stream, typename Operation> inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(FLATDATA(*this)); + READWRITE(hash); + READWRITE(n); } void SetNull() { hash.SetNull(); n = (uint32_t) -1; } diff --git a/src/protocol.cpp b/src/protocol.cpp index 74ac706d60..568580a595 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -5,7 +5,6 @@ #include "protocol.h" -#include "chainparams.h" #include "util.h" #include "utilstrencodings.h" @@ -21,17 +20,17 @@ static const char* ppszTypeName[] = "filtered block" }; -CMessageHeader::CMessageHeader() +CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn) { - memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); + memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE); memset(pchCommand, 0, sizeof(pchCommand)); nMessageSize = -1; nChecksum = 0; } -CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) +CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn) { - memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); + memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE); memset(pchCommand, 0, sizeof(pchCommand)); strncpy(pchCommand, pszCommand, COMMAND_SIZE); nMessageSize = nMessageSizeIn; @@ -43,10 +42,10 @@ std::string CMessageHeader::GetCommand() const return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE)); } -bool CMessageHeader::IsValid() const +bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const { // Check start string - if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) + if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0) return false; // Check the command string for errors diff --git a/src/protocol.h b/src/protocol.h index f8394ce52f..e838c0d363 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -29,11 +29,13 @@ class CMessageHeader { public: - CMessageHeader(); - CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn); + typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; + + CMessageHeader(const MessageStartChars& pchMessageStartIn); + CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn); std::string GetCommand() const; - bool IsValid() const; + bool IsValid(const MessageStartChars& messageStart) const; ADD_SERIALIZE_METHODS; diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 5c5da6dba0..1ec968ff2b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -151,7 +151,7 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) : // Create actions for the toolbar, menu bar and tray/dock icon // Needs walletFrame to be initialized - createActions(networkStyle); + createActions(); // Create application menu bar createMenuBar(); @@ -243,7 +243,7 @@ BitcoinGUI::~BitcoinGUI() delete rpcConsole; } -void BitcoinGUI::createActions(const NetworkStyle *networkStyle) +void BitcoinGUI::createActions() { QActionGroup *tabGroup = new QActionGroup(this); @@ -340,6 +340,7 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle) openAction->setStatusTip(tr("Open a bitcoin: URI or payment request")); showHelpMessageAction = new QAction(TextColorIcon(":/icons/info"), tr("&Command-line options"), this); + showHelpMessageAction->setMenuRole(QAction::NoRole); showHelpMessageAction->setStatusTip(tr("Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options")); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); @@ -435,8 +436,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) setNumConnections(clientModel->getNumConnections()); connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(clientModel->getNumBlocks()); - connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); + setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate()); + connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime))); // Receive and report messages from client model connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); @@ -652,7 +653,7 @@ void BitcoinGUI::setNumConnections(int count) labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count)); } -void BitcoinGUI::setNumBlocks(int count) +void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate) { if(!clientModel) return; @@ -680,9 +681,8 @@ void BitcoinGUI::setNumBlocks(int count) QString tooltip; - QDateTime lastBlockDate = clientModel->getLastBlockDate(); QDateTime currentDate = QDateTime::currentDateTime(); - qint64 secs = lastBlockDate.secsTo(currentDate); + qint64 secs = blockDate.secsTo(currentDate); tooltip = tr("Processed %n blocks of transaction history.", "", count); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 3216a7398e..5a289a9046 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -118,7 +118,7 @@ private: int spinnerFrame; /** Create the main UI actions. */ - void createActions(const NetworkStyle *networkStyle); + void createActions(); /** Create the menu bar and sub-menus. */ void createMenuBar(); /** Create the toolbars */ @@ -143,8 +143,8 @@ signals: public slots: /** Set number of connections shown in the UI */ void setNumConnections(int count); - /** Set number of blocks shown in the UI */ - void setNumBlocks(int count); + /** Set number of blocks and last block date shown in the UI */ + void setNumBlocks(int count, const QDateTime& blockDate); /** Notify the user of an event from the core network or transaction handling code. @param[in] title the message box / notification title diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 729eb84a18..dc32f81571 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -18,7 +18,6 @@ #include <stdint.h> -#include <QDateTime> #include <QDebug> #include <QTimer> @@ -29,6 +28,7 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : optionsModel(optionsModel), peerTableModel(0), cachedNumBlocks(0), + cachedBlockDate(QDateTime()), cachedReindexing(0), cachedImporting(0), pollTimer(0) @@ -79,10 +79,11 @@ quint64 ClientModel::getTotalBytesSent() const QDateTime ClientModel::getLastBlockDate() const { LOCK(cs_main); + if (chainActive.Tip()) return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); - else - return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network + + return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network } double ClientModel::getVerificationProgress() const @@ -97,21 +98,26 @@ void ClientModel::updateTimer() // periodical polls if the core is holding the locks for a longer time - // for example, during a wallet rescan. TRY_LOCK(cs_main, lockMain); - if(!lockMain) + if (!lockMain) return; + // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change. // Periodically check and update with a timer. int newNumBlocks = getNumBlocks(); + QDateTime newBlockDate = getLastBlockDate(); // check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state if (cachedNumBlocks != newNumBlocks || - cachedReindexing != fReindex || cachedImporting != fImporting) + cachedBlockDate != newBlockDate || + cachedReindexing != fReindex || + cachedImporting != fImporting) { cachedNumBlocks = newNumBlocks; + cachedBlockDate = newBlockDate; cachedReindexing = fReindex; cachedImporting = fImporting; - emit numBlocksChanged(newNumBlocks); + emit numBlocksChanged(newNumBlocks, newBlockDate); } emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 7b74728b26..214701810c 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -6,6 +6,7 @@ #define BITCOIN_QT_CLIENTMODEL_H #include <QObject> +#include <QDateTime> class AddressTableModel; class OptionsModel; @@ -15,7 +16,6 @@ class TransactionTableModel; class CWallet; QT_BEGIN_NAMESPACE -class QDateTime; class QTimer; QT_END_NAMESPACE @@ -73,6 +73,7 @@ private: PeerTableModel *peerTableModel; int cachedNumBlocks; + QDateTime cachedBlockDate; bool cachedReindexing; bool cachedImporting; @@ -83,7 +84,7 @@ private: signals: void numConnectionsChanged(int count); - void numBlocksChanged(int count); + void numBlocksChanged(int count, const QDateTime& blockDate); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 2a13f43ea4..9db0a75971 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -40,6 +40,7 @@ #if BOOST_FILESYSTEM_VERSION >= 3 #include <boost/filesystem/detail/utf8_codecvt_facet.hpp> #endif +#include <boost/scoped_array.hpp> #include <QAbstractItemView> #include <QApplication> @@ -567,12 +568,17 @@ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* t #ifdef WIN32 boost::filesystem::path static StartupShortcutPath() { + if (GetBoolArg("-testnet", false)) + return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (testnet).lnk"; + else if (GetBoolArg("-regtest", false)) + return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (regtest).lnk"; + return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk"; } bool GetStartOnSystemStartup() { - // check for Bitcoin.lnk + // check for Bitcoin*.lnk return boost::filesystem::exists(StartupShortcutPath()); } @@ -588,8 +594,8 @@ bool SetStartOnSystemStartup(bool fAutoStart) // Get a pointer to the IShellLink interface. IShellLink* psl = NULL; HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, - CLSCTX_INPROC_SERVER, IID_IShellLink, - reinterpret_cast<void**>(&psl)); + CLSCTX_INPROC_SERVER, IID_IShellLink, + reinterpret_cast<void**>(&psl)); if (SUCCEEDED(hres)) { @@ -597,20 +603,34 @@ bool SetStartOnSystemStartup(bool fAutoStart) TCHAR pszExePath[MAX_PATH]; GetModuleFileName(NULL, pszExePath, sizeof(pszExePath)); - TCHAR pszArgs[5] = TEXT("-min"); + // Start client minimized + QString strArgs = "-min"; + // Set -testnet /-regtest options + strArgs += QString::fromStdString(strprintf(" -testnet=%d -regtest=%d", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false))); + +#ifdef UNICODE + boost::scoped_array<TCHAR> args(new TCHAR[strArgs.length() + 1]); + // Convert the QString to TCHAR* + strArgs.toWCharArray(args.get()); + // Add missing '\0'-termination to string + args[strArgs.length()] = '\0'; +#endif // Set the path to the shortcut target psl->SetPath(pszExePath); PathRemoveFileSpec(pszExePath); psl->SetWorkingDirectory(pszExePath); psl->SetShowCmd(SW_SHOWMINNOACTIVE); - psl->SetArguments(pszArgs); +#ifndef UNICODE + psl->SetArguments(strArgs.toStdString().c_str()); +#else + psl->SetArguments(args.get()); +#endif // Query IShellLink for the IPersistFile interface for // saving the shortcut in persistent storage. IPersistFile* ppf = NULL; - hres = psl->QueryInterface(IID_IPersistFile, - reinterpret_cast<void**>(&ppf)); + hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf)); if (SUCCEEDED(hres)) { WCHAR pwsz[MAX_PATH]; @@ -630,11 +650,10 @@ bool SetStartOnSystemStartup(bool fAutoStart) } return true; } - #elif defined(Q_OS_LINUX) // Follow the Desktop Application Autostart Spec: -// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html +// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html boost::filesystem::path static GetAutostartDir() { @@ -690,8 +709,13 @@ bool SetStartOnSystemStartup(bool fAutoStart) // Write a bitcoin.desktop file to the autostart directory: optionFile << "[Desktop Entry]\n"; optionFile << "Type=Application\n"; - optionFile << "Name=Bitcoin\n"; - optionFile << "Exec=" << pszExePath << " -min\n"; + if (GetBoolArg("-testnet", false)) + optionFile << "Name=Bitcoin (testnet)\n"; + else if (GetBoolArg("-regtest", false)) + optionFile << "Name=Bitcoin (regtest)\n"; + else + optionFile << "Name=Bitcoin\n"; + optionFile << "Exec=" << pszExePath << strprintf(" -min -testnet=%d -regtest=%d\n", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false)); optionFile << "Terminal=false\n"; optionFile << "Hidden=false\n"; optionFile.close(); diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index a0f3993e69..a342b4bfea 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -38,7 +38,6 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : fProxyIpValid(true) { ui->setupUi(this); - GUIUtil::restoreWindowGeometry("nOptionsDialogWindow", this->size(), this); /* Main elements init */ ui->databaseCache->setMinimum(nMinDbCache); @@ -117,7 +116,6 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : OptionsDialog::~OptionsDialog() { - GUIUtil::saveWindowGeometry("nOptionsDialogWindow", this); delete ui; } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 9f3991c4c5..ccde44fb29 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -293,8 +293,8 @@ void RPCConsole::setClientModel(ClientModel *model) setNumConnections(model->getNumConnections()); connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(model->getNumBlocks()); - connect(model, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); + setNumBlocks(model->getNumBlocks(), model->getLastBlockDate()); + connect(model, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime))); updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); @@ -404,11 +404,10 @@ void RPCConsole::setNumConnections(int count) ui->numberOfConnections->setText(connections); } -void RPCConsole::setNumBlocks(int count) +void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate) { ui->numberOfBlocks->setText(QString::number(count)); - if(clientModel) - ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString()); + ui->lastBlockTime->setText(blockDate.toString()); } void RPCConsole::on_lineEdit_returnPressed() diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index fff5cfbf59..8737be35d1 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -63,8 +63,8 @@ public slots: void message(int category, const QString &message, bool html = false); /** Set number of connections shown in the UI */ void setNumConnections(int count); - /** Set number of blocks shown in the UI */ - void setNumBlocks(int count); + /** Set number of blocks and last block date shown in the UI */ + void setNumBlocks(int count, const QDateTime& blockDate); /** Go forward or back in history */ void browseHistory(int offset); /** Scroll console view to end */ diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 55ca65c8e6..d921fe2e1b 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -121,7 +121,7 @@ void SendCoinsDialog::setClientModel(ClientModel *clientModel) this->clientModel = clientModel; if (clientModel) { - connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(updateSmartFeeLabel())); + connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(updateSmartFeeLabel())); } } diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 63dd6efb52..386cf31d73 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -29,7 +29,6 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : ui(new Ui::HelpMessageDialog) { ui->setupUi(this); - GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this); QString version = tr("Bitcoin Core") + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion()); /* On x86 add a bit specifier to the version so that users can distinguish between @@ -63,13 +62,17 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : ui->helpMessage->setVisible(false); } else { setWindowTitle(tr("Command-line options")); + QString header = tr("Usage:") + "\n" + + " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; QTextCursor cursor(ui->helpMessage->document()); cursor.insertText(version); cursor.insertBlock(); - cursor.insertText(tr("Usage:") + '\n' + - " bitcoin-qt [" + tr("command-line options") + "]\n"); - + cursor.insertText(header); cursor.insertBlock(); + + QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); + text = version + "\n" + header + "\n" + coreOptions; + QTextTableFormat tf; tf.setBorderStyle(QTextFrameFormat::BorderStyle_None); tf.setCellPadding(2); @@ -77,63 +80,29 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : widths << QTextLength(QTextLength::PercentageLength, 35); widths << QTextLength(QTextLength::PercentageLength, 65); tf.setColumnWidthConstraints(widths); - QTextTable *table = cursor.insertTable(2, 2, tf); - QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); - bool first = true; QTextCharFormat bold; bold.setFontWeight(QFont::Bold); - // note that coreOptions is not translated. - foreach (const QString &line, coreOptions.split('\n')) { - if (!first) { - table->appendRows(1); + + foreach (const QString &line, coreOptions.split("\n")) { + if (line.startsWith(" -")) + { + cursor.currentTable()->appendRows(1); + cursor.movePosition(QTextCursor::PreviousCell); cursor.movePosition(QTextCursor::NextRow); + cursor.insertText(line.trimmed()); + cursor.movePosition(QTextCursor::NextCell); + } else if (line.startsWith(" ")) { + cursor.insertText(line.trimmed()+' '); + } else if (line.size() > 0) { + //Title of a group + if (cursor.currentTable()) + cursor.currentTable()->appendRows(1); + cursor.movePosition(QTextCursor::Down); + cursor.insertText(line.trimmed(), bold); + cursor.insertTable(1, 2, tf); } - first = false; - - if (line.startsWith(" ")) { - int index = line.indexOf(' ', 3); - if (index > 0) { - cursor.insertText(line.left(index).trimmed()); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText(line.mid(index).trimmed()); - continue; - } - } - cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor); - table->mergeCells(cursor); - cursor.insertText(line.trimmed(), bold); - } - - table->appendRows(6); - cursor.movePosition(QTextCursor::NextRow); - cursor.insertText(tr("UI options") + ":", bold); - cursor.movePosition(QTextCursor::NextRow); - if (GetBoolArg("-help-debug", false)) { - cursor.insertText("-allowselfsignedrootcertificates"); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText(tr("Allow self signed root certificates (default: 0)")); - cursor.movePosition(QTextCursor::NextCell); } - cursor.insertText("-choosedatadir"); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText(tr("Choose data directory on startup (default: 0)")); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText("-lang=<lang>"); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText(tr("Set language, for example \"de_DE\" (default: system locale)")); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText("-min"); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText(tr("Start minimized")); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText("-rootcertificates=<file>"); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText(tr("Set SSL root certificates for payment request (default: -system-)")); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText("-splash"); - cursor.movePosition(QTextCursor::NextCell); - cursor.insertText(tr("Show splash screen on startup (default: 1)")); ui->helpMessage->moveCursor(QTextCursor::Start); ui->scrollArea->setVisible(false); @@ -143,7 +112,6 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : HelpMessageDialog::~HelpMessageDialog() { - GUIUtil::saveWindowGeometry("nHelpMessageDialogWindow", this); delete ui; } diff --git a/src/script/script.h b/src/script/script.h index 8b36aa2f50..ed456f5c5a 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -14,6 +14,7 @@ #include <string.h> #include <string> #include <vector> +#include "crypto/common.h" static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes @@ -416,14 +417,16 @@ public: else if (b.size() <= 0xffff) { insert(end(), OP_PUSHDATA2); - unsigned short nSize = b.size(); - insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); + uint8_t data[2]; + WriteLE16(data, b.size()); + insert(end(), data, data + sizeof(data)); } else { insert(end(), OP_PUSHDATA4); - unsigned int nSize = b.size(); - insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); + uint8_t data[4]; + WriteLE32(data, b.size()); + insert(end(), data, data + sizeof(data)); } insert(end(), b.begin(), b.end()); return *this; @@ -496,15 +499,14 @@ public: { if (end() - pc < 2) return false; - nSize = 0; - memcpy(&nSize, &pc[0], 2); + nSize = ReadLE16(&pc[0]); pc += 2; } else if (opcode == OP_PUSHDATA4) { if (end() - pc < 4) return false; - memcpy(&nSize, &pc[0], 4); + nSize = ReadLE32(&pc[0]); pc += 4; } if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize) diff --git a/src/serialize.h b/src/serialize.h index a62760a793..741f78f8b4 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -18,6 +18,8 @@ #include <utility> #include <vector> +#include "compat/endian.h" + class CScript; static const unsigned int MAX_SIZE = 0x02000000; @@ -71,6 +73,79 @@ inline const T* end_ptr(const std::vector<T,TAl>& v) return v.empty() ? NULL : (&v[0] + v.size()); } +/* + * Lowest-level serialization and conversion. + * @note Sizes of these types are verified in the tests + */ +template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj) +{ + s.write((char*)&obj, 1); +} +template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj) +{ + obj = htole16(obj); + s.write((char*)&obj, 2); +} +template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj) +{ + obj = htole32(obj); + s.write((char*)&obj, 4); +} +template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj) +{ + obj = htole64(obj); + s.write((char*)&obj, 8); +} +template<typename Stream> inline uint8_t ser_readdata8(Stream &s) +{ + uint8_t obj; + s.read((char*)&obj, 1); + return obj; +} +template<typename Stream> inline uint16_t ser_readdata16(Stream &s) +{ + uint16_t obj; + s.read((char*)&obj, 2); + return le16toh(obj); +} +template<typename Stream> inline uint32_t ser_readdata32(Stream &s) +{ + uint32_t obj; + s.read((char*)&obj, 4); + return le32toh(obj); +} +template<typename Stream> inline uint64_t ser_readdata64(Stream &s) +{ + uint64_t obj; + s.read((char*)&obj, 8); + return le64toh(obj); +} +inline uint64_t ser_double_to_uint64(double x) +{ + union { double x; uint64_t y; } tmp; + tmp.x = x; + return tmp.y; +} +inline uint32_t ser_float_to_uint32(float x) +{ + union { float x; uint32_t y; } tmp; + tmp.x = x; + return tmp.y; +} +inline double ser_uint64_to_double(uint64_t y) +{ + union { double x; uint64_t y; } tmp; + tmp.y = y; + return tmp.x; +} +inline float ser_uint32_to_float(uint32_t y) +{ + union { float x; uint32_t y; } tmp; + tmp.y = y; + return tmp.x; +} + + ///////////////////////////////////////////////////////////////// // // Templates for serializing to anything that looks like a stream, @@ -108,59 +183,48 @@ enum SerializationOp(s, CSerActionUnserialize(), nType, nVersion); \ } - - /* * Basic Types */ -#define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj)) -#define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj)) - -inline unsigned int GetSerializeSize(char a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed char a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned char a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed short a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed int a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned int a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed long a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned long a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed long long a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned long long a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(float a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(double a, int, int=0) { return sizeof(a); } - -template<typename Stream> inline void Serialize(Stream& s, char a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, signed char a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, unsigned char a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, signed short a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, signed int a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, unsigned int a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, signed long a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, unsigned long a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, signed long long a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, unsigned long long a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, float a, int, int=0) { WRITEDATA(s, a); } -template<typename Stream> inline void Serialize(Stream& s, double a, int, int=0) { WRITEDATA(s, a); } - -template<typename Stream> inline void Unserialize(Stream& s, char& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, signed char& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, signed short& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, signed int& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, signed long& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, signed long long& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, unsigned long long& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, float& a, int, int=0) { READDATA(s, a); } -template<typename Stream> inline void Unserialize(Stream& s, double& a, int, int=0) { READDATA(s, a); } +inline unsigned int GetSerializeSize(char a, int, int=0) { return 1; } +inline unsigned int GetSerializeSize(int8_t a, int, int=0) { return 1; } +inline unsigned int GetSerializeSize(uint8_t a, int, int=0) { return 1; } +inline unsigned int GetSerializeSize(int16_t a, int, int=0) { return 2; } +inline unsigned int GetSerializeSize(uint16_t a, int, int=0) { return 2; } +inline unsigned int GetSerializeSize(int32_t a, int, int=0) { return 4; } +inline unsigned int GetSerializeSize(uint32_t a, int, int=0) { return 4; } +inline unsigned int GetSerializeSize(int64_t a, int, int=0) { return 8; } +inline unsigned int GetSerializeSize(uint64_t a, int, int=0) { return 8; } +inline unsigned int GetSerializeSize(float a, int, int=0) { return 4; } +inline unsigned int GetSerializeSize(double a, int, int=0) { return 8; } + +template<typename Stream> inline void Serialize(Stream& s, char a, int, int=0) { ser_writedata8(s, a); } // TODO Get rid of bare char +template<typename Stream> inline void Serialize(Stream& s, int8_t a, int, int=0) { ser_writedata8(s, a); } +template<typename Stream> inline void Serialize(Stream& s, uint8_t a, int, int=0) { ser_writedata8(s, a); } +template<typename Stream> inline void Serialize(Stream& s, int16_t a, int, int=0) { ser_writedata16(s, a); } +template<typename Stream> inline void Serialize(Stream& s, uint16_t a, int, int=0) { ser_writedata16(s, a); } +template<typename Stream> inline void Serialize(Stream& s, int32_t a, int, int=0) { ser_writedata32(s, a); } +template<typename Stream> inline void Serialize(Stream& s, uint32_t a, int, int=0) { ser_writedata32(s, a); } +template<typename Stream> inline void Serialize(Stream& s, int64_t a, int, int=0) { ser_writedata64(s, a); } +template<typename Stream> inline void Serialize(Stream& s, uint64_t a, int, int=0) { ser_writedata64(s, a); } +template<typename Stream> inline void Serialize(Stream& s, float a, int, int=0) { ser_writedata32(s, ser_float_to_uint32(a)); } +template<typename Stream> inline void Serialize(Stream& s, double a, int, int=0) { ser_writedata64(s, ser_double_to_uint64(a)); } + +template<typename Stream> inline void Unserialize(Stream& s, char& a, int, int=0) { a = ser_readdata8(s); } // TODO Get rid of bare char +template<typename Stream> inline void Unserialize(Stream& s, int8_t& a, int, int=0) { a = ser_readdata8(s); } +template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a, int, int=0) { a = ser_readdata8(s); } +template<typename Stream> inline void Unserialize(Stream& s, int16_t& a, int, int=0) { a = ser_readdata16(s); } +template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a, int, int=0) { a = ser_readdata16(s); } +template<typename Stream> inline void Unserialize(Stream& s, int32_t& a, int, int=0) { a = ser_readdata32(s); } +template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a, int, int=0) { a = ser_readdata32(s); } +template<typename Stream> inline void Unserialize(Stream& s, int64_t& a, int, int=0) { a = ser_readdata64(s); } +template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a, int, int=0) { a = ser_readdata64(s); } +template<typename Stream> inline void Unserialize(Stream& s, float& a, int, int=0) { a = ser_uint32_to_float(ser_readdata32(s)); } +template<typename Stream> inline void Unserialize(Stream& s, double& a, int, int=0) { a = ser_uint64_to_double(ser_readdata64(s)); } inline unsigned int GetSerializeSize(bool a, int, int=0) { return sizeof(char); } -template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; WRITEDATA(s, f); } -template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; } +template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; ser_writedata8(s, f); } +template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f=ser_readdata8(s); a=f; } @@ -187,29 +251,22 @@ void WriteCompactSize(Stream& os, uint64_t nSize) { if (nSize < 253) { - unsigned char chSize = nSize; - WRITEDATA(os, chSize); + ser_writedata8(os, nSize); } else if (nSize <= std::numeric_limits<unsigned short>::max()) { - unsigned char chSize = 253; - unsigned short xSize = nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); + ser_writedata8(os, 253); + ser_writedata16(os, nSize); } else if (nSize <= std::numeric_limits<unsigned int>::max()) { - unsigned char chSize = 254; - unsigned int xSize = nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); + ser_writedata8(os, 254); + ser_writedata32(os, nSize); } else { - unsigned char chSize = 255; - uint64_t xSize = nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); + ser_writedata8(os, 255); + ser_writedata64(os, nSize); } return; } @@ -217,8 +274,7 @@ void WriteCompactSize(Stream& os, uint64_t nSize) template<typename Stream> uint64_t ReadCompactSize(Stream& is) { - unsigned char chSize; - READDATA(is, chSize); + uint8_t chSize = ser_readdata8(is); uint64_t nSizeRet = 0; if (chSize < 253) { @@ -226,25 +282,19 @@ uint64_t ReadCompactSize(Stream& is) } else if (chSize == 253) { - unsigned short xSize; - READDATA(is, xSize); - nSizeRet = xSize; + nSizeRet = ser_readdata16(is); if (nSizeRet < 253) throw std::ios_base::failure("non-canonical ReadCompactSize()"); } else if (chSize == 254) { - unsigned int xSize; - READDATA(is, xSize); - nSizeRet = xSize; + nSizeRet = ser_readdata32(is); if (nSizeRet < 0x10000u) throw std::ios_base::failure("non-canonical ReadCompactSize()"); } else { - uint64_t xSize; - READDATA(is, xSize); - nSizeRet = xSize; + nSizeRet = ser_readdata64(is); if (nSizeRet < 0x100000000ULL) throw std::ios_base::failure("non-canonical ReadCompactSize()"); } @@ -303,7 +353,7 @@ void WriteVarInt(Stream& os, I n) len++; } do { - WRITEDATA(os, tmp[len]); + ser_writedata8(os, tmp[len]); } while(len--); } @@ -312,8 +362,7 @@ I ReadVarInt(Stream& is) { I n = 0; while(true) { - unsigned char chData; - READDATA(is, chData); + unsigned char chData = ser_readdata8(is); n = (n << 7) | (chData & 0x7F); if (chData & 0x80) n++; diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp index a9b6cd44a8..c3125d76dc 100644 --- a/src/test/Checkpoints_tests.cpp +++ b/src/test/Checkpoints_tests.cpp @@ -9,12 +9,13 @@ #include "checkpoints.h" #include "uint256.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> using namespace std; -BOOST_AUTO_TEST_SUITE(Checkpoints_tests) +BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sanity) { diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 9407511ecb..bf25548755 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -16,6 +16,8 @@ #include "serialize.h" #include "util.h" +#include "test/test_bitcoin.h" + #include <stdint.h> #include <boost/assign/list_of.hpp> // for 'map_list_of()' @@ -41,7 +43,7 @@ CService ip(uint32_t i) return CService(CNetAddr(s), Params().GetDefaultPort()); } -BOOST_AUTO_TEST_SUITE(DoS_tests) +BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup) BOOST_AUTO_TEST_CASE(DoS_banning) { diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index da07b8c7a6..36499f01a7 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -5,6 +5,8 @@ #include "wallet.h" #include "walletdb.h" +#include "test/test_bitcoin.h" + #include <stdint.h> #include <boost/foreach.hpp> @@ -12,7 +14,7 @@ extern CWallet* pwalletMain; -BOOST_AUTO_TEST_SUITE(accounting_tests) +BOOST_FIXTURE_TEST_SUITE(accounting_tests, TestingSetup) static void GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results) diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index efc9211717..5e1f5f0294 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -15,6 +15,8 @@ #include "util.h" #include "utilstrencodings.h" +#include "test/test_bitcoin.h" + #include <fstream> #include <boost/filesystem/operations.hpp> @@ -78,7 +80,7 @@ } #endif -struct ReadAlerts +struct ReadAlerts : public TestingSetup { ReadAlerts() { diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 991b4ac099..d4df7b5415 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -5,10 +5,11 @@ #include "util.h" #include "allocators.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(allocator_tests) +BOOST_FIXTURE_TEST_SUITE(allocator_tests, BasicTestingSetup) // Dummy memory page locker for platform independent tests static const void *last_lock_addr, *last_unlock_addr; diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 565b02ae64..17d6bed6d2 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -12,8 +12,9 @@ #include "arith_uint256.h" #include <string> #include "version.h" +#include "test/test_bitcoin.h" -BOOST_AUTO_TEST_SUITE(arith_uint256_tests) +BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup) /// Convert vector to arith_uint256, via uint256 blob inline arith_uint256 arith_uint256V(const std::vector<unsigned char>& vch) diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 5d20a90ad0..8ec8861425 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -3,10 +3,11 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "utilstrencodings.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(base32_tests) +BOOST_FIXTURE_TEST_SUITE(base32_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(base32_testvectors) { diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index e7d0281881..f07dd7a7db 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -13,6 +13,7 @@ #include "uint256.h" #include "util.h" #include "utilstrencodings.h" +#include "test/test_bitcoin.h" #include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> @@ -23,7 +24,7 @@ using namespace json_spirit; extern Array read_json(const std::string& jsondata); -BOOST_AUTO_TEST_SUITE(base58_tests) +BOOST_FIXTURE_TEST_SUITE(base58_tests, BasicTestingSetup) // Goal: test low-level base58 encoding functionality BOOST_AUTO_TEST_CASE(base58_EncodeBase58) @@ -127,6 +128,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) std::vector<unsigned char> result; CBitcoinSecret secret; CBitcoinAddress addr; + SelectParams(CBaseChainParams::MAIN); BOOST_FOREACH(Value& tv, tests) { @@ -176,7 +178,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); } } - SelectParams(CBaseChainParams::UNITTEST); } // Goal: check that generated keys match test vectors @@ -244,7 +245,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) CTxDestination nodest = CNoDestination(); BOOST_CHECK(!dummyAddr.Set(nodest)); - SelectParams(CBaseChainParams::UNITTEST); + SelectParams(CBaseChainParams::MAIN); } // Goal: check that base58 parsing code is robust against a variety of corrupted data diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 9e6cb342cc..54c081b0ef 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -3,10 +3,11 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "utilstrencodings.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(base64_tests) +BOOST_FIXTURE_TEST_SUITE(base64_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(base64_testvectors) { diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 3d28e06ffc..d738851c1f 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -8,6 +8,7 @@ #include "key.h" #include "uint256.h" #include "util.h" +#include "test/test_bitcoin.h" #include <string> #include <vector> @@ -107,7 +108,7 @@ void RunTest(const TestVector &test) { } } -BOOST_AUTO_TEST_SUITE(bip32_tests) +BOOST_FIXTURE_TEST_SUITE(bip32_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(bip32_test1) { RunTest(test1); diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 64d9909b98..73a146f05c 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -13,6 +13,7 @@ #include "uint256.h" #include "util.h" #include "utilstrencodings.h" +#include "test/test_bitcoin.h" #include <vector> @@ -21,7 +22,7 @@ using namespace std; -BOOST_AUTO_TEST_SUITE(bloom_tests) +BOOST_FIXTURE_TEST_SUITE(bloom_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize) { diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp index a4121caa8b..7abfad151e 100644 --- a/src/test/checkblock_tests.cpp +++ b/src/test/checkblock_tests.cpp @@ -11,6 +11,7 @@ #include "clientversion.h" #include "main.h" #include "utiltime.h" +#include "test/test_bitcoin.h" #include <cstdio> @@ -19,7 +20,7 @@ #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(CheckBlock_tests) +BOOST_FIXTURE_TEST_SUITE(CheckBlock_tests, BasicTestingSetup) bool read_block(const std::string& filename, CBlock& block) { diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 3ecd301bc7..2e2cc2214b 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -5,6 +5,7 @@ #include "coins.h" #include "random.h" #include "uint256.h" +#include "test/test_bitcoin.h" #include <vector> #include <map> @@ -60,7 +61,7 @@ public: }; } -BOOST_AUTO_TEST_SUITE(coins_tests) +BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) static const unsigned int NUM_SIMULATION_ITERATIONS = 40000; diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index b4e4f2046f..376ae93681 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -4,6 +4,7 @@ #include "compressor.h" #include "util.h" +#include "test/test_bitcoin.h" #include <stdint.h> @@ -21,7 +22,7 @@ // amounts 50 .. 21000000 #define NUM_MULTIPLES_50BTC 420000 -BOOST_AUTO_TEST_SUITE(compress_tests) +BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup) bool static TestEncode(uint64_t in) { return in == CTxOutCompressor::DecompressAmount(CTxOutCompressor::CompressAmount(in)); diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index d5e595cd8a..aeb2a5caa3 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -10,13 +10,14 @@ #include "crypto/hmac_sha512.h" #include "random.h" #include "utilstrencodings.h" +#include "test/test_bitcoin.h" #include <vector> #include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(crypto_tests) +BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup) template<typename Hasher, typename In, typename Out> void TestVector(const Hasher &h, const In &in, const Out &out) { diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 5fb0f4ccdd..a0c5592a95 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "util.h" +#include "test/test_bitcoin.h" #include <string> #include <vector> @@ -11,7 +12,7 @@ #include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(getarg_tests) +BOOST_FIXTURE_TEST_SUITE(getarg_tests, BasicTestingSetup) static void ResetArgs(const std::string& strArg) { diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index f1ad25e6ee..e5d2e5a439 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -4,6 +4,7 @@ #include "hash.h" #include "utilstrencodings.h" +#include "test/test_bitcoin.h" #include <vector> @@ -11,7 +12,7 @@ using namespace std; -BOOST_AUTO_TEST_SUITE(hash_tests) +BOOST_FIXTURE_TEST_SUITE(hash_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(murmurhash3) { diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 1333aba471..13ca949469 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -9,6 +9,7 @@ #include "uint256.h" #include "util.h" #include "utilstrencodings.h" +#include "test/test_bitcoin.h" #include <string> #include <vector> @@ -58,7 +59,7 @@ void dumpKeyInfo(uint256 privkey) #endif -BOOST_AUTO_TEST_SUITE(key_tests) +BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(key_test1) { diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 2a72a220a4..9ec533bcca 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -5,9 +5,11 @@ #include "primitives/transaction.h" #include "main.h" +#include "test/test_bitcoin.h" + #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(main_tests) +BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup) BOOST_AUTO_TEST_CASE(subsidy_limit_test) { @@ -21,4 +23,21 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test) BOOST_CHECK(nSum == 2099999997690000ULL); } +bool ReturnFalse() { return false; } +bool ReturnTrue() { return true; } + +BOOST_AUTO_TEST_CASE(test_combiner_all) +{ + boost::signals2::signal<bool (), CombinerAll> Test; + BOOST_CHECK(Test()); + Test.connect(&ReturnFalse); + BOOST_CHECK(!Test()); + Test.connect(&ReturnTrue); + BOOST_CHECK(!Test()); + Test.disconnect(&ReturnFalse); + BOOST_CHECK(Test()); + Test.disconnect(&ReturnTrue); + BOOST_CHECK(Test()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 44c57a8eaf..6ab9cb8a44 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -8,9 +8,11 @@ #include "uint256.h" #include "util.h" +#include "test/test_bitcoin.h" + #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(miner_tests) +BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup) static struct { diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp index 813ec9b8b2..bd4e9c1d38 100644 --- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -6,6 +6,7 @@ #include "random.h" #include "util.h" +#include "test/test_bitcoin.h" #include <set> @@ -34,7 +35,7 @@ public: } }; -BOOST_AUTO_TEST_SUITE(mruset_tests) +BOOST_FIXTURE_TEST_SUITE(mruset_tests, BasicTestingSetup) // Test that an mruset behaves like a set, as long as no more than MAX_SIZE elements are in it BOOST_AUTO_TEST_CASE(mruset_like_set) diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 2168a5fef1..054bc3b37b 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -10,6 +10,7 @@ #include "script/interpreter.h" #include "script/sign.h" #include "uint256.h" +#include "test/test_bitcoin.h" #ifdef ENABLE_WALLET #include "wallet_ismine.h" @@ -22,7 +23,7 @@ using namespace std; typedef vector<unsigned char> valtype; -BOOST_AUTO_TEST_SUITE(multisig_tests) +BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup) CScript sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn) diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 9361459949..cb357d295c 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "netbase.h" +#include "test/test_bitcoin.h" #include <string> @@ -10,7 +11,7 @@ using namespace std; -BOOST_AUTO_TEST_SUITE(netbase_tests) +BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(netbase_networks) { diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 4406b08e56..f6d06d6805 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -9,6 +9,7 @@ #include "arith_uint256.h" #include "version.h" #include "random.h" +#include "test/test_bitcoin.h" #include <vector> @@ -28,7 +29,7 @@ public: } }; -BOOST_AUTO_TEST_SUITE(pmt_tests) +BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(pmt_test1) { diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp new file mode 100644 index 0000000000..7b197c527d --- /dev/null +++ b/src/test/pow_tests.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "main.h" +#include "pow.h" +#include "util.h" +#include "test/test_bitcoin.h" + +#include <boost/test/unit_test.hpp> + +using namespace std; + +BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup) + +/* Test calculation of next difficulty target with no constraints applying */ +BOOST_AUTO_TEST_CASE(get_next_work) +{ + SelectParams(CBaseChainParams::MAIN); + + int64_t nLastRetargetTime = 1261130161; // Block #30240 + CBlockIndex pindexLast; + pindexLast.nHeight = 32255; + pindexLast.nTime = 1262152739; // Block #32255 + pindexLast.nBits = 0x1d00ffff; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00d86a); +} + +/* Test the constraint on the upper bound for next work */ +BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) +{ + SelectParams(CBaseChainParams::MAIN); + + int64_t nLastRetargetTime = 1231006505; // Block #0 + CBlockIndex pindexLast; + pindexLast.nHeight = 2015; + pindexLast.nTime = 1233061996; // Block #2015 + pindexLast.nBits = 0x1d00ffff; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00ffff); +} + +/* Test the constraint on the lower bound for actual time taken */ +BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) +{ + SelectParams(CBaseChainParams::MAIN); + + int64_t nLastRetargetTime = 1279008237; // Block #66528 + CBlockIndex pindexLast; + pindexLast.nHeight = 68543; + pindexLast.nTime = 1279297671; // Block #68543 + pindexLast.nBits = 0x1c05a3f4; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1c0168fd); +} + +/* Test the constraint on the upper bound for actual time taken */ +BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) +{ + SelectParams(CBaseChainParams::MAIN); + int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time + CBlockIndex pindexLast; + pindexLast.nHeight = 46367; + pindexLast.nTime = 1269211443; // Block #46367 + pindexLast.nBits = 0x1c387f6f; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00e1fd); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 1c6963001f..45cb551d04 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -8,6 +8,8 @@ #include "base58.h" #include "netbase.h" +#include "test/test_bitcoin.h" + #include <boost/algorithm/string.hpp> #include <boost/test/unit_test.hpp> @@ -45,7 +47,7 @@ Value CallRPC(string args) } -BOOST_AUTO_TEST_SUITE(rpc_tests) +BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup) BOOST_AUTO_TEST_CASE(rpc_rawparams) { diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 57c49c2dfc..44475076b3 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -8,6 +8,8 @@ #include "base58.h" #include "wallet.h" +#include "test/test_bitcoin.h" + #include <boost/algorithm/string.hpp> #include <boost/test/unit_test.hpp> @@ -19,7 +21,7 @@ extern Value CallRPC(string args); extern CWallet* pwalletMain; -BOOST_AUTO_TEST_SUITE(rpc_wallet_tests) +BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup) BOOST_AUTO_TEST_CASE(rpc_addmultisig) { diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index 464a8fbb8c..f5f7f381d3 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -4,9 +4,11 @@ #include "compat/sanity.h" #include "key.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> -BOOST_AUTO_TEST_SUITE(sanity_tests) + +BOOST_FIXTURE_TEST_SUITE(sanity_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(basic_sanity) { diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 94f2ce1a29..52171b9e3c 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -8,6 +8,7 @@ #include "script/script.h" #include "script/script_error.h" #include "script/sign.h" +#include "test/test_bitcoin.h" #ifdef ENABLE_WALLET #include "wallet_ismine.h" @@ -47,7 +48,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri } -BOOST_AUTO_TEST_SUITE(script_P2SH_tests) +BOOST_FIXTURE_TEST_SUITE(script_P2SH_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sign) { diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index e410b59710..c0614cca43 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -13,6 +13,7 @@ #include "script/script_error.h" #include "script/sign.h" #include "util.h" +#include "test/test_bitcoin.h" #if defined(HAVE_CONSENSUS_LIB) #include "script/bitcoinconsensus.h" @@ -53,7 +54,7 @@ read_json(const std::string& jsondata) return v.get_array(); } -BOOST_AUTO_TEST_SUITE(script_tests) +BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup) CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) { diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index cfbaf26e70..24c7dd3d5a 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -4,10 +4,13 @@ #include "bignum.h" #include "script/script.h" +#include "test/test_bitcoin.h" + #include <boost/test/unit_test.hpp> #include <limits.h> #include <stdint.h> -BOOST_AUTO_TEST_SUITE(scriptnum_tests) + +BOOST_FIXTURE_TEST_SUITE(scriptnum_tests, BasicTestingSetup) static const int64_t values[] = \ { 0, 1, CHAR_MIN, CHAR_MAX, UCHAR_MAX, SHRT_MIN, USHRT_MAX, INT_MIN, INT_MAX, UINT_MAX, LONG_MIN, LONG_MAX }; diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index fe49af711b..cc8f2b788d 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -4,6 +4,8 @@ #include "serialize.h" #include "streams.h" +#include "hash.h" +#include "test/test_bitcoin.h" #include <stdint.h> @@ -11,7 +13,120 @@ using namespace std; -BOOST_AUTO_TEST_SUITE(serialize_tests) +BOOST_FIXTURE_TEST_SUITE(serialize_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(sizes) +{ + BOOST_CHECK_EQUAL(sizeof(char), GetSerializeSize(char(0), 0)); + BOOST_CHECK_EQUAL(sizeof(int8_t), GetSerializeSize(int8_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(uint8_t), GetSerializeSize(uint8_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(int16_t), GetSerializeSize(int16_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(uint16_t), GetSerializeSize(uint16_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(int32_t), GetSerializeSize(int32_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(uint32_t), GetSerializeSize(uint32_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(int64_t), GetSerializeSize(int64_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(uint64_t), GetSerializeSize(uint64_t(0), 0)); + BOOST_CHECK_EQUAL(sizeof(float), GetSerializeSize(float(0), 0)); + BOOST_CHECK_EQUAL(sizeof(double), GetSerializeSize(double(0), 0)); + // Bool is serialized as char + BOOST_CHECK_EQUAL(sizeof(char), GetSerializeSize(bool(0), 0)); + + // Sanity-check GetSerializeSize and c++ type matching + BOOST_CHECK_EQUAL(GetSerializeSize(char(0), 0), 1); + BOOST_CHECK_EQUAL(GetSerializeSize(int8_t(0), 0), 1); + BOOST_CHECK_EQUAL(GetSerializeSize(uint8_t(0), 0), 1); + BOOST_CHECK_EQUAL(GetSerializeSize(int16_t(0), 0), 2); + BOOST_CHECK_EQUAL(GetSerializeSize(uint16_t(0), 0), 2); + BOOST_CHECK_EQUAL(GetSerializeSize(int32_t(0), 0), 4); + BOOST_CHECK_EQUAL(GetSerializeSize(uint32_t(0), 0), 4); + BOOST_CHECK_EQUAL(GetSerializeSize(int64_t(0), 0), 8); + BOOST_CHECK_EQUAL(GetSerializeSize(uint64_t(0), 0), 8); + BOOST_CHECK_EQUAL(GetSerializeSize(float(0), 0), 4); + BOOST_CHECK_EQUAL(GetSerializeSize(double(0), 0), 8); + BOOST_CHECK_EQUAL(GetSerializeSize(bool(0), 0), 1); +} + +BOOST_AUTO_TEST_CASE(floats_conversion) +{ + // Choose values that map unambigiously to binary floating point to avoid + // rounding issues at the compiler side. + BOOST_CHECK_EQUAL(ser_uint32_to_float(0x00000000), 0.0F); + BOOST_CHECK_EQUAL(ser_uint32_to_float(0x3f000000), 0.5F); + BOOST_CHECK_EQUAL(ser_uint32_to_float(0x3f800000), 1.0F); + BOOST_CHECK_EQUAL(ser_uint32_to_float(0x40000000), 2.0F); + BOOST_CHECK_EQUAL(ser_uint32_to_float(0x40800000), 4.0F); + BOOST_CHECK_EQUAL(ser_uint32_to_float(0x44444444), 785.066650390625F); + + BOOST_CHECK_EQUAL(ser_float_to_uint32(0.0F), 0x00000000); + BOOST_CHECK_EQUAL(ser_float_to_uint32(0.5F), 0x3f000000); + BOOST_CHECK_EQUAL(ser_float_to_uint32(1.0F), 0x3f800000); + BOOST_CHECK_EQUAL(ser_float_to_uint32(2.0F), 0x40000000); + BOOST_CHECK_EQUAL(ser_float_to_uint32(4.0F), 0x40800000); + BOOST_CHECK_EQUAL(ser_float_to_uint32(785.066650390625F), 0x44444444); +} + +BOOST_AUTO_TEST_CASE(doubles_conversion) +{ + // Choose values that map unambigiously to binary floating point to avoid + // rounding issues at the compiler side. + BOOST_CHECK_EQUAL(ser_uint64_to_double(0x0000000000000000ULL), 0.0); + BOOST_CHECK_EQUAL(ser_uint64_to_double(0x3fe0000000000000ULL), 0.5); + BOOST_CHECK_EQUAL(ser_uint64_to_double(0x3ff0000000000000ULL), 1.0); + BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4000000000000000ULL), 2.0); + BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4010000000000000ULL), 4.0); + BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4088888880000000ULL), 785.066650390625); + + BOOST_CHECK_EQUAL(ser_double_to_uint64(0.0), 0x0000000000000000ULL); + BOOST_CHECK_EQUAL(ser_double_to_uint64(0.5), 0x3fe0000000000000ULL); + BOOST_CHECK_EQUAL(ser_double_to_uint64(1.0), 0x3ff0000000000000ULL); + BOOST_CHECK_EQUAL(ser_double_to_uint64(2.0), 0x4000000000000000ULL); + BOOST_CHECK_EQUAL(ser_double_to_uint64(4.0), 0x4010000000000000ULL); + BOOST_CHECK_EQUAL(ser_double_to_uint64(785.066650390625), 0x4088888880000000ULL); +} +/* +Python code to generate the below hashes: + + def reversed_hex(x): + return binascii.hexlify(''.join(reversed(x))) + def dsha256(x): + return hashlib.sha256(hashlib.sha256(x).digest()).digest() + + reversed_hex(dsha256(''.join(struct.pack('<f', x) for x in range(0,1000)))) == '8e8b4cf3e4df8b332057e3e23af42ebc663b61e0495d5e7e32d85099d7f3fe0c' + reversed_hex(dsha256(''.join(struct.pack('<d', x) for x in range(0,1000)))) == '43d0c82591953c4eafe114590d392676a01585d25b25d433557f0d7878b23f96' +*/ +BOOST_AUTO_TEST_CASE(floats) +{ + CDataStream ss(SER_DISK, 0); + // encode + for (int i = 0; i < 1000; i++) { + ss << float(i); + } + BOOST_CHECK(Hash(ss.begin(), ss.end()) == uint256S("8e8b4cf3e4df8b332057e3e23af42ebc663b61e0495d5e7e32d85099d7f3fe0c")); + + // decode + for (int i = 0; i < 1000; i++) { + float j; + ss >> j; + BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i); + } +} + +BOOST_AUTO_TEST_CASE(doubles) +{ + CDataStream ss(SER_DISK, 0); + // encode + for (int i = 0; i < 1000; i++) { + ss << double(i); + } + BOOST_CHECK(Hash(ss.begin(), ss.end()) == uint256S("43d0c82591953c4eafe114590d392676a01585d25b25d433557f0d7878b23f96")); + + // decode + for (int i = 0; i < 1000; i++) { + double j; + ss >> j; + BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i); + } +} BOOST_AUTO_TEST_CASE(varints) { diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index ea41dbcde2..afb7a41bbd 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -10,6 +10,7 @@ #include "script/interpreter.h" #include "util.h" #include "version.h" +#include "test/test_bitcoin.h" #include <iostream> @@ -115,7 +116,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { } } -BOOST_AUTO_TEST_SUITE(sighash_tests) +BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sighash_test) { diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 3c8264d89d..b26fed99f2 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -7,6 +7,7 @@ #include "script/script.h" #include "script/standard.h" #include "uint256.h" +#include "test/test_bitcoin.h" #include <vector> @@ -23,7 +24,7 @@ Serialize(const CScript& s) return sSerialized; } -BOOST_AUTO_TEST_SUITE(sigopcount_tests) +BOOST_FIXTURE_TEST_SUITE(sigopcount_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(GetSigOpCount) { diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index c75e21a2ad..86a4bc6727 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -5,6 +5,7 @@ #include "main.h" #include "random.h" #include "util.h" +#include "test/test_bitcoin.h" #include <vector> @@ -12,7 +13,7 @@ #define SKIPLIST_LENGTH 300000 -BOOST_AUTO_TEST_SUITE(skiplist_tests) +BOOST_FIXTURE_TEST_SUITE(skiplist_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(skiplist_test) { diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index f2dae99d69..48e49ed757 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -4,6 +4,8 @@ #define BOOST_TEST_MODULE Bitcoin Test Suite +#include "test_bitcoin.h" + #include "main.h" #include "random.h" #include "txdb.h" @@ -24,18 +26,21 @@ CWallet* pwalletMain; extern bool fPrintToConsole; extern void noui_connect(); -struct TestingSetup { - CCoinsViewDB *pcoinsdbview; - boost::filesystem::path pathTemp; - boost::thread_group threadGroup; - - TestingSetup() { +BasicTestingSetup::BasicTestingSetup() +{ fPrintToDebugLog = false; // don't want to write to debug.log file - SelectParams(CBaseChainParams::UNITTEST); - noui_connect(); + SelectParams(CBaseChainParams::MAIN); +} +BasicTestingSetup::~BasicTestingSetup() +{ +} + +TestingSetup::TestingSetup() +{ #ifdef ENABLE_WALLET bitdb.MakeMock(); #endif + ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); boost::filesystem::create_directories(pathTemp); mapArgs["-datadir"] = pathTemp.string(); @@ -53,27 +58,28 @@ struct TestingSetup { for (int i=0; i < nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); RegisterNodeSignals(GetNodeSignals()); - } - ~TestingSetup() - { +} + +TestingSetup::~TestingSetup() +{ + UnregisterNodeSignals(GetNodeSignals()); threadGroup.interrupt_all(); threadGroup.join_all(); - UnregisterNodeSignals(GetNodeSignals()); #ifdef ENABLE_WALLET + UnregisterValidationInterface(pwalletMain); delete pwalletMain; pwalletMain = NULL; #endif + UnloadBlockIndex(); delete pcoinsTip; delete pcoinsdbview; delete pblocktree; #ifdef ENABLE_WALLET bitdb.Flush(true); + bitdb.Reset(); #endif boost::filesystem::remove_all(pathTemp); - } -}; - -BOOST_GLOBAL_FIXTURE(TestingSetup); +} void Shutdown(void* parg) { diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h new file mode 100644 index 0000000000..2f75332d40 --- /dev/null +++ b/src/test/test_bitcoin.h @@ -0,0 +1,30 @@ +#ifndef BITCOIN_TEST_TEST_BITCOIN_H +#define BITCOIN_TEST_TEST_BITCOIN_H + +#include "txdb.h" + +#include <boost/filesystem.hpp> +#include <boost/thread.hpp> + +/** Basic testing setup. + * This just configures logging and chain parameters. + */ +struct BasicTestingSetup { + BasicTestingSetup(); + ~BasicTestingSetup(); +}; + +/** Testing setup that configures a complete environment. + * Included are data directory, coins database, script check threads + * and wallet (if enabled) setup. + */ +struct TestingSetup: public BasicTestingSetup { + CCoinsViewDB *pcoinsdbview; + boost::filesystem::path pathTemp; + boost::thread_group threadGroup; + + TestingSetup(); + ~TestingSetup(); +}; + +#endif diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp index 58ed963274..887cfb4761 100644 --- a/src/test/timedata_tests.cpp +++ b/src/test/timedata_tests.cpp @@ -3,12 +3,13 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. // #include "timedata.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> using namespace std; -BOOST_AUTO_TEST_SUITE(timedata_tests) +BOOST_FIXTURE_TEST_SUITE(timedata_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(util_MedianFilter) { diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 52adfea992..2a3083316e 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -4,6 +4,7 @@ #include "data/tx_invalid.json.h" #include "data/tx_valid.json.h" +#include "test/test_bitcoin.h" #include "clientversion.h" #include "key.h" @@ -75,7 +76,7 @@ string FormatScriptFlags(unsigned int flags) return ret.substr(0, ret.size() - 1); } -BOOST_AUTO_TEST_SUITE(transaction_tests) +BOOST_FIXTURE_TEST_SUITE(transaction_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(tx_valid) { diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 5b33846ba9..426d296a9a 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -4,6 +4,7 @@ #include "arith_uint256.h" #include "uint256.h" #include "version.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> #include <stdint.h> @@ -14,7 +15,7 @@ #include <string> #include <stdio.h> -BOOST_AUTO_TEST_SUITE(uint256_tests) +BOOST_FIXTURE_TEST_SUITE(uint256_tests, BasicTestingSetup) const unsigned char R1Array[] = "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2" diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp index 5f0c1deb8e..8cecfbf651 100644 --- a/src/test/univalue_tests.cpp +++ b/src/test/univalue_tests.cpp @@ -7,12 +7,13 @@ #include <string> #include <map> #include "univalue/univalue.h" +#include "test/test_bitcoin.h" #include <boost/test/unit_test.hpp> using namespace std; -BOOST_AUTO_TEST_SUITE(univalue_tests) +BOOST_FIXTURE_TEST_SUITE(univalue_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(univalue_constructor) { diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index d829ec228d..3309e2e387 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -10,6 +10,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utilmoneystr.h" +#include "test/test_bitcoin.h" #include <stdint.h> #include <vector> @@ -18,7 +19,7 @@ using namespace std; -BOOST_AUTO_TEST_SUITE(util_tests) +BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(util_criticalsection) { diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 289cc8c905..25c8fab335 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -9,6 +9,8 @@ #include <utility> #include <vector> +#include "test/test_bitcoin.h" + #include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> @@ -23,7 +25,7 @@ using namespace std; typedef set<pair<const CWalletTx*,unsigned int> > CoinSet; -BOOST_AUTO_TEST_SUITE(wallet_tests) +BOOST_FIXTURE_TEST_SUITE(wallet_tests, TestingSetup) static CWallet wallet; static vector<COutput> vCoins; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 6e0f7e9c5a..0d50660327 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -337,7 +337,7 @@ public: void Write(CAutoFile& fileout) const { fileout << nBestSeenHeight; - fileout << history.size(); + fileout << (uint32_t)history.size(); BOOST_FOREACH(const CBlockAverage& entry, history) { entry.Write(fileout); @@ -348,7 +348,7 @@ public: { int nFileBestSeenHeight; filein >> nFileBestSeenHeight; - size_t numEntries; + uint32_t numEntries; filein >> numEntries; if (numEntries <= 0 || numEntries > 10000) throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entries."); diff --git a/src/uint256.cpp b/src/uint256.cpp index 3b1334a032..25148808c6 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -45,7 +45,7 @@ void base_blob<BITS>::SetHex(const char* psz) psz++; psz--; unsigned char* p1 = (unsigned char*)data; - unsigned char* pend = p1 + WIDTH * 4; + unsigned char* pend = p1 + WIDTH; while (psz >= pbegin && p1 < pend) { *p1 = ::HexDigit(*psz--); if (psz >= pbegin) { @@ -128,7 +128,7 @@ uint64_t uint256::GetHash(const uint256& salt) const uint32_t a, b, c; const uint32_t *pn = (const uint32_t*)data; const uint32_t *salt_pn = (const uint32_t*)salt.data; - a = b = c = 0xdeadbeef + (WIDTH << 2); + a = b = c = 0xdeadbeef + WIDTH; a += pn[0] ^ salt_pn[0]; b += pn[1] ^ salt_pn[1]; diff --git a/src/util.cpp b/src/util.cpp index 361b3631f5..792f00b61d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -346,6 +346,21 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue) return SoftSetArg(strArg, std::string("0")); } +static const int screenWidth = 79; +static const int optIndent = 2; +static const int msgIndent = 7; + +std::string HelpMessageGroup(const std::string &message) { + return std::string(message) + std::string("\n\n"); +} + +std::string HelpMessageOpt(const std::string &option, const std::string &message) { + return std::string(optIndent,' ') + std::string(option) + + std::string("\n") + std::string(msgIndent,' ') + + FormatParagraph(message, screenWidth - msgIndent, msgIndent) + + std::string("\n\n"); +} + static std::string FormatException(const std::exception* pex, const char* pszThread) { #ifdef WIN32 diff --git a/src/util.h b/src/util.h index bbb0e81039..9b5a4153dd 100644 --- a/src/util.h +++ b/src/util.h @@ -94,6 +94,7 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); bool TryCreateDirectory(const boost::filesystem::path& p); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); +void ClearDatadirCache(); boost::filesystem::path GetConfigFile(); #ifndef WIN32 boost::filesystem::path GetPidFile(); @@ -161,6 +162,23 @@ bool SoftSetArg(const std::string& strArg, const std::string& strValue); */ bool SoftSetBoolArg(const std::string& strArg, bool fValue); +/** + * Format a string to be used as group of options in help messages + * + * @param message Group name (e.g. "RPC server options:") + * @return the formatted string + */ +std::string HelpMessageGroup(const std::string& message); + +/** + * Format a string to be used as option description in help messages + * + * @param option Option message (e.g. "-rpcuser=<user>") + * @param message Option description (e.g. "Username for JSON-RPC connections") + * @return the formatted string + */ +std::string HelpMessageOpt(const std::string& option, const std::string& message); + void SetThreadPriority(int nPriority); void RenameThread(const char* name); diff --git a/src/walletdb.cpp b/src/walletdb.cpp index b2daf036ff..ddec57d9a9 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -903,8 +903,8 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) int64_t now = GetTime(); std::string newFilename = strprintf("wallet.%d.bak", now); - int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL, - newFilename.c_str(), DB_AUTO_COMMIT); + int result = dbenv.dbenv->dbrename(NULL, filename.c_str(), NULL, + newFilename.c_str(), DB_AUTO_COMMIT); if (result == 0) LogPrintf("Renamed %s to %s\n", filename, newFilename); else @@ -923,7 +923,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); bool fSuccess = allOK; - boost::scoped_ptr<Db> pdbCopy(new Db(&dbenv.dbenv, 0)); + boost::scoped_ptr<Db> pdbCopy(new Db(dbenv.dbenv, 0)); int ret = pdbCopy->open(NULL, // Txn pointer filename.c_str(), // Filename "main", // Logical db name |