From a07c374a0ae54bb96d788a2f6145d3b6a8e91bc5 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Fri, 10 Apr 2020 18:49:51 -0600 Subject: [PATCH 001/132] Cleaned up spacing and got travis working --- .travis.yml | 40 +- .travis/test_06_script_b.sh | 2 +- src/activemasternode.cpp | 4 +- src/bloom.cpp | 8 +- src/chainparams.cpp | 2 +- src/coins.h | 4 +- src/core_read.cpp | 2 +- src/core_write.cpp | 1 - src/crypto/sph_blake.h | 28 +- src/crypto/sph_bmw.h | 26 +- src/crypto/sph_cubehash.h | 14 +- src/crypto/sph_echo.h | 38 +- src/crypto/sph_groestl.h | 40 +- src/crypto/sph_jh.h | 24 +- src/crypto/sph_keccak.h | 20 +- src/crypto/sph_luffa.h | 30 +- src/crypto/sph_shavite.h | 30 +- src/crypto/sph_simd.h | 24 +- src/crypto/sph_skein.h | 16 +- src/crypto/sph_types.h | 612 ++++++------- src/ecwrapper.cpp | 10 +- src/libzerocoin/Accumulator.cpp | 94 +- src/libzerocoin/Accumulator.h | 212 ++--- .../AccumulatorProofOfKnowledge.cpp | 208 ++--- src/libzerocoin/AccumulatorProofOfKnowledge.h | 116 +-- src/libzerocoin/Coin.cpp | 220 ++--- src/libzerocoin/Coin.h | 54 +- src/libzerocoin/CoinSpend.h | 68 +- src/libzerocoin/Commitment.cpp | 238 ++--- src/libzerocoin/Commitment.h | 108 +-- src/libzerocoin/Denominations.cpp | 8 +- src/libzerocoin/ParamGeneration.cpp | 846 +++++++++--------- src/libzerocoin/Params.cpp | 28 +- src/libzerocoin/Params.h | 360 ++++---- .../SerialNumberSignatureOfKnowledge.cpp | 174 ++-- .../SerialNumberSignatureOfKnowledge.h | 62 +- src/libzerocoin/ZerocoinDefines.h | 6 +- src/libzerocoin/bignum.h | 16 +- src/libzerocoin/paramgen.cpp | 180 ++-- src/masternode.cpp | 44 +- src/masternodeconfig.cpp | 10 +- src/masternodeconfig.h | 4 +- src/masternodeman.cpp | 2 +- src/primitives/block.h | 4 +- src/protocol.cpp | 2 +- src/protocol.h | 6 +- src/qt/bitcoingui.cpp | 2 +- src/qt/coincontroldialog.cpp | 4 +- src/qt/configuremasternodepage.cpp | 82 +- src/qt/configuremasternodepage.h | 48 +- src/qt/masternodelist.cpp | 138 +-- src/qt/masternodelist.h | 10 +- src/qt/multisigdialog.cpp | 16 +- src/qt/optionsmodel.cpp | 5 + src/qt/paymentrequestplus.cpp | 2 +- src/qt/proposaldialog.cpp | 2 +- src/qt/proposallist.cpp | 8 +- src/qt/proposaltablemodel.cpp | 6 +- src/qt/transactiondesc.cpp | 4 +- src/qt/walletview.cpp | 2 +- src/qt/walletview.h | 4 +- src/qt/zphrcontroldialog.cpp | 2 +- src/rpc/blockchain.cpp | 2 +- src/rpc/masternode-budget.cpp | 21 +- src/rpc/net.cpp | 1 - src/script/sign.cpp | 1 - src/script/standard.cpp | 1 - src/secp256k1/src/scratch.h | 4 +- src/swifttx.cpp | 3 + src/test/base58_tests.cpp | 1 - src/test/benchmark_zerocoin.cpp | 496 +++++----- src/test/libzerocoin_tests.cpp | 2 +- src/test/rpc_tests.cpp | 52 +- src/test/rpc_wallet_tests.cpp | 74 +- src/test/transaction_tests.cpp | 8 +- src/test/tutorial_zerocoin.cpp | 436 ++++----- src/test/univalue_tests.cpp | 22 +- src/timedata.cpp | 1 - src/univalue/gen/gen.cpp | 64 +- src/univalue/lib/univalue_escapes.h | 512 +++++------ src/univalue/test/object.cpp | 12 +- src/wallet/crypter.cpp | 8 +- test/functional/__init__.py | 0 test/functional/create_cache.py | 27 + test/functional/decodetx.py | 0 test/functional/listtransactions.py | 0 test/functional/segwit.py | 0 test/functional/test_case_base.py | 0 test/functional/test_runner.py | 8 - test/functional/wallet.py | 0 test/functional/wallet_hd.py | 0 test/functional/zerocoin.py | 0 92 files changed, 3078 insertions(+), 3058 deletions(-) mode change 100644 => 100755 test/functional/__init__.py create mode 100755 test/functional/create_cache.py mode change 100644 => 100755 test/functional/decodetx.py mode change 100644 => 100755 test/functional/listtransactions.py mode change 100644 => 100755 test/functional/segwit.py mode change 100644 => 100755 test/functional/test_case_base.py mode change 100644 => 100755 test/functional/test_runner.py mode change 100644 => 100755 test/functional/wallet.py mode change 100644 => 100755 test/functional/wallet_hd.py mode change 100644 => 100755 test/functional/zerocoin.py diff --git a/.travis.yml b/.travis.yml index 9699732be7f5a..f997848bbe489 100644 --- a/.travis.yml +++ b/.travis.yml @@ -135,27 +135,27 @@ jobs: BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" CONFIG_SHELL="/bin/dash" - - stage: test - name: 'x86_64 Linux [GOAL: install] [bionic] [uses qt5 dev package instead of depends Qt to speed up build and avoid timeout]' - env: >- - HOST=x86_64-unknown-linux-gnu - PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev" - DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" - RUN_FUNCTIONAL_TESTS=true - #TEST_RUNNER_EXTRA="--coverage --extended" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash - GOAL="install" - BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports" +# - stage: test +# name: 'x86_64 Linux [GOAL: install] [bionic] [uses qt5 dev package instead of depends Qt to speed up build and avoid timeout]' +# env: >- +# HOST=x86_64-unknown-linux-gnu +# PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev" +# DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" +# RUN_FUNCTIONAL_TESTS=true +# #TEST_RUNNER_EXTRA="--coverage --extended" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash +# GOAL="install" +# BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports" - - stage: test - name: 'x86_64 Linux [GOAL: install] [trusty] [no functional tests, no depends, only system libs]' - env: >- - HOST=x86_64-unknown-linux-gnu - DOCKER_NAME_TAG=ubuntu:14.04 - PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev libgmp-dev" - NO_DEPENDS=1 - RUN_FUNCTIONAL_TESTS=false - GOAL="install" - BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no" +# - stage: test +# name: 'x86_64 Linux [GOAL: install] [trusty] [no functional tests, no depends, only system libs]' +# env: >- +# HOST=x86_64-unknown-linux-gnu +# DOCKER_NAME_TAG=ubuntu:14.04 +# PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev libgmp-dev" +# NO_DEPENDS=1 +# RUN_FUNCTIONAL_TESTS=false +# GOAL="install" +# BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no" - stage: test name: 'x86_64 Linux [GOAL: install] [xenial] [no depends, only system libs]' diff --git a/.travis/test_06_script_b.sh b/.travis/test_06_script_b.sh index 6c01f9fdb61da..11b8051488d57 100755 --- a/.travis/test_06_script_b.sh +++ b/.travis/test_06_script_b.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -cd "build/pivx-$HOST" || (echo "could not enter distdir build/pivx-$HOST"; exit 1) +cd "build/phore-$HOST" || (echo "could not enter distdir build/phore-$HOST"; exit 1) if [ "$RUN_UNIT_TESTS" = "true" ]; then BEGIN_FOLD unit-tests diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index ce429995f365b..5611b67f063d5 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -275,8 +275,8 @@ bool CActiveMasternode::CreateBroadcast(std::string strService, std::string strK bool CActiveMasternode::CreateBroadcast(CTxIn vin, CService service, CKey keyCollateralAddress, CPubKey pubKeyCollateralAddress, CKey keyMasternode, CPubKey pubKeyMasternode, std::string& errorMessage, CMasternodeBroadcast &mnb) { - // wait for reindex and/or import to finish - if (fImporting || fReindex) return false; + // wait for reindex and/or import to finish + if (fImporting || fReindex) return false; CMasternodePing mnp(vin); if (!mnp.Sign(keyMasternode, pubKeyMasternode)) { diff --git a/src/bloom.cpp b/src/bloom.cpp index 124970965c755..264da8ec29b91 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -20,19 +20,19 @@ CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn, unsigned char nFlagsIn) : - /** + /** * The ideal size for a bloom filter with a given number of elements and false positive rate is: * - nElements * log(fp rate) / ln(2)^2 * We ignore filter parameters which will create a bloom filter larger than the protocol limits */ - vData(std::min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8), + vData(std::min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8), /** * The ideal number of hash functions is filter size * ln(2) / number of elements * Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits * See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas */ - isFull(false), - isEmpty(false), + isFull(false), + isEmpty(false), nHashFuncs(std::min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)), nTweak(nTweakIn), nFlags(nFlagsIn) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 3d8b54a74e503..8f4fd52c80abd 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -194,7 +194,7 @@ class CMainParams : public CChainParams base58Prefixes[SECRET_KEY] = std::vector(1, 212); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x02)(0x2D)(0x25)(0x33).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x02)(0x21)(0x31)(0x2B).convert_to_container >(); - // BIP44 coin type is from https://github.com/satoshilabs/slips/blob/master/slip-0044.md + // BIP44 coin type is from https://github.com/satoshilabs/slips/blob/master/slip-0044.md nExtCoinType = 444; bech32_hrp = "ph"; diff --git a/src/coins.h b/src/coins.h index 7b77ce46b02fb..debf504ab0ae1 100644 --- a/src/coins.h +++ b/src/coins.h @@ -461,8 +461,8 @@ class CCoinsViewCache : public CCoinsViewBacked * Note that lightweight clients may not know anything besides the hash of previous transactions, * so may not be able to calculate this. * - * @param[in] tx transaction for which we are checking input total - * @return Sum of value of all inputs (scriptSigs) + * @param[in] tx transaction for which we are checking input total + * @return Sum of value of all inputs (scriptSigs) */ CAmount GetValueIn(const CTransaction& tx) const; diff --git a/src/core_read.cpp b/src/core_read.cpp index 13d579c4d04e0..4cd072bf63ae3 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -127,7 +127,7 @@ uint256 ParseHashUV(const UniValue& v, const std::string& strName) std::string strHex; if (v.isStr()) strHex = v.getValStr(); - return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error + return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a std::runtime_error } uint256 ParseHashStr(const std::string& strHex, const std::string& strName) diff --git a/src/core_write.cpp b/src/core_write.cpp index 0669457a42632..2f4c617cf6ba2 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -18,7 +18,6 @@ - std::string FormatScript(const CScript& script) { std::string ret; diff --git a/src/crypto/sph_blake.h b/src/crypto/sph_blake.h index d8d794399d00c..bad7a5aa4bec2 100644 --- a/src/crypto/sph_blake.h +++ b/src/crypto/sph_blake.h @@ -80,11 +80,11 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - size_t ptr; - sph_u32 H[8]; - sph_u32 S[4]; - sph_u32 T0, T1; + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 H[8]; + sph_u32 S[4]; + sph_u32 T0, T1; #endif } sph_blake_small_context; @@ -114,11 +114,11 @@ typedef sph_blake_small_context sph_blake256_context; */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[128]; /* first field, for alignment */ - size_t ptr; - sph_u64 H[8]; - sph_u64 S[4]; - sph_u64 T0, T1; + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u64 H[8]; + sph_u64 S[4]; + sph_u64 T0, T1; #endif } sph_blake_big_context; @@ -179,7 +179,7 @@ void sph_blake224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_blake224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a BLAKE-256 context. This process performs no memory allocation. @@ -224,7 +224,7 @@ void sph_blake256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_blake256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #if SPH_64 @@ -271,7 +271,7 @@ void sph_blake384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_blake384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a BLAKE-512 context. This process performs no memory allocation. @@ -316,7 +316,7 @@ void sph_blake512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_blake512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #endif diff --git a/src/crypto/sph_bmw.h b/src/crypto/sph_bmw.h index d386b0c140533..aeae2fb4fddc7 100644 --- a/src/crypto/sph_bmw.h +++ b/src/crypto/sph_bmw.h @@ -79,13 +79,13 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - size_t ptr; - sph_u32 H[16]; + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 H[16]; #if SPH_64 - sph_u64 bit_count; + sph_u64 bit_count; #else - sph_u32 bit_count_high, bit_count_low; + sph_u32 bit_count_high, bit_count_low; #endif #endif } sph_bmw_small_context; @@ -116,10 +116,10 @@ typedef sph_bmw_small_context sph_bmw256_context; */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[128]; /* first field, for alignment */ - size_t ptr; - sph_u64 H[16]; - sph_u64 bit_count; + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u64 H[16]; + sph_u64 bit_count; #endif } sph_bmw_big_context; @@ -180,7 +180,7 @@ void sph_bmw224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_bmw224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a BMW-256 context. This process performs no memory allocation. @@ -225,7 +225,7 @@ void sph_bmw256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_bmw256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #if SPH_64 @@ -272,7 +272,7 @@ void sph_bmw384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_bmw384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a BMW-512 context. This process performs no memory allocation. @@ -317,7 +317,7 @@ void sph_bmw512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_bmw512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #endif diff --git a/src/crypto/sph_cubehash.h b/src/crypto/sph_cubehash.h index 487a1946ad406..f4f502cb5096e 100644 --- a/src/crypto/sph_cubehash.h +++ b/src/crypto/sph_cubehash.h @@ -76,9 +76,9 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[32]; /* first field, for alignment */ - size_t ptr; - sph_u32 state[32]; + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 state[32]; #endif } sph_cubehash_context; @@ -146,7 +146,7 @@ void sph_cubehash224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_cubehash224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a CubeHash-256 context. This process performs no memory @@ -192,7 +192,7 @@ void sph_cubehash256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_cubehash256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a CubeHash-384 context. This process performs no memory @@ -238,7 +238,7 @@ void sph_cubehash384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_cubehash384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a CubeHash-512 context. This process performs no memory @@ -284,7 +284,7 @@ void sph_cubehash512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_cubehash512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #ifdef __cplusplus } #endif diff --git a/src/crypto/sph_echo.h b/src/crypto/sph_echo.h index 1ae1e3dd62435..aed0a1ae2428c 100644 --- a/src/crypto/sph_echo.h +++ b/src/crypto/sph_echo.h @@ -76,15 +76,15 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[192]; /* first field, for alignment */ - size_t ptr; - union { - sph_u32 Vs[4][4]; + unsigned char buf[192]; /* first field, for alignment */ + size_t ptr; + union { + sph_u32 Vs[4][4]; #if SPH_64 - sph_u64 Vb[4][2]; + sph_u64 Vb[4][2]; #endif - } u; - sph_u32 C0, C1, C2, C3; + } u; + sph_u32 C0, C1, C2, C3; #endif } sph_echo_small_context; @@ -101,15 +101,15 @@ typedef struct { */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[128]; /* first field, for alignment */ - size_t ptr; - union { - sph_u32 Vs[8][4]; + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + union { + sph_u32 Vs[8][4]; #if SPH_64 - sph_u64 Vb[8][2]; + sph_u64 Vb[8][2]; #endif - } u; - sph_u32 C0, C1, C2, C3; + } u; + sph_u32 C0, C1, C2, C3; #endif } sph_echo_big_context; @@ -176,7 +176,7 @@ void sph_echo224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_echo224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize an ECHO-256 context. This process performs no memory allocation. @@ -221,7 +221,7 @@ void sph_echo256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_echo256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize an ECHO-384 context. This process performs no memory allocation. @@ -266,7 +266,7 @@ void sph_echo384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_echo384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize an ECHO-512 context. This process performs no memory allocation. @@ -311,8 +311,8 @@ void sph_echo512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_echo512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); - + void *cc, unsigned ub, unsigned n, void *dst); + #ifdef __cplusplus } #endif diff --git a/src/crypto/sph_groestl.h b/src/crypto/sph_groestl.h index 495f05e21174b..bb638e9bdb38a 100644 --- a/src/crypto/sph_groestl.h +++ b/src/crypto/sph_groestl.h @@ -74,18 +74,18 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - size_t ptr; - union { + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + union { #if SPH_64 - sph_u64 wide[8]; + sph_u64 wide[8]; #endif - sph_u32 narrow[16]; - } state; + sph_u32 narrow[16]; + } state; #if SPH_64 - sph_u64 count; + sph_u64 count; #else - sph_u32 count_high, count_low; + sph_u32 count_high, count_low; #endif #endif } sph_groestl_small_context; @@ -114,18 +114,18 @@ typedef sph_groestl_small_context sph_groestl256_context; */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[128]; /* first field, for alignment */ - size_t ptr; - union { + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + union { #if SPH_64 - sph_u64 wide[16]; + sph_u64 wide[16]; #endif - sph_u32 narrow[32]; - } state; + sph_u32 narrow[32]; + } state; #if SPH_64 - sph_u64 count; + sph_u64 count; #else - sph_u32 count_high, count_low; + sph_u32 count_high, count_low; #endif #endif } sph_groestl_big_context; @@ -185,7 +185,7 @@ void sph_groestl224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_groestl224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Groestl-256 context. This process performs no memory allocation. @@ -230,7 +230,7 @@ void sph_groestl256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_groestl256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Groestl-384 context. This process performs no memory allocation. @@ -275,7 +275,7 @@ void sph_groestl384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_groestl384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Groestl-512 context. This process performs no memory allocation. @@ -320,7 +320,7 @@ void sph_groestl512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_groestl512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #ifdef __cplusplus } diff --git a/src/crypto/sph_jh.h b/src/crypto/sph_jh.h index 82fae58df8ccc..c8a9fabc05b5c 100644 --- a/src/crypto/sph_jh.h +++ b/src/crypto/sph_jh.h @@ -75,18 +75,18 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - size_t ptr; - union { + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + union { #if SPH_64 - sph_u64 wide[16]; + sph_u64 wide[16]; #endif - sph_u32 narrow[32]; - } H; + sph_u32 narrow[32]; + } H; #if SPH_64 - sph_u64 block_count; + sph_u64 block_count; #else - sph_u32 block_count_high, block_count_low; + sph_u32 block_count_high, block_count_low; #endif #endif } sph_jh_context; @@ -154,7 +154,7 @@ void sph_jh224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_jh224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a JH-256 context. This process performs no memory allocation. @@ -199,7 +199,7 @@ void sph_jh256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_jh256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a JH-384 context. This process performs no memory allocation. @@ -244,7 +244,7 @@ void sph_jh384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_jh384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a JH-512 context. This process performs no memory allocation. @@ -289,7 +289,7 @@ void sph_jh512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_jh512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #ifdef __cplusplus } diff --git a/src/crypto/sph_keccak.h b/src/crypto/sph_keccak.h index bdafdb88db020..233154209b9c0 100644 --- a/src/crypto/sph_keccak.h +++ b/src/crypto/sph_keccak.h @@ -75,14 +75,14 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[144]; /* first field, for alignment */ - size_t ptr, lim; - union { + unsigned char buf[144]; /* first field, for alignment */ + size_t ptr, lim; + union { #if SPH_64 - sph_u64 wide[25]; + sph_u64 wide[25]; #endif - sph_u32 narrow[50]; - } u; + sph_u32 narrow[50]; + } u; #endif } sph_keccak_context; @@ -149,7 +149,7 @@ void sph_keccak224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_keccak224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Keccak-256 context. This process performs no memory allocation. @@ -194,7 +194,7 @@ void sph_keccak256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_keccak256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Keccak-384 context. This process performs no memory allocation. @@ -239,7 +239,7 @@ void sph_keccak384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_keccak384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Keccak-512 context. This process performs no memory allocation. @@ -284,7 +284,7 @@ void sph_keccak512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_keccak512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #ifdef __cplusplus } diff --git a/src/crypto/sph_luffa.h b/src/crypto/sph_luffa.h index a32fd7b16be63..31182933d311c 100644 --- a/src/crypto/sph_luffa.h +++ b/src/crypto/sph_luffa.h @@ -75,9 +75,9 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[32]; /* first field, for alignment */ - size_t ptr; - sph_u32 V[3][8]; + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[3][8]; #endif } sph_luffa224_context; @@ -92,9 +92,9 @@ typedef sph_luffa224_context sph_luffa256_context; */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[32]; /* first field, for alignment */ - size_t ptr; - sph_u32 V[4][8]; + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[4][8]; #endif } sph_luffa384_context; @@ -103,9 +103,9 @@ typedef struct { */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[32]; /* first field, for alignment */ - size_t ptr; - sph_u32 V[5][8]; + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[5][8]; #endif } sph_luffa512_context; @@ -152,7 +152,7 @@ void sph_luffa224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_luffa224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Luffa-256 context. This process performs no memory allocation. @@ -197,7 +197,7 @@ void sph_luffa256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_luffa256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Luffa-384 context. This process performs no memory allocation. @@ -242,7 +242,7 @@ void sph_luffa384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_luffa384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Luffa-512 context. This process performs no memory allocation. @@ -287,10 +287,10 @@ void sph_luffa512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_luffa512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); - + void *cc, unsigned ub, unsigned n, void *dst); + #ifdef __cplusplus } #endif - + #endif diff --git a/src/crypto/sph_shavite.h b/src/crypto/sph_shavite.h index 0957e42a9f0e3..ed13b753b0cb2 100644 --- a/src/crypto/sph_shavite.h +++ b/src/crypto/sph_shavite.h @@ -77,10 +77,10 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - size_t ptr; - sph_u32 h[8]; - sph_u32 count0, count1; + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 h[8]; + sph_u32 count0, count1; #endif } sph_shavite_small_context; @@ -108,10 +108,10 @@ typedef sph_shavite_small_context sph_shavite256_context; */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[128]; /* first field, for alignment */ - size_t ptr; - sph_u32 h[16]; - sph_u32 count0, count1, count2, count3; + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u32 h[16]; + sph_u32 count0, count1, count2, count3; #endif } sph_shavite_big_context; @@ -170,7 +170,7 @@ void sph_shavite224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_shavite224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a SHAvite-256 context. This process performs no memory allocation. @@ -215,7 +215,7 @@ void sph_shavite256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_shavite256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a SHAvite-384 context. This process performs no memory allocation. @@ -260,7 +260,7 @@ void sph_shavite384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_shavite384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a SHAvite-512 context. This process performs no memory allocation. @@ -305,10 +305,10 @@ void sph_shavite512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_shavite512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); - + void *cc, unsigned ub, unsigned n, void *dst); + #ifdef __cplusplus } -#endif - +#endif + #endif diff --git a/src/crypto/sph_simd.h b/src/crypto/sph_simd.h index 92ee1e7275c4a..c674db2ce8ae5 100644 --- a/src/crypto/sph_simd.h +++ b/src/crypto/sph_simd.h @@ -76,10 +76,10 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - size_t ptr; - sph_u32 state[16]; - sph_u32 count_low, count_high; + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 state[16]; + sph_u32 count_low, count_high; #endif } sph_simd_small_context; @@ -96,10 +96,10 @@ typedef struct { */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[128]; /* first field, for alignment */ - size_t ptr; - sph_u32 state[32]; - sph_u32 count_low, count_high; + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u32 state[32]; + sph_u32 count_low, count_high; #endif } sph_simd_big_context; @@ -166,7 +166,7 @@ void sph_simd224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_simd224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize an SIMD-256 context. This process performs no memory allocation. @@ -211,7 +211,7 @@ void sph_simd256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_simd256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize an SIMD-384 context. This process performs no memory allocation. @@ -256,7 +256,7 @@ void sph_simd384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_simd384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize an SIMD-512 context. This process performs no memory allocation. @@ -301,7 +301,7 @@ void sph_simd512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_simd512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #ifdef __cplusplus } #endif diff --git a/src/crypto/sph_skein.h b/src/crypto/sph_skein.h index bddbc86fa5aac..924ba7413c3e7 100644 --- a/src/crypto/sph_skein.h +++ b/src/crypto/sph_skein.h @@ -82,10 +82,10 @@ extern "C"{ */ typedef struct { #ifndef DOXYGEN_IGNORE - unsigned char buf[64]; /* first field, for alignment */ - size_t ptr; - sph_u64 h0, h1, h2, h3, h4, h5, h6, h7; - sph_u64 bcount; + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u64 h0, h1, h2, h3, h4, h5, h6, h7; + sph_u64 bcount; #endif } sph_skein_big_context; @@ -152,7 +152,7 @@ void sph_skein224_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_skein224_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Skein-256 context. This process performs no memory allocation. @@ -197,7 +197,7 @@ void sph_skein256_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_skein256_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Skein-384 context. This process performs no memory allocation. @@ -242,7 +242,7 @@ void sph_skein384_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_skein384_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); /** * Initialize a Skein-512 context. This process performs no memory allocation. @@ -287,7 +287,7 @@ void sph_skein512_close(void *cc, void *dst); * @param dst the destination buffer */ void sph_skein512_addbits_and_close( - void *cc, unsigned ub, unsigned n, void *dst); + void *cc, unsigned ub, unsigned n, void *dst); #endif diff --git a/src/crypto/sph_types.h b/src/crypto/sph_types.h index 7295b0b37097a..cef79bde12d55 100644 --- a/src/crypto/sph_types.h +++ b/src/crypto/sph_types.h @@ -1028,7 +1028,7 @@ typedef long long sph_s64; * 64-bit Sparc architecture (implies v9). */ #elif ((defined __sparc__ || defined __sparc) && defined __arch64__) \ - || defined __sparcv9 + || defined __sparcv9 #define SPH_DETECT_BIG_ENDIAN 1 #define SPH_DETECT_UPTR sph_u64 @@ -1041,7 +1041,7 @@ typedef long long sph_s64; * 32-bit Sparc. */ #elif (defined __sparc__ || defined __sparc) \ - && !(defined __sparcv9 || defined __arch64__) + && !(defined __sparcv9 || defined __arch64__) #define SPH_DETECT_BIG_ENDIAN 1 #define SPH_DETECT_UPTR sph_u32 @@ -1075,7 +1075,7 @@ typedef long long sph_s64; * PowerPC. */ #elif defined __powerpc__ || defined __POWERPC__ || defined __ppc__ \ - || defined _ARCH_PPC + || defined _ARCH_PPC /* * Note: we do not declare cross-endian access to be "fast": even if @@ -1101,7 +1101,7 @@ typedef long long sph_s64; * Itanium, 64-bit. */ #elif defined __ia64 || defined __ia64__ \ - || defined __itanium__ || defined _M_IA64 + || defined __itanium__ || defined _M_IA64 #if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN #define SPH_DETECT_BIG_ENDIAN 1 @@ -1187,8 +1187,8 @@ typedef long long sph_s64; static SPH_INLINE sph_u32 sph_bswap32(sph_u32 x) { - __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); - return x; + __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); + return x; } #if SPH_64 @@ -1196,8 +1196,8 @@ sph_bswap32(sph_u32 x) static SPH_INLINE sph_u64 sph_bswap64(sph_u64 x) { - return ((sph_u64)sph_bswap32((sph_u32)x) << 32) - | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); + return ((sph_u64)sph_bswap32((sph_u32)x) << 32) + | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); } #endif @@ -1212,8 +1212,8 @@ sph_bswap64(sph_u64 x) static SPH_INLINE sph_u32 sph_bswap32(sph_u32 x) { - __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); - return x; + __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); + return x; } #if SPH_64 @@ -1221,8 +1221,8 @@ sph_bswap32(sph_u32 x) static SPH_INLINE sph_u64 sph_bswap64(sph_u64 x) { - __asm__ __volatile__ ("bswapq %0" : "=r" (x) : "0" (x)); - return x; + __asm__ __volatile__ ("bswapq %0" : "=r" (x) : "0" (x)); + return x; } #endif @@ -1238,11 +1238,11 @@ sph_bswap64(sph_u64 x) static __inline sph_u32 __declspec(naked) __fastcall sph_bswap32(sph_u32 x) { - __asm { - bswap ecx - mov eax,ecx - ret - } + __asm { + bswap ecx + mov eax,ecx + ret + } } #if SPH_64 @@ -1250,8 +1250,8 @@ sph_bswap32(sph_u32 x) static SPH_INLINE sph_u64 sph_bswap64(sph_u64 x) { - return ((sph_u64)sph_bswap32((sph_u32)x) << 32) - | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); + return ((sph_u64)sph_bswap32((sph_u32)x) << 32) + | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); } #endif @@ -1265,10 +1265,10 @@ sph_bswap64(sph_u64 x) static SPH_INLINE sph_u32 sph_bswap32(sph_u32 x) { - x = SPH_T32((x << 16) | (x >> 16)); - x = ((x & SPH_C32(0xFF00FF00)) >> 8) - | ((x & SPH_C32(0x00FF00FF)) << 8); - return x; + x = SPH_T32((x << 16) | (x >> 16)); + x = ((x & SPH_C32(0xFF00FF00)) >> 8) + | ((x & SPH_C32(0x00FF00FF)) << 8); + return x; } #if SPH_64 @@ -1282,12 +1282,12 @@ sph_bswap32(sph_u32 x) static SPH_INLINE sph_u64 sph_bswap64(sph_u64 x) { - x = SPH_T64((x << 32) | (x >> 32)); - x = ((x & SPH_C64(0xFFFF0000FFFF0000)) >> 16) - | ((x & SPH_C64(0x0000FFFF0000FFFF)) << 16); - x = ((x & SPH_C64(0xFF00FF00FF00FF00)) >> 8) - | ((x & SPH_C64(0x00FF00FF00FF00FF)) << 8); - return x; + x = SPH_T64((x << 32) | (x >> 32)); + x = ((x & SPH_C64(0xFFFF0000FFFF0000)) >> 16) + | ((x & SPH_C64(0x0000FFFF0000FFFF)) << 16); + x = ((x & SPH_C64(0xFF00FF00FF00FF00)) >> 8) + | ((x & SPH_C64(0x00FF00FF00FF00FF)) << 8); + return x; } #endif @@ -1313,48 +1313,48 @@ sph_bswap64(sph_u64 x) */ #define SPH_SPARCV9_SET_ASI \ - sph_u32 sph_sparcv9_asi; \ - __asm__ __volatile__ ( \ - "rd %%asi,%0\n\twr %%g0,0x88,%%asi" : "=r" (sph_sparcv9_asi)); + sph_u32 sph_sparcv9_asi; \ + __asm__ __volatile__ ( \ + "rd %%asi,%0\n\twr %%g0,0x88,%%asi" : "=r" (sph_sparcv9_asi)); #define SPH_SPARCV9_RESET_ASI \ - __asm__ __volatile__ ("wr %%g0,%0,%%asi" : : "r" (sph_sparcv9_asi)); + __asm__ __volatile__ ("wr %%g0,%0,%%asi" : : "r" (sph_sparcv9_asi)); #define SPH_SPARCV9_DEC32LE(base, idx) ({ \ - sph_u32 sph_sparcv9_tmp; \ - __asm__ __volatile__ ("lda [%1+" #idx "*4]%%asi,%0" \ - : "=r" (sph_sparcv9_tmp) : "r" (base)); \ - sph_sparcv9_tmp; \ - }) + sph_u32 sph_sparcv9_tmp; \ + __asm__ __volatile__ ("lda [%1+" #idx "*4]%%asi,%0" \ + : "=r" (sph_sparcv9_tmp) : "r" (base)); \ + sph_sparcv9_tmp; \ + }) #endif static SPH_INLINE void sph_enc16be(void *dst, unsigned val) { - ((unsigned char *)dst)[0] = (val >> 8); - ((unsigned char *)dst)[1] = val; + ((unsigned char *)dst)[0] = (val >> 8); + ((unsigned char *)dst)[1] = val; } static SPH_INLINE unsigned sph_dec16be(const void *src) { - return ((unsigned)(((const unsigned char *)src)[0]) << 8) - | (unsigned)(((const unsigned char *)src)[1]); + return ((unsigned)(((const unsigned char *)src)[0]) << 8) + | (unsigned)(((const unsigned char *)src)[1]); } static SPH_INLINE void sph_enc16le(void *dst, unsigned val) { - ((unsigned char *)dst)[0] = val; - ((unsigned char *)dst)[1] = val >> 8; + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = val >> 8; } static SPH_INLINE unsigned sph_dec16le(const void *src) { - return (unsigned)(((const unsigned char *)src)[0]) - | ((unsigned)(((const unsigned char *)src)[1]) << 8); + return (unsigned)(((const unsigned char *)src)[0]) + | ((unsigned)(((const unsigned char *)src)[1]) << 8); } /** @@ -1369,27 +1369,27 @@ sph_enc32be(void *dst, sph_u32 val) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_LITTLE_ENDIAN - val = sph_bswap32(val); + val = sph_bswap32(val); #endif - *(sph_u32 *)dst = val; + *(sph_u32 *)dst = val; #else - if (((SPH_UPTR)dst & 3) == 0) { + if (((SPH_UPTR)dst & 3) == 0) { #if SPH_LITTLE_ENDIAN - val = sph_bswap32(val); + val = sph_bswap32(val); #endif - *(sph_u32 *)dst = val; - } else { - ((unsigned char *)dst)[0] = (val >> 24); - ((unsigned char *)dst)[1] = (val >> 16); - ((unsigned char *)dst)[2] = (val >> 8); - ((unsigned char *)dst)[3] = val; - } + *(sph_u32 *)dst = val; + } else { + ((unsigned char *)dst)[0] = (val >> 24); + ((unsigned char *)dst)[1] = (val >> 16); + ((unsigned char *)dst)[2] = (val >> 8); + ((unsigned char *)dst)[3] = val; + } #endif #else - ((unsigned char *)dst)[0] = (val >> 24); - ((unsigned char *)dst)[1] = (val >> 16); - ((unsigned char *)dst)[2] = (val >> 8); - ((unsigned char *)dst)[3] = val; + ((unsigned char *)dst)[0] = (val >> 24); + ((unsigned char *)dst)[1] = (val >> 16); + ((unsigned char *)dst)[2] = (val >> 8); + ((unsigned char *)dst)[3] = val; #endif } @@ -1404,14 +1404,14 @@ static SPH_INLINE void sph_enc32be_aligned(void *dst, sph_u32 val) { #if SPH_LITTLE_ENDIAN - *(sph_u32 *)dst = sph_bswap32(val); + *(sph_u32 *)dst = sph_bswap32(val); #elif SPH_BIG_ENDIAN - *(sph_u32 *)dst = val; + *(sph_u32 *)dst = val; #else - ((unsigned char *)dst)[0] = (val >> 24); - ((unsigned char *)dst)[1] = (val >> 16); - ((unsigned char *)dst)[2] = (val >> 8); - ((unsigned char *)dst)[3] = val; + ((unsigned char *)dst)[0] = (val >> 24); + ((unsigned char *)dst)[1] = (val >> 16); + ((unsigned char *)dst)[2] = (val >> 8); + ((unsigned char *)dst)[3] = val; #endif } @@ -1427,29 +1427,29 @@ sph_dec32be(const void *src) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_LITTLE_ENDIAN - return sph_bswap32(*(const sph_u32 *)src); + return sph_bswap32(*(const sph_u32 *)src); #else - return *(const sph_u32 *)src; + return *(const sph_u32 *)src; #endif #else - if (((SPH_UPTR)src & 3) == 0) { + if (((SPH_UPTR)src & 3) == 0) { #if SPH_LITTLE_ENDIAN - return sph_bswap32(*(const sph_u32 *)src); + return sph_bswap32(*(const sph_u32 *)src); #else - return *(const sph_u32 *)src; + return *(const sph_u32 *)src; #endif - } else { - return ((sph_u32)(((const unsigned char *)src)[0]) << 24) - | ((sph_u32)(((const unsigned char *)src)[1]) << 16) - | ((sph_u32)(((const unsigned char *)src)[2]) << 8) - | (sph_u32)(((const unsigned char *)src)[3]); - } + } else { + return ((sph_u32)(((const unsigned char *)src)[0]) << 24) + | ((sph_u32)(((const unsigned char *)src)[1]) << 16) + | ((sph_u32)(((const unsigned char *)src)[2]) << 8) + | (sph_u32)(((const unsigned char *)src)[3]); + } #endif #else - return ((sph_u32)(((const unsigned char *)src)[0]) << 24) - | ((sph_u32)(((const unsigned char *)src)[1]) << 16) - | ((sph_u32)(((const unsigned char *)src)[2]) << 8) - | (sph_u32)(((const unsigned char *)src)[3]); + return ((sph_u32)(((const unsigned char *)src)[0]) << 24) + | ((sph_u32)(((const unsigned char *)src)[1]) << 16) + | ((sph_u32)(((const unsigned char *)src)[2]) << 8) + | (sph_u32)(((const unsigned char *)src)[3]); #endif } @@ -1464,14 +1464,14 @@ static SPH_INLINE sph_u32 sph_dec32be_aligned(const void *src) { #if SPH_LITTLE_ENDIAN - return sph_bswap32(*(const sph_u32 *)src); + return sph_bswap32(*(const sph_u32 *)src); #elif SPH_BIG_ENDIAN - return *(const sph_u32 *)src; + return *(const sph_u32 *)src; #else - return ((sph_u32)(((const unsigned char *)src)[0]) << 24) - | ((sph_u32)(((const unsigned char *)src)[1]) << 16) - | ((sph_u32)(((const unsigned char *)src)[2]) << 8) - | (sph_u32)(((const unsigned char *)src)[3]); + return ((sph_u32)(((const unsigned char *)src)[0]) << 24) + | ((sph_u32)(((const unsigned char *)src)[1]) << 16) + | ((sph_u32)(((const unsigned char *)src)[2]) << 8) + | (sph_u32)(((const unsigned char *)src)[3]); #endif } @@ -1487,27 +1487,27 @@ sph_enc32le(void *dst, sph_u32 val) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_BIG_ENDIAN - val = sph_bswap32(val); + val = sph_bswap32(val); #endif - *(sph_u32 *)dst = val; + *(sph_u32 *)dst = val; #else - if (((SPH_UPTR)dst & 3) == 0) { + if (((SPH_UPTR)dst & 3) == 0) { #if SPH_BIG_ENDIAN - val = sph_bswap32(val); + val = sph_bswap32(val); #endif - *(sph_u32 *)dst = val; - } else { - ((unsigned char *)dst)[0] = val; - ((unsigned char *)dst)[1] = (val >> 8); - ((unsigned char *)dst)[2] = (val >> 16); - ((unsigned char *)dst)[3] = (val >> 24); - } + *(sph_u32 *)dst = val; + } else { + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = (val >> 8); + ((unsigned char *)dst)[2] = (val >> 16); + ((unsigned char *)dst)[3] = (val >> 24); + } #endif #else - ((unsigned char *)dst)[0] = val; - ((unsigned char *)dst)[1] = (val >> 8); - ((unsigned char *)dst)[2] = (val >> 16); - ((unsigned char *)dst)[3] = (val >> 24); + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = (val >> 8); + ((unsigned char *)dst)[2] = (val >> 16); + ((unsigned char *)dst)[3] = (val >> 24); #endif } @@ -1522,14 +1522,14 @@ static SPH_INLINE void sph_enc32le_aligned(void *dst, sph_u32 val) { #if SPH_LITTLE_ENDIAN - *(sph_u32 *)dst = val; + *(sph_u32 *)dst = val; #elif SPH_BIG_ENDIAN - *(sph_u32 *)dst = sph_bswap32(val); + *(sph_u32 *)dst = sph_bswap32(val); #else - ((unsigned char *)dst)[0] = val; - ((unsigned char *)dst)[1] = (val >> 8); - ((unsigned char *)dst)[2] = (val >> 16); - ((unsigned char *)dst)[3] = (val >> 24); + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = (val >> 8); + ((unsigned char *)dst)[2] = (val >> 16); + ((unsigned char *)dst)[3] = (val >> 24); #endif } @@ -1545,25 +1545,25 @@ sph_dec32le(const void *src) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_BIG_ENDIAN - return sph_bswap32(*(const sph_u32 *)src); + return sph_bswap32(*(const sph_u32 *)src); #else - return *(const sph_u32 *)src; + return *(const sph_u32 *)src; #endif #else - if (((SPH_UPTR)src & 3) == 0) { + if (((SPH_UPTR)src & 3) == 0) { #if SPH_BIG_ENDIAN #if SPH_SPARCV9_GCC && !SPH_NO_ASM - sph_u32 tmp; - - /* - * "__volatile__" is needed here because without it, - * gcc-3.4.3 miscompiles the code and performs the - * access before the test on the address, thus triggering - * a bus error... - */ - __asm__ __volatile__ ( - "lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); - return tmp; + sph_u32 tmp; + + /* + * "__volatile__" is needed here because without it, + * gcc-3.4.3 miscompiles the code and performs the + * access before the test on the address, thus triggering + * a bus error... + */ + __asm__ __volatile__ ( + "lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; /* * On PowerPC, this turns out not to be worth the effort: the inline * assembly makes GCC optimizer uncomfortable, which tends to nullify @@ -1577,30 +1577,30 @@ sph_dec32le(const void *src) * functions, the generic code appears to be efficient enough already. * #elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM - sph_u32 tmp; + sph_u32 tmp; - __asm__ __volatile__ ( - "lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); - return tmp; + __asm__ __volatile__ ( + "lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; */ #else - return sph_bswap32(*(const sph_u32 *)src); + return sph_bswap32(*(const sph_u32 *)src); #endif #else - return *(const sph_u32 *)src; + return *(const sph_u32 *)src; #endif - } else { - return (sph_u32)(((const unsigned char *)src)[0]) - | ((sph_u32)(((const unsigned char *)src)[1]) << 8) - | ((sph_u32)(((const unsigned char *)src)[2]) << 16) - | ((sph_u32)(((const unsigned char *)src)[3]) << 24); - } + } else { + return (sph_u32)(((const unsigned char *)src)[0]) + | ((sph_u32)(((const unsigned char *)src)[1]) << 8) + | ((sph_u32)(((const unsigned char *)src)[2]) << 16) + | ((sph_u32)(((const unsigned char *)src)[3]) << 24); + } #endif #else - return (sph_u32)(((const unsigned char *)src)[0]) - | ((sph_u32)(((const unsigned char *)src)[1]) << 8) - | ((sph_u32)(((const unsigned char *)src)[2]) << 16) - | ((sph_u32)(((const unsigned char *)src)[3]) << 24); + return (sph_u32)(((const unsigned char *)src)[0]) + | ((sph_u32)(((const unsigned char *)src)[1]) << 8) + | ((sph_u32)(((const unsigned char *)src)[2]) << 16) + | ((sph_u32)(((const unsigned char *)src)[3]) << 24); #endif } @@ -1615,30 +1615,30 @@ static SPH_INLINE sph_u32 sph_dec32le_aligned(const void *src) { #if SPH_LITTLE_ENDIAN - return *(const sph_u32 *)src; + return *(const sph_u32 *)src; #elif SPH_BIG_ENDIAN #if SPH_SPARCV9_GCC && !SPH_NO_ASM - sph_u32 tmp; + sph_u32 tmp; - __asm__ __volatile__ ("lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); - return tmp; + __asm__ __volatile__ ("lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; /* * Not worth it generally. * #elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM - sph_u32 tmp; + sph_u32 tmp; - __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); - return tmp; + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; */ #else - return sph_bswap32(*(const sph_u32 *)src); + return sph_bswap32(*(const sph_u32 *)src); #endif #else - return (sph_u32)(((const unsigned char *)src)[0]) - | ((sph_u32)(((const unsigned char *)src)[1]) << 8) - | ((sph_u32)(((const unsigned char *)src)[2]) << 16) - | ((sph_u32)(((const unsigned char *)src)[3]) << 24); + return (sph_u32)(((const unsigned char *)src)[0]) + | ((sph_u32)(((const unsigned char *)src)[1]) << 8) + | ((sph_u32)(((const unsigned char *)src)[2]) << 16) + | ((sph_u32)(((const unsigned char *)src)[3]) << 24); #endif } @@ -1656,35 +1656,35 @@ sph_enc64be(void *dst, sph_u64 val) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_LITTLE_ENDIAN - val = sph_bswap64(val); + val = sph_bswap64(val); #endif - *(sph_u64 *)dst = val; + *(sph_u64 *)dst = val; #else - if (((SPH_UPTR)dst & 7) == 0) { + if (((SPH_UPTR)dst & 7) == 0) { #if SPH_LITTLE_ENDIAN - val = sph_bswap64(val); -#endif - *(sph_u64 *)dst = val; - } else { - ((unsigned char *)dst)[0] = (val >> 56); - ((unsigned char *)dst)[1] = (val >> 48); - ((unsigned char *)dst)[2] = (val >> 40); - ((unsigned char *)dst)[3] = (val >> 32); - ((unsigned char *)dst)[4] = (val >> 24); - ((unsigned char *)dst)[5] = (val >> 16); - ((unsigned char *)dst)[6] = (val >> 8); - ((unsigned char *)dst)[7] = val; - } + val = sph_bswap64(val); +#endif + *(sph_u64 *)dst = val; + } else { + ((unsigned char *)dst)[0] = (val >> 56); + ((unsigned char *)dst)[1] = (val >> 48); + ((unsigned char *)dst)[2] = (val >> 40); + ((unsigned char *)dst)[3] = (val >> 32); + ((unsigned char *)dst)[4] = (val >> 24); + ((unsigned char *)dst)[5] = (val >> 16); + ((unsigned char *)dst)[6] = (val >> 8); + ((unsigned char *)dst)[7] = val; + } #endif #else - ((unsigned char *)dst)[0] = (val >> 56); - ((unsigned char *)dst)[1] = (val >> 48); - ((unsigned char *)dst)[2] = (val >> 40); - ((unsigned char *)dst)[3] = (val >> 32); - ((unsigned char *)dst)[4] = (val >> 24); - ((unsigned char *)dst)[5] = (val >> 16); - ((unsigned char *)dst)[6] = (val >> 8); - ((unsigned char *)dst)[7] = val; + ((unsigned char *)dst)[0] = (val >> 56); + ((unsigned char *)dst)[1] = (val >> 48); + ((unsigned char *)dst)[2] = (val >> 40); + ((unsigned char *)dst)[3] = (val >> 32); + ((unsigned char *)dst)[4] = (val >> 24); + ((unsigned char *)dst)[5] = (val >> 16); + ((unsigned char *)dst)[6] = (val >> 8); + ((unsigned char *)dst)[7] = val; #endif } @@ -1699,18 +1699,18 @@ static SPH_INLINE void sph_enc64be_aligned(void *dst, sph_u64 val) { #if SPH_LITTLE_ENDIAN - *(sph_u64 *)dst = sph_bswap64(val); + *(sph_u64 *)dst = sph_bswap64(val); #elif SPH_BIG_ENDIAN - *(sph_u64 *)dst = val; + *(sph_u64 *)dst = val; #else - ((unsigned char *)dst)[0] = (val >> 56); - ((unsigned char *)dst)[1] = (val >> 48); - ((unsigned char *)dst)[2] = (val >> 40); - ((unsigned char *)dst)[3] = (val >> 32); - ((unsigned char *)dst)[4] = (val >> 24); - ((unsigned char *)dst)[5] = (val >> 16); - ((unsigned char *)dst)[6] = (val >> 8); - ((unsigned char *)dst)[7] = val; + ((unsigned char *)dst)[0] = (val >> 56); + ((unsigned char *)dst)[1] = (val >> 48); + ((unsigned char *)dst)[2] = (val >> 40); + ((unsigned char *)dst)[3] = (val >> 32); + ((unsigned char *)dst)[4] = (val >> 24); + ((unsigned char *)dst)[5] = (val >> 16); + ((unsigned char *)dst)[6] = (val >> 8); + ((unsigned char *)dst)[7] = val; #endif } @@ -1726,37 +1726,37 @@ sph_dec64be(const void *src) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_LITTLE_ENDIAN - return sph_bswap64(*(const sph_u64 *)src); + return sph_bswap64(*(const sph_u64 *)src); #else - return *(const sph_u64 *)src; + return *(const sph_u64 *)src; #endif #else - if (((SPH_UPTR)src & 7) == 0) { + if (((SPH_UPTR)src & 7) == 0) { #if SPH_LITTLE_ENDIAN - return sph_bswap64(*(const sph_u64 *)src); + return sph_bswap64(*(const sph_u64 *)src); #else - return *(const sph_u64 *)src; -#endif - } else { - return ((sph_u64)(((const unsigned char *)src)[0]) << 56) - | ((sph_u64)(((const unsigned char *)src)[1]) << 48) - | ((sph_u64)(((const unsigned char *)src)[2]) << 40) - | ((sph_u64)(((const unsigned char *)src)[3]) << 32) - | ((sph_u64)(((const unsigned char *)src)[4]) << 24) - | ((sph_u64)(((const unsigned char *)src)[5]) << 16) - | ((sph_u64)(((const unsigned char *)src)[6]) << 8) - | (sph_u64)(((const unsigned char *)src)[7]); - } + return *(const sph_u64 *)src; +#endif + } else { + return ((sph_u64)(((const unsigned char *)src)[0]) << 56) + | ((sph_u64)(((const unsigned char *)src)[1]) << 48) + | ((sph_u64)(((const unsigned char *)src)[2]) << 40) + | ((sph_u64)(((const unsigned char *)src)[3]) << 32) + | ((sph_u64)(((const unsigned char *)src)[4]) << 24) + | ((sph_u64)(((const unsigned char *)src)[5]) << 16) + | ((sph_u64)(((const unsigned char *)src)[6]) << 8) + | (sph_u64)(((const unsigned char *)src)[7]); + } #endif #else - return ((sph_u64)(((const unsigned char *)src)[0]) << 56) - | ((sph_u64)(((const unsigned char *)src)[1]) << 48) - | ((sph_u64)(((const unsigned char *)src)[2]) << 40) - | ((sph_u64)(((const unsigned char *)src)[3]) << 32) - | ((sph_u64)(((const unsigned char *)src)[4]) << 24) - | ((sph_u64)(((const unsigned char *)src)[5]) << 16) - | ((sph_u64)(((const unsigned char *)src)[6]) << 8) - | (sph_u64)(((const unsigned char *)src)[7]); + return ((sph_u64)(((const unsigned char *)src)[0]) << 56) + | ((sph_u64)(((const unsigned char *)src)[1]) << 48) + | ((sph_u64)(((const unsigned char *)src)[2]) << 40) + | ((sph_u64)(((const unsigned char *)src)[3]) << 32) + | ((sph_u64)(((const unsigned char *)src)[4]) << 24) + | ((sph_u64)(((const unsigned char *)src)[5]) << 16) + | ((sph_u64)(((const unsigned char *)src)[6]) << 8) + | (sph_u64)(((const unsigned char *)src)[7]); #endif } @@ -1771,18 +1771,18 @@ static SPH_INLINE sph_u64 sph_dec64be_aligned(const void *src) { #if SPH_LITTLE_ENDIAN - return sph_bswap64(*(const sph_u64 *)src); + return sph_bswap64(*(const sph_u64 *)src); #elif SPH_BIG_ENDIAN - return *(const sph_u64 *)src; + return *(const sph_u64 *)src; #else - return ((sph_u64)(((const unsigned char *)src)[0]) << 56) - | ((sph_u64)(((const unsigned char *)src)[1]) << 48) - | ((sph_u64)(((const unsigned char *)src)[2]) << 40) - | ((sph_u64)(((const unsigned char *)src)[3]) << 32) - | ((sph_u64)(((const unsigned char *)src)[4]) << 24) - | ((sph_u64)(((const unsigned char *)src)[5]) << 16) - | ((sph_u64)(((const unsigned char *)src)[6]) << 8) - | (sph_u64)(((const unsigned char *)src)[7]); + return ((sph_u64)(((const unsigned char *)src)[0]) << 56) + | ((sph_u64)(((const unsigned char *)src)[1]) << 48) + | ((sph_u64)(((const unsigned char *)src)[2]) << 40) + | ((sph_u64)(((const unsigned char *)src)[3]) << 32) + | ((sph_u64)(((const unsigned char *)src)[4]) << 24) + | ((sph_u64)(((const unsigned char *)src)[5]) << 16) + | ((sph_u64)(((const unsigned char *)src)[6]) << 8) + | (sph_u64)(((const unsigned char *)src)[7]); #endif } @@ -1798,35 +1798,35 @@ sph_enc64le(void *dst, sph_u64 val) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_BIG_ENDIAN - val = sph_bswap64(val); + val = sph_bswap64(val); #endif - *(sph_u64 *)dst = val; + *(sph_u64 *)dst = val; #else - if (((SPH_UPTR)dst & 7) == 0) { + if (((SPH_UPTR)dst & 7) == 0) { #if SPH_BIG_ENDIAN - val = sph_bswap64(val); -#endif - *(sph_u64 *)dst = val; - } else { - ((unsigned char *)dst)[0] = val; - ((unsigned char *)dst)[1] = (val >> 8); - ((unsigned char *)dst)[2] = (val >> 16); - ((unsigned char *)dst)[3] = (val >> 24); - ((unsigned char *)dst)[4] = (val >> 32); - ((unsigned char *)dst)[5] = (val >> 40); - ((unsigned char *)dst)[6] = (val >> 48); - ((unsigned char *)dst)[7] = (val >> 56); - } + val = sph_bswap64(val); +#endif + *(sph_u64 *)dst = val; + } else { + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = (val >> 8); + ((unsigned char *)dst)[2] = (val >> 16); + ((unsigned char *)dst)[3] = (val >> 24); + ((unsigned char *)dst)[4] = (val >> 32); + ((unsigned char *)dst)[5] = (val >> 40); + ((unsigned char *)dst)[6] = (val >> 48); + ((unsigned char *)dst)[7] = (val >> 56); + } #endif #else - ((unsigned char *)dst)[0] = val; - ((unsigned char *)dst)[1] = (val >> 8); - ((unsigned char *)dst)[2] = (val >> 16); - ((unsigned char *)dst)[3] = (val >> 24); - ((unsigned char *)dst)[4] = (val >> 32); - ((unsigned char *)dst)[5] = (val >> 40); - ((unsigned char *)dst)[6] = (val >> 48); - ((unsigned char *)dst)[7] = (val >> 56); + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = (val >> 8); + ((unsigned char *)dst)[2] = (val >> 16); + ((unsigned char *)dst)[3] = (val >> 24); + ((unsigned char *)dst)[4] = (val >> 32); + ((unsigned char *)dst)[5] = (val >> 40); + ((unsigned char *)dst)[6] = (val >> 48); + ((unsigned char *)dst)[7] = (val >> 56); #endif } @@ -1841,18 +1841,18 @@ static SPH_INLINE void sph_enc64le_aligned(void *dst, sph_u64 val) { #if SPH_LITTLE_ENDIAN - *(sph_u64 *)dst = val; + *(sph_u64 *)dst = val; #elif SPH_BIG_ENDIAN - *(sph_u64 *)dst = sph_bswap64(val); + *(sph_u64 *)dst = sph_bswap64(val); #else - ((unsigned char *)dst)[0] = val; - ((unsigned char *)dst)[1] = (val >> 8); - ((unsigned char *)dst)[2] = (val >> 16); - ((unsigned char *)dst)[3] = (val >> 24); - ((unsigned char *)dst)[4] = (val >> 32); - ((unsigned char *)dst)[5] = (val >> 40); - ((unsigned char *)dst)[6] = (val >> 48); - ((unsigned char *)dst)[7] = (val >> 56); + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = (val >> 8); + ((unsigned char *)dst)[2] = (val >> 16); + ((unsigned char *)dst)[3] = (val >> 24); + ((unsigned char *)dst)[4] = (val >> 32); + ((unsigned char *)dst)[5] = (val >> 40); + ((unsigned char *)dst)[6] = (val >> 48); + ((unsigned char *)dst)[7] = (val >> 56); #endif } @@ -1868,59 +1868,59 @@ sph_dec64le(const void *src) #if defined SPH_UPTR #if SPH_UNALIGNED #if SPH_BIG_ENDIAN - return sph_bswap64(*(const sph_u64 *)src); + return sph_bswap64(*(const sph_u64 *)src); #else - return *(const sph_u64 *)src; + return *(const sph_u64 *)src; #endif #else - if (((SPH_UPTR)src & 7) == 0) { + if (((SPH_UPTR)src & 7) == 0) { #if SPH_BIG_ENDIAN #if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM - sph_u64 tmp; + sph_u64 tmp; - __asm__ __volatile__ ( - "ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); - return tmp; + __asm__ __volatile__ ( + "ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; /* * Not worth it generally. * #elif SPH_PPC32_GCC && !SPH_NO_ASM - return (sph_u64)sph_dec32le_aligned(src) - | ((sph_u64)sph_dec32le_aligned( - (const char *)src + 4) << 32); + return (sph_u64)sph_dec32le_aligned(src) + | ((sph_u64)sph_dec32le_aligned( + (const char *)src + 4) << 32); #elif SPH_PPC64_GCC && !SPH_NO_ASM - sph_u64 tmp; + sph_u64 tmp; - __asm__ __volatile__ ( - "ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); - return tmp; + __asm__ __volatile__ ( + "ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; */ #else - return sph_bswap64(*(const sph_u64 *)src); + return sph_bswap64(*(const sph_u64 *)src); #endif #else - return *(const sph_u64 *)src; -#endif - } else { - return (sph_u64)(((const unsigned char *)src)[0]) - | ((sph_u64)(((const unsigned char *)src)[1]) << 8) - | ((sph_u64)(((const unsigned char *)src)[2]) << 16) - | ((sph_u64)(((const unsigned char *)src)[3]) << 24) - | ((sph_u64)(((const unsigned char *)src)[4]) << 32) - | ((sph_u64)(((const unsigned char *)src)[5]) << 40) - | ((sph_u64)(((const unsigned char *)src)[6]) << 48) - | ((sph_u64)(((const unsigned char *)src)[7]) << 56); - } + return *(const sph_u64 *)src; +#endif + } else { + return (sph_u64)(((const unsigned char *)src)[0]) + | ((sph_u64)(((const unsigned char *)src)[1]) << 8) + | ((sph_u64)(((const unsigned char *)src)[2]) << 16) + | ((sph_u64)(((const unsigned char *)src)[3]) << 24) + | ((sph_u64)(((const unsigned char *)src)[4]) << 32) + | ((sph_u64)(((const unsigned char *)src)[5]) << 40) + | ((sph_u64)(((const unsigned char *)src)[6]) << 48) + | ((sph_u64)(((const unsigned char *)src)[7]) << 56); + } #endif #else - return (sph_u64)(((const unsigned char *)src)[0]) - | ((sph_u64)(((const unsigned char *)src)[1]) << 8) - | ((sph_u64)(((const unsigned char *)src)[2]) << 16) - | ((sph_u64)(((const unsigned char *)src)[3]) << 24) - | ((sph_u64)(((const unsigned char *)src)[4]) << 32) - | ((sph_u64)(((const unsigned char *)src)[5]) << 40) - | ((sph_u64)(((const unsigned char *)src)[6]) << 48) - | ((sph_u64)(((const unsigned char *)src)[7]) << 56); + return (sph_u64)(((const unsigned char *)src)[0]) + | ((sph_u64)(((const unsigned char *)src)[1]) << 8) + | ((sph_u64)(((const unsigned char *)src)[2]) << 16) + | ((sph_u64)(((const unsigned char *)src)[3]) << 24) + | ((sph_u64)(((const unsigned char *)src)[4]) << 32) + | ((sph_u64)(((const unsigned char *)src)[5]) << 40) + | ((sph_u64)(((const unsigned char *)src)[6]) << 48) + | ((sph_u64)(((const unsigned char *)src)[7]) << 56); #endif } @@ -1935,37 +1935,37 @@ static SPH_INLINE sph_u64 sph_dec64le_aligned(const void *src) { #if SPH_LITTLE_ENDIAN - return *(const sph_u64 *)src; + return *(const sph_u64 *)src; #elif SPH_BIG_ENDIAN #if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM - sph_u64 tmp; + sph_u64 tmp; - __asm__ __volatile__ ("ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); - return tmp; + __asm__ __volatile__ ("ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; /* * Not worth it generally. * #elif SPH_PPC32_GCC && !SPH_NO_ASM - return (sph_u64)sph_dec32le_aligned(src) - | ((sph_u64)sph_dec32le_aligned((const char *)src + 4) << 32); + return (sph_u64)sph_dec32le_aligned(src) + | ((sph_u64)sph_dec32le_aligned((const char *)src + 4) << 32); #elif SPH_PPC64_GCC && !SPH_NO_ASM - sph_u64 tmp; + sph_u64 tmp; - __asm__ __volatile__ ("ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); - return tmp; + __asm__ __volatile__ ("ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; */ #else - return sph_bswap64(*(const sph_u64 *)src); + return sph_bswap64(*(const sph_u64 *)src); #endif #else - return (sph_u64)(((const unsigned char *)src)[0]) - | ((sph_u64)(((const unsigned char *)src)[1]) << 8) - | ((sph_u64)(((const unsigned char *)src)[2]) << 16) - | ((sph_u64)(((const unsigned char *)src)[3]) << 24) - | ((sph_u64)(((const unsigned char *)src)[4]) << 32) - | ((sph_u64)(((const unsigned char *)src)[5]) << 40) - | ((sph_u64)(((const unsigned char *)src)[6]) << 48) - | ((sph_u64)(((const unsigned char *)src)[7]) << 56); + return (sph_u64)(((const unsigned char *)src)[0]) + | ((sph_u64)(((const unsigned char *)src)[1]) << 8) + | ((sph_u64)(((const unsigned char *)src)[2]) << 16) + | ((sph_u64)(((const unsigned char *)src)[3]) << 24) + | ((sph_u64)(((const unsigned char *)src)[4]) << 32) + | ((sph_u64)(((const unsigned char *)src)[5]) << 40) + | ((sph_u64)(((const unsigned char *)src)[6]) << 48) + | ((sph_u64)(((const unsigned char *)src)[7]) << 56); #endif } diff --git a/src/ecwrapper.cpp b/src/ecwrapper.cpp index 4c7306e48aad5..6e6ef19ee8631 100644 --- a/src/ecwrapper.cpp +++ b/src/ecwrapper.cpp @@ -240,11 +240,11 @@ bool CECKey::Recover(const uint256& hash, const unsigned char* p64, int rec) BIGNUM *sig_s = NULL; if (!(sig_r = BN_bin2bn(&p64[0], 32, nullptr)) || !(sig_s = BN_bin2bn(&p64[32], 32, nullptr)) || - !ECDSA_SIG_set0(sig, sig_r, sig_s)) { - BN_free(sig_r); - BN_free(sig_s); - return false; - } + !ECDSA_SIG_set0(sig, sig_r, sig_s)) { + BN_free(sig_r); + BN_free(sig_s); + return false; + } #else BN_bin2bn(&p64[0], 32, sig->r); BN_bin2bn(&p64[32], 32, sig->s); diff --git a/src/libzerocoin/Accumulator.cpp b/src/libzerocoin/Accumulator.cpp index 5a56564bc22c2..350fc377a76bd 100644 --- a/src/libzerocoin/Accumulator.cpp +++ b/src/libzerocoin/Accumulator.cpp @@ -20,25 +20,25 @@ namespace libzerocoin { //Accumulator class Accumulator::Accumulator(const AccumulatorAndProofParams* p, const CoinDenomination d): params(p) { - if (!(params->initialized)) { - throw std::runtime_error("Invalid parameters for accumulator"); - } + if (!(params->initialized)) { + throw std::runtime_error("Invalid parameters for accumulator"); + } denomination = d; - this->value = this->params->accumulatorBase; + this->value = this->params->accumulatorBase; } Accumulator::Accumulator(const ZerocoinParams* p, const CoinDenomination d, const Bignum bnValue) { - this->params = &(p->accumulatorParams); + this->params = &(p->accumulatorParams); denomination = d; - if (!(params->initialized)) { - throw std::runtime_error("Invalid parameters for accumulator"); - } + if (!(params->initialized)) { + throw std::runtime_error("Invalid parameters for accumulator"); + } - if(bnValue != 0) - this->value = bnValue; - else - this->value = this->params->accumulatorBase; + if(bnValue != 0) + this->value = bnValue; + else + this->value = this->params->accumulatorBase; } void Accumulator::increment(const CBigNum& bnValue) { @@ -47,44 +47,44 @@ void Accumulator::increment(const CBigNum& bnValue) { } void Accumulator::accumulate(const PublicCoin& coin) { - // Make sure we're initialized - if(!(this->value)) { - throw std::runtime_error("Accumulator is not initialized"); - } + // Make sure we're initialized + if(!(this->value)) { + throw std::runtime_error("Accumulator is not initialized"); + } - if(this->denomination != coin.getDenomination()) { - std::cout << "Wrong denomination for coin. Expected coins of denomination: "; + if(this->denomination != coin.getDenomination()) { + std::cout << "Wrong denomination for coin. Expected coins of denomination: "; std::cout << this->denomination; std::cout << ". Instead, got a coin of denomination: "; std::cout << coin.getDenomination(); std::cout << "\n"; - throw std::runtime_error("Wrong denomination for coin"); - } + throw std::runtime_error("Wrong denomination for coin"); + } - if(coin.validate()) { - increment(coin.getValue()); - } else { - std::cout << "Coin not valid\n"; + if(coin.validate()) { + increment(coin.getValue()); + } else { + std::cout << "Coin not valid\n"; throw std::runtime_error("Coin is not valid"); - } + } } CoinDenomination Accumulator::getDenomination() const { - return this->denomination; + return this->denomination; } const CBigNum& Accumulator::getValue() const { - return this->value; + return this->value; } //Manually set accumulator value void Accumulator::setValue(CBigNum bnValue) { - this->value = bnValue; + this->value = bnValue; } Accumulator& Accumulator::operator += (const PublicCoin& c) { - this->accumulate(c); - return *this; + this->accumulate(c); + return *this; } Accumulator& Accumulator::operator = (Accumulator rhs) { @@ -93,7 +93,7 @@ Accumulator& Accumulator::operator = (Accumulator rhs) { } bool Accumulator::operator == (const Accumulator rhs) const { - return this->value == rhs.value; + return this->value == rhs.value; } //AccumulatorWitness class @@ -107,9 +107,9 @@ void AccumulatorWitness::resetValue(const Accumulator& checkpoint, const PublicC } void AccumulatorWitness::AddElement(const PublicCoin& c) { - if(element.getValue() != c.getValue()) { - witness += c; - } + if(element.getValue() != c.getValue()) { + witness += c; + } } //warning check pubcoin value & denom outside of this function! @@ -118,32 +118,32 @@ void AccumulatorWitness::addRawValue(const CBigNum& bnValue) { } const CBigNum& AccumulatorWitness::getValue() const { - return this->witness.getValue(); + return this->witness.getValue(); } bool AccumulatorWitness::VerifyWitness(const Accumulator& a, const PublicCoin &publicCoin) const { - Accumulator temp(witness); - temp += element; - if (!(temp == a)) { - LogPrintf("Accumulator does not verify.\n"); - } - if (this->element != publicCoin) { - LogPrintf("Pubcoin does not verify.\n"); - } - return (temp == a && this->element == publicCoin); + Accumulator temp(witness); + temp += element; + if (!(temp == a)) { + LogPrintf("Accumulator does not verify.\n"); + } + if (this->element != publicCoin) { + LogPrintf("Pubcoin does not verify.\n"); + } + return (temp == a && this->element == publicCoin); } AccumulatorWitness& AccumulatorWitness::operator +=( const PublicCoin& rhs) { - this->AddElement(rhs); - return *this; + this->AddElement(rhs); + return *this; } AccumulatorWitness& AccumulatorWitness::operator =(AccumulatorWitness rhs) { // Not pretty, but seems to work (SPOCK) if (&witness != &rhs.witness) this->witness = rhs.witness; if (&element != &rhs.element) std::swap(element, rhs.element); - return *this; + return *this; } } /* namespace libzerocoin */ diff --git a/src/libzerocoin/Accumulator.h b/src/libzerocoin/Accumulator.h index 8e4d3ef1e1740..d1c5e0ed8c7fd 100644 --- a/src/libzerocoin/Accumulator.h +++ b/src/libzerocoin/Accumulator.h @@ -23,80 +23,80 @@ namespace libzerocoin { class Accumulator { public: - /** - * @brief Construct an Accumulator from a stream. - * @param p An AccumulatorAndProofParams object containing global parameters - * @param d the denomination of coins we are accumulating - * @throw Zerocoin exception in case of invalid parameters - **/ - template - Accumulator(const AccumulatorAndProofParams* p, Stream& strm): params(p) { - strm >> *this; - } - - template - Accumulator(const ZerocoinParams* p, Stream& strm) { - strm >> *this; - this->params = &(p->accumulatorParams); - } - - /** - * @brief Construct an Accumulator from a Params object. - * @param p A Params object containing global parameters - * @param d the denomination of coins we are accumulating - * @throw Zerocoin exception in case of invalid parameters - **/ - Accumulator(const AccumulatorAndProofParams* p, const CoinDenomination d); - - Accumulator(const ZerocoinParams* p, const CoinDenomination d, Bignum bnValue = 0); - - /** - * Accumulate a coin into the accumulator. Validates - * the coin prior to accumulation. - * - * @param coin A PublicCoin to accumulate. - * - * @throw Zerocoin exception if the coin is not valid. - * - **/ - void accumulate(const PublicCoin &coin); + /** + * @brief Construct an Accumulator from a stream. + * @param p An AccumulatorAndProofParams object containing global parameters + * @param d the denomination of coins we are accumulating + * @throw Zerocoin exception in case of invalid parameters + **/ + template + Accumulator(const AccumulatorAndProofParams* p, Stream& strm): params(p) { + strm >> *this; + } + + template + Accumulator(const ZerocoinParams* p, Stream& strm) { + strm >> *this; + this->params = &(p->accumulatorParams); + } + + /** + * @brief Construct an Accumulator from a Params object. + * @param p A Params object containing global parameters + * @param d the denomination of coins we are accumulating + * @throw Zerocoin exception in case of invalid parameters + **/ + Accumulator(const AccumulatorAndProofParams* p, const CoinDenomination d); + + Accumulator(const ZerocoinParams* p, const CoinDenomination d, Bignum bnValue = 0); + + /** + * Accumulate a coin into the accumulator. Validates + * the coin prior to accumulation. + * + * @param coin A PublicCoin to accumulate. + * + * @throw Zerocoin exception if the coin is not valid. + * + **/ + void accumulate(const PublicCoin &coin); void increment(const CBigNum& bnValue); - CoinDenomination getDenomination() const; - /** Get the accumulator result - * - * @return a CBigNum containing the result. - */ - const CBigNum& getValue() const; - - void setValue(CBigNum bnValue); - - - // /** - // * Used to set the accumulator value - // * - // * Use this to handle accumulator checkpoints - // * @param b the value to set the accumulator to. - // * @throw A ZerocoinException if the accumulator value is invalid. - // */ - // void setValue(CBigNum &b); // shouldn't this be a constructor? - - /** Used to accumulate a coin - * - * @param c the coin to accumulate - * @return a refrence to the updated accumulator. - */ - Accumulator& operator +=(const PublicCoin& c); + CoinDenomination getDenomination() const; + /** Get the accumulator result + * + * @return a CBigNum containing the result. + */ + const CBigNum& getValue() const; + + void setValue(CBigNum bnValue); + + + // /** + // * Used to set the accumulator value + // * + // * Use this to handle accumulator checkpoints + // * @param b the value to set the accumulator to. + // * @throw A ZerocoinException if the accumulator value is invalid. + // */ + // void setValue(CBigNum &b); // shouldn't this be a constructor? + + /** Used to accumulate a coin + * + * @param c the coin to accumulate + * @return a refrence to the updated accumulator. + */ + Accumulator& operator +=(const PublicCoin& c); Accumulator& operator =(Accumulator rhs); - bool operator==(const Accumulator rhs) const; - ADD_SERIALIZE_METHODS; + bool operator==(const Accumulator rhs) const; + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(value); + READWRITE(value); READWRITE(denomination); - } + } private: - const AccumulatorAndProofParams* params; - CBigNum value; + const AccumulatorAndProofParams* params; + CBigNum value; CoinDenomination denomination; }; @@ -105,54 +105,54 @@ class Accumulator { */ class AccumulatorWitness { public: - template - AccumulatorWitness(const ZerocoinParams* p, Stream& strm) { - strm >> *this; - } - - /** Construct's a witness. You must add all elements after the witness - * @param p pointer to params - * @param checkpoint the last known accumulator value before the element was added - * @param coin the coin we want a witness to - */ - AccumulatorWitness(const ZerocoinParams* p, const Accumulator& checkpoint, const PublicCoin coin); - - /** Adds element to the set whose's accumulation we are proving coin is a member of - * - * @param c the coin to add - */ - void AddElement(const PublicCoin& c); + template + AccumulatorWitness(const ZerocoinParams* p, Stream& strm) { + strm >> *this; + } + + /** Construct's a witness. You must add all elements after the witness + * @param p pointer to params + * @param checkpoint the last known accumulator value before the element was added + * @param coin the coin we want a witness to + */ + AccumulatorWitness(const ZerocoinParams* p, const Accumulator& checkpoint, const PublicCoin coin); + + /** Adds element to the set whose's accumulation we are proving coin is a member of + * + * @param c the coin to add + */ + void AddElement(const PublicCoin& c); /** Adds element to the set whose's accumulation we are proving coin is a member of. No checks performed! - * - * @param bnValue the coin's value to add - */ + * + * @param bnValue the coin's value to add + */ void addRawValue(const CBigNum& bnValue); - /** - * - * @return the value of the witness - */ - const CBigNum& getValue() const; + /** + * + * @return the value of the witness + */ + const CBigNum& getValue() const; void resetValue(const Accumulator& checkpoint, const PublicCoin coin); - /** Checks that this is a witness to the accumulation of coin - * @param a the accumulator we are checking against. - * @param publicCoin the coin we're providing a witness for - * @return True if the witness computation validates - */ - bool VerifyWitness(const Accumulator& a, const PublicCoin &publicCoin) const; + /** Checks that this is a witness to the accumulation of coin + * @param a the accumulator we are checking against. + * @param publicCoin the coin we're providing a witness for + * @return True if the witness computation validates + */ + bool VerifyWitness(const Accumulator& a, const PublicCoin &publicCoin) const; - /** - * Adds rhs to the set whose's accumulation ware proving coin is a member of - * @param rhs the PublicCoin to add - * @return - */ - AccumulatorWitness& operator +=(const PublicCoin& rhs); + /** + * Adds rhs to the set whose's accumulation ware proving coin is a member of + * @param rhs the PublicCoin to add + * @return + */ + AccumulatorWitness& operator +=(const PublicCoin& rhs); AccumulatorWitness& operator =(AccumulatorWitness rhs); private: - Accumulator witness; + Accumulator witness; PublicCoin element; // was const but changed to use setting in assignment }; diff --git a/src/libzerocoin/AccumulatorProofOfKnowledge.cpp b/src/libzerocoin/AccumulatorProofOfKnowledge.cpp index b3a102dd3f2dc..eedeec2040e2d 100644 --- a/src/libzerocoin/AccumulatorProofOfKnowledge.cpp +++ b/src/libzerocoin/AccumulatorProofOfKnowledge.cpp @@ -21,126 +21,126 @@ AccumulatorProofOfKnowledge::AccumulatorProofOfKnowledge(const AccumulatorAndPro const Commitment& commitmentToCoin, const AccumulatorWitness& witness, Accumulator& a): params(p) { - CBigNum sg = params->accumulatorPoKCommitmentGroup.g; - CBigNum sh = params->accumulatorPoKCommitmentGroup.h; - - CBigNum g_n = params->accumulatorQRNCommitmentGroup.g; - CBigNum h_n = params->accumulatorQRNCommitmentGroup.h; - - CBigNum e = commitmentToCoin.getContents(); - CBigNum r = commitmentToCoin.getRandomness(); - - CBigNum aM_4 = params->accumulatorModulus/CBigNum((long)4); - - CBigNum r_1 = CBigNum::randBignum(params->accumulatorModulus/4); - CBigNum r_2 = CBigNum::randBignum(params->accumulatorModulus/4); - CBigNum r_3 = CBigNum::randBignum(params->accumulatorModulus/4); - - this->C_e = g_n.pow_mod(e, params->accumulatorModulus) * h_n.pow_mod(r_1, params->accumulatorModulus); - this->C_u = witness.getValue() * h_n.pow_mod(r_2, params->accumulatorModulus); - this->C_r = g_n.pow_mod(r_2, params->accumulatorModulus) * h_n.pow_mod(r_3, params->accumulatorModulus); - - CBigNum r_alpha = CBigNum::randBignum(params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime)); - if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { - r_alpha = 0-r_alpha; - } - - CBigNum r_gamma = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - CBigNum r_phi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - CBigNum r_psi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - CBigNum r_sigma = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - CBigNum r_xi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - - CBigNum r_epsilon = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime)); - if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { - r_epsilon = 0-r_epsilon; - } - CBigNum r_eta = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime)); - if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { - r_eta = 0-r_eta; - } - CBigNum r_zeta = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime)); - if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { - r_zeta = 0-r_zeta; - } - - CBigNum r_beta = CBigNum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * CBigNum(2).pow(params->k_prime + params->k_dprime)); - if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { - r_beta = 0-r_beta; - } - CBigNum r_delta = CBigNum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * CBigNum(2).pow(params->k_prime + params->k_dprime)); - if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { - r_delta = 0-r_delta; - } - - this->st_1 = (sg.pow_mod(r_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - this->st_2 = (((commitmentToCoin.getCommitmentValue() * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(r_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(r_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - this->st_3 = ((sg * commitmentToCoin.getCommitmentValue()).pow_mod(r_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - - this->t_1 = (h_n.pow_mod(r_zeta, params->accumulatorModulus) * g_n.pow_mod(r_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; - this->t_2 = (h_n.pow_mod(r_eta, params->accumulatorModulus) * g_n.pow_mod(r_alpha, params->accumulatorModulus)) % params->accumulatorModulus; - this->t_3 = (C_u.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; - this->t_4 = (C_r.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; - - CHashWriter hasher(0,0); - hasher << *params << sg << sh << g_n << h_n << commitmentToCoin.getCommitmentValue() << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; - - //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. - CBigNum c = CBigNum(hasher.GetHash()); - - this->s_alpha = r_alpha - c*e; - this->s_beta = r_beta - c*r_2*e; - this->s_zeta = r_zeta - c*r_3; - this->s_sigma = r_sigma - c*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); - this->s_eta = r_eta - c*r_1; - this->s_epsilon = r_epsilon - c*r_2; - this->s_delta = r_delta - c*r_3*e; - this->s_xi = r_xi + c*r*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); - this->s_phi = (r_phi - c*r) % params->accumulatorPoKCommitmentGroup.groupOrder; - this->s_gamma = r_gamma - c*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); - this->s_psi = r_psi + c*r*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); + CBigNum sg = params->accumulatorPoKCommitmentGroup.g; + CBigNum sh = params->accumulatorPoKCommitmentGroup.h; + + CBigNum g_n = params->accumulatorQRNCommitmentGroup.g; + CBigNum h_n = params->accumulatorQRNCommitmentGroup.h; + + CBigNum e = commitmentToCoin.getContents(); + CBigNum r = commitmentToCoin.getRandomness(); + + CBigNum aM_4 = params->accumulatorModulus/CBigNum((long)4); + + CBigNum r_1 = CBigNum::randBignum(params->accumulatorModulus/4); + CBigNum r_2 = CBigNum::randBignum(params->accumulatorModulus/4); + CBigNum r_3 = CBigNum::randBignum(params->accumulatorModulus/4); + + this->C_e = g_n.pow_mod(e, params->accumulatorModulus) * h_n.pow_mod(r_1, params->accumulatorModulus); + this->C_u = witness.getValue() * h_n.pow_mod(r_2, params->accumulatorModulus); + this->C_r = g_n.pow_mod(r_2, params->accumulatorModulus) * h_n.pow_mod(r_3, params->accumulatorModulus); + + CBigNum r_alpha = CBigNum::randBignum(params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime)); + if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { + r_alpha = 0-r_alpha; + } + + CBigNum r_gamma = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + CBigNum r_phi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + CBigNum r_psi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + CBigNum r_sigma = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + CBigNum r_xi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + + CBigNum r_epsilon = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime)); + if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { + r_epsilon = 0-r_epsilon; + } + CBigNum r_eta = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime)); + if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { + r_eta = 0-r_eta; + } + CBigNum r_zeta = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime)); + if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { + r_zeta = 0-r_zeta; + } + + CBigNum r_beta = CBigNum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * CBigNum(2).pow(params->k_prime + params->k_dprime)); + if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { + r_beta = 0-r_beta; + } + CBigNum r_delta = CBigNum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * CBigNum(2).pow(params->k_prime + params->k_dprime)); + if(!(CBigNum::randBignum(CBigNum(3)) % 2)) { + r_delta = 0-r_delta; + } + + this->st_1 = (sg.pow_mod(r_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + this->st_2 = (((commitmentToCoin.getCommitmentValue() * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(r_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(r_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + this->st_3 = ((sg * commitmentToCoin.getCommitmentValue()).pow_mod(r_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + + this->t_1 = (h_n.pow_mod(r_zeta, params->accumulatorModulus) * g_n.pow_mod(r_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; + this->t_2 = (h_n.pow_mod(r_eta, params->accumulatorModulus) * g_n.pow_mod(r_alpha, params->accumulatorModulus)) % params->accumulatorModulus; + this->t_3 = (C_u.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; + this->t_4 = (C_r.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; + + CHashWriter hasher(0,0); + hasher << *params << sg << sh << g_n << h_n << commitmentToCoin.getCommitmentValue() << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; + + //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. + CBigNum c = CBigNum(hasher.GetHash()); + + this->s_alpha = r_alpha - c*e; + this->s_beta = r_beta - c*r_2*e; + this->s_zeta = r_zeta - c*r_3; + this->s_sigma = r_sigma - c*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); + this->s_eta = r_eta - c*r_1; + this->s_epsilon = r_epsilon - c*r_2; + this->s_delta = r_delta - c*r_3*e; + this->s_xi = r_xi + c*r*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); + this->s_phi = (r_phi - c*r) % params->accumulatorPoKCommitmentGroup.groupOrder; + this->s_gamma = r_gamma - c*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); + this->s_psi = r_psi + c*r*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); } /** Verifies that a commitment c is accumulated in accumulator a */ bool AccumulatorProofOfKnowledge:: Verify(const Accumulator& a, const CBigNum& valueOfCommitmentToCoin) const { - CBigNum sg = params->accumulatorPoKCommitmentGroup.g; - CBigNum sh = params->accumulatorPoKCommitmentGroup.h; + CBigNum sg = params->accumulatorPoKCommitmentGroup.g; + CBigNum sh = params->accumulatorPoKCommitmentGroup.h; - CBigNum g_n = params->accumulatorQRNCommitmentGroup.g; - CBigNum h_n = params->accumulatorQRNCommitmentGroup.h; + CBigNum g_n = params->accumulatorQRNCommitmentGroup.g; + CBigNum h_n = params->accumulatorQRNCommitmentGroup.h; - //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. - CHashWriter hasher(0,0); - hasher << *params << sg << sh << g_n << h_n << valueOfCommitmentToCoin << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; + //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. + CHashWriter hasher(0,0); + hasher << *params << sg << sh << g_n << h_n << valueOfCommitmentToCoin << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; - CBigNum c = CBigNum(hasher.GetHash()); //this hash should be of length k_prime bits + CBigNum c = CBigNum(hasher.GetHash()); //this hash should be of length k_prime bits - CBigNum st_1_prime = (valueOfCommitmentToCoin.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * sg.pow_mod(s_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - CBigNum st_2_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * ((valueOfCommitmentToCoin * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(s_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(s_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - CBigNum st_3_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * (sg * valueOfCommitmentToCoin).pow_mod(s_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + CBigNum st_1_prime = (valueOfCommitmentToCoin.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * sg.pow_mod(s_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + CBigNum st_2_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * ((valueOfCommitmentToCoin * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(s_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(s_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + CBigNum st_3_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * (sg * valueOfCommitmentToCoin).pow_mod(s_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - CBigNum t_1_prime = (C_r.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_zeta, params->accumulatorModulus) * g_n.pow_mod(s_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; - CBigNum t_2_prime = (C_e.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_eta, params->accumulatorModulus) * g_n.pow_mod(s_alpha, params->accumulatorModulus)) % params->accumulatorModulus; - CBigNum t_3_prime = ((a.getValue()).pow_mod(c, params->accumulatorModulus) * C_u.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; - CBigNum t_4_prime = (C_r.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; + CBigNum t_1_prime = (C_r.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_zeta, params->accumulatorModulus) * g_n.pow_mod(s_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; + CBigNum t_2_prime = (C_e.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_eta, params->accumulatorModulus) * g_n.pow_mod(s_alpha, params->accumulatorModulus)) % params->accumulatorModulus; + CBigNum t_3_prime = ((a.getValue()).pow_mod(c, params->accumulatorModulus) * C_u.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; + CBigNum t_4_prime = (C_r.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; - bool result = false; + bool result = false; - bool result_st1 = (st_1 == st_1_prime); - bool result_st2 = (st_2 == st_2_prime); - bool result_st3 = (st_3 == st_3_prime); + bool result_st1 = (st_1 == st_1_prime); + bool result_st2 = (st_2 == st_2_prime); + bool result_st3 = (st_3 == st_3_prime); - bool result_t1 = (t_1 == t_1_prime); - bool result_t2 = (t_2 == t_2_prime); - bool result_t3 = (t_3 == t_3_prime); - bool result_t4 = (t_4 == t_4_prime); + bool result_t1 = (t_1 == t_1_prime); + bool result_t2 = (t_2 == t_2_prime); + bool result_t3 = (t_3 == t_3_prime); + bool result_t4 = (t_4 == t_4_prime); - bool result_range = ((s_alpha >= -(params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime + 1))) && (s_alpha <= (params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime + 1)))); + bool result_range = ((s_alpha >= -(params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime + 1))) && (s_alpha <= (params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime + 1)))); - result = result_st1 && result_st2 && result_st3 && result_t1 && result_t2 && result_t3 && result_t4 && result_range; + result = result_st1 && result_st2 && result_st3 && result_t1 && result_t2 && result_t3 && result_t4 && result_range; - return result; + return result; } } /* namespace libzerocoin */ diff --git a/src/libzerocoin/AccumulatorProofOfKnowledge.h b/src/libzerocoin/AccumulatorProofOfKnowledge.h index 8fa0f467baa46..4b9329f453ec5 100644 --- a/src/libzerocoin/AccumulatorProofOfKnowledge.h +++ b/src/libzerocoin/AccumulatorProofOfKnowledge.h @@ -24,71 +24,71 @@ namespace libzerocoin { */ class AccumulatorProofOfKnowledge { public: - AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p); + AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p); - /** Generates a proof that a commitment to a coin c was accumulated - * @param p Cryptographic parameters - * @param commitmentToCoin commitment containing the coin we want to prove is accumulated - * @param witness The witness to the accumulation of the coin - * @param a - */ - AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p, const Commitment& commitmentToCoin, const AccumulatorWitness& witness, Accumulator& a); - /** Verifies that a commitment c is accumulated in accumulated a - */ - bool Verify(const Accumulator& a,const CBigNum& valueOfCommitmentToCoin) const; - - ADD_SERIALIZE_METHODS; + /** Generates a proof that a commitment to a coin c was accumulated + * @param p Cryptographic parameters + * @param commitmentToCoin commitment containing the coin we want to prove is accumulated + * @param witness The witness to the accumulation of the coin + * @param a + */ + AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p, const Commitment& commitmentToCoin, const AccumulatorWitness& witness, Accumulator& a); + /** Verifies that a commitment c is accumulated in accumulated a + */ + bool Verify(const Accumulator& a,const CBigNum& valueOfCommitmentToCoin) const; + + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(C_e); - READWRITE(C_u); - READWRITE(C_r); - READWRITE(st_1); - READWRITE(st_2); - READWRITE(st_3); - READWRITE(t_1); - READWRITE(t_2); - READWRITE(t_3); - READWRITE(t_4); - READWRITE(s_alpha); - READWRITE(s_beta); - READWRITE(s_zeta); - READWRITE(s_sigma); - READWRITE(s_eta); - READWRITE(s_epsilon); - READWRITE(s_delta); - READWRITE(s_xi); - READWRITE(s_phi); - READWRITE(s_gamma); - READWRITE(s_psi); - } + READWRITE(C_e); + READWRITE(C_u); + READWRITE(C_r); + READWRITE(st_1); + READWRITE(st_2); + READWRITE(st_3); + READWRITE(t_1); + READWRITE(t_2); + READWRITE(t_3); + READWRITE(t_4); + READWRITE(s_alpha); + READWRITE(s_beta); + READWRITE(s_zeta); + READWRITE(s_sigma); + READWRITE(s_eta); + READWRITE(s_epsilon); + READWRITE(s_delta); + READWRITE(s_xi); + READWRITE(s_phi); + READWRITE(s_gamma); + READWRITE(s_psi); + } private: - const AccumulatorAndProofParams* params; + const AccumulatorAndProofParams* params; - /* Return values for proof */ - CBigNum C_e; - CBigNum C_u; - CBigNum C_r; + /* Return values for proof */ + CBigNum C_e; + CBigNum C_u; + CBigNum C_r; - CBigNum st_1; - CBigNum st_2; - CBigNum st_3; + CBigNum st_1; + CBigNum st_2; + CBigNum st_3; - CBigNum t_1; - CBigNum t_2; - CBigNum t_3; - CBigNum t_4; + CBigNum t_1; + CBigNum t_2; + CBigNum t_3; + CBigNum t_4; - CBigNum s_alpha; - CBigNum s_beta; - CBigNum s_zeta; - CBigNum s_sigma; - CBigNum s_eta; - CBigNum s_epsilon; - CBigNum s_delta; - CBigNum s_xi; - CBigNum s_phi; - CBigNum s_gamma; - CBigNum s_psi; + CBigNum s_alpha; + CBigNum s_beta; + CBigNum s_zeta; + CBigNum s_sigma; + CBigNum s_eta; + CBigNum s_epsilon; + CBigNum s_delta; + CBigNum s_xi; + CBigNum s_phi; + CBigNum s_gamma; + CBigNum s_psi; }; } /* namespace libzerocoin */ diff --git a/src/libzerocoin/Coin.cpp b/src/libzerocoin/Coin.cpp index 8ae7ce4e2bde0..4ccbc2a21f8ca 100644 --- a/src/libzerocoin/Coin.cpp +++ b/src/libzerocoin/Coin.cpp @@ -21,29 +21,29 @@ namespace libzerocoin { //PublicCoin class PublicCoin::PublicCoin(const ZerocoinParams* p): - params(p) { - if (this->params->initialized == false) { - throw std::runtime_error("Params are not initialized"); - } + params(p) { + if (this->params->initialized == false) { + throw std::runtime_error("Params are not initialized"); + } // Assume this will get set by another method later denomination = ZQ_ERROR; }; PublicCoin::PublicCoin(const ZerocoinParams* p, const CBigNum& coin, const CoinDenomination d): - params(p), value(coin) { - if (this->params->initialized == false) { - throw std::runtime_error("Params are not initialized"); - } - - denomination = d; - for(const CoinDenomination denom : libzerocoin::zerocoinDenomList) { - if(denom == d) - denomination = d; - } + params(p), value(coin) { + if (this->params->initialized == false) { + throw std::runtime_error("Params are not initialized"); + } + + denomination = d; + for(const CoinDenomination denom : libzerocoin::zerocoinDenomList) { + if(denom == d) + denomination = d; + } if(denomination == 0){ - std::cout << "denom does not exist\n"; - throw std::runtime_error("Denomination does not exist"); - } + std::cout << "denom does not exist\n"; + throw std::runtime_error("Denomination does not exist"); + } }; bool PublicCoin::validate() const @@ -68,10 +68,10 @@ bool PublicCoin::validate() const //PrivateCoin class PrivateCoin::PrivateCoin(const ZerocoinParams* p, const CoinDenomination denomination, bool fMintNew): params(p), publicCoin(p) { - // Verify that the parameters are valid - if(this->params->initialized == false) { - throw std::runtime_error("Params are not initialized"); - } + // Verify that the parameters are valid + if(this->params->initialized == false) { + throw std::runtime_error("Params are not initialized"); + } if (fMintNew) { #ifdef ZEROCOIN_FAST_MINT @@ -146,120 +146,120 @@ bool GenerateKeyPair(const CBigNum& bnGroupOrder, const uint256& nPrivkey, CKey& const CPubKey PrivateCoin::getPubKey() const { - CKey key; - key.SetPrivKey(privkey, true); - return key.GetPubKey(); + CKey key; + key.SetPrivKey(privkey, true); + return key.GetPubKey(); } bool PrivateCoin::sign(const uint256& hash, std::vector& vchSig) const { - CKey key; - key.SetPrivKey(privkey, true); - return key.Sign(hash, vchSig); + CKey key; + key.SetPrivKey(privkey, true); + return key.Sign(hash, vchSig); } void PrivateCoin::mintCoin(const CoinDenomination denomination) { - // Repeat this process up to MAX_COINMINT_ATTEMPTS times until - // we obtain a prime number - for(uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { - - // Generate a random serial number in the range 0...{q-1} where - // "q" is the order of the commitment group. - // And where the serial also doubles as a public key - CKey key; - CBigNum s; + // Repeat this process up to MAX_COINMINT_ATTEMPTS times until + // we obtain a prime number + for(uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { + + // Generate a random serial number in the range 0...{q-1} where + // "q" is the order of the commitment group. + // And where the serial also doubles as a public key + CKey key; + CBigNum s; bool isValid = false; while (!isValid) { isValid = GenerateKeyPair(this->params->coinCommitmentGroup.groupOrder, uint256(0), key, s); } - // Generate a Pedersen commitment to the serial number "s" - Commitment coin(¶ms->coinCommitmentGroup, s); - - // Now verify that the commitment is a prime number - // in the appropriate range. If not, we'll throw this coin - // away and generate a new one. - if (coin.getCommitmentValue().isPrime(ZEROCOIN_MINT_PRIME_PARAM) && - coin.getCommitmentValue() >= params->accumulatorParams.minCoinValue && - coin.getCommitmentValue() <= params->accumulatorParams.maxCoinValue) { - // Found a valid coin. Store it. - this->serialNumber = s; - this->randomness = coin.getRandomness(); - this->publicCoin = PublicCoin(params,coin.getCommitmentValue(), denomination); - this->privkey = key.GetPrivKey(); - this->version = 2; - - // Success! We're done. - return; - } - } - - // We only get here if we did not find a coin within - // MAX_COINMINT_ATTEMPTS. Throw an exception. - throw std::runtime_error("Unable to mint a new Zerocoin (too many attempts)"); + // Generate a Pedersen commitment to the serial number "s" + Commitment coin(¶ms->coinCommitmentGroup, s); + + // Now verify that the commitment is a prime number + // in the appropriate range. If not, we'll throw this coin + // away and generate a new one. + if (coin.getCommitmentValue().isPrime(ZEROCOIN_MINT_PRIME_PARAM) && + coin.getCommitmentValue() >= params->accumulatorParams.minCoinValue && + coin.getCommitmentValue() <= params->accumulatorParams.maxCoinValue) { + // Found a valid coin. Store it. + this->serialNumber = s; + this->randomness = coin.getRandomness(); + this->publicCoin = PublicCoin(params,coin.getCommitmentValue(), denomination); + this->privkey = key.GetPrivKey(); + this->version = 2; + + // Success! We're done. + return; + } + } + + // We only get here if we did not find a coin within + // MAX_COINMINT_ATTEMPTS. Throw an exception. + throw std::runtime_error("Unable to mint a new Zerocoin (too many attempts)"); } void PrivateCoin::mintCoinFast(const CoinDenomination denomination) { - // Generate a random serial number in the range 0...{q-1} where - // "q" is the order of the commitment group. - // And where the serial also doubles as a public key - CKey key; - CBigNum s; + // Generate a random serial number in the range 0...{q-1} where + // "q" is the order of the commitment group. + // And where the serial also doubles as a public key + CKey key; + CBigNum s; bool isValid = false; while (!isValid) { isValid = GenerateKeyPair(this->params->coinCommitmentGroup.groupOrder, uint256(0), key, s); } - // Generate a random number "r" in the range 0...{q-1} - CBigNum r = CBigNum::randBignum(this->params->coinCommitmentGroup.groupOrder); - - // Manually compute a Pedersen commitment to the serial number "s" under randomness "r" - // C = g^s * h^r mod p - CBigNum commitmentValue = this->params->coinCommitmentGroup.g.pow_mod(s, this->params->coinCommitmentGroup.modulus).mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); - - // Repeat this process up to MAX_COINMINT_ATTEMPTS times until - // we obtain a prime number - for (uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { - // First verify that the commitment is a prime number - // in the appropriate range. If not, we'll throw this coin - // away and generate a new one. - if (commitmentValue.isPrime(ZEROCOIN_MINT_PRIME_PARAM) && - commitmentValue >= params->accumulatorParams.minCoinValue && - commitmentValue <= params->accumulatorParams.maxCoinValue) { - // Found a valid coin. Store it. - this->serialNumber = s; - this->randomness = r; - this->publicCoin = PublicCoin(params, commitmentValue, denomination); - this->privkey = key.GetPrivKey(); - this->version = 2; - - // Success! We're done. - return; - } - - // Generate a new random "r_delta" in 0...{q-1} - CBigNum r_delta = CBigNum::randBignum(this->params->coinCommitmentGroup.groupOrder); - - // The commitment was not prime. Increment "r" and recalculate "C": - // r = r + r_delta mod q - // C = C * h mod p - r = (r + r_delta) % this->params->coinCommitmentGroup.groupOrder; - commitmentValue = commitmentValue.mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r_delta, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); - } - - // We only get here if we did not find a coin within - // MAX_COINMINT_ATTEMPTS. Throw an exception. - throw std::runtime_error("Unable to mint a new Zerocoin (too many attempts)"); + // Generate a random number "r" in the range 0...{q-1} + CBigNum r = CBigNum::randBignum(this->params->coinCommitmentGroup.groupOrder); + + // Manually compute a Pedersen commitment to the serial number "s" under randomness "r" + // C = g^s * h^r mod p + CBigNum commitmentValue = this->params->coinCommitmentGroup.g.pow_mod(s, this->params->coinCommitmentGroup.modulus).mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); + + // Repeat this process up to MAX_COINMINT_ATTEMPTS times until + // we obtain a prime number + for (uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { + // First verify that the commitment is a prime number + // in the appropriate range. If not, we'll throw this coin + // away and generate a new one. + if (commitmentValue.isPrime(ZEROCOIN_MINT_PRIME_PARAM) && + commitmentValue >= params->accumulatorParams.minCoinValue && + commitmentValue <= params->accumulatorParams.maxCoinValue) { + // Found a valid coin. Store it. + this->serialNumber = s; + this->randomness = r; + this->publicCoin = PublicCoin(params, commitmentValue, denomination); + this->privkey = key.GetPrivKey(); + this->version = 2; + + // Success! We're done. + return; + } + + // Generate a new random "r_delta" in 0...{q-1} + CBigNum r_delta = CBigNum::randBignum(this->params->coinCommitmentGroup.groupOrder); + + // The commitment was not prime. Increment "r" and recalculate "C": + // r = r + r_delta mod q + // C = C * h mod p + r = (r + r_delta) % this->params->coinCommitmentGroup.groupOrder; + commitmentValue = commitmentValue.mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r_delta, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); + } + + // We only get here if we did not find a coin within + // MAX_COINMINT_ATTEMPTS. Throw an exception. + throw std::runtime_error("Unable to mint a new Zerocoin (too many attempts)"); } int ExtractVersionFromSerial(const CBigNum& bnSerial) { - //Serial is marked as v2 only if the first byte is 0xF - uint256 nMark = bnSerial.getuint256() >> (256 - PrivateCoin::V2_BITSHIFT); - if (nMark == 0xf) - return PrivateCoin::PUBKEY_VERSION; + //Serial is marked as v2 only if the first byte is 0xF + uint256 nMark = bnSerial.getuint256() >> (256 - PrivateCoin::V2_BITSHIFT); + if (nMark == 0xf) + return PrivateCoin::PUBKEY_VERSION; - return 1; + return 1; } //Remove the first four bits for V2 serials diff --git a/src/libzerocoin/Coin.h b/src/libzerocoin/Coin.h index 2578a52e5582f..14162567bed88 100644 --- a/src/libzerocoin/Coin.h +++ b/src/libzerocoin/Coin.h @@ -45,11 +45,11 @@ class PublicCoin PublicCoin(const ZerocoinParams* p); /**Generates a public coin - * - * @param p cryptographic paramters - * @param coin the value of the commitment. - * @param denomination The denomination of the coin. - */ + * + * @param p cryptographic paramters + * @param coin the value of the commitment. + * @param denomination The denomination of the coin. + */ PublicCoin(const ZerocoinParams* p, const CBigNum& coin, const CoinDenomination d); const CBigNum& getValue() const { return this->value; } @@ -141,31 +141,31 @@ class PrivateCoin CPrivKey privkey; /** - * @brief Mint a new coin. - * @param denomination the denomination of the coin to mint - * @throws ZerocoinException if the process takes too long - * - * Generates a new Zerocoin by (a) selecting a random serial - * number, (b) committing to this serial number and repeating until - * the resulting commitment is prime. Stores the - * resulting commitment (coin) and randomness (trapdoor). - **/ + * @brief Mint a new coin. + * @param denomination the denomination of the coin to mint + * @throws ZerocoinException if the process takes too long + * + * Generates a new Zerocoin by (a) selecting a random serial + * number, (b) committing to this serial number and repeating until + * the resulting commitment is prime. Stores the + * resulting commitment (coin) and randomness (trapdoor). + **/ void mintCoin(const CoinDenomination denomination); /** - * @brief Mint a new coin using a faster process. - * @param denomination the denomination of the coin to mint - * @throws ZerocoinException if the process takes too long - * - * Generates a new Zerocoin by (a) selecting a random serial - * number, (b) committing to this serial number and repeating until - * the resulting commitment is prime. Stores the - * resulting commitment (coin) and randomness (trapdoor). - * This routine is substantially faster than the - * mintCoin() routine, but could be more vulnerable - * to timing attacks. Don't use it if you think someone - * could be timing your coin minting. - **/ + * @brief Mint a new coin using a faster process. + * @param denomination the denomination of the coin to mint + * @throws ZerocoinException if the process takes too long + * + * Generates a new Zerocoin by (a) selecting a random serial + * number, (b) committing to this serial number and repeating until + * the resulting commitment is prime. Stores the + * resulting commitment (coin) and randomness (trapdoor). + * This routine is substantially faster than the + * mintCoin() routine, but could be more vulnerable + * to timing attacks. Don't use it if you think someone + * could be timing your coin minting. + **/ void mintCoinFast(const CoinDenomination denomination); }; diff --git a/src/libzerocoin/CoinSpend.h b/src/libzerocoin/CoinSpend.h index 55ccca415b837..d2bf1baaa95c5 100644 --- a/src/libzerocoin/CoinSpend.h +++ b/src/libzerocoin/CoinSpend.h @@ -60,53 +60,53 @@ class CoinSpend } /**Generates a proof spending a zerocoin. - * - * To use this, provide an unspent PrivateCoin, the latest Accumulator - * (e.g from the most recent Bitcoin block) containing the public part - * of the coin, a witness to that, and whatever medeta data is needed. - * - * Once constructed, this proof can be serialized and sent. - * It is validated simply be calling validate. - * @warning Validation only checks that the proof is correct - * @warning for the specified values in this class. These values must be validated - * Clients ought to check that - * 1) params is the right params - * 2) the accumulator actually is in some block - * 3) that the serial number is unspent - * 4) that the transaction - * - * @param p cryptographic parameters - * @param coin The coin to be spend - * @param a The current accumulator containing the coin - * @param witness The witness showing that the accumulator contains the coin - * @param a hash of the partial transaction that contains this coin spend - * @throw ZerocoinException if the process fails - */ + * + * To use this, provide an unspent PrivateCoin, the latest Accumulator + * (e.g from the most recent Bitcoin block) containing the public part + * of the coin, a witness to that, and whatever medeta data is needed. + * + * Once constructed, this proof can be serialized and sent. + * It is validated simply be calling validate. + * @warning Validation only checks that the proof is correct + * @warning for the specified values in this class. These values must be validated + * Clients ought to check that + * 1) params is the right params + * 2) the accumulator actually is in some block + * 3) that the serial number is unspent + * 4) that the transaction + * + * @param p cryptographic parameters + * @param coin The coin to be spend + * @param a The current accumulator containing the coin + * @param witness The witness showing that the accumulator contains the coin + * @param a hash of the partial transaction that contains this coin spend + * @throw ZerocoinException if the process fails + */ CoinSpend(const ZerocoinParams* paramsCoin, const ZerocoinParams* paramsAcc, const PrivateCoin& coin, Accumulator& a, const uint32_t& checksum, const AccumulatorWitness& witness, const uint256& ptxHash, const SpendType& spendType); /** Returns the serial number of the coin spend by this proof. - * - * @return the coin's serial number - */ + * + * @return the coin's serial number + */ const CBigNum& getCoinSerialNumber() const { return this->coinSerialNumber; } /**Gets the denomination of the coin spent in this proof. - * - * @return the denomination - */ + * + * @return the denomination + */ CoinDenomination getDenomination() const { return this->denomination; } /**Gets the checksum of the accumulator used in this proof. - * - * @return the checksum - */ + * + * @return the checksum + */ uint32_t getAccumulatorChecksum() const { return this->accChecksum; } /**Gets the txout hash used in this proof. - * - * @return the txout hash - */ + * + * @return the txout hash + */ uint256 getTxOutHash() const { return ptxHash; } CBigNum getAccCommitment() const { return accCommitmentToCoinValue; } CBigNum getSerialComm() const { return serialCommitmentToCoinValue; } diff --git a/src/libzerocoin/Commitment.cpp b/src/libzerocoin/Commitment.cpp index acdf59faf3ee8..c6783ef4ee565 100644 --- a/src/libzerocoin/Commitment.cpp +++ b/src/libzerocoin/Commitment.cpp @@ -19,9 +19,9 @@ namespace libzerocoin { //Commitment class Commitment::Commitment(const IntegerGroupParams* p, const CBigNum& value): params(p), contents(value) { - this->randomness = CBigNum::randBignum(params->groupOrder); - this->commitmentValue = (params->g.pow_mod(this->contents, params->modulus).mul_mod( - params->h.pow_mod(this->randomness, params->modulus), params->modulus)); + this->randomness = CBigNum::randBignum(params->groupOrder); + this->commitmentValue = (params->g.pow_mod(this->contents, params->modulus).mul_mod( + params->h.pow_mod(this->randomness, params->modulus), params->modulus)); } Commitment::Commitment(const IntegerGroupParams* p, const CBigNum& bnSerial, const CBigNum& bnRandomness): params(p), contents(bnSerial) { @@ -31,15 +31,15 @@ Commitment::Commitment(const IntegerGroupParams* p, const CBigNum& bnSerial, con } const CBigNum& Commitment::getCommitmentValue() const { - return this->commitmentValue; + return this->commitmentValue; } const CBigNum& Commitment::getRandomness() const { - return this->randomness; + return this->randomness; } const CBigNum& Commitment::getContents() const { - return this->contents; + return this->contents; } //CommitmentProofOfKnowledge class @@ -48,127 +48,127 @@ CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* // TODO: get parameters from the commitment group CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b): - ap(aParams),bp(bParams) + ap(aParams),bp(bParams) { - CBigNum r1, r2, r3; - - // First: make sure that the two commitments have the - // same contents. - if (a.getContents() != b.getContents()) { - throw std::runtime_error("Both commitments must contain the same value"); - } - - // Select three random values "r1, r2, r3" in the range 0 to (2^l)-1 where l is: - // length of challenge value + std::max(modulus 1, modulus 2, order 1, order 2) + margin. - // We set "margin" to be a relatively generous security parameter. - // - // We choose these large values to ensure statistical zero knowledge. - uint32_t randomSize = COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + - std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), - std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize())); - CBigNum maxRange = (CBigNum(2).pow(randomSize) - CBigNum(1)); - - r1 = CBigNum::randBignum(maxRange); - r2 = CBigNum::randBignum(maxRange); - r3 = CBigNum::randBignum(maxRange); - - // Generate two random, ephemeral commitments "T1, T2" - // of the form: - // T1 = g1^r1 * h1^r2 mod p1 - // T2 = g2^r1 * h2^r3 mod p2 - // - // Where (g1, h1, p1) are from "aParams" and (g2, h2, p2) are from "bParams". - CBigNum T1 = this->ap->g.pow_mod(r1, this->ap->modulus).mul_mod((this->ap->h.pow_mod(r2, this->ap->modulus)), this->ap->modulus); - CBigNum T2 = this->bp->g.pow_mod(r1, this->bp->modulus).mul_mod((this->bp->h.pow_mod(r3, this->bp->modulus)), this->bp->modulus); - - // Now hash commitment "A" with commitment "B" as well as the - // parameters and the two ephemeral commitments "T1, T2" we just generated - this->challenge = calculateChallenge(a.getCommitmentValue(), b.getCommitmentValue(), T1, T2); - - // Let "m" be the contents of the commitments "A, B". We have: - // A = g1^m * h1^x mod p1 - // B = g2^m * h2^y mod p2 - // T1 = g1^r1 * h1^r2 mod p1 - // T2 = g2^r1 * h2^r3 mod p2 - // - // Now compute: - // S1 = r1 + (m * challenge) -- note, not modular arithmetic - // S2 = r2 + (x * challenge) -- note, not modular arithmetic - // S3 = r3 + (y * challenge) -- note, not modular arithmetic - this->S1 = r1 + (a.getContents() * this->challenge); - this->S2 = r2 + (a.getRandomness() * this->challenge); - this->S3 = r3 + (b.getRandomness() * this->challenge); - - // We're done. The proof is S1, S2, S3 and "challenge", all of which - // are stored in member variables. + CBigNum r1, r2, r3; + + // First: make sure that the two commitments have the + // same contents. + if (a.getContents() != b.getContents()) { + throw std::runtime_error("Both commitments must contain the same value"); + } + + // Select three random values "r1, r2, r3" in the range 0 to (2^l)-1 where l is: + // length of challenge value + std::max(modulus 1, modulus 2, order 1, order 2) + margin. + // We set "margin" to be a relatively generous security parameter. + // + // We choose these large values to ensure statistical zero knowledge. + uint32_t randomSize = COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + + std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), + std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize())); + CBigNum maxRange = (CBigNum(2).pow(randomSize) - CBigNum(1)); + + r1 = CBigNum::randBignum(maxRange); + r2 = CBigNum::randBignum(maxRange); + r3 = CBigNum::randBignum(maxRange); + + // Generate two random, ephemeral commitments "T1, T2" + // of the form: + // T1 = g1^r1 * h1^r2 mod p1 + // T2 = g2^r1 * h2^r3 mod p2 + // + // Where (g1, h1, p1) are from "aParams" and (g2, h2, p2) are from "bParams". + CBigNum T1 = this->ap->g.pow_mod(r1, this->ap->modulus).mul_mod((this->ap->h.pow_mod(r2, this->ap->modulus)), this->ap->modulus); + CBigNum T2 = this->bp->g.pow_mod(r1, this->bp->modulus).mul_mod((this->bp->h.pow_mod(r3, this->bp->modulus)), this->bp->modulus); + + // Now hash commitment "A" with commitment "B" as well as the + // parameters and the two ephemeral commitments "T1, T2" we just generated + this->challenge = calculateChallenge(a.getCommitmentValue(), b.getCommitmentValue(), T1, T2); + + // Let "m" be the contents of the commitments "A, B". We have: + // A = g1^m * h1^x mod p1 + // B = g2^m * h2^y mod p2 + // T1 = g1^r1 * h1^r2 mod p1 + // T2 = g2^r1 * h2^r3 mod p2 + // + // Now compute: + // S1 = r1 + (m * challenge) -- note, not modular arithmetic + // S2 = r2 + (x * challenge) -- note, not modular arithmetic + // S3 = r3 + (y * challenge) -- note, not modular arithmetic + this->S1 = r1 + (a.getContents() * this->challenge); + this->S2 = r2 + (a.getRandomness() * this->challenge); + this->S3 = r3 + (b.getRandomness() * this->challenge); + + // We're done. The proof is S1, S2, S3 and "challenge", all of which + // are stored in member variables. } bool CommitmentProofOfKnowledge::Verify(const CBigNum& A, const CBigNum& B) const { - // Compute the maximum range of S1, S2, S3 and verify that the given values are - // in a correct range. This might be an unnecessary check. - uint32_t maxSize = 64 * (COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + - std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), - std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize()))); - - if ((uint32_t)this->S1.bitSize() > maxSize || - (uint32_t)this->S2.bitSize() > maxSize || - (uint32_t)this->S3.bitSize() > maxSize || - this->S1 < CBigNum(0) || - this->S2 < CBigNum(0) || - this->S3 < CBigNum(0) || - this->challenge < CBigNum(0) || - this->challenge > (CBigNum(2).pow(COMMITMENT_EQUALITY_CHALLENGE_SIZE) - CBigNum(1))) { - // Invalid inputs. Reject. - return false; - } - - // Compute T1 = g1^S1 * h1^S2 * inverse(A^{challenge}) mod p1 - CBigNum T1 = A.pow_mod(this->challenge, ap->modulus).inverse(ap->modulus).mul_mod( - (ap->g.pow_mod(S1, ap->modulus).mul_mod(ap->h.pow_mod(S2, ap->modulus), ap->modulus)), - ap->modulus); - - // Compute T2 = g2^S1 * h2^S3 * inverse(B^{challenge}) mod p2 - CBigNum T2 = B.pow_mod(this->challenge, bp->modulus).inverse(bp->modulus).mul_mod( - (bp->g.pow_mod(S1, bp->modulus).mul_mod(bp->h.pow_mod(S3, bp->modulus), bp->modulus)), - bp->modulus); - - // Hash T1 and T2 along with all of the public parameters - CBigNum computedChallenge = calculateChallenge(A, B, T1, T2); - - // Return success if the computed challenge matches the incoming challenge - return computedChallenge == this->challenge; + // Compute the maximum range of S1, S2, S3 and verify that the given values are + // in a correct range. This might be an unnecessary check. + uint32_t maxSize = 64 * (COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + + std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), + std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize()))); + + if ((uint32_t)this->S1.bitSize() > maxSize || + (uint32_t)this->S2.bitSize() > maxSize || + (uint32_t)this->S3.bitSize() > maxSize || + this->S1 < CBigNum(0) || + this->S2 < CBigNum(0) || + this->S3 < CBigNum(0) || + this->challenge < CBigNum(0) || + this->challenge > (CBigNum(2).pow(COMMITMENT_EQUALITY_CHALLENGE_SIZE) - CBigNum(1))) { + // Invalid inputs. Reject. + return false; + } + + // Compute T1 = g1^S1 * h1^S2 * inverse(A^{challenge}) mod p1 + CBigNum T1 = A.pow_mod(this->challenge, ap->modulus).inverse(ap->modulus).mul_mod( + (ap->g.pow_mod(S1, ap->modulus).mul_mod(ap->h.pow_mod(S2, ap->modulus), ap->modulus)), + ap->modulus); + + // Compute T2 = g2^S1 * h2^S3 * inverse(B^{challenge}) mod p2 + CBigNum T2 = B.pow_mod(this->challenge, bp->modulus).inverse(bp->modulus).mul_mod( + (bp->g.pow_mod(S1, bp->modulus).mul_mod(bp->h.pow_mod(S3, bp->modulus), bp->modulus)), + bp->modulus); + + // Hash T1 and T2 along with all of the public parameters + CBigNum computedChallenge = calculateChallenge(A, B, T1, T2); + + // Return success if the computed challenge matches the incoming challenge + return computedChallenge == this->challenge; } const CBigNum CommitmentProofOfKnowledge::calculateChallenge(const CBigNum& a, const CBigNum& b, const CBigNum &commitOne, const CBigNum &commitTwo) const { - CHashWriter hasher(0,0); - - // Hash together the following elements: - // * A string identifying the proof - // * Commitment A - // * Commitment B - // * Ephemeral commitment T1 - // * Ephemeral commitment T2 - // * A serialized instance of the commitment A parameters - // * A serialized instance of the commitment B parameters - - hasher << std::string(ZEROCOIN_COMMITMENT_EQUALITY_PROOF); - hasher << commitOne; - hasher << std::string("||"); - hasher << commitTwo; - hasher << std::string("||"); - hasher << a; - hasher << std::string("||"); - hasher << b; - hasher << std::string("||"); - hasher << *(this->ap); - hasher << std::string("||"); - hasher << *(this->bp); - - // Convert the SHA256 result into a Bignum - // Note that if we ever change the size of the hash function we will have - // to update COMMITMENT_EQUALITY_CHALLENGE_SIZE appropriately! - return CBigNum(hasher.GetHash()); + CHashWriter hasher(0,0); + + // Hash together the following elements: + // * A string identifying the proof + // * Commitment A + // * Commitment B + // * Ephemeral commitment T1 + // * Ephemeral commitment T2 + // * A serialized instance of the commitment A parameters + // * A serialized instance of the commitment B parameters + + hasher << std::string(ZEROCOIN_COMMITMENT_EQUALITY_PROOF); + hasher << commitOne; + hasher << std::string("||"); + hasher << commitTwo; + hasher << std::string("||"); + hasher << a; + hasher << std::string("||"); + hasher << b; + hasher << std::string("||"); + hasher << *(this->ap); + hasher << std::string("||"); + hasher << *(this->bp); + + // Convert the SHA256 result into a Bignum + // Note that if we ever change the size of the hash function we will have + // to update COMMITMENT_EQUALITY_CHALLENGE_SIZE appropriately! + return CBigNum(hasher.GetHash()); } } /* namespace libzerocoin */ diff --git a/src/libzerocoin/Commitment.h b/src/libzerocoin/Commitment.h index 572c3367b7c66..5e5594b080509 100644 --- a/src/libzerocoin/Commitment.h +++ b/src/libzerocoin/Commitment.h @@ -32,27 +32,27 @@ namespace libzerocoin { */ class Commitment { public: - /**Generates a Pedersen commitment to the given value. - * - * @param p the group parameters for the coin - * @param value the value to commit to - */ - Commitment(const IntegerGroupParams* p, const CBigNum& value); + /**Generates a Pedersen commitment to the given value. + * + * @param p the group parameters for the coin + * @param value the value to commit to + */ + Commitment(const IntegerGroupParams* p, const CBigNum& value); explicit Commitment(const IntegerGroupParams* p, const CBigNum& bnSerial, const CBigNum& bnRandomness); - const CBigNum& getCommitmentValue() const; - const CBigNum& getRandomness() const; - const CBigNum& getContents() const; + const CBigNum& getCommitmentValue() const; + const CBigNum& getRandomness() const; + const CBigNum& getContents() const; private: - const IntegerGroupParams *params; - CBigNum commitmentValue; - CBigNum randomness; - const CBigNum contents; - ADD_SERIALIZE_METHODS; + const IntegerGroupParams *params; + CBigNum commitmentValue; + CBigNum randomness; + const CBigNum contents; + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(commitmentValue); - READWRITE(randomness); - READWRITE(contents); - } + READWRITE(commitmentValue); + READWRITE(randomness); + READWRITE(contents); + } }; /**Proof that two commitments open to the same value. @@ -60,47 +60,47 @@ class Commitment { */ class CommitmentProofOfKnowledge { public: - CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp); - /** Generates a proof that two commitments, a and b, open to the same value. - * - * @param ap the IntegerGroup for commitment a - * @param bp the IntegerGroup for commitment b - * @param a the first commitment - * @param b the second commitment - */ - CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b); - //FIXME: is it best practice that this is here? - template - CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, - const IntegerGroupParams* bParams, Stream& strm): ap(aParams), bp(bParams) - { - strm >> *this; - } + CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp); + /** Generates a proof that two commitments, a and b, open to the same value. + * + * @param ap the IntegerGroup for commitment a + * @param bp the IntegerGroup for commitment b + * @param a the first commitment + * @param b the second commitment + */ + CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b); + //FIXME: is it best practice that this is here? + template + CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, + const IntegerGroupParams* bParams, Stream& strm): ap(aParams), bp(bParams) + { + strm >> *this; + } - const CBigNum calculateChallenge(const CBigNum& a, const CBigNum& b, const CBigNum &commitOne, const CBigNum &commitTwo) const; + const CBigNum calculateChallenge(const CBigNum& a, const CBigNum& b, const CBigNum &commitOne, const CBigNum &commitTwo) const; - /**Verifies the proof - * - * @return true if the proof is valid. - */ - /**Verifies the proof of equality of the two commitments - * - * @param A value of commitment one - * @param B value of commitment two - * @return - */ - bool Verify(const CBigNum& A, const CBigNum& B) const; - ADD_SERIALIZE_METHODS; + /**Verifies the proof + * + * @return true if the proof is valid. + */ + /**Verifies the proof of equality of the two commitments + * + * @param A value of commitment one + * @param B value of commitment two + * @return + */ + bool Verify(const CBigNum& A, const CBigNum& B) const; + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(S1); - READWRITE(S2); - READWRITE(S3); - READWRITE(challenge); - } + READWRITE(S1); + READWRITE(S2); + READWRITE(S3); + READWRITE(challenge); + } private: - const IntegerGroupParams *ap, *bp; + const IntegerGroupParams *ap, *bp; - CBigNum S1, S2, S3, challenge; + CBigNum S1, S2, S3, challenge; }; } /* namespace libzerocoin */ diff --git a/src/libzerocoin/Denominations.cpp b/src/libzerocoin/Denominations.cpp index 57e4aa39f83c7..b48f58af621f6 100644 --- a/src/libzerocoin/Denominations.cpp +++ b/src/libzerocoin/Denominations.cpp @@ -18,10 +18,10 @@ CoinDenomination IntToZerocoinDenomination(int64_t amount) { CoinDenomination denomination; switch (amount) { - case 1: denomination = CoinDenomination::ZQ_ONE; break; - case 5: denomination = CoinDenomination::ZQ_FIVE; break; - case 10: denomination = CoinDenomination::ZQ_TEN; break; - case 50: denomination = CoinDenomination::ZQ_FIFTY; break; + case 1: denomination = CoinDenomination::ZQ_ONE; break; + case 5: denomination = CoinDenomination::ZQ_FIVE; break; + case 10: denomination = CoinDenomination::ZQ_TEN; break; + case 50: denomination = CoinDenomination::ZQ_FIFTY; break; case 100: denomination = CoinDenomination::ZQ_ONE_HUNDRED; break; case 500: denomination = CoinDenomination::ZQ_FIVE_HUNDRED; break; case 1000: denomination = CoinDenomination::ZQ_ONE_THOUSAND; break; diff --git a/src/libzerocoin/ParamGeneration.cpp b/src/libzerocoin/ParamGeneration.cpp index d50b4e5a8ca89..581e12679d146 100644 --- a/src/libzerocoin/ParamGeneration.cpp +++ b/src/libzerocoin/ParamGeneration.cpp @@ -38,78 +38,78 @@ namespace libzerocoin { void CalculateParams(ZerocoinParams ¶ms, CBigNum N, std::string aux, uint32_t securityLevel) { - params.initialized = false; - params.accumulatorParams.initialized = false; - - // Verify that |N| is > 1023 bits. - uint32_t NLen = N.bitSize(); - if (NLen < 1023) { - throw std::runtime_error("Modulus must be at least 1023 bits"); - } - - // Verify that "securityLevel" is at least 80 bits (minimum). - if (securityLevel < 80) { - throw std::runtime_error("Security level must be at least 80 bits."); - } - - // Set the accumulator modulus to "N". - params.accumulatorParams.accumulatorModulus = N; - - // Calculate the required size of the field "F_p" into which - // we're embedding the coin commitment group. This may throw an - // exception if the securityLevel is too large to be supported - // by the current modulus. - uint32_t pLen = 0; - uint32_t qLen = 0; - calculateGroupParamLengths(NLen - 2, securityLevel, &pLen, &qLen); - - // Calculate candidate parameters ("p", "q") for the coin commitment group - // using a deterministic process based on "N", the "aux" string, and - // the dedicated string "COMMITMENTGROUP". - params.coinCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_COMMIT_GROUP), - pLen, qLen); - - // Next, we derive parameters for a second Accumulated Value commitment group. - // This is a Schnorr group with the specific property that the order of the group - // must be exactly equal to "q" from the commitment group. We set - // the modulus of the new group equal to "2q+1" and test to see if this is prime. - params.serialNumberSoKCommitmentGroup = deriveIntegerGroupFromOrder(params.coinCommitmentGroup.modulus); - - // Calculate the parameters for the internal commitment - // using the same process. - params.accumulatorParams.accumulatorPoKCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_AIC_GROUP), - qLen + 300, qLen + 1); - - // Calculate the parameters for the accumulator QRN commitment generators. This isn't really - // a whole group, just a pair of random generators in QR_N. - uint32_t resultCtr; - params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1, - calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG), - &resultCtr).pow_mod(CBigNum(2),N); - params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1, - calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPH), - &resultCtr).pow_mod(CBigNum(2), N); - - // Calculate the accumulator base, which we calculate as "u = C**2 mod N" - // where C is an arbitrary value. In the unlikely case that "u = 1" we increment - // "C" and repeat. - CBigNum constant(ACCUMULATOR_BASE_CONSTANT); - params.accumulatorParams.accumulatorBase = CBigNum(1); - for (uint32_t count = 0; count < MAX_ACCUMGEN_ATTEMPTS && params.accumulatorParams.accumulatorBase.isOne(); count++) { - params.accumulatorParams.accumulatorBase = constant.pow_mod(CBigNum(2), params.accumulatorParams.accumulatorModulus); - } - - // Compute the accumulator range. The upper range is the largest possible coin commitment value. - // The lower range is sqrt(upper range) + 1. Since OpenSSL doesn't have - // a square root function we use a slightly higher approximation. - params.accumulatorParams.maxCoinValue = params.coinCommitmentGroup.modulus; - params.accumulatorParams.minCoinValue = CBigNum(2).pow((params.coinCommitmentGroup.modulus.bitSize() / 2) + 3); - - // If all went well, mark params as successfully initialized. - params.accumulatorParams.initialized = true; - - // If all went well, mark params as successfully initialized. - params.initialized = true; + params.initialized = false; + params.accumulatorParams.initialized = false; + + // Verify that |N| is > 1023 bits. + uint32_t NLen = N.bitSize(); + if (NLen < 1023) { + throw std::runtime_error("Modulus must be at least 1023 bits"); + } + + // Verify that "securityLevel" is at least 80 bits (minimum). + if (securityLevel < 80) { + throw std::runtime_error("Security level must be at least 80 bits."); + } + + // Set the accumulator modulus to "N". + params.accumulatorParams.accumulatorModulus = N; + + // Calculate the required size of the field "F_p" into which + // we're embedding the coin commitment group. This may throw an + // exception if the securityLevel is too large to be supported + // by the current modulus. + uint32_t pLen = 0; + uint32_t qLen = 0; + calculateGroupParamLengths(NLen - 2, securityLevel, &pLen, &qLen); + + // Calculate candidate parameters ("p", "q") for the coin commitment group + // using a deterministic process based on "N", the "aux" string, and + // the dedicated string "COMMITMENTGROUP". + params.coinCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_COMMIT_GROUP), + pLen, qLen); + + // Next, we derive parameters for a second Accumulated Value commitment group. + // This is a Schnorr group with the specific property that the order of the group + // must be exactly equal to "q" from the commitment group. We set + // the modulus of the new group equal to "2q+1" and test to see if this is prime. + params.serialNumberSoKCommitmentGroup = deriveIntegerGroupFromOrder(params.coinCommitmentGroup.modulus); + + // Calculate the parameters for the internal commitment + // using the same process. + params.accumulatorParams.accumulatorPoKCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_AIC_GROUP), + qLen + 300, qLen + 1); + + // Calculate the parameters for the accumulator QRN commitment generators. This isn't really + // a whole group, just a pair of random generators in QR_N. + uint32_t resultCtr; + params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1, + calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG), + &resultCtr).pow_mod(CBigNum(2),N); + params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1, + calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPH), + &resultCtr).pow_mod(CBigNum(2), N); + + // Calculate the accumulator base, which we calculate as "u = C**2 mod N" + // where C is an arbitrary value. In the unlikely case that "u = 1" we increment + // "C" and repeat. + CBigNum constant(ACCUMULATOR_BASE_CONSTANT); + params.accumulatorParams.accumulatorBase = CBigNum(1); + for (uint32_t count = 0; count < MAX_ACCUMGEN_ATTEMPTS && params.accumulatorParams.accumulatorBase.isOne(); count++) { + params.accumulatorParams.accumulatorBase = constant.pow_mod(CBigNum(2), params.accumulatorParams.accumulatorModulus); + } + + // Compute the accumulator range. The upper range is the largest possible coin commitment value. + // The lower range is sqrt(upper range) + 1. Since OpenSSL doesn't have + // a square root function we use a slightly higher approximation. + params.accumulatorParams.maxCoinValue = params.coinCommitmentGroup.modulus; + params.accumulatorParams.minCoinValue = CBigNum(2).pow((params.coinCommitmentGroup.modulus.bitSize() / 2) + 3); + + // If all went well, mark params as successfully initialized. + params.accumulatorParams.initialized = true; + + // If all went well, mark params as successfully initialized. + params.initialized = true; } /// \brief Format a seed string by hashing several values. @@ -124,24 +124,24 @@ CalculateParams(ZerocoinParams ¶ms, CBigNum N, std::string aux, uint32_t sec uint256 calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, std::string label, uint32_t index, uint32_t count) { - CHashWriter hasher(0,0); - uint256 hash; - - // Compute the hash of: - // ||||||groupName - hasher << seed; - hasher << std::string("||"); - hasher << pSeed; - hasher << std::string("||"); - hasher << qSeed; - hasher << std::string("||"); - hasher << label; - hasher << std::string("||"); - hasher << index; - hasher << std::string("||"); - hasher << count; - - return hasher.GetHash(); + CHashWriter hasher(0,0); + uint256 hash; + + // Compute the hash of: + // ||||||groupName + hasher << seed; + hasher << std::string("||"); + hasher << pSeed; + hasher << std::string("||"); + hasher << qSeed; + hasher << std::string("||"); + hasher << label; + hasher << std::string("||"); + hasher << index; + hasher << std::string("||"); + hasher << count; + + return hasher.GetHash(); } /// \brief Format a seed string by hashing several values. @@ -156,31 +156,31 @@ calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, std::string l uint256 calculateSeed(CBigNum modulus, std::string auxString, uint32_t securityLevel, std::string groupName) { - CHashWriter hasher(0,0); - uint256 hash; - - // Compute the hash of: - // ||||||groupName - hasher << modulus; - hasher << std::string("||"); - hasher << securityLevel; - hasher << std::string("||"); - hasher << auxString; - hasher << std::string("||"); - hasher << groupName; - - return hasher.GetHash(); + CHashWriter hasher(0,0); + uint256 hash; + + // Compute the hash of: + // ||||||groupName + hasher << modulus; + hasher << std::string("||"); + hasher << securityLevel; + hasher << std::string("||"); + hasher << auxString; + hasher << std::string("||"); + hasher << groupName; + + return hasher.GetHash(); } uint256 calculateHash(uint256 input) { - CHashWriter hasher(0,0); + CHashWriter hasher(0,0); - // Compute the hash of "input" - hasher << input; + // Compute the hash of "input" + hasher << input; - return hasher.GetHash(); + return hasher.GetHash(); } /// \brief Calculate field/group parameter sizes based on a security level. @@ -206,26 +206,26 @@ void calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, uint32_t *pLen, uint32_t *qLen) { - *pLen = *qLen = 0; - - if (securityLevel < 80) { - throw std::runtime_error("Security level must be at least 80 bits."); - } else if (securityLevel == 80) { - *qLen = 256; - *pLen = 1024; - } else if (securityLevel <= 112) { - *qLen = 256; - *pLen = 2048; - } else if (securityLevel <= 128) { - *qLen = 320; - *pLen = 3072; - } else { - throw std::runtime_error("Security level not supported."); - } - - if (*pLen > maxPLen) { - throw std::runtime_error("Modulus size is too small for this security level."); - } + *pLen = *qLen = 0; + + if (securityLevel < 80) { + throw std::runtime_error("Security level must be at least 80 bits."); + } else if (securityLevel == 80) { + *qLen = 256; + *pLen = 1024; + } else if (securityLevel <= 112) { + *qLen = 256; + *pLen = 2048; + } else if (securityLevel <= 128) { + *qLen = 320; + *pLen = 3072; + } else { + throw std::runtime_error("Security level not supported."); + } + + if (*pLen > maxPLen) { + throw std::runtime_error("Modulus size is too small for this security level."); + } } /// \brief Deterministically compute a set of group parameters using NIST procedures. @@ -243,40 +243,40 @@ calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, IntegerGroupParams deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen) { - IntegerGroupParams result; - CBigNum p; - CBigNum q; - uint256 pSeed, qSeed; - - // Calculate "p" and "q" and "domain_parameter_seed" from the - // "seed" buffer above, using the procedure described in NIST - // FIPS 186-3, Appendix A.1.2. - calculateGroupModulusAndOrder(seed, pLen, qLen, &(result.modulus), - &(result.groupOrder), &pSeed, &qSeed); - - // Calculate the generators "g", "h" using the process described in - // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", - // "domain_parameter_seed", "index"). We use "index" value 1 - // to generate "g" and "index" value 2 to generate "h". - result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); - result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); - - // Perform some basic tests to make sure we have good parameters - if ((uint32_t)(result.modulus.bitSize()) < pLen || // modulus is pLen bits long - (uint32_t)(result.groupOrder.bitSize()) < qLen || // order is qLen bits long - !(result.modulus.isPrime()) || // modulus is prime - !(result.groupOrder.isPrime()) || // order is prime - !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 - !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 - ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 - ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 - result.g == result.h || // g != h - result.g.isOne()) { // g != 1 - // If any of the above tests fail, throw an exception - throw std::runtime_error("Group parameters are not valid"); - } - - return result; + IntegerGroupParams result; + CBigNum p; + CBigNum q; + uint256 pSeed, qSeed; + + // Calculate "p" and "q" and "domain_parameter_seed" from the + // "seed" buffer above, using the procedure described in NIST + // FIPS 186-3, Appendix A.1.2. + calculateGroupModulusAndOrder(seed, pLen, qLen, &(result.modulus), + &(result.groupOrder), &pSeed, &qSeed); + + // Calculate the generators "g", "h" using the process described in + // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", + // "domain_parameter_seed", "index"). We use "index" value 1 + // to generate "g" and "index" value 2 to generate "h". + result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); + result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); + + // Perform some basic tests to make sure we have good parameters + if ((uint32_t)(result.modulus.bitSize()) < pLen || // modulus is pLen bits long + (uint32_t)(result.groupOrder.bitSize()) < qLen || // order is qLen bits long + !(result.modulus.isPrime()) || // modulus is prime + !(result.groupOrder.isPrime()) || // order is prime + !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 + !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 + ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 + ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 + result.g == result.h || // g != h + result.g.isOne()) { // g != 1 + // If any of the above tests fail, throw an exception + throw std::runtime_error("Group parameters are not valid"); + } + + return result; } /// \brief Deterministically compute a set of group parameters with a specified order. @@ -289,52 +289,52 @@ deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen) IntegerGroupParams deriveIntegerGroupFromOrder(CBigNum &groupOrder) { - IntegerGroupParams result; - - // Set the order to "groupOrder" - result.groupOrder = groupOrder; - - // Try possible values for "modulus" of the form "groupOrder * 2 * i" where - // "p" is prime and i is a counter starting at 1. - for (uint32_t i = 1; i < NUM_SCHNORRGEN_ATTEMPTS; i++) { - // Set modulus equal to "groupOrder * 2 * i" - result.modulus = (result.groupOrder * CBigNum(i*2)) + CBigNum(1); - - // Test the result for primality - // TODO: This is a probabilistic routine and thus not the right choice - if (result.modulus.isPrime(256)) { - - // Success. - // - // Calculate the generators "g", "h" using the process described in - // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", - // "domain_parameter_seed", "index"). We use "index" value 1 - // to generate "g" and "index" value 2 to generate "h". - uint256 seed = calculateSeed(groupOrder, "", 128, ""); - uint256 pSeed = calculateHash(seed); - uint256 qSeed = calculateHash(pSeed); - result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); - result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); - - // Perform some basic tests to make sure we have good parameters - if (!(result.modulus.isPrime()) || // modulus is prime - !(result.groupOrder.isPrime()) || // order is prime - !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 - !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 - ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 - ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 - result.g == result.h || // g != h - result.g.isOne()) { // g != 1 - // If any of the above tests fail, throw an exception - throw std::runtime_error("Group parameters are not valid"); - } - - return result; - } - } - - // If we reached this point group generation has failed. Throw an exception. - throw std::runtime_error("Too many attempts to generate Schnorr group."); + IntegerGroupParams result; + + // Set the order to "groupOrder" + result.groupOrder = groupOrder; + + // Try possible values for "modulus" of the form "groupOrder * 2 * i" where + // "p" is prime and i is a counter starting at 1. + for (uint32_t i = 1; i < NUM_SCHNORRGEN_ATTEMPTS; i++) { + // Set modulus equal to "groupOrder * 2 * i" + result.modulus = (result.groupOrder * CBigNum(i*2)) + CBigNum(1); + + // Test the result for primality + // TODO: This is a probabilistic routine and thus not the right choice + if (result.modulus.isPrime(256)) { + + // Success. + // + // Calculate the generators "g", "h" using the process described in + // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", + // "domain_parameter_seed", "index"). We use "index" value 1 + // to generate "g" and "index" value 2 to generate "h". + uint256 seed = calculateSeed(groupOrder, "", 128, ""); + uint256 pSeed = calculateHash(seed); + uint256 qSeed = calculateHash(pSeed); + result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); + result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); + + // Perform some basic tests to make sure we have good parameters + if (!(result.modulus.isPrime()) || // modulus is prime + !(result.groupOrder.isPrime()) || // order is prime + !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 + !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 + ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 + ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 + result.g == result.h || // g != h + result.g.isOne()) { // g != 1 + // If any of the above tests fail, throw an exception + throw std::runtime_error("Group parameters are not valid"); + } + + return result; + } + } + + // If we reached this point group generation has failed. Throw an exception. + throw std::runtime_error("Too many attempts to generate Schnorr group."); } /// \brief Deterministically compute a group description using NIST procedures. @@ -355,88 +355,88 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, CBigNum *resultModulus, CBigNum *resultGroupOrder, uint256 *resultPseed, uint256 *resultQseed) { - // Verify that the seed length is >= qLen - if (qLen > (sizeof(seed)) * 8) { - // TODO: The use of 256-bit seeds limits us to 256-bit group orders. We should probably change this. - // throw std::runtime_error("Seed is too short to support the required security level."); - } + // Verify that the seed length is >= qLen + if (qLen > (sizeof(seed)) * 8) { + // TODO: The use of 256-bit seeds limits us to 256-bit group orders. We should probably change this. + // throw std::runtime_error("Seed is too short to support the required security level."); + } #ifdef ZEROCOIN_DEBUG - cout << "calculateGroupModulusAndOrder: pLen = " << pLen << endl; + cout << "calculateGroupModulusAndOrder: pLen = " << pLen << endl; #endif - // Generate a random prime for the group order. - // This may throw an exception, which we'll pass upwards. - // Result is the value "resultGroupOrder", "qseed" and "qgen_counter". - uint256 qseed; - uint32_t qgen_counter; - *resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter); - - // Using ⎡pLen / 2 + 1⎤ as the length and qseed as the input_seed, use the random prime - // routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward. - uint32_t p0len = ceil((pLen / 2.0) + 1); - uint256 pseed; - uint32_t pgen_counter; - CBigNum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter); - - // Set x = 0, old_counter = pgen_counter - uint32_t old_counter = pgen_counter; - - // Generate a random integer "x" of pLen bits - uint32_t iterations; - CBigNum x = generateIntegerFromSeed(pLen, pseed, &iterations); - pseed += (iterations + 1); - - // Set x = 2^{pLen−1} + (x mod 2^{pLen–1}). - CBigNum powerOfTwo = CBigNum(2).pow(pLen-1); - x = powerOfTwo + (x % powerOfTwo); - - // t = ⎡x / (2 * resultGroupOrder * p0)⎤. - // TODO: we don't have a ceiling function - CBigNum t = x / (CBigNum(2) * (*resultGroupOrder) * p0); - - // Now loop until we find a valid prime "p" or we fail due to - // pgen_counter exceeding ((4*pLen) + old_counter). - for ( ; pgen_counter <= ((4*pLen) + old_counter) ; pgen_counter++) { - // If (2 * t * resultGroupOrder * p0 + 1) > 2^{pLen}, then - // t = ⎡2^{pLen−1} / (2 * resultGroupOrder * p0)⎤. - powerOfTwo = CBigNum(2).pow(pLen); - CBigNum prod = (CBigNum(2) * t * (*resultGroupOrder) * p0) + CBigNum(1); - if (prod > powerOfTwo) { - // TODO: implement a ceil function - t = CBigNum(2).pow(pLen-1) / (CBigNum(2) * (*resultGroupOrder) * p0); - } - - // Compute a candidate prime resultModulus = 2tqp0 + 1. - *resultModulus = (CBigNum(2) * t * (*resultGroupOrder) * p0) + CBigNum(1); - - // Verify that resultModulus is prime. First generate a pseudorandom integer "a". - CBigNum a = generateIntegerFromSeed(pLen, pseed, &iterations); - pseed += iterations + 1; - - // Set a = 2 + (a mod (resultModulus–3)). - a = CBigNum(2) + (a % ((*resultModulus) - CBigNum(3))); - - // Set z = a^{2 * t * resultGroupOrder} mod resultModulus - CBigNum z = a.pow_mod(CBigNum(2) * t * (*resultGroupOrder), (*resultModulus)); - - // If GCD(z–1, resultModulus) == 1 AND (z^{p0} mod resultModulus == 1) - // then we have found our result. Return. - if ((resultModulus->gcd(z - CBigNum(1))).isOne() && - (z.pow_mod(p0, (*resultModulus))).isOne()) { - // Success! Return the seeds and primes. - *resultPseed = pseed; - *resultQseed = qseed; - return; - } - - // This prime did not work out. Increment "t" and try again. - t = t + CBigNum(1); - } // loop continues until pgen_counter exceeds a limit - - // We reach this point only if we exceeded our maximum iteration count. - // Throw an exception. - throw std::runtime_error("Unable to generate a prime modulus for the group"); + // Generate a random prime for the group order. + // This may throw an exception, which we'll pass upwards. + // Result is the value "resultGroupOrder", "qseed" and "qgen_counter". + uint256 qseed; + uint32_t qgen_counter; + *resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter); + + // Using ⎡pLen / 2 + 1⎤ as the length and qseed as the input_seed, use the random prime + // routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward. + uint32_t p0len = ceil((pLen / 2.0) + 1); + uint256 pseed; + uint32_t pgen_counter; + CBigNum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter); + + // Set x = 0, old_counter = pgen_counter + uint32_t old_counter = pgen_counter; + + // Generate a random integer "x" of pLen bits + uint32_t iterations; + CBigNum x = generateIntegerFromSeed(pLen, pseed, &iterations); + pseed += (iterations + 1); + + // Set x = 2^{pLen−1} + (x mod 2^{pLen–1}). + CBigNum powerOfTwo = CBigNum(2).pow(pLen-1); + x = powerOfTwo + (x % powerOfTwo); + + // t = ⎡x / (2 * resultGroupOrder * p0)⎤. + // TODO: we don't have a ceiling function + CBigNum t = x / (CBigNum(2) * (*resultGroupOrder) * p0); + + // Now loop until we find a valid prime "p" or we fail due to + // pgen_counter exceeding ((4*pLen) + old_counter). + for ( ; pgen_counter <= ((4*pLen) + old_counter) ; pgen_counter++) { + // If (2 * t * resultGroupOrder * p0 + 1) > 2^{pLen}, then + // t = ⎡2^{pLen−1} / (2 * resultGroupOrder * p0)⎤. + powerOfTwo = CBigNum(2).pow(pLen); + CBigNum prod = (CBigNum(2) * t * (*resultGroupOrder) * p0) + CBigNum(1); + if (prod > powerOfTwo) { + // TODO: implement a ceil function + t = CBigNum(2).pow(pLen-1) / (CBigNum(2) * (*resultGroupOrder) * p0); + } + + // Compute a candidate prime resultModulus = 2tqp0 + 1. + *resultModulus = (CBigNum(2) * t * (*resultGroupOrder) * p0) + CBigNum(1); + + // Verify that resultModulus is prime. First generate a pseudorandom integer "a". + CBigNum a = generateIntegerFromSeed(pLen, pseed, &iterations); + pseed += iterations + 1; + + // Set a = 2 + (a mod (resultModulus–3)). + a = CBigNum(2) + (a % ((*resultModulus) - CBigNum(3))); + + // Set z = a^{2 * t * resultGroupOrder} mod resultModulus + CBigNum z = a.pow_mod(CBigNum(2) * t * (*resultGroupOrder), (*resultModulus)); + + // If GCD(z–1, resultModulus) == 1 AND (z^{p0} mod resultModulus == 1) + // then we have found our result. Return. + if ((resultModulus->gcd(z - CBigNum(1))).isOne() && + (z.pow_mod(p0, (*resultModulus))).isOne()) { + // Success! Return the seeds and primes. + *resultPseed = pseed; + *resultQseed = qseed; + return; + } + + // This prime did not work out. Increment "t" and try again. + t = t + CBigNum(1); + } // loop continues until pgen_counter exceeds a limit + + // We reach this point only if we exceeded our maximum iteration count. + // Throw an exception. + throw std::runtime_error("Unable to generate a prime modulus for the group"); } /// \brief Deterministically compute a generator for a given group. @@ -455,33 +455,33 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, CBigNum calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, CBigNum modulus, CBigNum groupOrder, uint32_t index) { - CBigNum result; + CBigNum result; - // Verify that 0 <= index < 256 - if (index > 255) { - throw std::runtime_error("Invalid index for group generation"); - } + // Verify that 0 <= index < 256 + if (index > 255) { + throw std::runtime_error("Invalid index for group generation"); + } - // Compute e = (modulus - 1) / groupOrder - CBigNum e = (modulus - CBigNum(1)) / groupOrder; + // Compute e = (modulus - 1) / groupOrder + CBigNum e = (modulus - CBigNum(1)) / groupOrder; - // Loop until we find a generator - for (uint32_t count = 1; count < MAX_GENERATOR_ATTEMPTS; count++) { - // hash = Hash(seed || pSeed || qSeed || “ggen” || index || count - uint256 hash = calculateGeneratorSeed(seed, pSeed, qSeed, "ggen", index, count); - CBigNum W(hash); + // Loop until we find a generator + for (uint32_t count = 1; count < MAX_GENERATOR_ATTEMPTS; count++) { + // hash = Hash(seed || pSeed || qSeed || “ggen” || index || count + uint256 hash = calculateGeneratorSeed(seed, pSeed, qSeed, "ggen", index, count); + CBigNum W(hash); - // Compute result = W^e mod p - result = W.pow_mod(e, modulus); + // Compute result = W^e mod p + result = W.pow_mod(e, modulus); - // If result > 1, we have a generator - if (result > 1) { - return result; - } - } + // If result > 1, we have a generator + if (result > 1) { + return result; + } + } - // We only get here if we failed to find a generator - throw std::runtime_error("Unable to find a generator, too many attempts"); + // We only get here if we failed to find a generator + throw std::runtime_error("Unable to find a generator, too many attempts"); } /// \brief Deterministically compute a random prime number. @@ -500,141 +500,141 @@ CBigNum generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, uint32_t *prime_gen_counter) { - // Verify that primeBitLen is not too small - if (primeBitLen < 2) { - throw std::runtime_error("Prime length is too short"); - } + // Verify that primeBitLen is not too small + if (primeBitLen < 2) { + throw std::runtime_error("Prime length is too short"); + } - // If primeBitLen < 33 bits, perform the base case. - if (primeBitLen < 33) { - CBigNum result(0); + // If primeBitLen < 33 bits, perform the base case. + if (primeBitLen < 33) { + CBigNum result(0); - // Set prime_seed = in_seed, prime_gen_counter = 0. - uint256 prime_seed = in_seed; - (*prime_gen_counter) = 0; + // Set prime_seed = in_seed, prime_gen_counter = 0. + uint256 prime_seed = in_seed; + (*prime_gen_counter) = 0; - // Loop up to "4 * primeBitLen" iterations. - while ((*prime_gen_counter) < (4 * primeBitLen)) { + // Loop up to "4 * primeBitLen" iterations. + while ((*prime_gen_counter) < (4 * primeBitLen)) { - // Generate a pseudorandom integer "c" of length primeBitLength bits - uint32_t iteration_count; - CBigNum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count); + // Generate a pseudorandom integer "c" of length primeBitLength bits + uint32_t iteration_count; + CBigNum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count); #ifdef ZEROCOIN_DEBUG - cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl; - cout << "Generated c = " << c << endl; + cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl; + cout << "Generated c = " << c << endl; #endif - prime_seed += (iteration_count + 1); - (*prime_gen_counter)++; + prime_seed += (iteration_count + 1); + (*prime_gen_counter)++; - // Set "intc" to be the least odd integer >= "c" we just generated - uint32_t intc = c.getulong(); - intc = (2 * floor(intc / 2.0)) + 1; + // Set "intc" to be the least odd integer >= "c" we just generated + uint32_t intc = c.getulong(); + intc = (2 * floor(intc / 2.0)) + 1; #ifdef ZEROCOIN_DEBUG - cout << "Should be odd. c = " << intc << endl; - cout << "The big num is: c = " << c << endl; + cout << "Should be odd. c = " << intc << endl; + cout << "The big num is: c = " << c << endl; #endif - // Perform trial division on this (relatively small) integer to determine if "intc" - // is prime. If so, return success. - if (primalityTestByTrialDivision(intc)) { - // Return "intc" converted back into a CBigNum and "prime_seed". We also updated - // the variable "prime_gen_counter" in previous statements. - result = intc; - *out_seed = prime_seed; - - // Success - return result; - } - } // while() - - // If we reached this point there was an error finding a candidate prime - // so throw an exception. - throw std::runtime_error("Unable to find prime in Shawe-Taylor algorithm"); - - // END OF BASE CASE - } - // If primeBitLen >= 33 bits, perform the recursive case. - else { - // Recurse to find a new random prime of roughly half the size - uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1; - CBigNum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter); - - // Generate a random integer "x" of primeBitLen bits using the output - // of the previous call. - uint32_t numIterations; - CBigNum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations); - (*out_seed) += numIterations + 1; - - // Compute "t" = ⎡x / (2 * c0⎤ - // TODO no Ceiling call - CBigNum t = x / (CBigNum(2) * c0); - - // Repeat the following procedure until we find a prime (or time out) - for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) { - - // If ((2 * t * c0) + 1 > 2^{primeBitLen}), - // then t = ⎡2^{primeBitLen} – 1 / (2 * c0)⎤. - if ((CBigNum(2) * t * c0) > (CBigNum(2).pow(CBigNum(primeBitLen)))) { - t = ((CBigNum(2).pow(CBigNum(primeBitLen))) - CBigNum(1)) / (CBigNum(2) * c0); - } - - // Set c = (2 * t * c0) + 1 - CBigNum c = (CBigNum(2) * t * c0) + CBigNum(1); - - // Increment prime_gen_counter - (*prime_gen_counter)++; - - // Test "c" for primality as follows: - // 1. First pick an integer "a" in between 2 and (c - 2) - CBigNum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations); - a = CBigNum(2) + (a % (c - CBigNum(3))); - (*out_seed) += (numIterations + 1); - - // 2. Compute "z" = a^{2*t} mod c - CBigNum z = a.pow_mod(CBigNum(2) * t, c); - - // 3. Check if "c" is prime. - // Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1 - // If so we return "c" as our result. - if (c.gcd(z - CBigNum(1)).isOne() && z.pow_mod(c0, c).isOne()) { - // Return "c", out_seed and prime_gen_counter - // (the latter two of which were already updated) - return c; - } - - // 4. If the test did not succeed, increment "t" and loop - t = t + CBigNum(1); - } // end of test loop - } - - // We only reach this point if the test loop has iterated MAX_PRIMEGEN_ATTEMPTS - // and failed to identify a valid prime. Throw an exception. - throw std::runtime_error("Unable to generate random prime (too many tests)"); + // Perform trial division on this (relatively small) integer to determine if "intc" + // is prime. If so, return success. + if (primalityTestByTrialDivision(intc)) { + // Return "intc" converted back into a CBigNum and "prime_seed". We also updated + // the variable "prime_gen_counter" in previous statements. + result = intc; + *out_seed = prime_seed; + + // Success + return result; + } + } // while() + + // If we reached this point there was an error finding a candidate prime + // so throw an exception. + throw std::runtime_error("Unable to find prime in Shawe-Taylor algorithm"); + + // END OF BASE CASE + } + // If primeBitLen >= 33 bits, perform the recursive case. + else { + // Recurse to find a new random prime of roughly half the size + uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1; + CBigNum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter); + + // Generate a random integer "x" of primeBitLen bits using the output + // of the previous call. + uint32_t numIterations; + CBigNum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations); + (*out_seed) += numIterations + 1; + + // Compute "t" = ⎡x / (2 * c0⎤ + // TODO no Ceiling call + CBigNum t = x / (CBigNum(2) * c0); + + // Repeat the following procedure until we find a prime (or time out) + for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) { + + // If ((2 * t * c0) + 1 > 2^{primeBitLen}), + // then t = ⎡2^{primeBitLen} – 1 / (2 * c0)⎤. + if ((CBigNum(2) * t * c0) > (CBigNum(2).pow(CBigNum(primeBitLen)))) { + t = ((CBigNum(2).pow(CBigNum(primeBitLen))) - CBigNum(1)) / (CBigNum(2) * c0); + } + + // Set c = (2 * t * c0) + 1 + CBigNum c = (CBigNum(2) * t * c0) + CBigNum(1); + + // Increment prime_gen_counter + (*prime_gen_counter)++; + + // Test "c" for primality as follows: + // 1. First pick an integer "a" in between 2 and (c - 2) + CBigNum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations); + a = CBigNum(2) + (a % (c - CBigNum(3))); + (*out_seed) += (numIterations + 1); + + // 2. Compute "z" = a^{2*t} mod c + CBigNum z = a.pow_mod(CBigNum(2) * t, c); + + // 3. Check if "c" is prime. + // Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1 + // If so we return "c" as our result. + if (c.gcd(z - CBigNum(1)).isOne() && z.pow_mod(c0, c).isOne()) { + // Return "c", out_seed and prime_gen_counter + // (the latter two of which were already updated) + return c; + } + + // 4. If the test did not succeed, increment "t" and loop + t = t + CBigNum(1); + } // end of test loop + } + + // We only reach this point if the test loop has iterated MAX_PRIMEGEN_ATTEMPTS + // and failed to identify a valid prime. Throw an exception. + throw std::runtime_error("Unable to generate random prime (too many tests)"); } CBigNum generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations) { - CBigNum result(0); - uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS); + CBigNum result(0); + uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS); #ifdef ZEROCOIN_DEBUG - cout << "numBits = " << numBits << endl; - cout << "iterations = " << iterations << endl; + cout << "numBits = " << numBits << endl; + cout << "iterations = " << iterations << endl; #endif - // Loop "iterations" times filling up the value "result" with random bits - for (uint32_t count = 0; count < iterations; count++) { - // result += ( H(pseed + count) * 2^{count * p0len} ) - result += CBigNum(calculateHash(seed + count)) * CBigNum(2).pow(count * HASH_OUTPUT_BITS); - } + // Loop "iterations" times filling up the value "result" with random bits + for (uint32_t count = 0; count < iterations; count++) { + // result += ( H(pseed + count) * 2^{count * p0len} ) + result += CBigNum(calculateHash(seed + count)) * CBigNum(2).pow(count * HASH_OUTPUT_BITS); + } - result = CBigNum(2).pow(numBits - 1) + (result % (CBigNum(2).pow(numBits - 1))); + result = CBigNum(2).pow(numBits - 1) + (result % (CBigNum(2).pow(numBits - 1))); - // Return the number of iterations and the result - *numIterations = iterations; - return result; + // Return the number of iterations and the result + *numIterations = iterations; + return result; } /// \brief Determines whether a uint32_t is a prime through trial division. @@ -646,10 +646,10 @@ generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations) bool primalityTestByTrialDivision(uint32_t candidate) { - // TODO: HACK HACK WRONG WRONG - CBigNum canBignum(candidate); + // TODO: HACK HACK WRONG WRONG + CBigNum canBignum(candidate); - return canBignum.isPrime(); + return canBignum.isPrime(); } } // namespace libzerocoin diff --git a/src/libzerocoin/Params.cpp b/src/libzerocoin/Params.cpp index dccdbd1502025..a010fbc17535e 100644 --- a/src/libzerocoin/Params.cpp +++ b/src/libzerocoin/Params.cpp @@ -16,32 +16,32 @@ namespace libzerocoin { ZerocoinParams::ZerocoinParams(CBigNum N, uint32_t securityLevel) { - this->zkp_hash_len = securityLevel; - this->zkp_iterations = securityLevel; + this->zkp_hash_len = securityLevel; + this->zkp_iterations = securityLevel; - this->accumulatorParams.k_prime = ACCPROOF_KPRIME; - this->accumulatorParams.k_dprime = ACCPROOF_KDPRIME; + this->accumulatorParams.k_prime = ACCPROOF_KPRIME; + this->accumulatorParams.k_dprime = ACCPROOF_KDPRIME; - // Generate the parameters - CalculateParams(*this, N, ZEROCOIN_PROTOCOL_VERSION, securityLevel); + // Generate the parameters + CalculateParams(*this, N, ZEROCOIN_PROTOCOL_VERSION, securityLevel); - this->accumulatorParams.initialized = true; - this->initialized = true; + this->accumulatorParams.initialized = true; + this->initialized = true; } AccumulatorAndProofParams::AccumulatorAndProofParams() { - this->initialized = false; + this->initialized = false; } IntegerGroupParams::IntegerGroupParams() { - this->initialized = false; + this->initialized = false; } CBigNum IntegerGroupParams::randomElement() const { - // The generator of the group raised - // to a random number less than the order of the group - // provides us with a uniformly distributed random number. - return this->g.pow_mod(CBigNum::randBignum(this->groupOrder),this->modulus); + // The generator of the group raised + // to a random number less than the order of the group + // provides us with a uniformly distributed random number. + return this->g.pow_mod(CBigNum::randBignum(this->groupOrder),this->modulus); } } /* namespace libzerocoin */ diff --git a/src/libzerocoin/Params.h b/src/libzerocoin/Params.h index 6e51a9ba72ff4..ff5f1b63ac7fc 100644 --- a/src/libzerocoin/Params.h +++ b/src/libzerocoin/Params.h @@ -20,198 +20,198 @@ namespace libzerocoin { class IntegerGroupParams { public: - /** @brief Integer group class, default constructor - * - * Allocates an empty (uninitialized) set of parameters. - **/ - IntegerGroupParams(); - - /** - * Generates a random group element - * @return a random element in the group. - */ - CBigNum randomElement() const; - bool initialized; - - /** - * A generator for the group. - */ - CBigNum g; - - /** - * A second generator for the group. - * Note log_g(h) and log_h(g) must - * be unknown. - */ - CBigNum h; - - /** - * The modulus for the group. - */ - CBigNum modulus; - - /** - * The order of the group - */ - CBigNum groupOrder; - - ADD_SERIALIZE_METHODS; + /** @brief Integer group class, default constructor + * + * Allocates an empty (uninitialized) set of parameters. + **/ + IntegerGroupParams(); + + /** + * Generates a random group element + * @return a random element in the group. + */ + CBigNum randomElement() const; + bool initialized; + + /** + * A generator for the group. + */ + CBigNum g; + + /** + * A second generator for the group. + * Note log_g(h) and log_h(g) must + * be unknown. + */ + CBigNum h; + + /** + * The modulus for the group. + */ + CBigNum modulus; + + /** + * The order of the group + */ + CBigNum groupOrder; + + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(initialized); - READWRITE(g); - READWRITE(h); - READWRITE(modulus); - READWRITE(groupOrder); - } + READWRITE(initialized); + READWRITE(g); + READWRITE(h); + READWRITE(modulus); + READWRITE(groupOrder); + } }; class AccumulatorAndProofParams { public: - /** @brief Construct a set of Zerocoin parameters from a modulus "N". - * @param N A trusted RSA modulus - * @param securityLevel A security level expressed in symmetric bits (default 80) - * - * Allocates and derives a set of Zerocoin parameters from - * a trustworthy RSA modulus "N". This routine calculates all - * of the remaining parameters (group descriptions etc.) from N - * using a verifiable, deterministic procedure. - * - * Note: this constructor makes the fundamental assumption that "N" - * encodes a valid RSA-style modulus of the form "e1 * e2" where - * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT - * be known to any party, or the security of Zerocoin is - * compromised. The integer "N" must be a MINIMUM of 1024 - * in length. 3072 bits is strongly recommended. - **/ - AccumulatorAndProofParams(); - - //AccumulatorAndProofParams(CBigNum accumulatorModulus); - - bool initialized; - - /** - * Modulus used for the accumulator. - * Product of two safe primes who's factorization is unknown. - */ - CBigNum accumulatorModulus; - - /** - * The initial value for the accumulator - * A random Quadratic residue mod n thats not 1 - */ - CBigNum accumulatorBase; - - /** - * Lower bound on the value for committed coin. - * Required by the accumulator proof. - */ - CBigNum minCoinValue; - - /** - * Upper bound on the value for a comitted coin. - * Required by the accumulator proof. - */ - CBigNum maxCoinValue; - - /** - * The second of two groups used to form a commitment to - * a coin (which it self is a commitment to a serial number). - * This one differs from serialNumberSokCommitment due to - * restrictions from Camenisch and Lysyanskaya's paper. - */ - IntegerGroupParams accumulatorPoKCommitmentGroup; - - /** - * Hidden order quadratic residue group mod N. - * Used in the accumulator proof. - */ - IntegerGroupParams accumulatorQRNCommitmentGroup; - - /** - * Security parameter. - * Bit length of the challenges used in the accumulator proof. - */ - uint32_t k_prime; - - /** - * Security parameter. - * The statistical zero-knowledgeness of the accumulator proof. - */ - uint32_t k_dprime; - ADD_SERIALIZE_METHODS; + /** @brief Construct a set of Zerocoin parameters from a modulus "N". + * @param N A trusted RSA modulus + * @param securityLevel A security level expressed in symmetric bits (default 80) + * + * Allocates and derives a set of Zerocoin parameters from + * a trustworthy RSA modulus "N". This routine calculates all + * of the remaining parameters (group descriptions etc.) from N + * using a verifiable, deterministic procedure. + * + * Note: this constructor makes the fundamental assumption that "N" + * encodes a valid RSA-style modulus of the form "e1 * e2" where + * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT + * be known to any party, or the security of Zerocoin is + * compromised. The integer "N" must be a MINIMUM of 1024 + * in length. 3072 bits is strongly recommended. + **/ + AccumulatorAndProofParams(); + + //AccumulatorAndProofParams(CBigNum accumulatorModulus); + + bool initialized; + + /** + * Modulus used for the accumulator. + * Product of two safe primes who's factorization is unknown. + */ + CBigNum accumulatorModulus; + + /** + * The initial value for the accumulator + * A random Quadratic residue mod n thats not 1 + */ + CBigNum accumulatorBase; + + /** + * Lower bound on the value for committed coin. + * Required by the accumulator proof. + */ + CBigNum minCoinValue; + + /** + * Upper bound on the value for a comitted coin. + * Required by the accumulator proof. + */ + CBigNum maxCoinValue; + + /** + * The second of two groups used to form a commitment to + * a coin (which it self is a commitment to a serial number). + * This one differs from serialNumberSokCommitment due to + * restrictions from Camenisch and Lysyanskaya's paper. + */ + IntegerGroupParams accumulatorPoKCommitmentGroup; + + /** + * Hidden order quadratic residue group mod N. + * Used in the accumulator proof. + */ + IntegerGroupParams accumulatorQRNCommitmentGroup; + + /** + * Security parameter. + * Bit length of the challenges used in the accumulator proof. + */ + uint32_t k_prime; + + /** + * Security parameter. + * The statistical zero-knowledgeness of the accumulator proof. + */ + uint32_t k_dprime; + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(initialized); - READWRITE(accumulatorModulus); - READWRITE(accumulatorBase); - READWRITE(accumulatorPoKCommitmentGroup); - READWRITE(accumulatorQRNCommitmentGroup); - READWRITE(minCoinValue); - READWRITE(maxCoinValue); - READWRITE(k_prime); - READWRITE(k_dprime); + READWRITE(initialized); + READWRITE(accumulatorModulus); + READWRITE(accumulatorBase); + READWRITE(accumulatorPoKCommitmentGroup); + READWRITE(accumulatorQRNCommitmentGroup); + READWRITE(minCoinValue); + READWRITE(maxCoinValue); + READWRITE(k_prime); + READWRITE(k_dprime); } }; class ZerocoinParams { public: - /** @brief Construct a set of Zerocoin parameters from a modulus "N". - * @param N A trusted RSA modulus - * @param securityLevel A security level expressed in symmetric bits (default 80) - * - * Allocates and derives a set of Zerocoin parameters from - * a trustworthy RSA modulus "N". This routine calculates all - * of the remaining parameters (group descriptions etc.) from N - * using a verifiable, deterministic procedure. - * - * Note: this constructor makes the fundamental assumption that "N" - * encodes a valid RSA-style modulus of the form "e1 * e2" where - * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT - * be known to any party, or the security of Zerocoin is - * compromised. The integer "N" must be a MINIMUM of 1024 - * in length. 3072 bits is strongly recommended. - **/ - ZerocoinParams(CBigNum accumulatorModulus, - uint32_t securityLevel = ZEROCOIN_DEFAULT_SECURITYLEVEL); - - bool initialized; - - AccumulatorAndProofParams accumulatorParams; - - /** - * The Quadratic Residue group from which we form - * a coin as a commitment to a serial number. - */ - IntegerGroupParams coinCommitmentGroup; - - /** - * One of two groups used to form a commitment to - * a coin (which it self is a commitment to a serial number). - * This is the one used in the serial number poof. - * It's order must be equal to the modulus of coinCommitmentGroup. - */ - IntegerGroupParams serialNumberSoKCommitmentGroup; - - /** - * The number of iterations to use in the serial - * number proof. - */ - uint32_t zkp_iterations; - - /** - * The amount of the hash function we use for - * proofs. - */ - uint32_t zkp_hash_len; - - ADD_SERIALIZE_METHODS; + /** @brief Construct a set of Zerocoin parameters from a modulus "N". + * @param N A trusted RSA modulus + * @param securityLevel A security level expressed in symmetric bits (default 80) + * + * Allocates and derives a set of Zerocoin parameters from + * a trustworthy RSA modulus "N". This routine calculates all + * of the remaining parameters (group descriptions etc.) from N + * using a verifiable, deterministic procedure. + * + * Note: this constructor makes the fundamental assumption that "N" + * encodes a valid RSA-style modulus of the form "e1 * e2" where + * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT + * be known to any party, or the security of Zerocoin is + * compromised. The integer "N" must be a MINIMUM of 1024 + * in length. 3072 bits is strongly recommended. + **/ + ZerocoinParams(CBigNum accumulatorModulus, + uint32_t securityLevel = ZEROCOIN_DEFAULT_SECURITYLEVEL); + + bool initialized; + + AccumulatorAndProofParams accumulatorParams; + + /** + * The Quadratic Residue group from which we form + * a coin as a commitment to a serial number. + */ + IntegerGroupParams coinCommitmentGroup; + + /** + * One of two groups used to form a commitment to + * a coin (which it self is a commitment to a serial number). + * This is the one used in the serial number poof. + * It's order must be equal to the modulus of coinCommitmentGroup. + */ + IntegerGroupParams serialNumberSoKCommitmentGroup; + + /** + * The number of iterations to use in the serial + * number proof. + */ + uint32_t zkp_iterations; + + /** + * The amount of the hash function we use for + * proofs. + */ + uint32_t zkp_hash_len; + + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(initialized); - READWRITE(accumulatorParams); - READWRITE(coinCommitmentGroup); - READWRITE(serialNumberSoKCommitmentGroup); - READWRITE(zkp_iterations); - READWRITE(zkp_hash_len); - } + READWRITE(initialized); + READWRITE(accumulatorParams); + READWRITE(coinCommitmentGroup); + READWRITE(serialNumberSoKCommitmentGroup); + READWRITE(zkp_iterations); + READWRITE(zkp_hash_len); + } }; } /* namespace libzerocoin */ diff --git a/src/libzerocoin/SerialNumberSignatureOfKnowledge.cpp b/src/libzerocoin/SerialNumberSignatureOfKnowledge.cpp index 313462ec1f2fc..5de263f663439 100644 --- a/src/libzerocoin/SerialNumberSignatureOfKnowledge.cpp +++ b/src/libzerocoin/SerialNumberSignatureOfKnowledge.cpp @@ -37,31 +37,31 @@ CBigNum SeedTo1024(uint256 hashSeed) { SerialNumberSignatureOfKnowledge::SerialNumberSignatureOfKnowledge(const ZerocoinParams* p, const PrivateCoin& coin, const Commitment& commitmentToCoin, uint256 msghash):params(p), - s_notprime(p->zkp_iterations), - sprime(p->zkp_iterations) { - - // Sanity check: verify that the order of the "accumulatedValueCommitmentGroup" is - // equal to the modulus of "coinCommitmentGroup". Otherwise we will produce invalid - // proofs. - if (params->coinCommitmentGroup.modulus != params->serialNumberSoKCommitmentGroup.groupOrder) { - throw std::runtime_error("Groups are not structured correctly."); - } - - CBigNum a = params->coinCommitmentGroup.g; - CBigNum b = params->coinCommitmentGroup.h; - CBigNum g = params->serialNumberSoKCommitmentGroup.g; - CBigNum h = params->serialNumberSoKCommitmentGroup.h; - - CHashWriter hasher(0,0); - hasher << *params << commitmentToCoin.getCommitmentValue() << coin.getSerialNumber() << msghash; - - std::vector r(params->zkp_iterations); - std::vector v_seed(params->zkp_iterations); + s_notprime(p->zkp_iterations), + sprime(p->zkp_iterations) { + + // Sanity check: verify that the order of the "accumulatedValueCommitmentGroup" is + // equal to the modulus of "coinCommitmentGroup". Otherwise we will produce invalid + // proofs. + if (params->coinCommitmentGroup.modulus != params->serialNumberSoKCommitmentGroup.groupOrder) { + throw std::runtime_error("Groups are not structured correctly."); + } + + CBigNum a = params->coinCommitmentGroup.g; + CBigNum b = params->coinCommitmentGroup.h; + CBigNum g = params->serialNumberSoKCommitmentGroup.g; + CBigNum h = params->serialNumberSoKCommitmentGroup.h; + + CHashWriter hasher(0,0); + hasher << *params << commitmentToCoin.getCommitmentValue() << coin.getSerialNumber() << msghash; + + std::vector r(params->zkp_iterations); + std::vector v_seed(params->zkp_iterations); std::vector v_expanded(params->zkp_iterations); - std::vector c(params->zkp_iterations); + std::vector c(params->zkp_iterations); - for(uint32_t i=0; i < params->zkp_iterations; i++) { - r[i] = CBigNum::randBignum(params->coinCommitmentGroup.groupOrder); + for(uint32_t i=0; i < params->zkp_iterations; i++) { + r[i] = CBigNum::randBignum(params->coinCommitmentGroup.groupOrder); //use a random 256 bit seed that expands to 1024 bit for v[i] while (true) { @@ -75,81 +75,81 @@ SerialNumberSignatureOfKnowledge::SerialNumberSignatureOfKnowledge(const v_expanded[i] = bnExpanded; break; } - } - - for(uint32_t i=0; i < params->zkp_iterations; i++) { - // compute g^{ {a^x b^r} h^v} mod p2 - c[i] = challengeCalculation(coin.getSerialNumber(), r[i], v_expanded[i]); - } - - // We can't hash data in parallel either - // because OPENMP cannot not guarantee loops - // execute in order. - for(uint32_t i=0; i < params->zkp_iterations; i++) { - hasher << c[i]; - } - this->hash = hasher.GetHash(); - unsigned char *hashbytes = (unsigned char*) &hash; - - for(uint32_t i = 0; i < params->zkp_iterations; i++) { - int bit = i % 8; - int byte = i / 8; - - bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); - if (challenge_bit) { - s_notprime[i] = r[i]; - sprime[i] = v_seed[i]; - } else { - s_notprime[i] = r[i] - coin.getRandomness(); - sprime[i] = v_expanded[i] - (commitmentToCoin.getRandomness() * - b.pow_mod(r[i] - coin.getRandomness(), params->serialNumberSoKCommitmentGroup.groupOrder)); - } - } + } + + for(uint32_t i=0; i < params->zkp_iterations; i++) { + // compute g^{ {a^x b^r} h^v} mod p2 + c[i] = challengeCalculation(coin.getSerialNumber(), r[i], v_expanded[i]); + } + + // We can't hash data in parallel either + // because OPENMP cannot not guarantee loops + // execute in order. + for(uint32_t i=0; i < params->zkp_iterations; i++) { + hasher << c[i]; + } + this->hash = hasher.GetHash(); + unsigned char *hashbytes = (unsigned char*) &hash; + + for(uint32_t i = 0; i < params->zkp_iterations; i++) { + int bit = i % 8; + int byte = i / 8; + + bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); + if (challenge_bit) { + s_notprime[i] = r[i]; + sprime[i] = v_seed[i]; + } else { + s_notprime[i] = r[i] - coin.getRandomness(); + sprime[i] = v_expanded[i] - (commitmentToCoin.getRandomness() * + b.pow_mod(r[i] - coin.getRandomness(), params->serialNumberSoKCommitmentGroup.groupOrder)); + } + } } inline CBigNum SerialNumberSignatureOfKnowledge::challengeCalculation(const CBigNum& a_exp,const CBigNum& b_exp, const CBigNum& h_exp) const { - CBigNum a = params->coinCommitmentGroup.g; - CBigNum b = params->coinCommitmentGroup.h; - CBigNum g = params->serialNumberSoKCommitmentGroup.g; - CBigNum h = params->serialNumberSoKCommitmentGroup.h; + CBigNum a = params->coinCommitmentGroup.g; + CBigNum b = params->coinCommitmentGroup.h; + CBigNum g = params->serialNumberSoKCommitmentGroup.g; + CBigNum h = params->serialNumberSoKCommitmentGroup.h; - CBigNum exponent = (a.pow_mod(a_exp, params->serialNumberSoKCommitmentGroup.groupOrder) - * b.pow_mod(b_exp, params->serialNumberSoKCommitmentGroup.groupOrder)) % params->serialNumberSoKCommitmentGroup.groupOrder; + CBigNum exponent = (a.pow_mod(a_exp, params->serialNumberSoKCommitmentGroup.groupOrder) + * b.pow_mod(b_exp, params->serialNumberSoKCommitmentGroup.groupOrder)) % params->serialNumberSoKCommitmentGroup.groupOrder; - return (g.pow_mod(exponent, params->serialNumberSoKCommitmentGroup.modulus) * h.pow_mod(h_exp, params->serialNumberSoKCommitmentGroup.modulus)) % params->serialNumberSoKCommitmentGroup.modulus; + return (g.pow_mod(exponent, params->serialNumberSoKCommitmentGroup.modulus) * h.pow_mod(h_exp, params->serialNumberSoKCommitmentGroup.modulus)) % params->serialNumberSoKCommitmentGroup.modulus; } bool SerialNumberSignatureOfKnowledge::Verify(const CBigNum& coinSerialNumber, const CBigNum& valueOfCommitmentToCoin, const uint256 msghash) const { - CBigNum a = params->coinCommitmentGroup.g; - CBigNum b = params->coinCommitmentGroup.h; - CBigNum g = params->serialNumberSoKCommitmentGroup.g; - CBigNum h = params->serialNumberSoKCommitmentGroup.h; - CHashWriter hasher(0,0); - hasher << *params << valueOfCommitmentToCoin << coinSerialNumber << msghash; - - std::vector tprime(params->zkp_iterations); - unsigned char *hashbytes = (unsigned char*) &this->hash; - - for(uint32_t i = 0; i < params->zkp_iterations; i++) { - int bit = i % 8; - int byte = i / 8; - bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); - if(challenge_bit) { - tprime[i] = challengeCalculation(coinSerialNumber, s_notprime[i], SeedTo1024(sprime[i].getuint256())); - } else { - CBigNum exp = b.pow_mod(s_notprime[i], params->serialNumberSoKCommitmentGroup.groupOrder); - tprime[i] = ((valueOfCommitmentToCoin.pow_mod(exp, params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus) * - (h.pow_mod(sprime[i], params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus)) % - params->serialNumberSoKCommitmentGroup.modulus; - } - } - for(uint32_t i = 0; i < params->zkp_iterations; i++) { - hasher << tprime[i]; - } - return hasher.GetHash() == hash; + CBigNum a = params->coinCommitmentGroup.g; + CBigNum b = params->coinCommitmentGroup.h; + CBigNum g = params->serialNumberSoKCommitmentGroup.g; + CBigNum h = params->serialNumberSoKCommitmentGroup.h; + CHashWriter hasher(0,0); + hasher << *params << valueOfCommitmentToCoin << coinSerialNumber << msghash; + + std::vector tprime(params->zkp_iterations); + unsigned char *hashbytes = (unsigned char*) &this->hash; + + for(uint32_t i = 0; i < params->zkp_iterations; i++) { + int bit = i % 8; + int byte = i / 8; + bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); + if(challenge_bit) { + tprime[i] = challengeCalculation(coinSerialNumber, s_notprime[i], SeedTo1024(sprime[i].getuint256())); + } else { + CBigNum exp = b.pow_mod(s_notprime[i], params->serialNumberSoKCommitmentGroup.groupOrder); + tprime[i] = ((valueOfCommitmentToCoin.pow_mod(exp, params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus) * + (h.pow_mod(sprime[i], params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus)) % + params->serialNumberSoKCommitmentGroup.modulus; + } + } + for(uint32_t i = 0; i < params->zkp_iterations; i++) { + hasher << tprime[i]; + } + return hasher.GetHash() == hash; } } /* namespace libzerocoin */ diff --git a/src/libzerocoin/SerialNumberSignatureOfKnowledge.h b/src/libzerocoin/SerialNumberSignatureOfKnowledge.h index ccaba9ca3692e..915bfdd452550 100644 --- a/src/libzerocoin/SerialNumberSignatureOfKnowledge.h +++ b/src/libzerocoin/SerialNumberSignatureOfKnowledge.h @@ -33,41 +33,41 @@ namespace libzerocoin { */ class SerialNumberSignatureOfKnowledge { public: - SerialNumberSignatureOfKnowledge(const ZerocoinParams* p); - /** Creates a Signature of knowledge object that a commitment to a coin contains a coin with serial number x - * - * @param p params - * @param coin the coin we are going to prove the serial number of. - * @param commitmentToCoin the commitment to the coin - * @param msghash hash of meta data to create a signature of knowledge on. - */ - SerialNumberSignatureOfKnowledge(const ZerocoinParams* p, const PrivateCoin& coin, const Commitment& commitmentToCoin, uint256 msghash); + SerialNumberSignatureOfKnowledge(const ZerocoinParams* p); + /** Creates a Signature of knowledge object that a commitment to a coin contains a coin with serial number x + * + * @param p params + * @param coin the coin we are going to prove the serial number of. + * @param commitmentToCoin the commitment to the coin + * @param msghash hash of meta data to create a signature of knowledge on. + */ + SerialNumberSignatureOfKnowledge(const ZerocoinParams* p, const PrivateCoin& coin, const Commitment& commitmentToCoin, uint256 msghash); - /** Verifies the Signature of knowledge. - * - * @param msghash hash of meta data to create a signature of knowledge on. - * @return - */ - bool Verify(const CBigNum& coinSerialNumber, const CBigNum& valueOfCommitmentToCoin,const uint256 msghash) const; - ADD_SERIALIZE_METHODS; + /** Verifies the Signature of knowledge. + * + * @param msghash hash of meta data to create a signature of knowledge on. + * @return + */ + bool Verify(const CBigNum& coinSerialNumber, const CBigNum& valueOfCommitmentToCoin,const uint256 msghash) const; + ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(s_notprime); - READWRITE(sprime); - READWRITE(hash); - } + READWRITE(s_notprime); + READWRITE(sprime); + READWRITE(hash); + } private: - const ZerocoinParams* params; - // challenge hash - uint256 hash; //TODO For efficiency, should this be a bitset where Templates define params? + const ZerocoinParams* params; + // challenge hash + uint256 hash; //TODO For efficiency, should this be a bitset where Templates define params? - // challenge response values - // this is s_notprime instead of s - // because the serialization macros - // define something named s and it conflicts - std::vector s_notprime; - std::vector sprime; - inline CBigNum challengeCalculation(const CBigNum& a_exp, const CBigNum& b_exp, - const CBigNum& h_exp) const; + // challenge response values + // this is s_notprime instead of s + // because the serialization macros + // define something named s and it conflicts + std::vector s_notprime; + std::vector sprime; + inline CBigNum challengeCalculation(const CBigNum& a_exp, const CBigNum& b_exp, + const CBigNum& h_exp) const; }; } /* namespace libzerocoin */ diff --git a/src/libzerocoin/ZerocoinDefines.h b/src/libzerocoin/ZerocoinDefines.h index 9f19a461227cf..e5cf00759b100 100644 --- a/src/libzerocoin/ZerocoinDefines.h +++ b/src/libzerocoin/ZerocoinDefines.h @@ -22,9 +22,9 @@ #define ACCPROOF_KPRIME 160 #define ACCPROOF_KDPRIME 128 #define MAX_COINMINT_ATTEMPTS 10000 -#define ZEROCOIN_MINT_PRIME_PARAM 20 +#define ZEROCOIN_MINT_PRIME_PARAM 20 #define ZEROCOIN_VERSION_STRING "0.11" -#define ZEROCOIN_VERSION_INT 11 +#define ZEROCOIN_VERSION_INT 11 #define ZEROCOIN_PROTOCOL_VERSION "1" #define HASH_OUTPUT_BITS 256 #define ZEROCOIN_COMMITMENT_EQUALITY_PROOF "COMMITMENT_EQUALITY_PROOF" @@ -36,6 +36,6 @@ // Uses a fast technique for coin generation. Could be more vulnerable // to timing attacks. Turn off if an attacker can measure coin minting time. -#define ZEROCOIN_FAST_MINT 1 +#define ZEROCOIN_FAST_MINT 1 #endif /* ZEROCOIN_H_ */ diff --git a/src/libzerocoin/bignum.h b/src/libzerocoin/bignum.h index f5276c68ec6ed..769bd890fcf46 100644 --- a/src/libzerocoin/bignum.h +++ b/src/libzerocoin/bignum.h @@ -94,7 +94,7 @@ class CBigNum CBigNum(short n) { bn = BN_new(); if (n >= 0) setulong(n); else setint64(n); } CBigNum(int n) { bn = BN_new(); if (n >= 0) setulong(n); else setint64(n); } CBigNum(long n) { bn = BN_new(); if (n >= 0) setulong(n); else setint64(n); } -#ifdef __APPLE__ +#ifdef __APPLE__ CBigNum(int64_t n) { bn = BN_new(); setint64(n); } #endif CBigNum(unsigned char n) { bn = BN_new(); setulong(n); } @@ -423,7 +423,7 @@ class CBigNum CAutoBN_CTX pctx; CBigNum bnBase = nBase; CBigNum bn0 = 0; - CBigNum locBn = *this; + CBigNum locBn = *this; std::string str; BN_set_negative(locBn.bn, false); CBigNum dv; @@ -573,7 +573,7 @@ class CBigNum /** * Miller-Rabin primality test on this element * @param checks: optional, the number of Miller-Rabin tests to run - * default causes error rate of 2^-80. + * default causes error rate of 2^-80. * @return true if prime */ bool isPrime(const int checks=BN_prime_checks) const { @@ -606,7 +606,7 @@ class CBigNum CBigNum& operator-=(const CBigNum& b) { if (!BN_sub(bn, bn, b.bn)) - throw bignum_error("CBigNum::operator-= : BN_sub failed"); + throw bignum_error("CBigNum::operator-= : BN_sub failed"); return *this; } @@ -620,17 +620,17 @@ class CBigNum CBigNum& operator/=(const CBigNum& b) { - CAutoBN_CTX pctx; + CAutoBN_CTX pctx; if (!BN_div(bn, NULL, bn, b.bn, pctx)) - throw bignum_error("CBigNum::operator/= : BN_div failed"); + throw bignum_error("CBigNum::operator/= : BN_div failed"); return *this; } CBigNum& operator%=(const CBigNum& b) { - CAutoBN_CTX pctx; + CAutoBN_CTX pctx; if (!BN_mod(bn, b.bn, bn, pctx)) - throw bignum_error("CBigNum::operator%= : BN_mod failed"); + throw bignum_error("CBigNum::operator%= : BN_mod failed"); return *this; } diff --git a/src/libzerocoin/paramgen.cpp b/src/libzerocoin/paramgen.cpp index 8e29f332aab06..2f47828501349 100644 --- a/src/libzerocoin/paramgen.cpp +++ b/src/libzerocoin/paramgen.cpp @@ -25,103 +25,103 @@ void PrintWarning() { - cout << "Zerocoin parameter generation utility" << endl; - cout << "-------------------------------------" << endl << endl; - cout << "This utility generates an l-bit modulus N as the product of" << endl; - cout << "two safe primes p, q. The values p and q are not stored." << endl; - cout << "Call this program with no arguments to see usage options." << endl; - cout << endl; - cout << "SECURITY WARNING: ZEROCOIN PARAMETERS MUST BE GENERATED BY" << endl; - cout << "A TRUSTED PARTY WHO DOES NOT STORE THE FACTORS. WHILE WE MAKE" << endl; - cout << "A BEST EFFORT TO DESTROY THIS INFORMATION WE DO NOT TAKE" << endl; - cout << "SPECIAL PRECAUTIONS TO ENSURE THAT THEY ARE DESTROYED." << endl; - cout << endl; - cout << "USE THIS UTILITY AT YOUR OWN RISK" << endl << endl; + cout << "Zerocoin parameter generation utility" << endl; + cout << "-------------------------------------" << endl << endl; + cout << "This utility generates an l-bit modulus N as the product of" << endl; + cout << "two safe primes p, q. The values p and q are not stored." << endl; + cout << "Call this program with no arguments to see usage options." << endl; + cout << endl; + cout << "SECURITY WARNING: ZEROCOIN PARAMETERS MUST BE GENERATED BY" << endl; + cout << "A TRUSTED PARTY WHO DOES NOT STORE THE FACTORS. WHILE WE MAKE" << endl; + cout << "A BEST EFFORT TO DESTROY THIS INFORMATION WE DO NOT TAKE" << endl; + cout << "SPECIAL PRECAUTIONS TO ENSURE THAT THEY ARE DESTROYED." << endl; + cout << endl; + cout << "USE THIS UTILITY AT YOUR OWN RISK" << endl << endl; } void usage() { - printf("Usage:\n"); - printf(" -b \n"); - printf(" -o \n"); + printf("Usage:\n"); + printf(" -b \n"); + printf(" -o \n"); - exit (8); + exit (8); } int main(int argc, char **argv) { - static CBigNum resultModulus(0); - uint32_t numBits = DEFAULT_MODULUS_SIZE; - ofstream outfile; - char* outfileName; - bool writeToFile = false; - - while ((argc > 1) && (argv[1][0] == '-')) - { - switch (argv[1][1]) - { - case 'b': - numBits = atoi(argv[2]); - ++argv; - --argc; - break; - - case 'o': - outfileName = argv[2]; - writeToFile = true; - break; - - case 'h': - usage(); - break; - - default: - printf("Wrong Argument: %s\n", argv[1]); - usage(); - break; - } - - ++argv; - --argc; - } - - if (numBits < MIN_MODULUS_SIZE) { - cout << "Modulus is below minimum length (" << MIN_MODULUS_SIZE << ") bits" << endl; - return(0); - } - - PrintWarning(); - - cout << "Modulus size set to " << numBits << " bits." << endl; - cout << "Generating parameters. This may take a few minutes..." << endl; - - // Generate two safe primes "p" and "q" - CBigNum *p, *q; - p = new CBigNum(0); - q = new CBigNum(0); - *p = CBigNum::generatePrime(numBits / 2, true); - *q = CBigNum::generatePrime(numBits / 2, true); - - // Multiply to compute N - resultModulus = (*p) * (*q); - - // Wipe out the factors - delete p; - delete q; - - // Convert to a hexidecimal string - std::string resultHex = resultModulus.ToString(16); - - cout << endl << "N = " << endl << resultHex << endl; - - if (writeToFile) { - try { - outfile.open (outfileName); - outfile << resultHex; - outfile.close(); - cout << endl << "Result has been written to file '" << outfileName << "'." << endl; - } catch (std::runtime_error &e) { - cout << "Unable to write to file:" << e.what() << endl; - } - } + static CBigNum resultModulus(0); + uint32_t numBits = DEFAULT_MODULUS_SIZE; + ofstream outfile; + char* outfileName; + bool writeToFile = false; + + while ((argc > 1) && (argv[1][0] == '-')) + { + switch (argv[1][1]) + { + case 'b': + numBits = atoi(argv[2]); + ++argv; + --argc; + break; + + case 'o': + outfileName = argv[2]; + writeToFile = true; + break; + + case 'h': + usage(); + break; + + default: + printf("Wrong Argument: %s\n", argv[1]); + usage(); + break; + } + + ++argv; + --argc; + } + + if (numBits < MIN_MODULUS_SIZE) { + cout << "Modulus is below minimum length (" << MIN_MODULUS_SIZE << ") bits" << endl; + return(0); + } + + PrintWarning(); + + cout << "Modulus size set to " << numBits << " bits." << endl; + cout << "Generating parameters. This may take a few minutes..." << endl; + + // Generate two safe primes "p" and "q" + CBigNum *p, *q; + p = new CBigNum(0); + q = new CBigNum(0); + *p = CBigNum::generatePrime(numBits / 2, true); + *q = CBigNum::generatePrime(numBits / 2, true); + + // Multiply to compute N + resultModulus = (*p) * (*q); + + // Wipe out the factors + delete p; + delete q; + + // Convert to a hexidecimal string + std::string resultHex = resultModulus.ToString(16); + + cout << endl << "N = " << endl << resultHex << endl; + + if (writeToFile) { + try { + outfile.open (outfileName); + outfile << resultHex; + outfile.close(); + cout << endl << "Result has been written to file '" << outfileName << "'." << endl; + } catch (std::runtime_error &e) { + cout << "Unable to write to file:" << e.what() << endl; + } + } } diff --git a/src/masternode.cpp b/src/masternode.cpp index 59f392aba5271..a9262d42e586c 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -209,8 +209,8 @@ void CMasternode::Check(bool forceCheck) } if(lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS){ - activeState = MASTERNODE_PRE_ENABLED; - return; + activeState = MASTERNODE_PRE_ENABLED; + return; } if (!unitTest) { @@ -523,7 +523,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos) std::string errorMessage = ""; if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetNewStrMessage(), errorMessage) - && !obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetOldStrMessage(), errorMessage)) + && !obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetOldStrMessage(), errorMessage)) { // don't ban for old masternodes, their sigs could be broken because of the bug nDos = protocolVersion < MIN_PEER_MNANNOUNCE ? 0 : 100; @@ -542,11 +542,11 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos) if (pmn == NULL) return true; // this broadcast is older or equal than the one that we already have - it's bad and should never happen - // unless someone is doing something fishy - // (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates) - if(pmn->sigTime >= sigTime) { - return error("CMasternodeBroadcast::CheckAndUpdate - Bad sigTime %d for Masternode %20s %105s (existing broadcast is at %d)", - sigTime, addr.ToString(), vin.ToString(), pmn->sigTime); + // unless someone is doing something fishy + // (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates) + if(pmn->sigTime >= sigTime) { + return error("CMasternodeBroadcast::CheckAndUpdate - Bad sigTime %d for Masternode %20s %105s (existing broadcast is at %d)", + sigTime, addr.ToString(), vin.ToString(), pmn->sigTime); } // masternode is not enabled yet/already, nothing to update @@ -666,16 +666,16 @@ bool CMasternodeBroadcast::Sign(CKey& keyCollateralAddress) std::string strMessage; if(chainActive.Height() <= Params().Zerocoin_LastOldParams()) - strMessage = GetOldStrMessage(); + strMessage = GetOldStrMessage(); else - strMessage = GetNewStrMessage(); + strMessage = GetNewStrMessage(); if (!obfuScationSigner.SignMessage(strMessage, errorMessage, sig, keyCollateralAddress)) - return error("CMasternodeBroadcast::Sign() - Error: %s", errorMessage); + return error("CMasternodeBroadcast::Sign() - Error: %s", errorMessage); if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, strMessage, errorMessage)) - return error("CMasternodeBroadcast::Sign() - Error: %s", errorMessage); + return error("CMasternodeBroadcast::Sign() - Error: %s", errorMessage); return true; } @@ -752,13 +752,13 @@ bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode) bool CMasternodePing::VerifySignature(CPubKey& pubKeyMasternode, int &nDos) { std::string strMessage = vin.ToString() + blockHash.ToString() + std::to_string(sigTime); - std::string errorMessage = ""; + std::string errorMessage = ""; - if(!obfuScationSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage)){ - nDos = 33; - return error("CMasternodePing::VerifySignature - Got bad Masternode ping signature %s Error: %s", vin.ToString(), errorMessage); - } - return true; + if(!obfuScationSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage)){ + nDos = 33; + return error("CMasternodePing::VerifySignature - Got bad Masternode ping signature %s Error: %s", vin.ToString(), errorMessage); + } + return true; } bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled, bool fCheckSigTimeOnly) @@ -772,9 +772,9 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled, bool fChec if(fCheckSigTimeOnly) { - CMasternode* pmn = mnodeman.Find(vin); - if(pmn) return VerifySignature(pmn->pubKeyMasternode, nDos); - return true; + CMasternode* pmn = mnodeman.Find(vin); + if(pmn) return VerifySignature(pmn->pubKeyMasternode, nDos); + return true; } LogPrint("masternode", "CMasternodePing::CheckAndUpdate - New Ping - %s - %s - %lli\n", GetHash().ToString(), blockHash.ToString(), sigTime); @@ -788,7 +788,7 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled, bool fChec // update only if there is no known ping for this masternode or // last ping was more then MASTERNODE_MIN_MNP_SECONDS-60 ago comparing to this one if (!pmn->IsPingedWithin(MASTERNODE_MIN_MNP_SECONDS - 60, sigTime)) { - if (!VerifySignature(pmn->pubKeyMasternode, nDos)) + if (!VerifySignature(pmn->pubKeyMasternode, nDos)) return false; BlockMap::iterator mi = mapBlockIndex.find(blockHash); diff --git a/src/masternodeconfig.cpp b/src/masternodeconfig.cpp index b90224b64b48b..1a78d32d0f642 100644 --- a/src/masternodeconfig.cpp +++ b/src/masternodeconfig.cpp @@ -106,13 +106,13 @@ bool CMasternodeConfig::CMasternodeEntry::castOutputIndex(int &n) void CMasternodeConfig::clear() { - entries.clear(); + entries.clear(); } void CMasternodeConfig::deleteAlias(int count) { - count = count - 1; - entries.erase(entries.begin()+count); + count = count - 1; + entries.erase(entries.begin()+count); } void CMasternodeConfig::writeToMasternodeConf() @@ -127,9 +127,9 @@ void CMasternodeConfig::writeToMasternodeConf() "# Format: alias IP:port masternodeprivkey collateral_output_txid collateral_output_index\n" "# Example: mn1 127.0.0.2:11771 93HaYBVUCYjEMeeH1Y4sBGLALQZE1Yc1K64xiqgX37tGBDQL8Xg 2bcd3c84c84f87eaa86e4e56834c92927a07f9e18718810b92e0d0324456a67c 0\n"; fwrite(strHeader.c_str(), std::strlen(strHeader.c_str()), 1, configFile); - + std::string masternodeAliasBase = ""; - + for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) { // Orders configs in proper strings std::string masternodeAliasLine = mne.getAlias() + " " + mne.getIp() + " " + mne.getPrivKey() + " " + mne.getTxHash() + " " + mne.getOutputIndex() + "\n"; diff --git a/src/masternodeconfig.h b/src/masternodeconfig.h index f53c5958b0ad4..ac32cfd6e95cd 100644 --- a/src/masternodeconfig.h +++ b/src/masternodeconfig.h @@ -97,9 +97,9 @@ class CMasternodeConfig void clear(); bool read(std::string& strErr); - void writeToMasternodeConf(); + void writeToMasternodeConf(); void add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex); - void deleteAlias(int count); + void deleteAlias(int count); std::vector& getEntries() { diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index e202b2c3ad173..25fbd81cc0f09 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -1161,7 +1161,7 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb) CMasternode mn(mnb); Add(mn); } else { - pmn->UpdateFromNewBroadcast(mnb); + pmn->UpdateFromNewBroadcast(mnb); } } diff --git a/src/primitives/block.h b/src/primitives/block.h index c53833dcfa69f..4193344adb99d 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -113,8 +113,8 @@ class CBlock : public CBlockHeader inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(*(CBlockHeader*)this); READWRITE(vtx); - if(vtx.size() > 1 && vtx[1].IsCoinStake()) - READWRITE(vchBlockSig); + if(vtx.size() > 1 && vtx[1].IsCoinStake()) + READWRITE(vchBlockSig); } void SetNull() diff --git a/src/protocol.cpp b/src/protocol.cpp index 89ed9a3f4f8d4..352b017007083 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -254,7 +254,7 @@ bool CInv::IsKnownType() const } bool CInv::IsMasterNodeType() const{ - return (type >= 6); + return (type >= 6); } const char* CInv::GetCommand() const diff --git a/src/protocol.h b/src/protocol.h index 88ec6e66fe08d..ad530bfdb22bb 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -315,10 +315,10 @@ enum { // witness data. NODE_WITNESS = (1 << 3), - // NODE_BLOOM_WITHOUT_MN means the node has the same features as NODE_BLOOM with the only difference - // that the node doens't want to receive master nodes messages. (the 1<<3 was not picked as constant because on bitcoin 0.14 is witness and we want that update here ) + // NODE_BLOOM_WITHOUT_MN means the node has the same features as NODE_BLOOM with the only difference + // that the node doens't want to receive master nodes messages. (the 1<<3 was not picked as constant because on bitcoin 0.14 is witness and we want that update here ) - NODE_BLOOM_WITHOUT_MN = (1 << 4), + NODE_BLOOM_WITHOUT_MN = (1 << 4), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index bb610b15b1707..ea41b94bd4d9b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -114,7 +114,7 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle* networkStyle, QWidget* parent) : QMai QFontDatabase::addApplicationFont(":/fonts/Hind-SemiBold"); QFontDatabase::addApplicationFont(":/fonts/Hind-Regular"); QFontDatabase::addApplicationFont(":/fonts/Hind-Light"); - QFontDatabase::addApplicationFont(":/fonts/Montserrat-Bold"); + QFontDatabase::addApplicationFont(":/fonts/Montserrat-Bold"); /* Open CSS when configured */ this->setStyleSheet(GUIUtil::loadStyleSheet()); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 0ac50bb3e7572..6cdc5260098f5 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -539,7 +539,7 @@ void CoinControlDialog::updateLabels(WalletModel* model, QDialog* dialog) nPayAmount += amount; if (amount > 0) { - CTxOut txout(amount, (CScript)vector(24, 0)); + CTxOut txout(amount, (CScript)std::vector(24, 0)); txDummy.vout.push_back(txout); if (txout.IsDust(::minRelayTxFee)) fDust = true; @@ -645,7 +645,7 @@ void CoinControlDialog::updateLabels(WalletModel* model, QDialog* dialog) // Never create dust outputs; if we would, just add the dust to the fee. if (nChange > 0 && nChange < CENT) { - CTxOut txout(nChange, (CScript)vector(24, 0)); + CTxOut txout(nChange, (CScript)std::vector(24, 0)); if (txout.IsDust(::minRelayTxFee)) { nPayFee += nChange; nChange = 0; diff --git a/src/qt/configuremasternodepage.cpp b/src/qt/configuremasternodepage.cpp index a381043f4d426..2f491de80cb46 100644 --- a/src/qt/configuremasternodepage.cpp +++ b/src/qt/configuremasternodepage.cpp @@ -39,12 +39,12 @@ ConfigureMasternodePage::ConfigureMasternodePage(Mode mode, QWidget* parent) : Q mode(mode) { ui->setupUi(this); - - GUIUtil::setupAliasWidget(ui->aliasEdit, this); - GUIUtil::setupIPWidget(ui->vpsIpEdit, this); - GUIUtil::setupPrivKeyWidget(ui->privKeyEdit, this); - GUIUtil::setupTXIDWidget(ui->outputEdit, this); - GUIUtil::setupTXIDIndexWidget(ui->outputIdEdit, this); + + GUIUtil::setupAliasWidget(ui->aliasEdit, this); + GUIUtil::setupIPWidget(ui->vpsIpEdit, this); + GUIUtil::setupPrivKeyWidget(ui->privKeyEdit, this); + GUIUtil::setupTXIDWidget(ui->outputEdit, this); + GUIUtil::setupTXIDIndexWidget(ui->outputIdEdit, this); switch (mode) { case NewConfigureMasternode: @@ -105,53 +105,53 @@ void ConfigureMasternodePage::saveCurrentRow() switch (mode) { case NewConfigureMasternode: - if(ui->aliasEdit->text().toStdString().empty() || ui->vpsIpEdit->text().toStdString().empty() || ui->privKeyEdit->text().toStdString().empty() || ui->outputEdit->text().toStdString().empty() || ui->outputIdEdit->text().toStdString().empty()) { - break; - } - masternodeConfig.add(ui->aliasEdit->text().toStdString(), ui->vpsIpEdit->text().toStdString(), ui->privKeyEdit->text().toStdString(), ui->outputEdit->text().toStdString(), ui->outputIdEdit->text().toStdString()); - masternodeConfig.writeToMasternodeConf(); + if(ui->aliasEdit->text().toStdString().empty() || ui->vpsIpEdit->text().toStdString().empty() || ui->privKeyEdit->text().toStdString().empty() || ui->outputEdit->text().toStdString().empty() || ui->outputIdEdit->text().toStdString().empty()) { + break; + } + masternodeConfig.add(ui->aliasEdit->text().toStdString(), ui->vpsIpEdit->text().toStdString(), ui->privKeyEdit->text().toStdString(), ui->outputEdit->text().toStdString(), ui->outputIdEdit->text().toStdString()); + masternodeConfig.writeToMasternodeConf(); break; case EditConfigureMasternode: - if(ui->aliasEdit->text().toStdString().empty() || ui->vpsIpEdit->text().toStdString().empty() || ui->privKeyEdit->text().toStdString().empty() || ui->outputEdit->text().toStdString().empty() || ui->outputIdEdit->text().toStdString().empty()) { - break; - } - - QString MnAlias = getMnAliasCache(); - ConfigureMasternodePage::updateAlias(ui->aliasEdit->text().toStdString(), ui->vpsIpEdit->text().toStdString(), ui->privKeyEdit->text().toStdString(), ui->outputEdit->text().toStdString(), ui->outputIdEdit->text().toStdString(), MnAlias.toStdString()); - break; + if(ui->aliasEdit->text().toStdString().empty() || ui->vpsIpEdit->text().toStdString().empty() || ui->privKeyEdit->text().toStdString().empty() || ui->outputEdit->text().toStdString().empty() || ui->outputIdEdit->text().toStdString().empty()) { + break; + } + + QString MnAlias = getMnAliasCache(); + ConfigureMasternodePage::updateAlias(ui->aliasEdit->text().toStdString(), ui->vpsIpEdit->text().toStdString(), ui->privKeyEdit->text().toStdString(), ui->outputEdit->text().toStdString(), ui->outputIdEdit->text().toStdString(), MnAlias.toStdString()); + break; } } void ConfigureMasternodePage::accept() { - saveCurrentRow(); - emit accepted(); + saveCurrentRow(); + emit accepted(); QDialog::accept(); } void ConfigureMasternodePage::updateAlias(std::string Alias, std::string IP, std::string PrivKey, std::string TxHash, std::string OutputIndex, std::string mnAlias) { - for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) { - if(mnAlias == mne.getAlias()) { - int count = 0; - count = getCounters(); - std::vector confLockedCoins; - uint256 mnTxHash; - mnTxHash.SetHex(mne.getTxHash()); - int nIndex; - if(!mne.castOutputIndex(nIndex)) - continue; - COutPoint outpoint = COutPoint(mnTxHash, nIndex); - confLockedCoins.push_back(outpoint); - pwalletMain->UnlockCoin(outpoint); - - masternodeConfig.deleteAlias(count); - masternodeConfig.add(Alias, IP, PrivKey, TxHash, OutputIndex); - // write to masternode.conf - masternodeConfig.writeToMasternodeConf(); - } - } + for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) { + if(mnAlias == mne.getAlias()) { + int count = 0; + count = getCounters(); + std::vector confLockedCoins; + uint256 mnTxHash; + mnTxHash.SetHex(mne.getTxHash()); + int nIndex; + if(!mne.castOutputIndex(nIndex)) + continue; + COutPoint outpoint = COutPoint(mnTxHash, nIndex); + confLockedCoins.push_back(outpoint); + pwalletMain->UnlockCoin(outpoint); + + masternodeConfig.deleteAlias(count); + masternodeConfig.add(Alias, IP, PrivKey, TxHash, OutputIndex); + // write to masternode.conf + masternodeConfig.writeToMasternodeConf(); + } + } } @@ -160,7 +160,7 @@ void ConfigureMasternodePage::on_AutoFillPrivKey_clicked() CKey secret; secret.MakeNewKey(false); - ui->privKeyEdit->setText(QString::fromStdString(CBitcoinSecret(secret).ToString())); + ui->privKeyEdit->setText(QString::fromStdString(CBitcoinSecret(secret).ToString())); } diff --git a/src/qt/configuremasternodepage.h b/src/qt/configuremasternodepage.h index e6c8467502edf..ef78a275cbc7f 100644 --- a/src/qt/configuremasternodepage.h +++ b/src/qt/configuremasternodepage.h @@ -47,33 +47,33 @@ class ConfigureMasternodePage : public QDialog explicit ConfigureMasternodePage(Mode mode, QWidget* parent); ~ConfigureMasternodePage(); - void counter(int counter); - void MNAliasCache(QString MnAliasCache); + void counter(int counter); + void MNAliasCache(QString MnAliasCache); void loadAlias(QString strAlias); void loadIP(QString strIP); void loadPrivKey(QString strPrivKey); void loadTxHash(QString strTxHash); void loadOutputIndex(QString strOutputIndex); - void updateAlias(std::string Alias, std::string IP, std::string PrivKey, std::string TxHash, std::string OutputIndex, std::string mnAlias); - int getCounters() - { - return counters; - } - - int setCounters(int counter) - { - counters = counter; - } - - QString getMnAliasCache() - { - return mnAliasCache; - } - - void setMnAliasCache(QString mnAliasCaches) - { - mnAliasCache = mnAliasCaches; - } + void updateAlias(std::string Alias, std::string IP, std::string PrivKey, std::string TxHash, std::string OutputIndex, std::string mnAlias); + int getCounters() + { + return counters; + } + + int setCounters(int counter) + { + counters = counter; + } + + QString getMnAliasCache() + { + return mnAliasCache; + } + + void setMnAliasCache(QString mnAliasCaches) + { + mnAliasCache = mnAliasCaches; + } QString getAddress() const; void setAddress(const QString& address); @@ -85,8 +85,8 @@ public slots: private: void saveCurrentRow(); - int counters; - QString mnAliasCache; + int counters; + QString mnAliasCache; Ui::ConfigureMasternodePage* ui; QDataWidgetMapper* mapper; Mode mode; diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index 5df4220bccb05..f1784c82a70b0 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -59,21 +59,21 @@ MasternodeList::MasternodeList(QWidget* parent) : QWidget(parent), QAction* startAliasAction = new QAction(tr("Start alias"), this); QAction* copyAliasAction = new QAction(tr("Copy alias"), this); QAction* editAliasAction = new QAction(tr("Edit alias"), this); - QAction* deleteAliasAction = new QAction(tr("Delete"), this); + QAction* deleteAliasAction = new QAction(tr("Delete"), this); contextMenu = new QMenu(); contextMenu->addAction(startAliasAction); contextMenu->addAction(copyAliasAction); contextMenu->addAction(editAliasAction); - contextMenu->addAction(deleteAliasAction); - + contextMenu->addAction(deleteAliasAction); + connect(ui->tableWidgetMyMasternodes, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&))); - connect(startAliasAction, SIGNAL(triggered()), this, SLOT(on_startButton_clicked())); - connect(copyAliasAction, SIGNAL(triggered()), this, SLOT(copyAlias())); - connect(editAliasAction, SIGNAL(triggered()), this, SLOT(on_editConfigureMasternode_clicked())); - connect(deleteAliasAction, SIGNAL(triggered()), this, SLOT(deleteAlias())); - - + connect(startAliasAction, SIGNAL(triggered()), this, SLOT(on_startButton_clicked())); + connect(copyAliasAction, SIGNAL(triggered()), this, SLOT(copyAlias())); + connect(editAliasAction, SIGNAL(triggered()), this, SLOT(on_editConfigureMasternode_clicked())); + connect(deleteAliasAction, SIGNAL(triggered()), this, SLOT(deleteAlias())); + + timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateMyNodeList())); timer->start(1000); @@ -186,7 +186,7 @@ void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, C bool fOldRowFound = false; int nNewRow = 0; - + for (int i = 0; i < ui->tableWidgetMyMasternodes->rowCount(); i++) { if (ui->tableWidgetMyMasternodes->item(i, 0)->text() == strAlias) { fOldRowFound = true; @@ -291,35 +291,35 @@ void MasternodeList::on_editConfigureMasternode_clicked() int nSelectedRow = index.row(); std::string strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString(); - int count = 0; + int count = 0; for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) { - count = count + 1; - if(strAlias == mne.getAlias()) { - MasternodeList::openEditConfigureMasternodePage(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), QString::fromStdString(mne.getPrivKey()), QString::fromStdString(mne.getTxHash()), QString::fromStdString(mne.getOutputIndex()), count); - break; - - } + count = count + 1; + if(strAlias == mne.getAlias()) { + MasternodeList::openEditConfigureMasternodePage(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), QString::fromStdString(mne.getPrivKey()), QString::fromStdString(mne.getTxHash()), QString::fromStdString(mne.getOutputIndex()), count); + break; + + } } } void MasternodeList::on_configureMasternodeButton_clicked() { - + ConfigureMasternodePage dlg(ConfigureMasternodePage::NewConfigureMasternode, this); if ( QDialog::Accepted == dlg.exec() ) { while (ui->tableWidgetMyMasternodes->rowCount() > 0) - { - ui->tableWidgetMyMasternodes->removeRow(0); - } - - // clear cache - masternodeConfig.clear(); + { + ui->tableWidgetMyMasternodes->removeRow(0); + } + + // clear cache + masternodeConfig.clear(); // parse masternode.conf std::string strErr; if (!masternodeConfig.read(strErr)) { LogPrintf("Error reading masternode configuration file: \n"); - } + } updateMyNodeList(true); } } @@ -328,26 +328,26 @@ void MasternodeList::openEditConfigureMasternodePage(QString strAlias, QString s { ConfigureMasternodePage dlg(ConfigureMasternodePage::EditConfigureMasternode, this); dlg.loadAlias(strAlias); - dlg.loadIP(strIP); - dlg.loadPrivKey(strPrivKey); - dlg.loadTxHash(strTxHash); - dlg.loadOutputIndex(strOutputIndex); - dlg.counter(count); - dlg.MNAliasCache(strAlias); + dlg.loadIP(strIP); + dlg.loadPrivKey(strPrivKey); + dlg.loadTxHash(strTxHash); + dlg.loadOutputIndex(strOutputIndex); + dlg.counter(count); + dlg.MNAliasCache(strAlias); if ( QDialog::Accepted == dlg.exec() ) { while (ui->tableWidgetMyMasternodes->rowCount() > 0) - { - ui->tableWidgetMyMasternodes->removeRow(0); - } - - // clear cache - masternodeConfig.clear(); + { + ui->tableWidgetMyMasternodes->removeRow(0); + } + + // clear cache + masternodeConfig.clear(); // parse masternode.conf std::string strErr; if (!masternodeConfig.read(strErr)) { LogPrintf("Error reading masternode configuration file: \n"); - } + } updateMyNodeList(true); } } @@ -363,38 +363,38 @@ void MasternodeList::deleteAlias() QModelIndex index = selected.at(0); int nSelectedRow = index.row(); std::string strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString(); - int count = 0; + int count = 0; for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) { - count = count + 1; - if(strAlias == mne.getAlias()) { - std::vector confLockedCoins; - uint256 mnTxHash; - mnTxHash.SetHex(mne.getTxHash()); + count = count + 1; + if(strAlias == mne.getAlias()) { + std::vector confLockedCoins; + uint256 mnTxHash; + mnTxHash.SetHex(mne.getTxHash()); int nIndex; if(!mne.castOutputIndex(nIndex)) continue; - COutPoint outpoint = COutPoint(mnTxHash, nIndex); - confLockedCoins.push_back(outpoint); - pwalletMain->UnlockCoin(outpoint); - masternodeConfig.deleteAlias(count); - // write to masternode.conf - masternodeConfig.writeToMasternodeConf(); + COutPoint outpoint = COutPoint(mnTxHash, nIndex); + confLockedCoins.push_back(outpoint); + pwalletMain->UnlockCoin(outpoint); + masternodeConfig.deleteAlias(count); + // write to masternode.conf + masternodeConfig.writeToMasternodeConf(); while (ui->tableWidgetMyMasternodes->rowCount() > 0) - { - ui->tableWidgetMyMasternodes->removeRow(0); - } - - // clear cache - masternodeConfig.clear(); + { + ui->tableWidgetMyMasternodes->removeRow(0); + } + + // clear cache + masternodeConfig.clear(); // parse masternode.conf std::string strErr; if (!masternodeConfig.read(strErr)) { LogPrintf("Error reading masternode configuration file: \n"); - } - updateMyNodeList(true); - break; - - } + } + updateMyNodeList(true); + break; + + } } } @@ -411,14 +411,14 @@ void MasternodeList::copyAlias() std::string strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString(); for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) { - - if(strAlias == mne.getAlias()) { - - std::string fullAliasCopy = mne.getAlias() + " " + mne.getIp() + " " + mne.getPrivKey() + " " + mne.getTxHash() + " " + mne.getOutputIndex(); - GUIUtil::setClipboard(QString::fromStdString(fullAliasCopy)); - break; - - } + + if(strAlias == mne.getAlias()) { + + std::string fullAliasCopy = mne.getAlias() + " " + mne.getIp() + " " + mne.getPrivKey() + " " + mne.getTxHash() + " " + mne.getOutputIndex(); + GUIUtil::setClipboard(QString::fromStdString(fullAliasCopy)); + break; + + } } } diff --git a/src/qt/masternodelist.h b/src/qt/masternodelist.h index c058d3784e453..0e6a5a9624383 100644 --- a/src/qt/masternodelist.h +++ b/src/qt/masternodelist.h @@ -50,7 +50,7 @@ class MasternodeList : public QWidget void setWalletModel(WalletModel* walletModel); void StartAlias(std::string strAlias); void StartAll(std::string strCommand = "start-all"); - void deleteAlias(std::string Alias); + void deleteAlias(std::string Alias); private: QMenu* contextMenu; @@ -73,14 +73,14 @@ public Q_SLOTS: private Q_SLOTS: void showContextMenu(const QPoint&); - void deleteAlias(); - void copyAlias(); + void deleteAlias(); + void copyAlias(); void on_startButton_clicked(); void on_editConfigureMasternode_clicked(); void on_startAllButton_clicked(); void on_startMissingButton_clicked(); - void on_configureMasternodeButton_clicked(); - void openEditConfigureMasternodePage(QString strAlias, QString strIP, QString strPrivKey, QString strTxHash, QString strOutputIndex, int count); + void on_configureMasternodeButton_clicked(); + void openEditConfigureMasternodePage(QString strAlias, QString strIP, QString strPrivKey, QString strTxHash, QString strOutputIndex, int count); void on_tableWidgetMyMasternodes_itemSelectionChanged(); void on_UpdateButton_clicked(); }; diff --git a/src/qt/multisigdialog.cpp b/src/qt/multisigdialog.cpp index acceeb7801f56..cea10fa968aca 100644 --- a/src/qt/multisigdialog.cpp +++ b/src/qt/multisigdialog.cpp @@ -274,7 +274,7 @@ bool MultisigDialog::addMultisig(int m, std::vector keys){ QString::fromStdString(EncodeDestination(innerID)) + " has been added to the wallet.\nSend the redeem below for other owners to import:\n" + QString::fromStdString(redeem.ToString())); - }catch(const runtime_error& e) { + }catch(const std::runtime_error& e) { ui->addMultisigStatus->setStyleSheet("QLabel { color: red; }"); ui->addMultisigStatus->setText(tr(e.what())); return false; @@ -377,7 +377,7 @@ void MultisigDialog::on_createButton_clicked() ui->transactionHex->setText(QString::fromStdString(EncodeHexTx(multisigTx, PROTOCOL_VERSION))); } - }catch(const runtime_error& e){ + }catch(const std::runtime_error& e){ ui->createButtonStatus->setStyleSheet("QTextEdit{ color: red }"); ui->createButtonStatus->setText(tr(e.what())); } @@ -497,7 +497,7 @@ bool MultisigDialog::createMultisigTransaction(std::vector vUserIn, std:: in.scriptSig.clear(); } multisigTx = tx; - }catch(const runtime_error& e){ + }catch(const std::runtime_error& e){ errorRet = e.what(); return false; } @@ -556,7 +556,7 @@ void MultisigDialog::on_signButton_clicked() ui->signButtonStatus->setStyleSheet("QTextEdit{ color: black }"); ui->signButtonStatus->setText(buildMultisigTxStatusString(fComplete, tx)); - }catch(const runtime_error& e){ + }catch(const std::runtime_error& e){ ui->signButtonStatus->setStyleSheet("QTextEdit{ color: red }"); ui->signButtonStatus->setText(tr(e.what())); } @@ -713,7 +713,7 @@ bool MultisigDialog::signMultisigTx(CMutableTransaction& tx, std::string& errorO ui->signButtonStatus->setText(buildMultisigTxStatusString(fComplete, tx)); - }catch(const runtime_error& e){ + }catch(const std::runtime_error& e){ errorOut = std::string(e.what()); fComplete = false; } @@ -746,7 +746,7 @@ bool MultisigDialog::isFullyVerified(CMutableTransaction& tx){ nIn++; } - }catch(const runtime_error& e){ + }catch(const std::runtime_error& e){ return false; } @@ -787,7 +787,7 @@ void MultisigDialog::commitMultisigTx() //disable commit if successfully committed ui->commitButton->setEnabled(false); ui->signButtonStatus->setText(strprintf("Transaction has been successfully published with transaction ID:\n %s", tx.GetHash().GetHex()).c_str()); - }catch(const runtime_error& e){ + }catch(const std::runtime_error& e){ ui->signButtonStatus->setText(e.what()); } } @@ -858,7 +858,7 @@ bool MultisigDialog::createRedeemScript(int m, std::vector vKeys, C redeemRet << redeemRet.EncodeOP_N(pubkeys.size()); redeemRet << OP_CHECKMULTISIG; return true; - }catch(const runtime_error& e){ + }catch(const std::runtime_error& e){ errorRet = std::string(e.what()); return false; } diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index f0d8bef368bd5..1ceccbc4d1e96 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -391,6 +391,11 @@ bool OptionsModel::setData(const QModelIndex& index, const QVariant& value, int settings.setValue("fHideOrphans", fHideOrphans); emit hideOrphansChanged(fHideOrphans); break; + case AnonymizePhoreAmount: + nAnonymizePhoreAmount = value.toInt(); + settings.setValue("nAnonymizePhoreAmount", nAnonymizePhoreAmount); + emit anonymizePhoreAmountChanged(nAnonymizePhoreAmount); + break; case CoinControlFeatures: fCoinControlFeatures = value.toBool(); settings.setValue("fCoinControlFeatures", fCoinControlFeatures); diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 103f2e3bafb87..a41363d672a2f 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -44,7 +44,7 @@ bool PaymentRequestPlus::parse(const QByteArray& data) return true; } -bool PaymentRequestPlus::SerializeToString(string* output) const +bool PaymentRequestPlus::SerializeToString(std::string* output) const { return paymentRequest.SerializeToString(output); } diff --git a/src/qt/proposaldialog.cpp b/src/qt/proposaldialog.cpp index 26685fed01546..f4aca06112183 100644 --- a/src/qt/proposaldialog.cpp +++ b/src/qt/proposaldialog.cpp @@ -286,7 +286,7 @@ void ProposalDialog::on_acceptButton_clicked() { prepareProposal(); } - else if (mode == SubmitProposal) + else if (mode == SubmitProposal) { submitProposal(); } diff --git a/src/qt/proposallist.cpp b/src/qt/proposallist.cpp index 5729e727db24e..74b11f9f88f6d 100644 --- a/src/qt/proposallist.cpp +++ b/src/qt/proposallist.cpp @@ -468,10 +468,10 @@ void ProposalList::vote_click_handler(const std::string voteString) int success = 0; int failed = 0; - std::string strVote = voteString; - int nVote = VOTE_ABSTAIN; - if (strVote == "yes") nVote = VOTE_YES; - if (strVote == "no") nVote = VOTE_NO; + std::string strVote = voteString; + int nVote = VOTE_ABSTAIN; + if (strVote == "yes") nVote = VOTE_YES; + if (strVote == "no") nVote = VOTE_NO; for (const auto& mne : masternodeConfig.getEntries()) { diff --git a/src/qt/proposaltablemodel.cpp b/src/qt/proposaltablemodel.cpp index aec26bf650781..0d81d5fd494f7 100644 --- a/src/qt/proposaltablemodel.cpp +++ b/src/qt/proposaltablemodel.cpp @@ -82,7 +82,7 @@ void budgetToST(CBudgetProposal* pbudgetProposal, UniValue& bObj) bObj.push_back(pbudgetProposal->GetNays()); bObj.push_back(pbudgetProposal->GetAbstains()); bObj.push_back(ValueFromAmount(pbudgetProposal->GetAmount() * pbudgetProposal->GetTotalPaymentCount())); - bObj.push_back(pbudgetProposal->GetAmount()); + bObj.push_back(pbudgetProposal->GetAmount()); bObj.push_back(pbudgetProposal->IsEstablished()); std::string strError = ""; @@ -128,8 +128,8 @@ void ProposalTableModel::refreshProposals() //std::vector arr2 = arr1.at( 0 ).getValues(); //dataObj = arr2.at( 1 ); - UniValue bObj(UniValue::VOBJ); - budgetToST(pbudgetProposal, bObj); + UniValue bObj(UniValue::VOBJ); + budgetToST(pbudgetProposal, bObj); int votesNeeded = 0; int voteGap = 0; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index b10c8cde8c4fa..ee018f1dd8a9d 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -256,14 +256,14 @@ QString TransactionDesc::toHTML(CWallet* wallet, CWalletTx& wtx, TransactionReco strHTML += "" + tr("Output index") + ": " + QString::number(rec->getOutputIndex()) + "
"; // Message from normal phore:URI (phore:XyZ...?message=example) - foreach (const PAIRTYPE(string, std::string) & r, wtx.vOrderForm) + foreach (const PAIRTYPE(std::string, std::string) & r, wtx.vOrderForm) if (r.first == "Message") strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(r.second, true) + "
"; // // PaymentRequest info: // - foreach (const PAIRTYPE(string, std::string) & r, wtx.vOrderForm) { + foreach (const PAIRTYPE(std::string, std::string) & r, wtx.vOrderForm) { if (r.first == "PaymentRequest") { PaymentRequestPlus req; req.parse(QByteArray::fromRawData(r.second.data(), r.second.size())); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index dc4ac1e8183dd..a74c3ae31d084 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -133,7 +133,7 @@ WalletView::WalletView(QWidget* parent) : QStackedWidget(parent), masternodeListPage = new MasternodeList(); addWidget(masternodeListPage); } - + QVBoxLayout* vbox_2 = new QVBoxLayout(); proposalList = new ProposalList(this); vbox_2->addWidget(proposalList); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index f734db6e2b29e..cba714f3ce9d3 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -69,7 +69,7 @@ class WalletView : public QStackedWidget SendCoinsDialog* sendCoinsPage; BlockExplorer* explorerWindow; MasternodeList* masternodeListPage; - QWidget* proposalListPage; + QWidget* proposalListPage; TransactionView* transactionView; ProposalList* proposalList; @@ -89,7 +89,7 @@ public slots: /** Switch to privacy page */ void gotoPrivacyPage(); /** Switch to proposal page */ - void gotoProposalPage(); + void gotoProposalPage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); /** Switch to send coins page */ diff --git a/src/qt/zphrcontroldialog.cpp b/src/qt/zphrcontroldialog.cpp index a7967c6adb66f..b317bebf569fa 100644 --- a/src/qt/zphrcontroldialog.cpp +++ b/src/qt/zphrcontroldialog.cpp @@ -68,7 +68,7 @@ void ZPhrControlDialog::updateList() //populate rows with mint info int nBestHeight = chainActive.Height(); - std::map mapMaturityHeight = GetMintMaturityHeight(); + std::map mapMaturityHeight = GetMintMaturityHeight(); for(const CMintMeta& mint : setMints) { // assign this mint to the correct denomination in the tree view libzerocoin::CoinDenomination denom = mint.denom; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f1511fc9db707..e9a5595e2d904 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -469,7 +469,7 @@ UniValue gettxout(const UniValue& params, bool fHelp) " \"reqSigs\" : n, (numeric) Number of required signatures\n" " \"type\" : \"pubkeyhash\", (string) The type, e.g. pubkeyhash\n" " \"addresses\" : [ (array of string) array of phore addresses\n" - " \"phoreaddress\" (string) phore address\n" + " \"phoreaddress\" (string) phore address\n" " ,...\n" " ]\n" " },\n" diff --git a/src/rpc/masternode-budget.cpp b/src/rpc/masternode-budget.cpp index 1c2911fa64d8a..4899cbb0075f3 100644 --- a/src/rpc/masternode-budget.cpp +++ b/src/rpc/masternode-budget.cpp @@ -50,7 +50,7 @@ void budgetToJSON(CBudgetProposal* pbudgetProposal, UniValue& bObj) } void checkBudgetInputs(const UniValue& params, std::string &strProposalName, std::string &strURL, - int &nPaymentCount, int &nBlockStart, CBitcoinAddress &address, CAmount &nAmount) + int &nPaymentCount, int &nBlockStart, CAmount &nAmount) { int nBlockMin = 0; CBlockIndex* pindexPrev = chainActive.Tip(); @@ -86,8 +86,7 @@ void checkBudgetInputs(const UniValue& params, std::string &strProposalName, std if (nBlockEnd < pindexPrev->nHeight) throw std::runtime_error("Invalid ending block, starting block + (payment_cycle*payments) must be more than current height."); - address = params[4].get_str(); - if (!address.IsValid()) + if (!IsValidDestinationString(params[4].get_str())) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Phore address"); nAmount = AmountFromValue(params[5]); @@ -112,8 +111,8 @@ UniValue preparebudget(const UniValue& params, bool fHelp) "\"xxxx\" (string) proposal fee hash (if successful) or error message (if failed)\n" "\nExamples:\n" + - HelpExampleCli("preparebudget", "\"test-proposal\" \"https://forum.phore.org/t/test-proposal\\" 2 820800 \"D9oc6C3dttUbv8zd7zGNq1qKBGf4ZQ1XEE\" 500") + - HelpExampleRpc("preparebudget", "\"test-proposal\" \"https://forum.phore.org/t/test-proposal\\" 2 820800 \"D9oc6C3dttUbv8zd7zGNq1qKBGf4ZQ1XEE\" 500")); + HelpExampleCli("preparebudget", "\"test-proposal\" \"https://forum.phore.org/t/test-proposal\" 2 820800 \"D9oc6C3dttUbv8zd7zGNq1qKBGf4ZQ1XEE\" 500") + + HelpExampleRpc("preparebudget", "\"test-proposal\" \"https://forum.phore.org/t/test-proposal\" 2 820800 \"D9oc6C3dttUbv8zd7zGNq1qKBGf4ZQ1XEE\" 500")); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -123,13 +122,13 @@ UniValue preparebudget(const UniValue& params, bool fHelp) std::string strURL; int nPaymentCount; int nBlockStart; - CBitcoinAddress address; + CTxDestination address = DecodeDestination(params[4].get_str()); CAmount nAmount; - checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, address, nAmount); + checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, nAmount); // Parse Phore address - CScript scriptPubKey = GetScriptForDestination(address.Get()); + CScript scriptPubKey = GetScriptForDestination(address); // create transaction 15 minutes into the future, to allow for confirmation time CBudgetProposalBroadcast budgetProposalBroadcast(strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart, 0); @@ -184,13 +183,13 @@ UniValue submitbudget(const UniValue& params, bool fHelp) std::string strURL; int nPaymentCount; int nBlockStart; - CBitcoinAddress address; + CTxDestination address = DecodeDestination(params[4].get_str()); CAmount nAmount; - checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, address, nAmount); + checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, nAmount); // Parse Phore address - CScript scriptPubKey = GetScriptForDestination(address.Get()); + CScript scriptPubKey = GetScriptForDestination(address); uint256 hash = ParseHashV(params[6], "parameter 1"); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 84e300fa25f2d..9932ebcb381be 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -18,7 +18,6 @@ #include "version.h" - #include UniValue getconnectioncount(const UniValue& params, bool fHelp) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 99769e1ede665..372f889087c89 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -13,7 +13,6 @@ #include "util.h" - typedef std::vector valtype; TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {} diff --git a/src/script/standard.cpp b/src/script/standard.cpp index d93416a2303f2..64a7236486d2a 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -15,7 +15,6 @@ - typedef std::vector valtype; unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY; diff --git a/src/secp256k1/src/scratch.h b/src/secp256k1/src/scratch.h index fef377af0d942..e876d0c3e02b0 100644 --- a/src/secp256k1/src/scratch.h +++ b/src/secp256k1/src/scratch.h @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2017 Andrew Poelstra * + * Copyright (c) 2017 Andrew Poelstra * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ @@ -7,7 +7,7 @@ #ifndef _SECP256K1_SCRATCH_ #define _SECP256K1_SCRATCH_ -#define SECP256K1_SCRATCH_MAX_FRAMES 5 +#define SECP256K1_SCRATCH_MAX_FRAMES 5 /* The typedef is used internally; the struct name is used in the public API * (where it is exposed as a different typedef) */ diff --git a/src/swifttx.cpp b/src/swifttx.cpp index 60caa8b64f4e2..b519e39443580 100644 --- a/src/swifttx.cpp +++ b/src/swifttx.cpp @@ -19,6 +19,9 @@ #include "validationinterface.h" #include +using namespace std; +using namespace boost; + std::map mapTxLockReq; std::map mapTxLockReqRejected; std::map mapTxLockVote; diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index ae0573dda1cf9..ac8b89578e99b 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -13,7 +13,6 @@ #include "utilstrencodings.h" #include "test/test_phore.h" - #include #include diff --git a/src/test/benchmark_zerocoin.cpp b/src/test/benchmark_zerocoin.cpp index 2f9f903021264..fce0061c760f3 100644 --- a/src/test/benchmark_zerocoin.cpp +++ b/src/test/benchmark_zerocoin.cpp @@ -50,35 +50,35 @@ ZerocoinParams *gg_Params; class Timer { - timeval timer[2]; + timeval timer[2]; public: - timeval start() - { - gettimeofday(&this->timer[0], NULL); - return this->timer[0]; - } - - timeval stop() - { - gettimeofday(&this->timer[1], NULL); - return this->timer[1]; - } - - int duration() const - { - int secs(this->timer[1].tv_sec - this->timer[0].tv_sec); - int usecs(this->timer[1].tv_usec - this->timer[0].tv_usec); - - if(usecs < 0) - { - --secs; - usecs += 1000000; - } - - return static_cast(secs * 1000 + usecs / 1000.0 + 0.5); - } + timeval start() + { + gettimeofday(&this->timer[0], NULL); + return this->timer[0]; + } + + timeval stop() + { + gettimeofday(&this->timer[1], NULL); + return this->timer[1]; + } + + int duration() const + { + int secs(this->timer[1].tv_sec - this->timer[0].tv_sec); + int usecs(this->timer[1].tv_usec - this->timer[0].tv_usec); + + if(usecs < 0) + { + --secs; + usecs += 1000000; + } + + return static_cast(secs * 1000 + usecs / 1000.0 + 0.5); + } }; // Global timer @@ -87,38 +87,38 @@ Timer timer; void gLogTestResult(std::string testName, bool (*testPtr)()) { - std::string colorGreen(COLOR_STR_GREEN); - std::string colorNormal(COLOR_STR_NORMAL); - std::string colorRed(COLOR_STR_RED); + std::string colorGreen(COLOR_STR_GREEN); + std::string colorNormal(COLOR_STR_NORMAL); + std::string colorRed(COLOR_STR_RED); - cout << "Testing if " << testName << "..." << endl; + cout << "Testing if " << testName << "..." << endl; - bool testResult = testPtr(); + bool testResult = testPtr(); - if (testResult == true) { - cout << "\t" << colorGreen << "[PASS]" << colorNormal << endl; - ggSuccessfulTests++; - } else { - cout << colorRed << "\t[FAIL]" << colorNormal << endl; - } + if (testResult == true) { + cout << "\t" << colorGreen << "[PASS]" << colorNormal << endl; + ggSuccessfulTests++; + } else { + cout << colorRed << "\t[FAIL]" << colorNormal << endl; + } - ggNumTests++; + ggNumTests++; } CBigNum gGetTestModulus() { - static CBigNum testModulus(0); + static CBigNum testModulus(0); - // TODO: should use a hard-coded RSA modulus for testing - if (!testModulus) { - CBigNum p, q; - p = CBigNum::generatePrime(1024, false); - q = CBigNum::generatePrime(1024, false); - testModulus = p * q; - } + // TODO: should use a hard-coded RSA modulus for testing + if (!testModulus) { + CBigNum p, q; + p = CBigNum::generatePrime(1024, false); + q = CBigNum::generatePrime(1024, false); + testModulus = p * q; + } - return testModulus; + return testModulus; } ////////// @@ -129,286 +129,286 @@ gGetTestModulus() bool Testb_GenRSAModulus() { - CBigNum result = gGetTestModulus(); - - if (!result) { - return false; - } - else { - return true; - } + CBigNum result = gGetTestModulus(); + + if (!result) { + return false; + } + else { + return true; + } } bool Testb_CalcParamSizes() { - bool result = true; + bool result = true; #if 0 - uint32_t pLen, qLen; - - try { - calculateGroupParamLengths(4000, 80, &pLen, &qLen); - if (pLen < 1024 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 96, &pLen, &qLen); - if (pLen < 2048 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 112, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 120, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 128, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - } catch (exception &e) { - result = false; - } + uint32_t pLen, qLen; + + try { + calculateGroupParamLengths(4000, 80, &pLen, &qLen); + if (pLen < 1024 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 96, &pLen, &qLen); + if (pLen < 2048 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 112, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 120, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 128, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + } catch (exception &e) { + result = false; + } #endif - return result; + return result; } bool Testb_GenerateGroupParams() { - uint32_t pLen = 1024, qLen = 256, count; - IntegerGroupParams group; + uint32_t pLen = 1024, qLen = 256, count; + IntegerGroupParams group; - for (count = 0; count < 1; count++) { + for (count = 0; count < 1; count++) { - try { - group = deriveIntegerGroupParams(calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (std::runtime_error e) { - cout << "Caught exception " << e.what() << endl; - return false; - } + try { + group = deriveIntegerGroupParams(calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); + } catch (std::runtime_error e) { + cout << "Caught exception " << e.what() << endl; + return false; + } - // Now perform some simple tests on the resulting parameters - if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { - return false; - } + // Now perform some simple tests on the resulting parameters + if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { + return false; + } - CBigNum c = group.g.pow_mod(group.groupOrder, group.modulus); - //cout << "g^q mod p = " << c << endl; - if (!(c.isOne())) return false; + CBigNum c = group.g.pow_mod(group.groupOrder, group.modulus); + //cout << "g^q mod p = " << c << endl; + if (!(c.isOne())) return false; - // Try at multiple parameter sizes - pLen = pLen * 1.5; - qLen = qLen * 1.5; - } + // Try at multiple parameter sizes + pLen = pLen * 1.5; + qLen = qLen * 1.5; + } - return true; + return true; } bool Testb_ParamGen() { - bool result = true; + bool result = true; - try { - timer.start(); - // Instantiating testParams runs the parameter generation code - ZerocoinParams testParams(gGetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); - timer.stop(); + try { + timer.start(); + // Instantiating testParams runs the parameter generation code + ZerocoinParams testParams(gGetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); + timer.stop(); - cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - } catch (runtime_error e) { - cout << e.what() << endl; - result = false; - } + cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; + } catch (runtime_error e) { + cout << e.what() << endl; + result = false; + } - return result; + return result; } bool Testb_Accumulator() { - // This test assumes a list of coins were generated during - // the Testb_MintCoin() test. - if (ggCoins[0] == NULL) { - return false; - } - try { - // Accumulate the coin list from first to last into one accumulator + // This test assumes a list of coins were generated during + // the Testb_MintCoin() test. + if (ggCoins[0] == NULL) { + return false; + } + try { + // Accumulate the coin list from first to last into one accumulator Accumulator accOne(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); Accumulator accTwo(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); Accumulator accThree(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); Accumulator accFour(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); - AccumulatorWitness wThree(gg_Params, accThree, ggCoins[0]->getPublicCoin()); - - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - accOne += ggCoins[i]->getPublicCoin(); - accTwo += ggCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); - accThree += ggCoins[i]->getPublicCoin(); - wThree += ggCoins[i]->getPublicCoin(); - if(i != 0) { - accFour += ggCoins[i]->getPublicCoin(); - } - } - - // Compare the accumulated results - if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { - cout << "Accumulators don't match" << endl; - return false; - } - - if(accFour.getValue() != wThree.getValue()) { - cout << "Witness math not working," << endl; - return false; - } - - // Verify that the witness is correct - if (!wThree.VerifyWitness(accThree, ggCoins[0]->getPublicCoin()) ) { - cout << "Witness not valid" << endl; - return false; - } - - } catch (runtime_error e) { - cout << e.what() << endl; + AccumulatorWitness wThree(gg_Params, accThree, ggCoins[0]->getPublicCoin()); + + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + accOne += ggCoins[i]->getPublicCoin(); + accTwo += ggCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); + accThree += ggCoins[i]->getPublicCoin(); + wThree += ggCoins[i]->getPublicCoin(); + if(i != 0) { + accFour += ggCoins[i]->getPublicCoin(); + } + } + + // Compare the accumulated results + if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { + cout << "Accumulators don't match" << endl; + return false; + } + + if(accFour.getValue() != wThree.getValue()) { + cout << "Witness math not working," << endl; + return false; + } + + // Verify that the witness is correct + if (!wThree.VerifyWitness(accThree, ggCoins[0]->getPublicCoin()) ) { + cout << "Witness not valid" << endl; + return false; + } + + } catch (runtime_error e) { + cout << e.what() << endl; return false; - } + } - return true; + return true; } bool Testb_MintCoin() { - try { - // Generate a list of coins - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + try { + // Generate a list of coins + timer.start(); + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { ggCoins[i] = new PrivateCoin(gg_Params,CoinDenomination::ZQ_ONE); - } - timer.stop(); - } catch (exception &e) { - return false; - } + } + timer.stop(); + } catch (exception &e) { + return false; + } - cout << "\tMINT ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Coin: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; + cout << "\tMINT ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Coin: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; - return true; + return true; } bool Testb_MintAndSpend() { - try { - // This test assumes a list of coins were generated in Testb_MintCoin() - if (ggCoins[0] == NULL) - { - // No coins: mint some. - Testb_MintCoin(); - if (ggCoins[0] == NULL) { - return false; - } - } - - // Accumulate the list of generated coins into a fresh accumulator. - // The first one gets marked as accumulated for a witness, the - // others just get accumulated normally. + try { + // This test assumes a list of coins were generated in Testb_MintCoin() + if (ggCoins[0] == NULL) + { + // No coins: mint some. + Testb_MintCoin(); + if (ggCoins[0] == NULL) { + return false; + } + } + + // Accumulate the list of generated coins into a fresh accumulator. + // The first one gets marked as accumulated for a witness, the + // others just get accumulated normally. Accumulator acc(&gg_Params->accumulatorParams,CoinDenomination::ZQ_ONE); - AccumulatorWitness wAcc(gg_Params, acc, ggCoins[0]->getPublicCoin()); + AccumulatorWitness wAcc(gg_Params, acc, ggCoins[0]->getPublicCoin()); - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - acc += ggCoins[i]->getPublicCoin(); - } - timer.stop(); + timer.start(); + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + acc += ggCoins[i]->getPublicCoin(); + } + timer.stop(); - cout << "\tACCUMULATOR ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; + cout << "\tACCUMULATOR ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - wAcc +=ggCoins[i]->getPublicCoin(); - } - timer.stop(); + timer.start(); + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + wAcc +=ggCoins[i]->getPublicCoin(); + } + timer.stop(); - cout << "\tWITNESS ELAPSED TIME: \n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; + cout << "\tWITNESS ELAPSED TIME: \n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; - // Now spend the coin - timer.start(); - CoinSpend spend(gg_Params, gg_Params, *(ggCoins[0]), acc, 0, wAcc, 0, SpendType::SPEND); //(0) presstab - timer.stop(); + // Now spend the coin + timer.start(); + CoinSpend spend(gg_Params, gg_Params, *(ggCoins[0]), acc, 0, wAcc, 0, SpendType::SPEND); //(0) presstab + timer.stop(); - cout << "\tSPEND ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; + cout << "\tSPEND ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - // Serialize the proof and deserialize into newSpend - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + // Serialize the proof and deserialize into newSpend + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - timer.start(); - ss << spend; - timer.stop(); + timer.start(); + ss << spend; + timer.stop(); - CoinSpend newSpend(gg_Params, gg_Params, ss); + CoinSpend newSpend(gg_Params, gg_Params, ss); - cout << "\tSERIALIZE ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; + cout << "\tSERIALIZE ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - // Finally, see if we can verify the deserialized proof (return our result) - timer.start(); - bool ret = newSpend.Verify(acc); - timer.stop(); + // Finally, see if we can verify the deserialized proof (return our result) + timer.start(); + bool ret = newSpend.Verify(acc); + timer.stop(); - cout << "\tSPEND VERIFY ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; + cout << "\tSPEND VERIFY ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - return ret; - } catch (runtime_error &e) { - cout << e.what() << endl; - return false; - } + return ret; + } catch (runtime_error &e) { + cout << e.what() << endl; + return false; + } - return false; + return false; } void Testb_RunAllTests() { - // Make a new set of parameters from a random RSA modulus - gg_Params = new ZerocoinParams(gGetTestModulus()); - - ggNumTests = ggSuccessfulTests = 0; - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - ggCoins[i] = NULL; - } - - // Run through all of the Zerocoin tests - gLogTestResult("an RSA modulus can be generated", Testb_GenRSAModulus); - gLogTestResult("parameter sizes are correct", Testb_CalcParamSizes); - gLogTestResult("group/field parameters can be generated", Testb_GenerateGroupParams); - gLogTestResult("parameter generation is correct", Testb_ParamGen); - gLogTestResult("coins can be minted", Testb_MintCoin); - gLogTestResult("the accumulator works", Testb_Accumulator); - gLogTestResult("a minted coin can be spent", Testb_MintAndSpend); - - // Summarize test results - if (ggSuccessfulTests < ggNumTests) { - cout << endl << "ERROR: SOME TESTS FAILED" << endl; - } - - // Clear any generated coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - delete ggCoins[i]; - } - - cout << ggSuccessfulTests << " out of " << ggNumTests << " tests passed." << endl << endl; - delete gg_Params; + // Make a new set of parameters from a random RSA modulus + gg_Params = new ZerocoinParams(gGetTestModulus()); + + ggNumTests = ggSuccessfulTests = 0; + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + ggCoins[i] = NULL; + } + + // Run through all of the Zerocoin tests + gLogTestResult("an RSA modulus can be generated", Testb_GenRSAModulus); + gLogTestResult("parameter sizes are correct", Testb_CalcParamSizes); + gLogTestResult("group/field parameters can be generated", Testb_GenerateGroupParams); + gLogTestResult("parameter generation is correct", Testb_ParamGen); + gLogTestResult("coins can be minted", Testb_MintCoin); + gLogTestResult("the accumulator works", Testb_Accumulator); + gLogTestResult("a minted coin can be spent", Testb_MintAndSpend); + + // Summarize test results + if (ggSuccessfulTests < ggNumTests) { + cout << endl << "ERROR: SOME TESTS FAILED" << endl; + } + + // Clear any generated coins + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + delete ggCoins[i]; + } + + cout << ggSuccessfulTests << " out of " << ggNumTests << " tests passed." << endl << endl; + delete gg_Params; } BOOST_FIXTURE_TEST_SUITE(benchmark_zerocoin, TestingSetup) BOOST_AUTO_TEST_CASE(benchmark_test) { - cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " benchmark utility." << endl << endl; + cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " benchmark utility." << endl << endl; - Testb_RunAllTests(); + Testb_RunAllTests(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/libzerocoin_tests.cpp b/src/test/libzerocoin_tests.cpp index 79a1a94014d4f..02e6484778f34 100644 --- a/src/test/libzerocoin_tests.cpp +++ b/src/test/libzerocoin_tests.cpp @@ -417,7 +417,7 @@ Test_MintAndSpend() cc << *gCoins[0]; PrivateCoin myCoin(g_Params,cc); - CoinSpend spend(g_Params, g_Params, myCoin, acc, 0, wAcc, 0, SpendType::SPEND); + CoinSpend spend(g_Params, g_Params, myCoin, acc, 0, wAcc, 0, SpendType::SPEND); // Serialize the proof and deserialize into newSpend CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 0acc79b878619..c79d3f22e0c2e 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -55,40 +55,40 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams) // Test raw transaction API argument handling UniValue r; - BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error); - BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error); - BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), runtime_error); - - BOOST_CHECK_THROW(CallRPC("createrawtransaction"), runtime_error); - BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), runtime_error); - BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), runtime_error); - BOOST_CHECK_THROW(CallRPC("createrawtransaction [] []"), runtime_error); - BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), runtime_error); + BOOST_CHECK_THROW(CallRPC("getrawtransaction"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), std::runtime_error); + + BOOST_CHECK_THROW(CallRPC("createrawtransaction"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("createrawtransaction [] []"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}")); - BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), runtime_error); + BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), runtime_error); - BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), runtime_error); - BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), runtime_error); + BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), std::runtime_error); std::string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx)); BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1); BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0); - BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), runtime_error); + BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("signrawtransaction"), runtime_error); - BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), runtime_error); - BOOST_CHECK_THROW(CallRPC("signrawtransaction ff00"), runtime_error); + BOOST_CHECK_THROW(CallRPC("signrawtransaction"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("signrawtransaction ff00"), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC(std::string("signrawtransaction ")+rawtx)); BOOST_CHECK_NO_THROW(CallRPC(std::string("signrawtransaction ")+rawtx+" null null NONE|ANYONECANPAY")); BOOST_CHECK_NO_THROW(CallRPC(std::string("signrawtransaction ")+rawtx+" [] [] NONE|ANYONECANPAY")); - BOOST_CHECK_THROW(CallRPC(std::string("signrawtransaction ")+rawtx+" null null badenum"), runtime_error); + BOOST_CHECK_THROW(CallRPC(std::string("signrawtransaction ")+rawtx+" null null badenum"), std::runtime_error); // Only check failure cases for sendrawtransaction, there's no network to send to... - BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), runtime_error); - BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), runtime_error); - BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), runtime_error); - BOOST_CHECK_THROW(CallRPC(std::string("sendrawtransaction ")+rawtx+" extra"), runtime_error); + BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC(std::string("sendrawtransaction ")+rawtx+" extra"), std::runtime_error); } BOOST_AUTO_TEST_CASE(rpc_rawsign) @@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) UniValue r; BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0 add"))); - BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.0:8334")), runtime_error); //portnumber for setban not allowed + BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.0:8334")), std::runtime_error); //portnumber for setban not allowed BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned"))); UniValue ar = r.get_array(); UniValue o1 = ar[0].get_obj(); @@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) BOOST_CHECK(banned_until.get_int64()-now <= 200); // must throw an exception because 127.0.0.1 is in already banned suubnet range - BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.1 add")), runtime_error); + BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.1 add")), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0/24 remove")));; BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned"))); @@ -230,14 +230,14 @@ BOOST_AUTO_TEST_CASE(rpc_ban) BOOST_CHECK_EQUAL(ar.size(), 0); BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/255.255.0.0 add"))); - BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.1.1 add")), runtime_error); + BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.1.1 add")), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned"))); BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned"))); ar = r.get_array(); BOOST_CHECK_EQUAL(ar.size(), 0); - BOOST_CHECK_THROW(r = CallRPC(std::string("setban test add")), runtime_error); //invalid IP + BOOST_CHECK_THROW(r = CallRPC(std::string("setban test add")), std::runtime_error); //invalid IP //IPv6 tests BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add"))); diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index c539d1fc5c173..3931c4b2e5cec 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -49,18 +49,18 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) address.SetString(v.get_str()); BOOST_CHECK(address.IsValid() && address.IsScript()); - BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(0), false), std::runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(1), false), std::runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), std::runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), std::runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), std::runtime_error); std::string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), std::runtime_error); std::string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), std::runtime_error); } BOOST_AUTO_TEST_CASE(rpc_wallet) @@ -87,59 +87,59 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) CBitcoinAddress setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID())); /********************************* - * setaccount + * setaccount *********************************/ BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount")); /* D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R is not owned by the test wallet. */ - BOOST_CHECK_THROW(CallRPC("setaccount D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R nullaccount"), runtime_error); - BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); + BOOST_CHECK_THROW(CallRPC("setaccount D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R nullaccount"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("setaccount"), std::runtime_error); /* D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 (33 chars) is an illegal address (should be 34 chars) */ - BOOST_CHECK_THROW(CallRPC("setaccount D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 nullaccount"), runtime_error); + BOOST_CHECK_THROW(CallRPC("setaccount D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 nullaccount"), std::runtime_error); /********************************* - * listunspent + * listunspent *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listunspent")); - BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error); + BOOST_CHECK_THROW(CallRPC("listunspent string"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), std::runtime_error); BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []")); BOOST_CHECK(r.get_array().empty()); /********************************* - * listreceivedbyaddress + * listreceivedbyaddress *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error); + BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error); + BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), std::runtime_error); /********************************* - * listreceivedbyaccount + * listreceivedbyaccount *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error); + BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error); + BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), std::runtime_error); /********************************* - * getrawchangeaddress + * getrawchangeaddress *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress")); /********************************* - * getnewaddress + * getnewaddress *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getnewaddress")); BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount")); /********************************* - * getaccountaddress + * getaccountaddress *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\"")); BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account @@ -147,24 +147,24 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); /********************************* - * getaccount + * getaccount *********************************/ - BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); + BOOST_CHECK_THROW(CallRPC("getaccount"), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); /********************************* - * signmessage + verifymessage + * signmessage + verifymessage *********************************/ BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); - BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); + BOOST_CHECK_THROW(CallRPC("signmessage"), std::runtime_error); /* Should throw error because this address is not loaded in the wallet */ - BOOST_CHECK_THROW(CallRPC("signmessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R mymessage"), runtime_error); + BOOST_CHECK_THROW(CallRPC("signmessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R mymessage"), std::runtime_error); /* missing arguments */ - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error); - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), std::runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), std::runtime_error); /* Illegal address */ - BOOST_CHECK_THROW(CallRPC("verifymessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 " + retValue.get_str() + " mymessage"), runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 " + retValue.get_str() + " mymessage"), std::runtime_error); /* wrong address */ BOOST_CHECK(CallRPC("verifymessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R " + retValue.get_str() + " mymessage").get_bool() == false); /* Correct address and signature but wrong message */ @@ -173,9 +173,9 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); /********************************* - * getaddressesbyaccount + * getaddressesbyaccount *********************************/ - BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); + BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), std::runtime_error); BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); UniValue arr = retValue.get_array(); BOOST_CHECK(arr.size() > 0); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index c26e1e06cb3b4..4c5138b670053 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -121,8 +121,8 @@ BOOST_AUTO_TEST_CASE(tx_valid) std::map mapprevOutValues; UniValue inputs = test[0].get_array(); bool fValid = true; - for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { - const UniValue& input = inputs[inpIdx]; + for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { + const UniValue& input = inputs[inpIdx]; if (!input.isArray()) { fValid = false; @@ -206,8 +206,8 @@ BOOST_AUTO_TEST_CASE(tx_invalid) std::map mapprevOutValues; UniValue inputs = test[0].get_array(); bool fValid = true; - for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { - const UniValue& input = inputs[inpIdx]; + for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { + const UniValue& input = inputs[inpIdx]; if (!input.isArray()) { fValid = false; diff --git a/src/test/tutorial_zerocoin.cpp b/src/test/tutorial_zerocoin.cpp index 483bbfb5f2650..8917f1df96239 100644 --- a/src/test/tutorial_zerocoin.cpp +++ b/src/test/tutorial_zerocoin.cpp @@ -48,236 +48,236 @@ bool ZerocoinTutorial() { - // The following simple code illustrates the call flow for Zerocoin - // applications. In a real currency network these operations would - // be split between individual payers/payees, network nodes and miners. - // - // For each call we specify the participant who would use it. - - // Zerocoin uses exceptions (based on the runtime_error class) - // to indicate all sorts of problems. Always remember to catch them! - - try { - - /********************************************************************/ - // What is it: Parameter loading - // Who does it: ALL ZEROCOIN PARTICIPANTS - // What it does: Loads a trusted Zerocoin modulus "N" and - // generates all associated parameters from it. - // We use a hardcoded "N" that we generated using - // the included 'paramgen' utility. - /********************************************************************/ - - // Load a test modulus from our hardcoded string (above) - CBigNum testModulus; - testModulus.SetHex(std::string(TUTORIAL_TEST_MODULUS)); - - // Set up the Zerocoin Params object - libzerocoin::ZerocoinParams* params = new libzerocoin::ZerocoinParams(testModulus); - - cout << "Successfully loaded parameters." << endl; - - /********************************************************************/ - // What is it: Coin generation - // Who does it: ZEROCOIN CLIENTS - // What it does: Generates a new 'zerocoin' coin using the - // public parameters. Once generated, the client - // will transmit the public portion of this coin - // in a ZEROCOIN_MINT transaction. The inputs - // to this transaction must add up to the zerocoin - // denomination plus any transaction fees. - /********************************************************************/ - - // The following constructor does all the work of minting a brand - // new zerocoin. It stores all the private values inside the - // PrivateCoin object. This includes the coin secrets, which must be - // stored in a secure location (wallet) at the client. + // The following simple code illustrates the call flow for Zerocoin + // applications. In a real currency network these operations would + // be split between individual payers/payees, network nodes and miners. + // + // For each call we specify the participant who would use it. + + // Zerocoin uses exceptions (based on the std::runtime_error class) + // to indicate all sorts of problems. Always remember to catch them! + + try { + + /********************************************************************/ + // What is it: Parameter loading + // Who does it: ALL ZEROCOIN PARTICIPANTS + // What it does: Loads a trusted Zerocoin modulus "N" and + // generates all associated parameters from it. + // We use a hardcoded "N" that we generated using + // the included 'paramgen' utility. + /********************************************************************/ + + // Load a test modulus from our hardcoded string (above) + CBigNum testModulus; + testModulus.SetHex(std::string(TUTORIAL_TEST_MODULUS)); + + // Set up the Zerocoin Params object + libzerocoin::ZerocoinParams* params = new libzerocoin::ZerocoinParams(testModulus); + + cout << "Successfully loaded parameters." << endl; + + /********************************************************************/ + // What is it: Coin generation + // Who does it: ZEROCOIN CLIENTS + // What it does: Generates a new 'zerocoin' coin using the + // public parameters. Once generated, the client + // will transmit the public portion of this coin + // in a ZEROCOIN_MINT transaction. The inputs + // to this transaction must add up to the zerocoin + // denomination plus any transaction fees. + /********************************************************************/ + + // The following constructor does all the work of minting a brand + // new zerocoin. It stores all the private values inside the + // PrivateCoin object. This includes the coin secrets, which must be + // stored in a secure location (wallet) at the client. libzerocoin::PrivateCoin newCoin(params, libzerocoin::CoinDenomination::ZQ_ONE); - // Get a copy of the 'public' portion of the coin. You should - // embed this into a Zerocoin 'MINT' transaction along with a series - // of currency inputs totaling the assigned value of one zerocoin. - libzerocoin::PublicCoin pubCoin = newCoin.getPublicCoin(); - - cout << "Successfully minted a zerocoin." << endl; - - // Serialize the public coin to a CDataStream object. - CDataStream serializedCoin(SER_NETWORK, PROTOCOL_VERSION); - serializedCoin << pubCoin; - - /********************************************************************/ - // What is it: Coin verification - // Who does it: TRANSACTION VERIFIERS - // What it does: Verifies the structure of a zerocoin obtained from - // a ZEROCOIN_MINT transaction. All coins must be - // verified before you operate on them. - // Note that this is only part of the transaction - // verification process! The client must also check - // that (1) the inputs to the transaction are valid - // and add up to the value of one zerocoin, (2) that - // this particular zerocoin has not been minted before. - /********************************************************************/ - - // Deserialize the public coin into a fresh object. - libzerocoin::PublicCoin pubCoinNew(params, serializedCoin); - - // Now make sure the coin is valid. - if (!pubCoinNew.validate()) { - // If this returns false, don't accept the coin for any purpose! - // Any ZEROCOIN_MINT with an invalid coin should NOT be - // accepted as a valid transaction in the block chain. - cout << "Error: coin is not valid!"; - } - - cout << "Deserialized and verified the coin." << endl; - - /********************************************************************/ - // What is it: Accumulator computation - // Who does it: ZEROCOIN CLIENTS & TRANSACTION VERIFIERS - // What it does: Collects a number of PublicCoin values drawn from - // the block chain and calculates an accumulator. - // This accumulator is incrementally computable; - // you can stop and serialize it at any point - // then continue accumulating new transactions. - // The accumulator is also order-independent, so - // the same coins can be accumulated in any order - // to give the same result. - // WARNING: do not accumulate the same coin twice! - /********************************************************************/ - - // Create an empty accumulator object + // Get a copy of the 'public' portion of the coin. You should + // embed this into a Zerocoin 'MINT' transaction along with a series + // of currency inputs totaling the assigned value of one zerocoin. + libzerocoin::PublicCoin pubCoin = newCoin.getPublicCoin(); + + cout << "Successfully minted a zerocoin." << endl; + + // Serialize the public coin to a CDataStream object. + CDataStream serializedCoin(SER_NETWORK, PROTOCOL_VERSION); + serializedCoin << pubCoin; + + /********************************************************************/ + // What is it: Coin verification + // Who does it: TRANSACTION VERIFIERS + // What it does: Verifies the structure of a zerocoin obtained from + // a ZEROCOIN_MINT transaction. All coins must be + // verified before you operate on them. + // Note that this is only part of the transaction + // verification process! The client must also check + // that (1) the inputs to the transaction are valid + // and add up to the value of one zerocoin, (2) that + // this particular zerocoin has not been minted before. + /********************************************************************/ + + // Deserialize the public coin into a fresh object. + libzerocoin::PublicCoin pubCoinNew(params, serializedCoin); + + // Now make sure the coin is valid. + if (!pubCoinNew.validate()) { + // If this returns false, don't accept the coin for any purpose! + // Any ZEROCOIN_MINT with an invalid coin should NOT be + // accepted as a valid transaction in the block chain. + cout << "Error: coin is not valid!"; + } + + cout << "Deserialized and verified the coin." << endl; + + /********************************************************************/ + // What is it: Accumulator computation + // Who does it: ZEROCOIN CLIENTS & TRANSACTION VERIFIERS + // What it does: Collects a number of PublicCoin values drawn from + // the block chain and calculates an accumulator. + // This accumulator is incrementally computable; + // you can stop and serialize it at any point + // then continue accumulating new transactions. + // The accumulator is also order-independent, so + // the same coins can be accumulated in any order + // to give the same result. + // WARNING: do not accumulate the same coin twice! + /********************************************************************/ + + // Create an empty accumulator object libzerocoin::Accumulator accumulator(params,libzerocoin::CoinDenomination::ZQ_ONE); - // Add several coins to it (we'll generate them here on the fly). - for (uint32_t i = 0; i < COINS_TO_ACCUMULATE; i++) { + // Add several coins to it (we'll generate them here on the fly). + for (uint32_t i = 0; i < COINS_TO_ACCUMULATE; i++) { libzerocoin::PrivateCoin testCoin(params, libzerocoin::CoinDenomination::ZQ_ONE); - accumulator += testCoin.getPublicCoin(); - } - - // Serialize the accumulator object. - // - // If you're using Accumulator Checkpoints, each miner would - // start by deserializing the accumulator checkpoint from the - // previous block (or creating a new Accumulator if no previous - // block exists). It will then add all the coins in the new block, - // then serialize the resulting Accumulator object to obtain the - // new checkpoint. All block verifiers should do the same thing - // to check their work. - CDataStream serializedAccumulator(SER_NETWORK, PROTOCOL_VERSION); - serializedAccumulator << accumulator; - - // Deserialize the accumulator object - libzerocoin::Accumulator newAccumulator(params, serializedAccumulator); - - // We can now continue accumulating things into the accumulator - // we just deserialized. For example, let's put in the coin - // we generated up above. - newAccumulator += pubCoinNew; - - cout << "Successfully accumulated coins." << endl; - - /********************************************************************/ - // What is it: Coin spend - // Who does it: ZEROCOIN CLIENTS - // What it does: Create a new transaction that spends a Zerocoin. - // The user first authors a transaction specifying - // a set of destination addresses (outputs). They - // next compute an Accumulator over all coins in the - // block chain (see above) and a Witness based on the - // coin to be spent. Finally they instantiate a CoinSpend - // object that 'signs' the transaction with a special - // zero knowledge signature of knowledge over the coin - // data, Witness and Accumulator. - /********************************************************************/ - - // We are going to spend the coin "newCoin" that we generated at the - // top of this function. - // - // We'll use the accumulator we constructed above. This contains - // a set of coins, but does NOT include the coin "newCoin". - // - // To generate the witness, we start with this accumulator and - // add the public half of the coin we want to spend. - libzerocoin::AccumulatorWitness witness(params, accumulator, newCoin.getPublicCoin()); - - // Add the public half of "newCoin" to the Accumulator itself. - accumulator += newCoin.getPublicCoin(); - - // At this point we should generate a ZEROCOIN_SPEND transaction to - // send to the network. This network should include a set of outputs - // totalling to the value of one zerocoin (minus transaction fees). - - // Construct the CoinSpend object. This acts like a signature on the - // transaction. + accumulator += testCoin.getPublicCoin(); + } + + // Serialize the accumulator object. + // + // If you're using Accumulator Checkpoints, each miner would + // start by deserializing the accumulator checkpoint from the + // previous block (or creating a new Accumulator if no previous + // block exists). It will then add all the coins in the new block, + // then serialize the resulting Accumulator object to obtain the + // new checkpoint. All block verifiers should do the same thing + // to check their work. + CDataStream serializedAccumulator(SER_NETWORK, PROTOCOL_VERSION); + serializedAccumulator << accumulator; + + // Deserialize the accumulator object + libzerocoin::Accumulator newAccumulator(params, serializedAccumulator); + + // We can now continue accumulating things into the accumulator + // we just deserialized. For example, let's put in the coin + // we generated up above. + newAccumulator += pubCoinNew; + + cout << "Successfully accumulated coins." << endl; + + /********************************************************************/ + // What is it: Coin spend + // Who does it: ZEROCOIN CLIENTS + // What it does: Create a new transaction that spends a Zerocoin. + // The user first authors a transaction specifying + // a set of destination addresses (outputs). They + // next compute an Accumulator over all coins in the + // block chain (see above) and a Witness based on the + // coin to be spent. Finally they instantiate a CoinSpend + // object that 'signs' the transaction with a special + // zero knowledge signature of knowledge over the coin + // data, Witness and Accumulator. + /********************************************************************/ + + // We are going to spend the coin "newCoin" that we generated at the + // top of this function. + // + // We'll use the accumulator we constructed above. This contains + // a set of coins, but does NOT include the coin "newCoin". + // + // To generate the witness, we start with this accumulator and + // add the public half of the coin we want to spend. + libzerocoin::AccumulatorWitness witness(params, accumulator, newCoin.getPublicCoin()); + + // Add the public half of "newCoin" to the Accumulator itself. + accumulator += newCoin.getPublicCoin(); + + // At this point we should generate a ZEROCOIN_SPEND transaction to + // send to the network. This network should include a set of outputs + // totalling to the value of one zerocoin (minus transaction fees). + + // Construct the CoinSpend object. This acts like a signature on the + // transaction. libzerocoin::CoinSpend spend(params, params, newCoin, accumulator, 0, witness, 0, libzerocoin::SpendType::SPEND);//(0) - Presstab - // This is a sanity check. The CoinSpend object should always verify, - // but why not check before we put it onto the wire? - if (!spend.Verify(accumulator)) { - cout << "ERROR: Our new CoinSpend transaction did not verify!" << endl; - return false; - } - - // Serialize the CoinSpend object into a buffer. - CDataStream serializedCoinSpend(SER_NETWORK, PROTOCOL_VERSION); - serializedCoinSpend << spend; - - cout << "Successfully generated a coin spend transaction." << endl; - - /********************************************************************/ - // What is it: Coin spend verification - // Who does it: ALL PARTIES - // What it does: Verifies that a CoinSpend signature is correct - // with respect to a ZEROCOIN_SPEND transaction hash. - // The client must also extract the serial number from - // the CoinSpend and verify that this serial number has - // not previously appeared in another ZEROCOIN_SPEND - // transaction. - /********************************************************************/ - - // Deserialize the CoinSpend intro a fresh object - libzerocoin::CoinSpend newSpend(params, params, serializedCoinSpend); - - // Create a new metadata object to contain the hash of the received - // ZEROCOIN_SPEND transaction. If we were a real client we'd actually - // compute the hash of the received transaction here. - - // If we were a real client we would now re-compute the Accumulator - // from the information given in the ZEROCOIN_SPEND transaction. - // For our purposes we'll just use the one we calculated above. - // - // Verify that the spend is valid with respect to the Accumulator - // and the Metadata - if (!newSpend.Verify(accumulator)) { - cout << "ERROR: The CoinSpend transaction did not verify!" << endl; - return false; - } - - // Pull the serial number out of the CoinSpend object. If we - // were a real Zerocoin client we would now check that the serial number - // has not been spent before (in another ZEROCOIN_SPEND) transaction. - // The serial number is stored as a CBigNum. - CBigNum serialNumber = newSpend.getCoinSerialNumber(); - - cout << "Successfully verified a coin spend transaction." << endl; - cout << endl << "Coin serial number is:" << endl << serialNumber << endl; - - // We're done - return true; - - } catch (runtime_error &e) { - cout << e.what() << endl; - return false; - } - - return false; + // This is a sanity check. The CoinSpend object should always verify, + // but why not check before we put it onto the wire? + if (!spend.Verify(accumulator)) { + cout << "ERROR: Our new CoinSpend transaction did not verify!" << endl; + return false; + } + + // Serialize the CoinSpend object into a buffer. + CDataStream serializedCoinSpend(SER_NETWORK, PROTOCOL_VERSION); + serializedCoinSpend << spend; + + cout << "Successfully generated a coin spend transaction." << endl; + + /********************************************************************/ + // What is it: Coin spend verification + // Who does it: ALL PARTIES + // What it does: Verifies that a CoinSpend signature is correct + // with respect to a ZEROCOIN_SPEND transaction hash. + // The client must also extract the serial number from + // the CoinSpend and verify that this serial number has + // not previously appeared in another ZEROCOIN_SPEND + // transaction. + /********************************************************************/ + + // Deserialize the CoinSpend intro a fresh object + libzerocoin::CoinSpend newSpend(params, params, serializedCoinSpend); + + // Create a new metadata object to contain the hash of the received + // ZEROCOIN_SPEND transaction. If we were a real client we'd actually + // compute the hash of the received transaction here. + + // If we were a real client we would now re-compute the Accumulator + // from the information given in the ZEROCOIN_SPEND transaction. + // For our purposes we'll just use the one we calculated above. + // + // Verify that the spend is valid with respect to the Accumulator + // and the Metadata + if (!newSpend.Verify(accumulator)) { + cout << "ERROR: The CoinSpend transaction did not verify!" << endl; + return false; + } + + // Pull the serial number out of the CoinSpend object. If we + // were a real Zerocoin client we would now check that the serial number + // has not been spent before (in another ZEROCOIN_SPEND) transaction. + // The serial number is stored as a CBigNum. + CBigNum serialNumber = newSpend.getCoinSerialNumber(); + + cout << "Successfully verified a coin spend transaction." << endl; + cout << endl << "Coin serial number is:" << endl << serialNumber << endl; + + // We're done + return true; + + } catch (runtime_error &e) { + cout << e.what() << endl; + return false; + } + + return false; } BOOST_FIXTURE_TEST_SUITE(tutorial_libzerocoin, TestingSetup) BOOST_AUTO_TEST_CASE(tutorial_libzerocoin_tests) { - cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " tutorial." << endl << endl; + cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " tutorial." << endl << endl; - ZerocoinTutorial(); + ZerocoinTutorial(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp index 401896ed3fd4c..0c09d24507c99 100644 --- a/src/test/univalue_tests.cpp +++ b/src/test/univalue_tests.cpp @@ -66,41 +66,41 @@ BOOST_AUTO_TEST_CASE(univalue_typecheck) UniValue v1; BOOST_CHECK(v1.setNumStr("1")); BOOST_CHECK(v1.isNum()); - BOOST_CHECK_THROW(v1.get_bool(), runtime_error); + BOOST_CHECK_THROW(v1.get_bool(), std::runtime_error); UniValue v2; BOOST_CHECK(v2.setBool(true)); BOOST_CHECK_EQUAL(v2.get_bool(), true); - BOOST_CHECK_THROW(v2.get_int(), runtime_error); + BOOST_CHECK_THROW(v2.get_int(), std::runtime_error); UniValue v3; BOOST_CHECK(v3.setNumStr("32482348723847471234")); - BOOST_CHECK_THROW(v3.get_int64(), runtime_error); + BOOST_CHECK_THROW(v3.get_int64(), std::runtime_error); BOOST_CHECK(v3.setNumStr("1000")); BOOST_CHECK_EQUAL(v3.get_int64(), 1000); UniValue v4; BOOST_CHECK(v4.setNumStr("2147483648")); BOOST_CHECK_EQUAL(v4.get_int64(), 2147483648); - BOOST_CHECK_THROW(v4.get_int(), runtime_error); + BOOST_CHECK_THROW(v4.get_int(), std::runtime_error); BOOST_CHECK(v4.setNumStr("1000")); BOOST_CHECK_EQUAL(v4.get_int(), 1000); - BOOST_CHECK_THROW(v4.get_str(), runtime_error); + BOOST_CHECK_THROW(v4.get_str(), std::runtime_error); BOOST_CHECK_EQUAL(v4.get_real(), 1000); - BOOST_CHECK_THROW(v4.get_array(), runtime_error); - BOOST_CHECK_THROW(v4.getKeys(), runtime_error); - BOOST_CHECK_THROW(v4.getValues(), runtime_error); - BOOST_CHECK_THROW(v4.get_obj(), runtime_error); + BOOST_CHECK_THROW(v4.get_array(), std::runtime_error); + BOOST_CHECK_THROW(v4.getKeys(), std::runtime_error); + BOOST_CHECK_THROW(v4.getValues(), std::runtime_error); + BOOST_CHECK_THROW(v4.get_obj(), std::runtime_error); UniValue v5; BOOST_CHECK(v5.read("[true, 10]")); BOOST_CHECK_NO_THROW(v5.get_array()); std::vector vals = v5.getValues(); - BOOST_CHECK_THROW(vals[0].get_int(), runtime_error); + BOOST_CHECK_THROW(vals[0].get_int(), std::runtime_error); BOOST_CHECK_EQUAL(vals[0].get_bool(), true); BOOST_CHECK_EQUAL(vals[1].get_int(), 10); - BOOST_CHECK_THROW(vals[1].get_bool(), runtime_error); + BOOST_CHECK_THROW(vals[1].get_bool(), std::runtime_error); } BOOST_AUTO_TEST_CASE(univalue_set) diff --git a/src/timedata.cpp b/src/timedata.cpp index ddd30a78447f9..1f60f68ef79b4 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -12,7 +12,6 @@ - static CCriticalSection cs_nTimeOffset; static int64_t nTimeOffset = 0; diff --git a/src/univalue/gen/gen.cpp b/src/univalue/gen/gen.cpp index 17f361941d9e9..d96d1a076db7e 100644 --- a/src/univalue/gen/gen.cpp +++ b/src/univalue/gen/gen.cpp @@ -40,45 +40,45 @@ static void initJsonEscape() static void outputEscape() { - printf( "// Automatically generated file. Do not modify.\n" - "#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" - "#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" - "static const char *escapes[256] = {\n"); + printf( "// Automatically generated file. Do not modify.\n" + "#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" + "#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" + "static const char *escapes[256] = {\n"); - for (unsigned int i = 0; i < 256; i++) { - if (escapes[i].empty()) { - printf("\tNULL,\n"); - } else { - printf("\t\""); + for (unsigned int i = 0; i < 256; i++) { + if (escapes[i].empty()) { + printf("\tNULL,\n"); + } else { + printf("\t\""); - unsigned int si; - for (si = 0; si < escapes[i].size(); si++) { - char ch = escapes[i][si]; - switch (ch) { - case '"': - printf("\\\""); - break; - case '\\': - printf("\\\\"); - break; - default: - printf("%c", escapes[i][si]); - break; - } - } + unsigned int si; + for (si = 0; si < escapes[i].size(); si++) { + char ch = escapes[i][si]; + switch (ch) { + case '"': + printf("\\\""); + break; + case '\\': + printf("\\\\"); + break; + default: + printf("%c", escapes[i][si]); + break; + } + } - printf("\",\n"); - } - } + printf("\",\n"); + } + } - printf( "};\n" - "#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"); + printf( "};\n" + "#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"); } int main (int argc, char *argv[]) { - initJsonEscape(); - outputEscape(); - return 0; + initJsonEscape(); + outputEscape(); + return 0; } diff --git a/src/univalue/lib/univalue_escapes.h b/src/univalue/lib/univalue_escapes.h index 74596aab6d2c9..9219979d302db 100644 --- a/src/univalue/lib/univalue_escapes.h +++ b/src/univalue/lib/univalue_escapes.h @@ -2,261 +2,261 @@ #ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H #define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H static const char *escapes[256] = { - "\\u0000", - "\\u0001", - "\\u0002", - "\\u0003", - "\\u0004", - "\\u0005", - "\\u0006", - "\\u0007", - "\\b", - "\\t", - "\\n", - "\\u000b", - "\\f", - "\\r", - "\\u000e", - "\\u000f", - "\\u0010", - "\\u0011", - "\\u0012", - "\\u0013", - "\\u0014", - "\\u0015", - "\\u0016", - "\\u0017", - "\\u0018", - "\\u0019", - "\\u001a", - "\\u001b", - "\\u001c", - "\\u001d", - "\\u001e", - "\\u001f", - NULL, - NULL, - "\\\"", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "\\\\", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "\\u007f", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + "\\u0000", + "\\u0001", + "\\u0002", + "\\u0003", + "\\u0004", + "\\u0005", + "\\u0006", + "\\u0007", + "\\b", + "\\t", + "\\n", + "\\u000b", + "\\f", + "\\r", + "\\u000e", + "\\u000f", + "\\u0010", + "\\u0011", + "\\u0012", + "\\u0013", + "\\u0014", + "\\u0015", + "\\u0016", + "\\u0017", + "\\u0018", + "\\u0019", + "\\u001a", + "\\u001b", + "\\u001c", + "\\u001d", + "\\u001e", + "\\u001f", + NULL, + NULL, + "\\\"", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "\\\\", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "\\u007f", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; #endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp index f1f2e63b3d6f0..24f1f605b9b92 100644 --- a/src/univalue/test/object.cpp +++ b/src/univalue/test/object.cpp @@ -20,16 +20,16 @@ try { \ (stmt); \ } catch (excMatch & e) { \ - } catch (...) { \ - assert(0); \ - } \ + } catch (...) { \ + assert(0); \ + } \ } #define BOOST_CHECK_NO_THROW(stmt) { \ try { \ (stmt); \ - } catch (...) { \ - assert(0); \ - } \ + } catch (...) { \ + assert(0); \ + } \ } BOOST_FIXTURE_TEST_SUITE(univalue_tests, BasicTestingSetup) diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index e5febe863e8be..feff143003726 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -240,10 +240,10 @@ bool DecryptAES256(const SecureString& sKey, const std::string& sCiphertext, con if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (unsigned char*)(&sPlaintext[0]) + nPLen, &nFLen); EVP_CIPHER_CTX_cleanup(ctx); #else - if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, (const unsigned char*)&sKey[0], (const unsigned char*)&sIV[0]); if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, (const unsigned char*)&sKey[0], (const unsigned char*)&sIV[0]); - if (fOk) fOk = EVP_DecryptUpdate(&ctx, (unsigned char*)&sPlaintext[0], &nPLen, (const unsigned char*)&sCiphertext[0], nLen); if (fOk) fOk = EVP_DecryptUpdate(&ctx, (unsigned char*)&sPlaintext[0], &nPLen, (const unsigned char*)&sCiphertext[0], nLen); - if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (unsigned char*)(&sPlaintext[0]) + nPLen, &nFLen); if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (unsigned char*)(&sPlaintext[0]) + nPLen, &nFLen); - EVP_CIPHER_CTX_cleanup(&ctx); EVP_CIPHER_CTX_cleanup(&ctx); + if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, (const unsigned char*)&sKey[0], (const unsigned char*)&sIV[0]); if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, (const unsigned char*)&sKey[0], (const unsigned char*)&sIV[0]); + if (fOk) fOk = EVP_DecryptUpdate(&ctx, (unsigned char*)&sPlaintext[0], &nPLen, (const unsigned char*)&sCiphertext[0], nLen); if (fOk) fOk = EVP_DecryptUpdate(&ctx, (unsigned char*)&sPlaintext[0], &nPLen, (const unsigned char*)&sCiphertext[0], nLen); + if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (unsigned char*)(&sPlaintext[0]) + nPLen, &nFLen); if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (unsigned char*)(&sPlaintext[0]) + nPLen, &nFLen); + EVP_CIPHER_CTX_cleanup(&ctx); EVP_CIPHER_CTX_cleanup(&ctx); #endif if (!fOk) return false; diff --git a/test/functional/__init__.py b/test/functional/__init__.py old mode 100644 new mode 100755 diff --git a/test/functional/create_cache.py b/test/functional/create_cache.py new file mode 100755 index 0000000000000..8e95116992504 --- /dev/null +++ b/test/functional/create_cache.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016-2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Create a blockchain cache. +Creating a cache of the blockchain speeds up test execution when running +multiple functional tests. This helper script is executed by test_runner when multiple +tests are being run in parallel. +""" + +from test_framework.test_framework import BitcoinTestFramework + +class CreateCache(BitcoinTestFramework): + # Test network and test nodes are not required: + + def set_test_params(self): + self.num_nodes = 0 + self.supports_cli = True + + def setup_network(self): + pass + + def run_test(self): + pass + +if __name__ == '__main__': + CreateCache().main() \ No newline at end of file diff --git a/test/functional/decodetx.py b/test/functional/decodetx.py old mode 100644 new mode 100755 diff --git a/test/functional/listtransactions.py b/test/functional/listtransactions.py old mode 100644 new mode 100755 diff --git a/test/functional/segwit.py b/test/functional/segwit.py old mode 100644 new mode 100755 diff --git a/test/functional/test_case_base.py b/test/functional/test_case_base.py old mode 100644 new mode 100755 diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py old mode 100644 new mode 100755 index f6010172c6de8..73c866b660a3a --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -215,14 +215,6 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove else: coverage = None - if len(test_list) > 1 and jobs > 1: - # Populate cache - try: - subprocess.check_output([tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir]) - except subprocess.CalledProcessError as e: - sys.stdout.buffer.write(e.output) - raise - #Run Tests job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags) time0 = time.time() diff --git a/test/functional/wallet.py b/test/functional/wallet.py old mode 100644 new mode 100755 diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py old mode 100644 new mode 100755 diff --git a/test/functional/zerocoin.py b/test/functional/zerocoin.py old mode 100644 new mode 100755 From 9875777d05575f9cd1f1fd3ee25577282f48cf8e Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 27 Aug 2019 15:17:37 -0300 Subject: [PATCH 002/132] [DB] Db runtime error cleaning the variable that needs to be logged right before print it. --- src/wallet/db.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 640be8e554b76..fcd7f8fa7652f 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -264,8 +264,9 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, int nSerVersion) : delete pdb; pdb = NULL; --bitdb.mapFileUseCount[strFile]; + std::string tempCopy(strFile); strFile = ""; - throw std::runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, strFile)); + throw std::runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, tempCopy)); } if (fCreate && !Exists(std::string("version"))) { From 83c2cf7b8ac7bfc4f0dec49613a2034e385bd4f4 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Sun, 4 Aug 2019 22:56:24 -0700 Subject: [PATCH 003/132] [Build] CMake Improvements This includes some improvements and fixes for the CMake build system. * Use explicit per-target includes instead of global includes for dependencies. * Don't assume the availability of optional dependencies. * Fix Ubuntu build issues relating to endian/byteswap. * Ignore the qt subdir for windows WSL based builds. * Add TravisCI stage to test CMake builds. Windows support is still a work in progress, with the qt subdir being ignored due to an issue with CMake linking against a static Qt library. CMake Builds on TravisCI are allowed to fail for the time being. --- .travis.yml | 60 ++++++- CMakeLists.txt | 270 ++++++++++++++++++++----------- contrib/cmake/FindLibEvent.cmake | 10 +- contrib/cmake/FindMiniupnp.cmake | 33 ++++ src/qt/CMakeLists.txt | 106 +++++++----- 5 files changed, 340 insertions(+), 139 deletions(-) create mode 100644 contrib/cmake/FindMiniupnp.cmake diff --git a/.travis.yml b/.travis.yml index f997848bbe489..069342f113a8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,14 +14,14 @@ # # These caches can be manually removed if necessary. This is one of the very # few manual operations that is possible with Travis, and it can be done by a -# PIVX GitHub member via the Travis web interface [0]. +# Phore GitHub member via the Travis web interface [0]. # # Travis CI uploads the cache after the script phase of the build [1]. # However, the build is terminated without saving the chache if it takes over # 50 minutes [2]. Thus, if we spent too much time in early build stages, fail # with an error and save the cache. # -# [0] https://travis-ci.org/pivx-project/pivx/caches +# [0] https://travis-ci.org/phoreproject/Phore/caches # [1] https://docs.travis-ci.com/user/caching/#build-phases # [2] https://docs.travis-ci.com/user/customizing-the-build#build-timeouts @@ -33,10 +33,12 @@ cache: directories: - $TRAVIS_BUILD_DIR/depends/built - $TRAVIS_BUILD_DIR/depends/sdk-sources + - $TRAVIS_BUILD_DIR/cmake-build-debug - $HOME/.ccache stages: - lint - test + - cmake env: global: - MAKEJOBS=-j3 @@ -70,6 +72,9 @@ after_script: - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG jobs: + allow_failures: + - stage: cmake + fast_finish: true include: - stage: lint @@ -207,3 +212,54 @@ jobs: RUN_FUNCTIONAL_TESTS=false GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" + + - stage: cmake + name: 'CMake Linux' + language: cpp + compiler: + - gcc + addons: + apt: + packages: + - python3-zmq qtbase5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev libgmp-dev + before_install: + install: + before_script: + script: + - mkdir -p $TRAVIS_BUILD_DIR/cmake-build-debug && cd $TRAVIS_BUILD_DIR/cmake-build-debug + - cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" $TRAVIS_BUILD_DIR + - cmake --build $TRAVIS_BUILD_DIR/cmake-build-debug --target all -- -j 3 + + - stage: cmake + name: 'CMake macOS' + os: osx + osx_image: xcode10.1 + language: cpp + compiler: + - clang + addons: + homebrew: + packages: + - autoconf + - automake + - berkeley-db4 + - libtool + - boost + - miniupnpc + - openssl + - pkg-config + - protobuf + - python3 + - qt5 + - zmq + - libevent + - qrencode + - gmp + update: true + before_install: + install: + before_script: + script: + - mkdir -p $TRAVIS_BUILD_DIR/cmake-build-debug && cd $TRAVIS_BUILD_DIR/cmake-build-debug + - cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" $TRAVIS_BUILD_DIR + - cmake --build $TRAVIS_BUILD_DIR/cmake-build-debug --target all -- -j 3 diff --git a/CMakeLists.txt b/CMakeLists.txt index 43797e3b5c722..4f8b067173ff3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,15 @@ cmake_minimum_required(VERSION 3.10) -project(PIVX) +project(Phore) set(BDB_VER "4.8.30") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/contrib/cmake") set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") include(${CMAKE_ROOT}/Modules/ExternalProject.cmake) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") message(STATUS "Compiling on macOS") + set(ENV{target} "Mac") list(APPEND CMAKE_PREFIX_PATH /usr/local/opt/qt5) list(APPEND CMAKE_PREFIX_PATH /usr/local/opt/openssl) list(APPEND CMAKE_PREFIX_PATH /usr/local/Cellar/berkeley-db@4) @@ -21,88 +22,96 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") std::string(REGEX MATCH "Microsoft" _SYSTEM_VERSION_PARSED "${_SYS_VERSION}") if(${_SYSTEM_VERSION_PARSED} MATCHES "Microsoft") message(STATUS "Compiling on WSL") - set(ENV{triple} x86_64-w64-mingw32) - set(ENV{target} Windows) + set(ENV{triple} "x86_64-w64-mingw32") + set(ENV{target} "Windows") + set(WINDOWS_LDADD + /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/libstdc++.a + -lssp -lcrypt32 -liphlpapi -lshlwapi -lmswsock -lws2_32 + -ladvapi32 -lrpcrt4 -luuid -loleaut32 -lole32 -lcomctl32 + -lshell32 -lwinmm -lwinspool -lcomdlg32 -lgdi32 -luser32 + -lkernel32 -lmingwthrd + ) execute_process( - COMMAND make HOST=x86_64-w64-mingw32 -j16 + COMMAND make HOST=x86_64-w64-mingw32 -j6 NO_QT=1 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/depends ) - file(REMOVE ${CMAKE_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CMakeCXXCompiler.cmake) - file(REMOVE ${CMAKE_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CMakeCCompiler.cmake) - set(CMAKE_C_COMPILER /usr/bin/$ENV{triple}-gcc) - set(CMAKE_CXX_COMPILER /usr/bin/$ENV{triple}-g++) - set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}) - set(BOOST_INCLUDEDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/include/) - set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib) + #file(REMOVE ${CMAKE_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CMakeCXXCompiler.cmake) + #file(REMOVE ${CMAKE_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CMakeCCompiler.cmake) + set(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc) + set(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++) + set(CMAKE_EXECUTABLE_SUFFIX .exe) + set(CMAKE_CXX_FLAGS "-pthread -std=c++11 -Wa,-mbig-obj ${CMAKE_CXX_FLAGS}") + set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32) + set(BOOST_INCLUDEDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/include/) + set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/lib) + set(BOOST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32) + set(Boost_USE_STATIC_RUNTIME ON) + set(Boost_THREADAPI /depends/x86_64-w64-mingw32) + set(BOOST_INCLUDEDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/include/) + set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/lib) + set(BOOST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32) set(Boost_USE_STATIC_RUNTIME ON) set(Boost_THREADAPI "win32") + set(Boost_USE_STATIC_LIBS ON) + list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}) + list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/native/bin) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/include) + set(CONFIGSITE "CONFIG_SITE=${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/share/config.site") else() message(STATUS "Compiling on Linux") + set(ENV{target} "Linux") list(APPEND CMAKE_PREFIX_PATH /usr/lib/x86_64-linux-gnu/cmake/Qt5) set(Qt5core_DIR "/usr/lib/x86_64-linux-gnu/cmake/Qt5/QtCore") - include_directories("/usr/include") - include_directories("/usr/include/x86_64-linux-gnu") - add_definitions("-D__BYTE_ORDER -D__LITTLE_ENDIAN") + add_definitions("-D__BYTE_ORDER -D__LITTLE_ENDIAN -D__GLIBC__ -DHAVE_DECL_BSWAP_16=0 -DHAVE_DECL_BSWAP_32=0 -DHAVE_DECL_BSWAP_64=0") endif() endif() # Find Dependencies find_package(BerkeleyDB ${BDB_VER} REQUIRED) -if (BerkeleyDB_FOUND) +if(BerkeleyDB_FOUND) if(NOT ${BerkeleyDB_VERSION} MATCHES "${BDB_VER}") message(WARNING "BerkeleyDB version other than ${BDB_VER} found!") set(BDB_CONFIGURE_FLAGS "--with-incompatible-bdb") endif() - include_directories( ${BerkeleyDB_INCLUDE_DIRS} ) - link_directories( ${BerkeleyDB_ROOT_DIR}/lib ) -endif () +endif() find_package(OpenSSL REQUIRED) -if (OPENSSL_FOUND) +if(OPENSSL_FOUND) message(STATUS "Found OpenSSL (${OPENSSL_VERSION}): ${OPENSSL_LIBRARIES}") - include_directories( ${OPENSSL_INCLUDE_DIR} ) + if(OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1) + message(STATUS "Found unsupported OpenSSL version!") + set(SSL_CONFIGURE_FLAGS "--with-unsupported-ssl") + endif() endif() find_package(LibEvent REQUIRED) -if (LibEvent_FOUND) - include_directories ( ${LibEvent_INCLUDE_DIR} ) - link_directories ( ${LibEvent_LIBRARY_DIRS} ) -endif() find_package(GMP) -if (GMP_FOUND) - include_directories ( ${GMP_INCLUDE_DIR} ) - link_directories ( ${GMP_LIBRARY_DIRS} ) +if(GMP_FOUND) else() message(WARNING "GMP not found, falling back to OpenSSL for bignum!") set(BIGNUM_CONFIGURE_FLAGS "--with-zerocoin-bignum=openssl") endif() find_package(ZMQ) -if (ZMQ_Found) - include_directories ( ${ZMQ_INCLUDE_DIR} ) - link_directories ( ${ZMQ_LIB_DIRS} ) -endif() - +find_package(Miniupnp) find_package(Boost COMPONENTS system filesystem thread program_options REQUIRED) -include_directories( ${Boost_INCLUDE_DIRS} ) -link_directories ( ${Boost_LIBRARY_DIRS} ) # run autogen.sh if missing header files from configure on Linux/Mac -if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/configure") +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/configure") else() execute_process( - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/autogen.sh - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/autogen.sh + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif() -# run configure if pivx_config.h doesn't exist -if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/config/pivx-config.h") +# run configure if phore_config.h doesn't exist +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/config/phore-config.h") else() execute_process( - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/configure ${BDB_CONFIGURE_FLAGS} ${BIGNUM_CONFIGURE_FLAGS} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/configure ${CONFIGSITE} ${BDB_CONFIGURE_FLAGS} ${BIGNUM_CONFIGURE_FLAGS} ${SSL_CONFIGURE_FLAGS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif() add_definitions(-DHAVE_CONFIG_H) @@ -111,7 +120,7 @@ ExternalProject_Add ( libunivalue SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/univalue CONFIGURE_COMMAND "" - BUILD_COMMAND make + BUILD_COMMAND $(MAKE) BUILD_IN_SOURCE 1 INSTALL_COMMAND "" ) @@ -120,31 +129,13 @@ ExternalProject_Add ( libsecp256k1 SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/secp256k1 CONFIGURE_COMMAND "" - BUILD_COMMAND make + BUILD_COMMAND $(MAKE) BUILD_IN_SOURCE 1 INSTALL_COMMAND "" -) - -link_directories( - ${CMAKE_SOURCE_DIR}/src/univalue/.libs - ${CMAKE_SOURCE_DIR}/src/secp256k1/.libs -) - -include_directories( - ${CMAKE_SOURCE_DIR}/src - ${CMAKE_SOURCE_DIR}/src/compat - ${CMAKE_SOURCE_DIR}/src/config - ${CMAKE_SOURCE_DIR}/src/obj - ${CMAKE_SOURCE_DIR}/src/leveldb - ${CMAKE_SOURCE_DIR}/src/leveldb/include - ${CMAKE_SOURCE_DIR}/src/leveldb/helpers/memenv - ${CMAKE_SOURCE_DIR}/src/secp256k1 - ${CMAKE_SOURCE_DIR}/src/secp256k1/include - ${CMAKE_SOURCE_DIR}/src/univalue/include -) + ) set(libleveldb_a_headers - ${CMAKE_CURRENT_SOURCE_DIR}/src/config/pivx-config.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/config/phore-config.h ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/atomic_pointer.h ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/port_example.h ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/port_posix.h @@ -244,22 +235,27 @@ set(libleveldb_a_sources ) set(libleveldb_cpp_flags) -if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(libleveldb_cpp_flags -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1) - list(APPEND libleveldb_a_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/util/env_win.cc) - list(APPEND libleveldb_a_srouces ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/port_win.cc) +if($ENV{target} MATCHES "Windows") + set(libleveldb_cpp_flags -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1) + set(libleveldb_a_sources ${libleveldb_a_sources} ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/util/env_win.cc + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/port_win.cc) else() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(libleveldb_cpp_flags -DOS_MACOSX -DLEVELDB_PLATFORM_POSIX) else() set(libleveldb_cpp_flags -DOS_LINUX -DLEVELDB_PLATFORM_POSIX) endif() - list(APPEND libleveldb_a_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/port_posix.cc) + set(libleveldb_a_sources ${libleveldb_a_sources} ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/port_posix.cc) endif() add_library(leveldb STATIC ${libleveldb_a_headers} ${libleveldb_a_sources}) target_compile_definitions(leveldb PUBLIC ${libleveldb_cpp_flags} -DLEVELDB_ATOMIC_PRESENT -D__STDC_LIMIT_MACROS) -target_compile_options(leveldb PUBLIC -I${CMAKE_CURRENT_SOURCE_DIR}/src/compat) +target_include_directories(leveldb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/helpers/memenv + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/compat + ) set(libmemenv_a_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/helpers/memenv/memenv.cc @@ -267,11 +263,17 @@ set(libmemenv_a_sources ) add_library(memenv STATIC ${libmemenv_a_sources}) target_compile_definitions(memenv PUBLIC ${libleveldb_cpp_flags}) +target_include_directories(memenv PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/helpers/memenv + ) set(libleveldb_sse42_a_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/port/port_posix_sse.cc) add_library(leveldb_sse42 ${libleveldb_sse42_a_sources}) - -link_directories ( ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb ) +target_include_directories(leveldb_sse42 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/helpers/memenv + ) file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) file(GLOB CRYPTO_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/*.h) @@ -328,14 +330,25 @@ set(SERVER_SOURCES ./src/zpivchain.cpp ) add_library(SERVER_A STATIC ${BitcoinHeaders} ${SERVER_SOURCES}) +if(MINIUPNP_FOUND) + target_compile_definitions(SERVER_A PUBLIC "-DSTATICLIB -DMINIUPNP_STATICLIB") +endif() +target_include_directories(SERVER_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/univalue/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/helpers/memenv + ${ZMQ_INCLUDE_DIR} ${LIBEVENT_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${BerkeleyDB_INCLUDE_DIRS} + ) -if (ZMQ_FOUND) +if(ZMQ_FOUND) set(ZMQ_SOURCES ./src/zmq/zmqabstractnotifier.cpp ./src/zmq/zmqnotificationinterface.cpp ./src/zmq/zmqpublishnotifier.cpp ) - add_library(ZMQ_A STATIC ${BitcoinHeaders} ${ZMQ_SOURCES}) + add_library(ZMQ_A STATIC ${BitcoinHeaders} ${ZMQ_SOURCES} ${ZMQ_LIB}) + target_include_directories(ZMQ_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ${ZMQ_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}) + target_compile_definitions(ZMQ_A PUBLIC "-DZMQ_STATIC") endif() set(WALLET_SOURCES @@ -370,6 +383,13 @@ set(WALLET_SOURCES ./src/lightzpivthread.cpp ) add_library(WALLET_A STATIC ${BitcoinHeaders} ${WALLET_SOURCES}) +target_include_directories(WALLET_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/secp256k1/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/univalue/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/include + ${OPENSSL_INCLUDE_DIR} + ${BerkeleyDB_INCLUDE_DIRS} + ) set(BITCOIN_CRYPTO_SOURCES ./src/crypto/sha1.cpp @@ -405,6 +425,7 @@ set(BITCOIN_CRYPTO_SOURCES ./src/crypto/sph_types.h ) add_library(BITCOIN_CRYPTO_A STATIC ${BITCOIN_CRYPTO_SOURCES}) +target_include_directories(BITCOIN_CRYPTO_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ${OPENSSL_INCLUDE_DIR}) set(ZEROCOIN_SOURCES ./src/libzerocoin/Accumulator.h @@ -436,6 +457,9 @@ else() list(APPEND ZEROCOIN_SOURCES ./src/libzerocoin/bignum_openssl.cpp) endif() add_library(ZEROCOIN_A STATIC ${ZEROCOIN_SOURCES}) +target_include_directories(ZEROCOIN_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${OPENSSL_INCLUDE_DIR} + ) set(COMMON_SOURCES ./src/zpiv/accumulators.cpp @@ -472,6 +496,13 @@ set(COMMON_SOURCES ./src/sporkdb.cpp ) add_library(COMMON_A STATIC ${BitcoinHeaders} ${COMMON_SOURCES}) +target_include_directories(COMMON_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/secp256k1/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/univalue/include + ${OPENSSL_INCLUDE_DIR} + ${BerkeleyDB_INCLUDE_DIRS} + ) set(UTIL_SOURCES ./src/allocators.cpp @@ -491,23 +522,46 @@ set(UTIL_SOURCES ./src/support/cleanse.cpp ) add_library(UTIL_A STATIC ${BitcoinHeaders} ${UTIL_SOURCES}) +target_include_directories(UTIL_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/univalue/include + ${OPENSSL_INCLUDE_DIR} + ) + +set(CLI_A_SOURCES ./src/rpc/client.cpp) +add_library(CLI_A STATIC ${BitcoinHeaders} ${CLI_A_SOURCES}) +target_include_directories(CLI_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/univalue/include + ) -set(CLI_SOURCES ./src/rpc/client.cpp) -add_library(CLI_A STATIC ${BitcoinHeaders} ${CLI_SOURCES}) +link_directories( + ${CMAKE_SOURCE_DIR}/src/univalue/.libs + ${CMAKE_SOURCE_DIR}/src/secp256k1/.libs + ) -add_executable(pivx-cli ${CMAKE_CURRENT_SOURCE_DIR}/src/pivx-cli.cpp) -add_dependencies(pivx-cli libunivalue) -target_link_libraries(pivx-cli +set(phore-cli_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/phore-cli.cpp) +if($ENV{target} MATCHES "Windows") + list(APPEND phore-cli_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/phore-cli-res.rc) +endif() +add_executable(phore-cli ${phore-cli_SOURCES}) +add_dependencies(phore-cli libunivalue) +target_link_libraries(phore-cli CLI_A univalue UTIL_A BITCOIN_CRYPTO_A ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${LIBEVENT_LIB} ) +if($ENV{target} MATCHES "Windows") + target_link_libraries(phore-cli ${WINDOWS_LDADD}) +endif() -add_executable(pivx-tx ${CMAKE_CURRENT_SOURCE_DIR}/src/pivx-tx.cpp) -add_dependencies(pivx-tx libunivalue libsecp256k1) -target_link_libraries(pivx-tx +set(phore-tx_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/phore-tx.cpp) +if($ENV{target} MATCHES "Windows") + list(APPEND phore-tx_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/phore-tx-res.rc) +endif() +add_executable(phore-tx ${phore-tx_SOURCES}) +add_dependencies(phore-tx libunivalue libsecp256k1) +target_link_libraries(phore-tx univalue COMMON_A ZEROCOIN_A @@ -516,13 +570,28 @@ target_link_libraries(pivx-tx secp256k1 ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${LIBEVENT_LIB} ) +if($ENV{target} MATCHES "Windows") + target_link_libraries(phore-tx ${WINDOWS_LDADD}) +endif() if(GMP_FOUND) - target_link_libraries(pivx-tx ${GMP_LIBRARY}) + target_link_libraries(phore-tx ${GMP_LIBRARY}) endif() -add_executable(pivxd ${CMAKE_CURRENT_SOURCE_DIR}/src/pivxd.cpp) -add_dependencies(pivxd libunivalue libsecp256k1 leveldb leveldb_sse42 memenv) -target_link_libraries(pivxd +link_directories(${CMAKE_BINARY_DIR}) + +set(phored_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/phored.cpp) +if($ENV{target} MATCHES "Windows") + list(APPEND phored_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/phored-res.rc) +endif() +add_executable(phored ${phored_SOURCES} ${BitcoinHeaders}) +add_dependencies(phored libunivalue libsecp256k1 leveldb leveldb_sse42 memenv) +target_include_directories(phored PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/leveldb/helpers/memenv + ${LIBEVENT_INCLUDE_DIR}) +target_link_libraries(phored + pthread SERVER_A COMMON_A univalue @@ -530,15 +599,32 @@ target_link_libraries(pivxd UTIL_A WALLET_A BITCOIN_CRYPTO_A - leveldb leveldb_sse42 memenv secp256k1 - ${BerkeleyDB_LIBRARIES} ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} ${LIBEVENT_LIB} miniupnpc pthread + ${CMAKE_BINARY_DIR}/libleveldb.a + ${CMAKE_BINARY_DIR}/libleveldb_sse42.a + ${CMAKE_BINARY_DIR}/libmemenv.a + secp256k1 + ${BerkeleyDB_LIBRARIES} ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} ${LIBEVENT_LIB} pthread ) +if($ENV{target} MATCHES "Windows") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wstack-protector -fstack-protector-all -fPIE -pipe -O2 -pthread -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -pie --static") + target_link_libraries(phored ${WINDOWS_LDADD}) +endif() if(GMP_FOUND) - target_link_libraries(pivxd ${GMP_LIBRARY}) + target_link_libraries(phored ${GMP_LIBRARY}) + target_include_directories(phored PUBLIC ${GMP_INCLUDE_DIR}) endif() if(ZMQ_FOUND) - target_link_libraries(pivxd ZMQ_A ${ZMQ_LIB}) -endif () + target_link_libraries(phored ZMQ_A ${ZMQ_LIB}) + target_include_directories(phored PUBLIC ${ZMQ_INCLUDE_DIR}) +endif() +if(MINIUPNP_FOUND) + target_compile_definitions(phored PUBLIC "-DSTATICLIB -DMINIUPNP_STATICLIB") + target_link_libraries(phored ${MINIUPNP_LIBRARY}) + target_include_directories(phored PUBLIC ${MINIUPNP_INCLUDE_DIR}) +endif() +target_link_libraries(phored -lpthread) -add_subdirectory(src/qt) +if(NOT $ENV{target} MATCHES "Windows") + add_subdirectory(src/qt) +endif() \ No newline at end of file diff --git a/contrib/cmake/FindLibEvent.cmake b/contrib/cmake/FindLibEvent.cmake index d0ffdf0ad4720..7d02ded579865 100644 --- a/contrib/cmake/FindLibEvent.cmake +++ b/contrib/cmake/FindLibEvent.cmake @@ -4,10 +4,12 @@ # LIBEVENT_LIB, LibEvent libraries # LibEvent_FOUND, If false, do not try to use libevent -if(($ENV{triple}) AND (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}")) - set(LIBEVENT_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/include") - set(LIBEVENT_LIB "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib/libevent.a") - set(LIBEVENT_PTHREAD_LIB "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib/libevent.a") +if($ENV{target} MATCHES "Windows") + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}") + set(LIBEVENT_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/include") + set(LIBEVENT_LIB "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib/libevent.a") + set(LIBEVENT_PTHREAD_LIB "${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib/libevent.a") + endif() else() set(LibEvent_EXTRA_PREFIXES /usr/local /opt/local "$ENV{HOME}") foreach(prefix ${LibEvent_EXTRA_PREFIXES}) diff --git a/contrib/cmake/FindMiniupnp.cmake b/contrib/cmake/FindMiniupnp.cmake new file mode 100644 index 0000000000000..31e2e39e58aaa --- /dev/null +++ b/contrib/cmake/FindMiniupnp.cmake @@ -0,0 +1,33 @@ +# - Find Miniupnp +# This module defines +# MINIUPNP_INCLUDE_DIR, where to find Miniupnp headers +# MINIUPNP_LIBRARY, Miniupnp libraries +# MINIUPNP_FOUND, If false, do not try to use Miniupnp + +set(MINIUPNP_PREFIX "" CACHE PATH "path ") + +find_path(MINIUPNP_INCLUDE_DIR miniupnpc/miniupnpc.h + PATHS ${MINIUPNP_PREFIX}/include /usr/include /usr/local/include ) + +find_library(MINIUPNP_LIBRARY NAMES miniupnpc libminiupnpc + PATHS ${MINIUPNP_PREFIX}/lib /usr/lib /usr/local/lib) + +if(MINIUPNP_INCLUDE_DIR AND MINIUPNP_LIBRARY) + get_filename_component(MINIUPNP_LIBRARY_DIR ${MINIUPNP_LIBRARY} PATH) + set(MINIUPNP_FOUND TRUE) +endif() + +if(MINIUPNP_FOUND) + if(NOT Miniupnp_FIND_QUIETLY) + MESSAGE(STATUS "Found Miniupnp: ${MINIUPNP_LIBRARY}") + endif() +else() + if(MINIUPNP_FIND_REQUIRED) + message(FATAL_ERROR "Could not find Miniupnp") + endif() +endif() + +mark_as_advanced( + MINIUPNP_LIBRARY + MINIUPNP_INCLUDE_DIR +) \ No newline at end of file diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 71979b725f00d..baabd0d9ec6ee 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -8,6 +8,10 @@ set(CMAKE_AUTOUIC ON) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(CMAKE_POSITION_INDEPENDENT_CODE ON) + execute_process( + COMMAND sed -i /HAVE_DECL_BSWAP/d phore-config.h + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/config + ) endif () find_package(Qrcode) @@ -16,39 +20,44 @@ if (QRCODE_FOUND) link_directories ( ${QRCODE_LIBRARY_DIRS} ) endif() -if($ENV{target} MATCHES "Windows") - find_package(Qt5) -else() - unset(Qt5Enables) - foreach(comp Widgets Core Gui Network LinguistTools DBus) - find_package(Qt5${comp}) - set(Qt5Enables "${Qt5Enables};Qt5${comp}_FOUND") - if(Qt5${comp}_FOUND) - MESSAGE(STATUS "FOUND QT5${comp}") - include_directories(${include_directories} ${Qt5${comp}_INCLUDE_DIRS} ${QT_USE_FILE}) - add_definitions(${Qt5${comp}_DEFINITIONS}) - list(APPEND Qt5_LIBRARIES ${Qt5${comp}_LIBRARIES}) - else() - MESSAGE(WARNING "Cant find Qt5${comp}") - endif() - endforeach(comp) - - find_package(Qt5DBus) - if (Qt5DBus_FOUND) - include_directories(${include_directories} "/usr/local/opt/qt5/include/QtDBus/") - add_compile_options("-DUSE_DBUS") +unset(Qt5Enables) +foreach(comp Widgets Core Gui Network LinguistTools DBus) + find_package(Qt5${comp}) + set(Qt5Enables "${Qt5Enables};Qt5${comp}_FOUND") + if(Qt5${comp}_FOUND) + MESSAGE(STATUS "FOUND QT5${comp}") + include_directories(${include_directories} ${Qt5${comp}_INCLUDE_DIRS} ${QT_USE_FILE}) + add_definitions(${Qt5${comp}_DEFINITIONS}) + list(APPEND Qt5_LIBRARIES ${Qt5${comp}_LIBRARIES}) + else() + MESSAGE(WARNING "Cant find Qt5${comp}") endif() +endforeach(comp) + +#find_package(Qt5DBus) +if (Qt5DBus_FOUND) +# include_directories(${include_directories} "/usr/local/opt/qt5/include/QtDBus/") + add_compile_options("-DUSE_DBUS") endif() # Why isn't this done automatically?? if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_AUTOMOC_MOC_OPTIONS "-DQ_OS_MAC") endif() +if($ENV{target} MATCHES "Windows") + set(CMAKE_AUTOMOC_MOC_OPTIONS "-DQ_OS_WIN") + include_directories(${CMAKE_SOURCE_DIR}/depends/$ENV{triple}/include) + set(CMAKE_EXE_LINKER_FLAGS "-pthread -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -pie -mwindows") +endif() file(GLOB LOCAL_QT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) source_group("QtHeaders" FILES ${LOCAL_QT_HEADERS}) find_package(Protobuf REQUIRED) +if(Protobuf_FOUND) + message(STATUS "Found Protobuf compiler: ${Protobuf_PROTOC_EXECUTABLE}") + message(STATUS "Found Protobuf library: ${Protobuf_LIBRARIES}") +endif() include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) @@ -146,12 +155,19 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") list(APPEND QT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/macnotificationhandler.mm) endif() -if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") - list(APPEND QT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/winshutdownmonitor.cpp) +if ($ENV{target} MATCHES "Windows") + list(APPEND QT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/winshutdownmonitor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/res/phore-qt-res.rc) endif () add_library(qt_stuff STATIC ${BitcoinHeaders} ${QtHeaders} ${QT_SOURCES} ${PROTO_SRCS} ${PROTO_HDRS}) -target_include_directories(qt_stuff PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(qt_stuff PUBLIC ${CMAKE_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/src/leveldb/include + ${CMAKE_SOURCE_DIR}/src/univalue/include + ${CMAKE_SOURCE_DIR}/src/secp256k1/include + ${CMAKE_CURRENT_SOURCE_DIR} + ${OPENSSL_INCLUDE_DIR} + ${BerkeleyDB_INCLUDE_DIRS} + ) set_property(TARGET qt_stuff PROPERTY CXX_STANDARD 11) file(GLOB QT_TRANSLATIONS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/locale/*.ts) @@ -162,38 +178,46 @@ set_source_files_properties(${QT_TRANSLATIONS_FILES} PROPERTIES OUTPUT_LOCATION QT5_ADD_TRANSLATION(QM ${QT_TRANSLATIONS_FILES}) add_custom_target(translations_target ALL DEPENDS ${QM}) -QT5_ADD_RESOURCES(QRC_RESOURCE pivx.qrc) -QT5_ADD_RESOURCES(QRC_LOCALE_RESOURCE pivx_locale.qrc) +QT5_ADD_RESOURCES(QRC_RESOURCE phore.qrc) +QT5_ADD_RESOURCES(QRC_LOCALE_RESOURCE phore_locale.qrc) -add_executable(pivx-qt pivx.cpp ${QM} ${QRC_RESOURCE} ${QRC_LOCALE_RESOURCE}) -add_dependencies(pivx-qt translations_target libunivalue libsecp256k1 leveldb leveldb_sse42 memenv) -target_link_libraries(pivx-qt +add_executable(phore-qt phore.cpp ${QM} ${QRC_RESOURCE} ${QRC_LOCALE_RESOURCE}) +add_dependencies(phore-qt translations_target libunivalue libsecp256k1 leveldb leveldb_sse42 memenv) +target_link_libraries(phore-qt qt_stuff univalue SERVER_A UTIL_A WALLET_A CLI_A COMMON_A BITCOIN_CRYPTO_A ZEROCOIN_A - leveldb leveldb_sse42 memenv miniupnpc secp256k1 + leveldb leveldb_sse42 memenv secp256k1 ${BerkeleyDB_LIBRARIES} ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} ${PROTOBUF_LIBRARIES} ${LIBEVENT_LIB} pthread ) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - target_link_libraries(pivx-qt "-framework Cocoa") + target_link_libraries(phore-qt "-framework Cocoa") +endif() +if($ENV{target} MATCHES "Windows") +# link_directories(${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib) + #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wstack-protector -fstack-protector-all -fPIE -pipe -O2 -pthread -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -pie --static") + target_link_libraries(phore-qt -L${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib ${WINDOWS_QT_LDADD} ${WINDOWS_LDADD}) endif() if(GMP_FOUND) - target_link_libraries(pivx-qt ${GMP_LIBRARY}) + target_link_libraries(phore-qt ${GMP_LIBRARY}) + target_include_directories(phore-qt PUBLIC ${GMP_INCLUDE_DIR}) endif() if(ZMQ_FOUND) - target_link_libraries(pivx-qt ZMQ_A ${ZMQ_LIB}) + target_link_libraries(phore-qt ZMQ_A ${ZMQ_LIB}) + target_include_directories(phore-qt PUBLIC ${ZMQ_INCLUDE_DIR}) endif() if (QRCODE_FOUND) - target_link_libraries(pivx-qt ${QRCODE_LIB}) + target_link_libraries(phore-qt ${QRCODE_LIB}) + target_include_directories(phore-qt PUBLIC ${QRCODE_INCLUDE_DIR}) +endif() +if(MINIUPNP_FOUND) + target_compile_definitions(phore-qt PUBLIC "-DSTATICLIB -DMINIUPNP_STATICLIB") + target_link_libraries(phore-qt ${MINIUPNP_LIBRARY}) + target_include_directories(phore-qt PUBLIC ${MINIUPNP_INCLUDE_DIR}) endif() -QT5_USE_Modules(pivx-qt Gui) -QT5_USE_Modules(pivx-qt Core) -QT5_USE_Modules(pivx-qt Widgets) -QT5_USE_Modules(pivx-qt Test) -QT5_USE_Modules(pivx-qt PrintSupport) -QT5_USE_Modules(pivx-qt Network) +target_link_libraries(phore-qt Qt5::Gui Qt5::Core Qt5::Widgets Qt5::Network ${QT_LIBRARIES}) if (Qt5DBus_FOUND) - QT5_USE_Modules(pivx-qt DBus) + target_link_libraries(phore-qt Qt5::DBus ${QT_LIBRARIES}) endif() From 79ece4e2b38fff27c3cb3af71574b56c01421695 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Wed, 21 Aug 2019 17:27:34 -0700 Subject: [PATCH 004/132] Allow WSL builds with cmake Requires VcXsrv for running of resulting builds. --- CMakeLists.txt | 55 ++++++++++--------------------------------- src/qt/CMakeLists.txt | 16 ------------- 2 files changed, 13 insertions(+), 58 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f8b067173ff3..75a7f22634aac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,10 @@ set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") include(${CMAKE_ROOT}/Modules/ExternalProject.cmake) +if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + message(FATAL_ERROR "Native Windows CMake is not supported yet, use WSL instead") +endif() + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") message(STATUS "Compiling on macOS") set(ENV{target} "Mac") @@ -18,52 +22,21 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(ENV{LDFLAGS} "-L${OPENSSL_ROOT_DIR}/lib") set(BerkeleyDB_ROOT_DIR "/usr/local/Cellar/berkeley-db@4/${BDB_VER}/") elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(ENV{target} "Linux") file(READ "/proc/version" _SYS_VERSION) std::string(REGEX MATCH "Microsoft" _SYSTEM_VERSION_PARSED "${_SYS_VERSION}") if(${_SYSTEM_VERSION_PARSED} MATCHES "Microsoft") message(STATUS "Compiling on WSL") - set(ENV{triple} "x86_64-w64-mingw32") - set(ENV{target} "Windows") - set(WINDOWS_LDADD - /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/libstdc++.a - -lssp -lcrypt32 -liphlpapi -lshlwapi -lmswsock -lws2_32 - -ladvapi32 -lrpcrt4 -luuid -loleaut32 -lole32 -lcomctl32 - -lshell32 -lwinmm -lwinspool -lcomdlg32 -lgdi32 -luser32 - -lkernel32 -lmingwthrd - ) - execute_process( - COMMAND make HOST=x86_64-w64-mingw32 -j6 NO_QT=1 - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/depends - ) - #file(REMOVE ${CMAKE_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CMakeCXXCompiler.cmake) - #file(REMOVE ${CMAKE_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CMakeCCompiler.cmake) - set(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc) - set(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++) - set(CMAKE_EXECUTABLE_SUFFIX .exe) - set(CMAKE_CXX_FLAGS "-pthread -std=c++11 -Wa,-mbig-obj ${CMAKE_CXX_FLAGS}") - set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32) - set(BOOST_INCLUDEDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/include/) - set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/lib) - set(BOOST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32) - set(Boost_USE_STATIC_RUNTIME ON) - set(Boost_THREADAPI /depends/x86_64-w64-mingw32) - set(BOOST_INCLUDEDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/include/) - set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/lib) - set(BOOST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32) - set(Boost_USE_STATIC_RUNTIME ON) - set(Boost_THREADAPI "win32") - set(Boost_USE_STATIC_LIBS ON) - list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}) - list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/native/bin) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/include) - set(CONFIGSITE "CONFIG_SITE=${CMAKE_CURRENT_SOURCE_DIR}/depends/x86_64-w64-mingw32/share/config.site") + set(ENV{DISPLAY} ":0") + set(ENV{LIBGL_ALWAYS_INDIRECT} 1) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY /home/$ENV{USER}/pivx-run) + message(WARNING "WSL Runtime support requires VcXsrv to be installed and running") else() message(STATUS "Compiling on Linux") - set(ENV{target} "Linux") - list(APPEND CMAKE_PREFIX_PATH /usr/lib/x86_64-linux-gnu/cmake/Qt5) - set(Qt5core_DIR "/usr/lib/x86_64-linux-gnu/cmake/Qt5/QtCore") - add_definitions("-D__BYTE_ORDER -D__LITTLE_ENDIAN -D__GLIBC__ -DHAVE_DECL_BSWAP_16=0 -DHAVE_DECL_BSWAP_32=0 -DHAVE_DECL_BSWAP_64=0") endif() + list(APPEND CMAKE_PREFIX_PATH /usr/lib/x86_64-linux-gnu/cmake/Qt5) + set(Qt5core_DIR "/usr/lib/x86_64-linux-gnu/cmake/Qt5/QtCore") + add_definitions("-D__BYTE_ORDER -D__LITTLE_ENDIAN -D__GLIBC__ -DHAVE_DECL_BSWAP_16=0 -DHAVE_DECL_BSWAP_32=0 -DHAVE_DECL_BSWAP_64=0") endif() # Find Dependencies @@ -625,6 +598,4 @@ endif() target_link_libraries(phored -lpthread) -if(NOT $ENV{target} MATCHES "Windows") - add_subdirectory(src/qt) -endif() \ No newline at end of file +add_subdirectory(src/qt) \ No newline at end of file diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index baabd0d9ec6ee..fd2117bedd084 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -34,9 +34,7 @@ foreach(comp Widgets Core Gui Network LinguistTools DBus) endif() endforeach(comp) -#find_package(Qt5DBus) if (Qt5DBus_FOUND) -# include_directories(${include_directories} "/usr/local/opt/qt5/include/QtDBus/") add_compile_options("-DUSE_DBUS") endif() @@ -44,11 +42,6 @@ endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_AUTOMOC_MOC_OPTIONS "-DQ_OS_MAC") endif() -if($ENV{target} MATCHES "Windows") - set(CMAKE_AUTOMOC_MOC_OPTIONS "-DQ_OS_WIN") - include_directories(${CMAKE_SOURCE_DIR}/depends/$ENV{triple}/include) - set(CMAKE_EXE_LINKER_FLAGS "-pthread -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -pie -mwindows") -endif() file(GLOB LOCAL_QT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) source_group("QtHeaders" FILES ${LOCAL_QT_HEADERS}) @@ -155,10 +148,6 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") list(APPEND QT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/macnotificationhandler.mm) endif() -if ($ENV{target} MATCHES "Windows") - list(APPEND QT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/winshutdownmonitor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/res/phore-qt-res.rc) -endif () - add_library(qt_stuff STATIC ${BitcoinHeaders} ${QtHeaders} ${QT_SOURCES} ${PROTO_SRCS} ${PROTO_HDRS}) target_include_directories(qt_stuff PUBLIC ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/leveldb/include @@ -194,11 +183,6 @@ target_link_libraries(phore-qt if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(phore-qt "-framework Cocoa") endif() -if($ENV{target} MATCHES "Windows") -# link_directories(${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib) - #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wstack-protector -fstack-protector-all -fPIE -pipe -O2 -pthread -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -pie --static") - target_link_libraries(phore-qt -L${CMAKE_CURRENT_SOURCE_DIR}/depends/$ENV{triple}/lib ${WINDOWS_QT_LDADD} ${WINDOWS_LDADD}) -endif() if(GMP_FOUND) target_link_libraries(phore-qt ${GMP_LIBRARY}) target_include_directories(phore-qt PUBLIC ${GMP_INCLUDE_DIR}) From 0066758054679755060f806c3d88bb2d336813f5 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 26 Feb 2016 09:35:39 +0100 Subject: [PATCH 005/132] Remove openssl info from init/log and from Qt debug window Backport of https://github.com/bitcoin/bitcoin/pull/7605 --- src/init.cpp | 1 - src/qt/forms/rpcconsole.ui | 110 ++++++++++++++----------------------- src/qt/rpcconsole.cpp | 1 - 3 files changed, 42 insertions(+), 70 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 5ee8fd4ff12b2..252121a6f6c82 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1039,7 +1039,6 @@ bool AppInit2(const std::vector& words) ShrinkDebugFile(); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); LogPrintf("Phore version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); - LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); #endif diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index 1d45558713a72..de3b49737abcf 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -7,7 +7,7 @@ 0 0 769 - 516 + 496 @@ -27,13 +27,6 @@ 12 - - - - N/A - - - @@ -94,9 +87,9 @@ - + - Using OpenSSL version + Using BerkeleyDB version 10 @@ -104,7 +97,7 @@ - + IBeamCursor @@ -120,17 +113,14 @@ - + - Using BerkeleyDB version - - - 10 + Build date - + IBeamCursor @@ -146,14 +136,14 @@ - + - Build date + Startup time - + IBeamCursor @@ -169,29 +159,20 @@ - + - Startup time + Data Directory - - - IBeamCursor - + N/A - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - + @@ -204,14 +185,14 @@ - + Name - + IBeamCursor @@ -227,14 +208,14 @@ - + Number of connections - + IBeamCursor @@ -250,14 +231,14 @@ - + Number of Masternodes - + IBeamCursor @@ -273,7 +254,7 @@ - + @@ -286,14 +267,14 @@ - + Current number of blocks - + IBeamCursor @@ -309,14 +290,14 @@ - + Last block time - + IBeamCursor @@ -332,7 +313,21 @@ - + + + + Last block hash + + + + + + + N/A + + + + Qt::Vertical @@ -345,7 +340,7 @@ - + @@ -358,7 +353,7 @@ - + Open the Phore debug log file from the current data directory. This can take a few seconds for large log files. @@ -371,27 +366,6 @@ - - - - Data Directory - - - - - - - Last block hash - - - - - - - N/A - - - diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 70a7d4f185f42..8ccd6518163e0 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -287,7 +287,6 @@ RPCConsole::RPCConsole(QWidget* parent) : QDialog(parent, Qt::WindowSystemMenuHi connect(ui->btn_resync, SIGNAL(clicked()), this, SLOT(walletResync())); // set library version labels - ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); #ifdef ENABLE_WALLET std::string strPathCustom = GetArg("-backuppath", ""); std::string strzphrPathCustom = GetArg("-zphrbackuppath", ""); From 55fd07a735e69fbf6831d23be616c3a6580f6e4c Mon Sep 17 00:00:00 2001 From: warrows Date: Wed, 28 Aug 2019 17:40:25 +0200 Subject: [PATCH 006/132] [Refactor] Remove unused OpenSSL includes --- src/bip38.cpp | 1 - src/init.cpp | 1 - src/qt/paymentrequestplus.cpp | 2 -- src/qt/paymentserver.cpp | 2 -- src/qt/rpcconsole.cpp | 2 -- src/qt/test/paymentservertests.cpp | 3 --- src/util.cpp | 3 --- src/wallet/rpcdump.cpp | 2 -- 8 files changed, 16 deletions(-) diff --git a/src/bip38.cpp b/src/bip38.cpp index 07c856b803448..523641f27cf3f 100644 --- a/src/bip38.cpp +++ b/src/bip38.cpp @@ -11,7 +11,6 @@ #include "random.h" #include -#include #include #include diff --git a/src/init.cpp b/src/init.cpp index 252121a6f6c82..e7a26b6f28dae 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -62,7 +62,6 @@ #include #include #include -#include #if ENABLE_ZMQ #include "zmq/zmqnotificationinterface.h" diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index a41363d672a2f..657a2f20903e5 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -11,8 +11,6 @@ #include -#include - #include #include #include diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 9e05191178cf1..16f24556d45a2 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -19,8 +19,6 @@ #include -#include - #include #include #include diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 8ccd6518163e0..ae0279131a49b 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -21,8 +21,6 @@ #include "wallet/wallet.h" #endif // ENABLE_WALLET -#include - #include #ifdef ENABLE_WALLET diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 1a7123700539c..6d5a703fe37b5 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -11,9 +11,6 @@ #include "util.h" #include "utilstrencodings.h" -#include -#include - #include #include diff --git a/src/util.cpp b/src/util.cpp index df90f4249cabc..58515ca5d86bf 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -23,9 +23,6 @@ #include #include -#include -#include -#include #ifndef WIN32 diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 13bb773613fe9..45f8903d62914 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -22,8 +22,6 @@ #include #include -#include -#include #include From 53c0de3531af1b365371e04b827440d51d500b1a Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 11 Sep 2019 00:55:47 +0200 Subject: [PATCH 007/132] [Consensus] Remove Old message format in CMasternodeBroadcast --- src/masternode.cpp | 36 ++++++++++-------------------------- src/masternode.h | 3 +-- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/masternode.cpp b/src/masternode.cpp index a9262d42e586c..c3880e7a1faef 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -522,8 +522,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos) } std::string errorMessage = ""; - if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetNewStrMessage(), errorMessage) - && !obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetOldStrMessage(), errorMessage)) + if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetStrMessage(), errorMessage)) { // don't ban for old masternodes, their sigs could be broken because of the bug nDos = protocolVersion < MIN_PEER_MNANNOUNCE ? 0 : 100; @@ -664,11 +663,7 @@ bool CMasternodeBroadcast::Sign(CKey& keyCollateralAddress) std::string errorMessage; sigTime = GetAdjustedTime(); - std::string strMessage; - if(chainActive.Height() <= Params().Zerocoin_LastOldParams()) - strMessage = GetOldStrMessage(); - else - strMessage = GetNewStrMessage(); + std::string strMessage = GetStrMessage(); if (!obfuScationSigner.SignMessage(strMessage, errorMessage, sig, keyCollateralAddress)) return error("CMasternodeBroadcast::Sign() - Error: %s", errorMessage); @@ -684,31 +679,20 @@ bool CMasternodeBroadcast::VerifySignature() { std::string errorMessage; - if(!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetNewStrMessage(), errorMessage) - && !obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetOldStrMessage(), errorMessage)) + if(!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetStrMessage(), errorMessage)) return error("CMasternodeBroadcast::VerifySignature() - Error: %s", errorMessage); return true; } -std::string CMasternodeBroadcast::GetOldStrMessage() +std::string CMasternodeBroadcast::GetStrMessage() { - std::string strMessage; - - std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); - std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); - strMessage = addr.ToString() + std::to_string(sigTime) + vchPubKey + vchPubKey2 + std::to_string(protocolVersion); - - return strMessage; -} - -std::string CMasternodeBroadcast::GetNewStrMessage() -{ - std::string strMessage; - - strMessage = addr.ToString() + std::to_string(sigTime) + pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() + std::to_string(protocolVersion); - - return strMessage; + return (addr.ToString() + + std::to_string(sigTime) + + pubKeyCollateralAddress.GetID().ToString() + + pubKeyMasternode.GetID().ToString() + + std::to_string(protocolVersion) + ); } CMasternodePing::CMasternodePing() diff --git a/src/masternode.h b/src/masternode.h index 8831197f93fc1..0906c091a2485 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -300,8 +300,7 @@ class CMasternodeBroadcast : public CMasternode bool Sign(CKey& keyCollateralAddress); bool VerifySignature(); void Relay(); - std::string GetOldStrMessage(); - std::string GetNewStrMessage(); + std::string GetStrMessage(); ADD_SERIALIZE_METHODS; From 93f8dfe368cd66b3769a0b9c736d2e4512c8f261 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 16 Apr 2016 12:25:12 +0200 Subject: [PATCH 008/132] Always require OS randomness when generating secret keys --- src/init.cpp | 1 - src/key.cpp | 2 +- src/main.cpp | 3 +-- src/random.cpp | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index e7a26b6f28dae..7e13bdcd53309 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1677,7 +1677,6 @@ bool AppInit2(const std::vector& words) if (GetArg("-mnemonicpassphrase", "").size() > 256) return InitError(_("Mnemonic passphrase is too long, must be at most 256 characters")); // generate a new master key - InitError(_("test 2"));; pwalletMain->GenerateNewHDChain(words); // ensure this wallet.dat can only be opened by clients supporting HD pwalletMain->SetMinVersion(FEATURE_HD); diff --git a/src/key.cpp b/src/key.cpp index 6aefada0c18fc..21763fa48e2e3 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -158,7 +158,7 @@ bool CKey::Check(const unsigned char* vch) void CKey::MakeNewKey(bool fCompressedIn) { do { - GetRandBytes(keydata.data(), keydata.size()); + GetStrongRandBytes(keydata.data(), keydata.size()); } while (!Check(keydata.data())); fValid = true; fCompressed = fCompressedIn; diff --git a/src/main.cpp b/src/main.cpp index c4521c6e1d96e..96a94b82eff72 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5814,8 +5814,7 @@ void static ProcessGetData(CNode* pfrom) bool fRequestedSporksIDB = false; bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { - if (fDebug) - LogPrintf("received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); + LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) { LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); return true; diff --git a/src/random.cpp b/src/random.cpp index c2d1f5d6c487a..da9b3dad8d0f4 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -133,7 +133,7 @@ void GetStrongRandBytes(unsigned char* out, int num) // Produce output hasher.Finalize(buf); memcpy(out, buf, num); - memory_cleanse((void*)&buf, sizeof(buf)); + memory_cleanse(buf, 64); } uint64_t GetRand(uint64_t nMax) From 3da089f608dc577e7acaa84e6c1ee1cfc585e7a0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 23 Apr 2016 18:07:35 +0200 Subject: [PATCH 009/132] Don't use assert for catching randomness failures --- src/random.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index da9b3dad8d0f4..c3d399362373e 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -14,6 +14,7 @@ #include "util.h" // for LogPrint() #include "utilstrencodings.h" // for GetTime() +#include #include #ifndef WIN32 @@ -23,6 +24,12 @@ #include #include +static void RandFailure() +{ + LogPrintf("Failed to read randomness, aborting\n"); + abort(); +} + static inline int64_t GetPerformanceCounter() { int64_t nCounter = 0; @@ -90,17 +97,25 @@ static void GetOSRand(unsigned char *ent32) #ifdef WIN32 HCRYPTPROV hProvider; int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - assert(ret); + if (!ret) { + RandFailure(); + } ret = CryptGenRandom(hProvider, 32, ent32); - assert(ret); + if (!ret) { + RandFailure(); + } CryptReleaseContext(hProvider, 0); #else int f = open("/dev/urandom", O_RDONLY); - assert(f != -1); + if (f == -1) { + RandFailure(); + } int have = 0; do { ssize_t n = read(f, ent32 + have, 32 - have); - assert(n > 0 && n <= 32 - have); + if (n <= 0 || n + have > 32) { + RandFailure(); + } have += n; } while (have < 32); close(f); @@ -110,8 +125,7 @@ static void GetOSRand(unsigned char *ent32) void GetRandBytes(unsigned char* buf, int num) { if (RAND_bytes(buf, num) != 1) { - LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL)); - assert(false); + RandFailure(); } } From 17a818cc006c4dd6644399338523cd24abc1c51d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 21 Feb 2017 17:36:37 +0100 Subject: [PATCH 010/132] util: Specific GetOSRandom for Linux/FreeBSD/OpenBSD These are available in sandboxes without access to files or devices. Also [they are safer and more straightforward](https://en.wikipedia.org/wiki/Entropy-supplying_system_calls) to use than `/dev/urandom` as reading from a file has quite a few edge cases: - Linux: `getrandom(buf, buflen, 0)`. [getrandom(2)](http://man7.org/linux/man-pages/man2/getrandom.2.html) was introduced in version 3.17 of the Linux kernel. - OpenBSD: `getentropy(buf, buflen)`. The [getentropy(2)](http://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) function appeared in OpenBSD 5.6. - FreeBSD and NetBSD: `sysctl(KERN_ARND)`. Not sure when this was added but it has existed for quite a while. Alternatives: - Linux has sysctl `CTL_KERN` / `KERN_RANDOM` / `RANDOM_UUID` which gives 16 bytes of randomness. This may be available on older kernels, however [sysctl is deprecated on Linux](https://lwn.net/Articles/605392/) and even removed in some distros so we shouldn't use it. Add tests for `GetOSRand()`: - Test that no error happens (otherwise `RandFailure()` which aborts) - Test that all 32 bytes are overwritten (initialize with zeros, try multiple times) Discussion: - When to use these? Currently they are always used when available. Another option would be to use them only when `/dev/urandom` is not available. But this would mean these code paths receive less testing, and I'm not sure there is any reason to prefer `/dev/urandom`. Closes: #9676 --- configure.ac | 26 ++++++++++++++++++ src/random.cpp | 56 ++++++++++++++++++++++++++++++++++----- src/random.h | 8 ++++++ src/test/random_tests.cpp | 46 ++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 src/test/random_tests.cpp diff --git a/configure.ac b/configure.ac index d239eae3b61c0..5a86b163d3fa5 100644 --- a/configure.ac +++ b/configure.ac @@ -801,6 +801,32 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([ ) LDFLAGS="$TEMP_LDFLAGS" +# Check for different ways of gathering OS randomness +AC_MSG_CHECKING(for Linux getrandom syscall) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include + #include ]], + [[ syscall(SYS_getrandom, nullptr, 32, 0); ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYS_GETRANDOM, 1,[Define this symbol if the Linux getrandom system call is available]) ], + [ AC_MSG_RESULT(no)] +) + +AC_MSG_CHECKING(for getentropy) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[ getentropy(nullptr, 32) ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GETENTROPY, 1,[Define this symbol if the BSD getentropy system call is available]) ], + [ AC_MSG_RESULT(no)] +) + +AC_MSG_CHECKING(for sysctl KERN_ARND) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], + [[ static const int name[2] = {CTL_KERN, KERN_ARND}; + sysctl(name, 2, nullptr, nullptr, nullptr, 0); ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCTL_ARND, 1,[Define this symbol if the BSD sysctl(KERN_ARND) is available]) ], + [ AC_MSG_RESULT(no)] +) + # Check for reduced exports if test x$use_reduce_exports = xyes; then AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"], diff --git a/src/random.cpp b/src/random.cpp index c3d399362373e..860ebc5302fdb 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -21,6 +21,17 @@ #include #endif +#ifdef HAVE_SYS_GETRANDOM +#include +#include +#endif +#ifdef HAVE_GETENTROPY +#include +#endif +#ifdef HAVE_SYSCTL_ARND +#include +#endif + #include #include @@ -92,32 +103,65 @@ static void RandAddSeedPerfmon() } /** Get 32 bytes of system entropy. */ -static void GetOSRand(unsigned char *ent32) +void GetOSRand(unsigned char *ent32) { -#ifdef WIN32 +#if defined(WIN32) HCRYPTPROV hProvider; int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!ret) { RandFailure(); } - ret = CryptGenRandom(hProvider, 32, ent32); + ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32); if (!ret) { RandFailure(); } CryptReleaseContext(hProvider, 0); +#elif defined(HAVE_SYS_GETRANDOM) + /* Linux. From the getrandom(2) man page: + * "If the urandom source has been initialized, reads of up to 256 bytes + * will always return as many bytes as requested and will not be + * interrupted by signals." + */ + if (syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) { + RandFailure(); + } +#elif defined(HAVE_GETENTROPY) + /* On OpenBSD this can return up to 256 bytes of entropy, will return an + * error if more are requested. + * The call cannot return less than the requested number of bytes. + */ + if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { + RandFailure(); + } +#elif defined(HAVE_SYSCTL_ARND) + /* FreeBSD and similar. It is possible for the call to return less + * bytes than requested, so need to read in a loop. + */ + static const int name[2] = {CTL_KERN, KERN_ARND}; + int have = 0; + do { + size_t len = NUM_OS_RANDOM_BYTES - have; + if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) { + RandFailure(); + } + have += len; + } while (have < NUM_OS_RANDOM_BYTES); #else + /* Fall back to /dev/urandom if there is no specific method implemented to + * get system entropy for this OS. + */ int f = open("/dev/urandom", O_RDONLY); if (f == -1) { RandFailure(); } int have = 0; do { - ssize_t n = read(f, ent32 + have, 32 - have); - if (n <= 0 || n + have > 32) { + ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); + if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { RandFailure(); } have += n; - } while (have < 32); + } while (have < NUM_OS_RANDOM_BYTES); close(f); #endif } diff --git a/src/random.h b/src/random.h index fdddce2fdd4a1..e479a17f43e75 100644 --- a/src/random.h +++ b/src/random.h @@ -49,4 +49,12 @@ static inline uint32_t insecure_rand(void) return (insecure_rand_Rw << 16) + insecure_rand_Rz; } +/* Number of random bytes returned by GetOSRand */ +static const ssize_t NUM_OS_RANDOM_BYTES = 32; + +/** Get 32 bytes of system entropy. Do not use this in application code: use + * GetStrongRandBytes instead. + */ +void GetOSRand(unsigned char *ent32); + #endif // BITCOIN_RANDOM_H diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp new file mode 100644 index 0000000000000..4f67415c7c583 --- /dev/null +++ b/src/test/random_tests.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "random.h" + +#include "test/test_bitcoin.h" + +#include + +BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup) + +static const ssize_t MAX_TRIES = 1024; + +BOOST_AUTO_TEST_CASE(osrandom_tests) +{ + /* This does not measure the quality of randomness, but it does test that + * OSRandom() overwrites all 32 bytes of the output given a maximum + * number of tries. + */ + uint8_t data[NUM_OS_RANDOM_BYTES]; + bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ + int num_overwritten; + int tries = 0; + /* Loop until all bytes have been overwritten at least once */ + do { + memset(data, 0, NUM_OS_RANDOM_BYTES); + GetOSRand(data); + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + overwritten[x] |= (data[x] != 0); + } + + num_overwritten = 0; + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + if (overwritten[x]) { + num_overwritten += 1; + } + } + + tries += 1; + } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); + BOOST_CHECK(num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ +} + +BOOST_AUTO_TEST_SUITE_END() + From c4a4ebc09f15328b5bf06af3957f6e8f00d8a036 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Feb 2017 07:38:42 +0100 Subject: [PATCH 011/132] squashme: comment that NUM_OS_RANDOM_BYTES should not be changed lightly --- src/random.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/random.h b/src/random.h index e479a17f43e75..70cebdfcd9129 100644 --- a/src/random.h +++ b/src/random.h @@ -49,7 +49,11 @@ static inline uint32_t insecure_rand(void) return (insecure_rand_Rw << 16) + insecure_rand_Rz; } -/* Number of random bytes returned by GetOSRand */ +/* Number of random bytes returned by GetOSRand. + * When changing this constant make sure to change all call sites, and make + * sure that the underlying OS APIs for all platforms support the number. + * (many cap out at 256 bytes). + */ static const ssize_t NUM_OS_RANDOM_BYTES = 32; /** Get 32 bytes of system entropy. Do not use this in application code: use From 8cf6365dacf24e5381a28c25ed9ba9d7106e3591 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Feb 2017 08:02:50 +0100 Subject: [PATCH 012/132] sanity: Move OS random to sanity check function Move the OS random test to a sanity check function that is called every time bitcoind is initialized. Keep `src/test/random_tests.cpp` for the case that later random tests are added, and keep a rudimentary test that just calls the sanity check. --- src/init.cpp | 6 ++++++ src/random.cpp | 31 +++++++++++++++++++++++++++++++ src/random.h | 5 +++++ src/test/random_tests.cpp | 29 +---------------------------- 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 7e13bdcd53309..cdefed9effa97 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -705,9 +705,15 @@ bool InitSanityCheck(void) InitError("Elliptic curve cryptography sanity check failure. Aborting."); return false; } + if (!glibc_sanity_test() || !glibcxx_sanity_test()) return false; + if (!Random_SanityCheck()) { + InitError("OS cryptographic RNG sanity check failure. Aborting."); + return false; + } + return true; } diff --git a/src/random.cpp b/src/random.cpp index 860ebc5302fdb..4e0e4aec0173f 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -240,3 +240,34 @@ void seed_insecure_rand(bool fDeterministic) insecure_rand_Rw = tmp; } } + +bool Random_SanityCheck() +{ + /* This does not measure the quality of randomness, but it does test that + * OSRandom() overwrites all 32 bytes of the output given a maximum + * number of tries. + */ + static const ssize_t MAX_TRIES = 1024; + uint8_t data[NUM_OS_RANDOM_BYTES]; + bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ + int num_overwritten; + int tries = 0; + /* Loop until all bytes have been overwritten at least once, or max number tries reached */ + do { + memset(data, 0, NUM_OS_RANDOM_BYTES); + GetOSRand(data); + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + overwritten[x] |= (data[x] != 0); + } + + num_overwritten = 0; + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + if (overwritten[x]) { + num_overwritten += 1; + } + } + + tries += 1; + } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); + return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ +} diff --git a/src/random.h b/src/random.h index 70cebdfcd9129..0586efd112835 100644 --- a/src/random.h +++ b/src/random.h @@ -61,4 +61,9 @@ static const ssize_t NUM_OS_RANDOM_BYTES = 32; */ void GetOSRand(unsigned char *ent32); +/** Check that OS randomness is available and returning the requested number + * of bytes. + */ +bool Random_SanityCheck(); + #endif // BITCOIN_RANDOM_H diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 4f67415c7c583..d2c46c0daabc3 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -10,36 +10,9 @@ BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup) -static const ssize_t MAX_TRIES = 1024; - BOOST_AUTO_TEST_CASE(osrandom_tests) { - /* This does not measure the quality of randomness, but it does test that - * OSRandom() overwrites all 32 bytes of the output given a maximum - * number of tries. - */ - uint8_t data[NUM_OS_RANDOM_BYTES]; - bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ - int num_overwritten; - int tries = 0; - /* Loop until all bytes have been overwritten at least once */ - do { - memset(data, 0, NUM_OS_RANDOM_BYTES); - GetOSRand(data); - for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { - overwritten[x] |= (data[x] != 0); - } - - num_overwritten = 0; - for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { - if (overwritten[x]) { - num_overwritten += 1; - } - } - - tries += 1; - } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); - BOOST_CHECK(num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ + BOOST_CHECK(Random_SanityCheck()); } BOOST_AUTO_TEST_SUITE_END() From ac8773c140d80fb4cb035829fb74e10ce718af02 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Feb 2017 08:51:26 +0100 Subject: [PATCH 013/132] random: Add fallback if getrandom syscall not available If the code was compiled with newer (>=3.17) kernel headers but executed on a system without the system call, every use of random would crash the program. Add a fallback for that case. --- src/random.cpp | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 4e0e4aec0173f..8f58f9f049f0a 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -102,6 +102,28 @@ static void RandAddSeedPerfmon() #endif } +#ifndef WIN32 +/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most + * compatible way to get cryptographic randomness on UNIX-ish platforms. + */ +void GetDevURandom(unsigned char *ent32) +{ + int f = open("/dev/urandom", O_RDONLY); + if (f == -1) { + RandFailure(); + } + int have = 0; + do { + ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); + if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { + RandFailure(); + } + have += n; + } while (have < NUM_OS_RANDOM_BYTES); + close(f); +} +#endif + /** Get 32 bytes of system entropy. */ void GetOSRand(unsigned char *ent32) { @@ -122,8 +144,17 @@ void GetOSRand(unsigned char *ent32) * will always return as many bytes as requested and will not be * interrupted by signals." */ - if (syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) { - RandFailure(); + int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0); + if (rv != NUM_OS_RANDOM_BYTES) { + if (rv < 0 && errno == ENOSYS) { + /* Fallback for kernel <3.17: the return value will be -1 and errno + * ENOSYS if the syscall is not available, in that case fall back + * to /dev/urandom. + */ + GetDevURandom(ent32); + } else { + RandFailure(); + } } #elif defined(HAVE_GETENTROPY) /* On OpenBSD this can return up to 256 bytes of entropy, will return an @@ -150,19 +181,7 @@ void GetOSRand(unsigned char *ent32) /* Fall back to /dev/urandom if there is no specific method implemented to * get system entropy for this OS. */ - int f = open("/dev/urandom", O_RDONLY); - if (f == -1) { - RandFailure(); - } - int have = 0; - do { - ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); - if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { - RandFailure(); - } - have += n; - } while (have < NUM_OS_RANDOM_BYTES); - close(f); + GetDevURandom(ent32); #endif } From ca89d95663075af17cf8ccbed13d68965eb6d318 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 3 May 2017 03:07:53 -0700 Subject: [PATCH 014/132] Maintain state across GetStrongRandBytes calls --- src/random.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/random.cpp b/src/random.cpp index 8f58f9f049f0a..fdd1308d60f67 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -32,6 +32,8 @@ #include #endif +#include + #include #include @@ -192,6 +194,10 @@ void GetRandBytes(unsigned char* buf, int num) } } +static std::mutex cs_rng_state; +static unsigned char rng_state[32] = {0}; +static uint64_t rng_counter = 0; + void GetStrongRandBytes(unsigned char* out, int num) { assert(num <= 32); @@ -207,8 +213,17 @@ void GetStrongRandBytes(unsigned char* out, int num) GetOSRand(buf); hasher.Write(buf, 32); + // Combine with and update state + { + std::unique_lock lock(cs_rng_state); + hasher.Write(rng_state, sizeof(rng_state)); + hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter)); + ++rng_counter; + hasher.Finalize(buf); + memcpy(rng_state, buf + 32, 32); + } + // Produce output - hasher.Finalize(buf); memcpy(out, buf, num); memory_cleanse(buf, 64); } From acef28690926fcd740a5a741c836a341e2263086 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 13 Oct 2016 16:19:20 +0200 Subject: [PATCH 015/132] Kill insecure_random and associated global state There are only a few uses of `insecure_random` outside the tests. This PR replaces uses of insecure_random (and its accompanying global state) in the core code with an FastRandomContext that is automatically seeded on creation. This is meant to be used for inner loops. The FastRandomContext can be in the outer scope, or the class itself, then rand32() is used inside the loop. Useful e.g. for pushing addresses in CNode or the fee rounding, or randomization for coin selection. As a context is created per purpose, thus it gets rid of cross-thread unprotected shared usage of a single set of globals, this should also get rid of the potential race conditions. - I'd say TxMempool::check is not called enough to warrant using a special fast random context, this is switched to GetRand() (open for discussion...) - The use of `insecure_rand` in ConnectThroughProxy has been replaced by an atomic integer counter. The only goal here is to have a different credentials pair for each connection to go on a different Tor circuit, it does not need to be random nor unpredictable. - To avoid having a FastRandomContext on every CNode, the context is passed into PushAddress as appropriate. There remains an insecure_random for test usage in `test_random.h`. --- src/addrman.cpp | 8 ++++---- src/addrman.h | 3 +++ src/main.cpp | 16 +++++++++------- src/net.cpp | 5 +++-- src/net.h | 4 ++-- src/netbase.cpp | 4 ++-- src/random.cpp | 10 ++++------ src/random.h | 33 +++++++++++++++------------------ src/test/addrman_tests.cpp | 2 +- src/test/coins_tests.cpp | 2 +- src/test/crypto_tests.cpp | 2 +- src/test/pmt_tests.cpp | 2 +- src/test/scheduler_tests.cpp | 4 +--- src/test/sighash_tests.cpp | 2 +- src/test/skiplist_tests.cpp | 2 +- src/test/test_phore.cpp | 2 ++ src/test/test_random.h | 23 +++++++++++++++++++++++ src/test/util_tests.cpp | 2 +- src/txmempool.h | 1 + src/wallet/wallet.cpp | 4 ++-- 20 files changed, 78 insertions(+), 53 deletions(-) create mode 100644 src/test/test_random.h diff --git a/src/addrman.cpp b/src/addrman.cpp index ea8f9aba1b751..e982950d83ec7 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -346,8 +346,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT); int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvTried[nKBucket][nKBucketPos] == -1) { - nKBucket = (nKBucket + insecure_rand()) % ADDRMAN_TRIED_BUCKET_COUNT; - nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + nKBucket = (nKBucket + insecure_rand.rand32()) % ADDRMAN_TRIED_BUCKET_COUNT; + nKBucketPos = (nKBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; } int nId = vvTried[nKBucket][nKBucketPos]; assert(mapInfo.count(nId) == 1); @@ -363,8 +363,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvNew[nUBucket][nUBucketPos] == -1) { - nUBucket = (nUBucket + insecure_rand()) % ADDRMAN_NEW_BUCKET_COUNT; - nUBucketPos = (nUBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + nUBucket = (nUBucket + insecure_rand.rand32()) % ADDRMAN_NEW_BUCKET_COUNT; + nUBucketPos = (nUBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; } int nId = vvNew[nUBucket][nUBucketPos]; assert(mapInfo.count(nId) == 1); diff --git a/src/addrman.h b/src/addrman.h index 947ab6dd900af..8022b969d8e18 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -202,6 +202,9 @@ class CAddrMan //! secret key to randomize bucket select with uint256 nKey; + //! Source of random numbers for randomization in inner loops + FastRandomContext insecure_rand; + //! Find an entry. CAddrInfo* Find(const CNetAddr& addr, int* pnId = NULL); diff --git a/src/main.cpp b/src/main.cpp index 96a94b82eff72..86667fab6d14e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5578,7 +5578,6 @@ bool static AlreadyHave(const CInv& inv) return true; } - void static ProcessGetData(CNode* pfrom) { std::deque::iterator it = pfrom->vRecvGetData.begin(); @@ -5915,13 +5914,14 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR // Advertise our address if (fListen && !IsInitialBlockDownload()) { CAddress addr = GetLocalAddress(&pfrom->addr); + FastRandomContext insecure_rand; if (addr.IsRoutable()) { - LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString()); - pfrom->PushAddress(addr); + LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString()); + pfrom->PushAddress(addr, insecure_rand); } else if (IsPeerAddrLocalGood(pfrom)) { addr.SetIP(pfrom->addrLocal); - LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString()); - pfrom->PushAddress(addr); + LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString()); + pfrom->PushAddress(addr, insecure_rand); } } @@ -6031,8 +6031,9 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR mapMix.insert(std::make_pair(hashKey, pnode)); } int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) + FastRandomContext insecure_rand; for (std::multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) - ((*mi).second)->PushAddress(addr); + ((*mi).second)->PushAddress(addr, insecure_rand); } } // Do not store addresses outside our network @@ -6486,8 +6487,9 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR else if ((strCommand == NetMsgType::GETADDR) && (pfrom->fInbound)) { pfrom->vAddrToSend.clear(); std::vector vAddr = addrman.GetAddr(); + FastRandomContext insecure_rand; for (const CAddress& addr : vAddr) - pfrom->PushAddress(addr); + pfrom->PushAddress(addr, insecure_rand); } diff --git a/src/net.cpp b/src/net.cpp index 3ad5fd55fd57a..c1974fd38e29e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -236,8 +236,9 @@ void AdvertizeLocal(CNode* pnode) addrLocal.SetIP(pnode->addrLocal); } if (addrLocal.IsRoutable()) { - LogPrintf("AdvertizeLocal: advertizing address %s\n", addrLocal.ToString()); - pnode->PushAddress(addrLocal); + LogPrintf("AdvertizeLocal: advertising address %s\n", addrLocal.ToString()); + FastRandomContext insecure_rand; + pnode->PushAddress(addrLocal, insecure_rand); } } } diff --git a/src/net.h b/src/net.h index 1190ea9fa3fef..af3e6f9a4e60c 100644 --- a/src/net.h +++ b/src/net.h @@ -442,14 +442,14 @@ class CNode setAddrKnown.insert(addr); } - void PushAddress(const CAddress& addr) + void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand) { // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. if (addr.IsValid() && !setAddrKnown.count(addr)) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { - vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr; + vAddrToSend[insecure_rand.rand32() % vAddrToSend.size()] = _addr; } else { vAddrToSend.push_back(addr); } diff --git a/src/netbase.cpp b/src/netbase.cpp index c1ef243a666bb..443d7bb8f51b0 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -537,8 +537,8 @@ static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDe // do socks negotiation if (proxy.randomize_credentials) { ProxyCredentials random_auth; - random_auth.username = strprintf("%i", insecure_rand()); - random_auth.password = strprintf("%i", insecure_rand()); + static std::atomic_int counter; + random_auth.username = random_auth.password = strprintf("%i", counter++); if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) return false; } else { diff --git a/src/random.cpp b/src/random.cpp index fdd1308d60f67..ff667bf49d134 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -255,23 +255,21 @@ uint256 GetRandHash() return hash; } -uint32_t insecure_rand_Rz = 11; -uint32_t insecure_rand_Rw = 11; -void seed_insecure_rand(bool fDeterministic) +FastRandomContext::FastRandomContext(bool fDeterministic) { // The seed values have some unlikely fixed points which we avoid. if (fDeterministic) { - insecure_rand_Rz = insecure_rand_Rw = 11; + Rz = Rw = 11; } else { uint32_t tmp; do { GetRandBytes((unsigned char*)&tmp, 4); } while (tmp == 0 || tmp == 0x9068ffffU); - insecure_rand_Rz = tmp; + Rz = tmp; do { GetRandBytes((unsigned char*)&tmp, 4); } while (tmp == 0 || tmp == 0x464fffffU); - insecure_rand_Rw = tmp; + Rw = tmp; } } diff --git a/src/random.h b/src/random.h index 0586efd112835..75417d1d0466c 100644 --- a/src/random.h +++ b/src/random.h @@ -28,26 +28,23 @@ uint256 GetRandHash(); void GetStrongRandBytes(unsigned char* buf, int num); /** - * Seed insecure_rand using the random pool. - * @param Deterministic Use a deterministic seed + * Fast randomness source. This is seeded once with secure random data, but + * is completely deterministic and insecure after that. + * This class is not thread-safe. */ -void seed_insecure_rand(bool fDeterministic = false); +class FastRandomContext { +public: + explicit FastRandomContext(bool fDeterministic=false); -/** - * MWC RNG of George Marsaglia - * This is intended to be fast. It has a period of 2^59.3, though the - * least significant 16 bits only have a period of about 2^30.1. - * - * @return random value - */ -extern uint32_t insecure_rand_Rz; -extern uint32_t insecure_rand_Rw; -static inline uint32_t insecure_rand(void) -{ - insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16); - insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16); - return (insecure_rand_Rw << 16) + insecure_rand_Rz; -} + uint32_t rand32() { + Rz = 36969 * (Rz & 65535) + (Rz >> 16); + Rw = 18000 * (Rw & 65535) + (Rw >> 16); + return (Rw << 16) + Rz; + } + + uint32_t Rz; + uint32_t Rw; +}; /* Number of random bytes returned by GetOSRand. * When changing this constant make sure to change all call sites, and make diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index f2aaa78a5bd44..72477d57555cb 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -24,7 +24,7 @@ class CAddrManTest : public CAddrMan void MakeDeterministic() { nKey.SetNull(); - seed_insecure_rand(true); + insecure_rand = FastRandomContext(true); } int RandomInt(int nMax) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index e78c80c436a8a..d31c47fb88b9e 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "coins.h" -#include "random.h" +#include "test_random.h" #include "uint256.h" #include "test/test_phore.h" diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 9f49ee89db31e..7110e3db40428 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -9,7 +9,7 @@ #include "crypto/sha512.h" #include "crypto/hmac_sha256.h" #include "crypto/hmac_sha512.h" -#include "random.h" +#include "test_random.h" #include "utilstrencodings.h" #include "test/test_phore.h" diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 8598af620fde8..55056963c93ad 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -7,8 +7,8 @@ #include "streams.h" #include "uint256.h" #include "version.h" -#include "random.h" #include "test/test_phore.h" +#include "test_random.h" #include diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index 242108e355228..68f6c86d2caa0 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -45,8 +45,6 @@ static void MicroSleep(uint64_t n) BOOST_AUTO_TEST_CASE(manythreads) { - seed_insecure_rand(false); - // Stress test: hundreds of microsecond-scheduled tasks, // serviced by 10 threads. // @@ -61,7 +59,7 @@ BOOST_AUTO_TEST_CASE(manythreads) boost::mutex counterMutex[10]; int counter[10] = { 0 }; - boost::random::mt19937 rng(insecure_rand()); + boost::random::mt19937 rng(42); boost::random::uniform_int_distribution<> zeroToNine(0, 9); boost::random::uniform_int_distribution<> randomMsec(-11, 1000); boost::random::uniform_int_distribution<> randomDelta(-1000, 1000); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 2834dd3c9f50f..b83b2ff5b1993 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -5,7 +5,7 @@ #include "consensus/validation.h" #include "data/sighash.json.h" #include "main.h" -#include "random.h" +#include "test_random.h" #include "serialize.h" #include "script/script.h" #include "script/interpreter.h" diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index a6a5ced4a745d..571d208b07f3d 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "main.h" -#include "random.h" +#include "test_random.h" #include "util.h" #include "test/test_phore.h" diff --git a/src/test/test_phore.cpp b/src/test/test_phore.cpp index 209c8efadd186..a213a10a08fcf 100644 --- a/src/test/test_phore.cpp +++ b/src/test/test_phore.cpp @@ -21,6 +21,8 @@ CClientUIInterface uiInterface; CWallet* pwalletMain; +FastRandomContext insecure_rand_ctx(true); + extern bool fPrintToConsole; extern void noui_connect(); diff --git a/src/test/test_random.h b/src/test/test_random.h new file mode 100644 index 0000000000000..e61b92b7bce94 --- /dev/null +++ b/src/test/test_random.h @@ -0,0 +1,23 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-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. + +#ifndef BITCOIN_TEST_RANDOM_H +#define BITCOIN_TEST_RANDOM_H + +#include "random.h" + +extern FastRandomContext insecure_rand_ctx; + +static inline void seed_insecure_rand(bool fDeterministic = false) +{ + insecure_rand_ctx = FastRandomContext(fDeterministic); +} + +static inline uint32_t insecure_rand(void) +{ + return insecure_rand_ctx.rand32(); +} + +#endif diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 4354a31d48c70..796d1bca2da36 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -6,7 +6,7 @@ #include "clientversion.h" #include "primitives/transaction.h" -#include "random.h" +#include "test_random.h" #include "sync.h" #include "utilstrencodings.h" #include "utilmoneystr.h" diff --git a/src/txmempool.h b/src/txmempool.h index 6bc377770e179..5a831144830a2 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -14,6 +14,7 @@ #include "coins.h" #include "primitives/transaction.h" #include "sync.h" +#include "random.h" class CAutoFile; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7cfc8bf7eaeb1..311d9b7637398 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1991,7 +1991,7 @@ static void ApproximateBestSubset(std::vector= nTargetValue) { From 7bbc2ee3d745afe261b856fafbc5da77fb9af937 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 15 Feb 2017 12:29:23 -0800 Subject: [PATCH 016/132] Add ChaCha20 --- src/Makefile.am | 2 + src/crypto/chacha20.cpp | 180 ++++++++++++++++++++++++++++++++++++++ src/crypto/chacha20.h | 26 ++++++ src/test/crypto_tests.cpp | 45 ++++++++++ 4 files changed, 253 insertions(+) create mode 100644 src/crypto/chacha20.cpp create mode 100644 src/crypto/chacha20.h diff --git a/src/Makefile.am b/src/Makefile.am index ab8a83c8dc128..435e18e115271 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -284,6 +284,8 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.cpp \ crypto/sha256.cpp \ crypto/sha512.cpp \ + crypto/chacha20.h \ + crypto/chacha20.cpp \ crypto/hmac_sha256.cpp \ crypto/pkcs5_pbkdf2.h \ crypto/pkcs5_pbkdf2.cpp \ diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp new file mode 100644 index 0000000000000..816ae870e138a --- /dev/null +++ b/src/crypto/chacha20.cpp @@ -0,0 +1,180 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// Based on the public domain implementation 'merged' by D. J. Bernstein +// See https://cr.yp.to/chacha.html. + +#include "crypto/common.h" +#include "crypto/chacha20.h" + +#include + +constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (v >> (32 - c)); } + +#define QUARTERROUND(a,b,c,d) \ + a += b; d = rotl32(d ^ a, 16); \ + c += d; b = rotl32(b ^ c, 12); \ + a += b; d = rotl32(d ^ a, 8); \ + c += d; b = rotl32(b ^ c, 7); + +static const unsigned char sigma[] = "expand 32-byte k"; +static const unsigned char tau[] = "expand 16-byte k"; + +void ChaCha20::SetKey(const unsigned char* k, size_t keylen) +{ + const unsigned char *constants; + + input[4] = ReadLE32(k + 0); + input[5] = ReadLE32(k + 4); + input[6] = ReadLE32(k + 8); + input[7] = ReadLE32(k + 12); + if (keylen == 32) { /* recommended */ + k += 16; + constants = sigma; + } else { /* keylen == 16 */ + constants = tau; + } + input[8] = ReadLE32(k + 0); + input[9] = ReadLE32(k + 4); + input[10] = ReadLE32(k + 8); + input[11] = ReadLE32(k + 12); + input[0] = ReadLE32(constants + 0); + input[1] = ReadLE32(constants + 4); + input[2] = ReadLE32(constants + 8); + input[3] = ReadLE32(constants + 12); + input[12] = 0; + input[13] = 0; + input[14] = 0; + input[15] = 0; +} + +ChaCha20::ChaCha20() +{ + memset(input, 0, sizeof(input)); +} + +ChaCha20::ChaCha20(const unsigned char* k, size_t keylen) +{ + SetKey(k, keylen); +} + +void ChaCha20::SetIV(uint64_t iv) +{ + input[14] = iv; + input[15] = iv >> 32; +} + +void ChaCha20::Seek(uint64_t pos) +{ + input[12] = pos; + input[13] = pos >> 32; +} + +void ChaCha20::Output(unsigned char* c, size_t bytes) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + unsigned char *ctarget = NULL; + unsigned char tmp[64]; + unsigned int i; + + if (!bytes) return; + + j0 = input[0]; + j1 = input[1]; + j2 = input[2]; + j3 = input[3]; + j4 = input[4]; + j5 = input[5]; + j6 = input[6]; + j7 = input[7]; + j8 = input[8]; + j9 = input[9]; + j10 = input[10]; + j11 = input[11]; + j12 = input[12]; + j13 = input[13]; + j14 = input[14]; + j15 = input[15]; + + for (;;) { + if (bytes < 64) { + ctarget = c; + c = tmp; + } + x0 = j0; + x1 = j1; + x2 = j2; + x3 = j3; + x4 = j4; + x5 = j5; + x6 = j6; + x7 = j7; + x8 = j8; + x9 = j9; + x10 = j10; + x11 = j11; + x12 = j12; + x13 = j13; + x14 = j14; + x15 = j15; + for (i = 20;i > 0;i -= 2) { + QUARTERROUND( x0, x4, x8,x12) + QUARTERROUND( x1, x5, x9,x13) + QUARTERROUND( x2, x6,x10,x14) + QUARTERROUND( x3, x7,x11,x15) + QUARTERROUND( x0, x5,x10,x15) + QUARTERROUND( x1, x6,x11,x12) + QUARTERROUND( x2, x7, x8,x13) + QUARTERROUND( x3, x4, x9,x14) + } + x0 += j0; + x1 += j1; + x2 += j2; + x3 += j3; + x4 += j4; + x5 += j5; + x6 += j6; + x7 += j7; + x8 += j8; + x9 += j9; + x10 += j10; + x11 += j11; + x12 += j12; + x13 += j13; + x14 += j14; + x15 += j15; + + ++j12; + if (!j12) ++j13; + + WriteLE32(c + 0, x0); + WriteLE32(c + 4, x1); + WriteLE32(c + 8, x2); + WriteLE32(c + 12, x3); + WriteLE32(c + 16, x4); + WriteLE32(c + 20, x5); + WriteLE32(c + 24, x6); + WriteLE32(c + 28, x7); + WriteLE32(c + 32, x8); + WriteLE32(c + 36, x9); + WriteLE32(c + 40, x10); + WriteLE32(c + 44, x11); + WriteLE32(c + 48, x12); + WriteLE32(c + 52, x13); + WriteLE32(c + 56, x14); + WriteLE32(c + 60, x15); + + if (bytes <= 64) { + if (bytes < 64) { + for (i = 0;i < bytes;++i) ctarget[i] = c[i]; + } + input[12] = j12; + input[13] = j13; + return; + } + bytes -= 64; + c += 64; + } +} diff --git a/src/crypto/chacha20.h b/src/crypto/chacha20.h new file mode 100644 index 0000000000000..a305977bcd5f4 --- /dev/null +++ b/src/crypto/chacha20.h @@ -0,0 +1,26 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CRYPTO_CHACHA20_H +#define BITCOIN_CRYPTO_CHACHA20_H + +#include +#include + +/** A PRNG class for ChaCha20. */ +class ChaCha20 +{ +private: + uint32_t input[16]; + +public: + ChaCha20(); + ChaCha20(const unsigned char* key, size_t keylen); + void SetKey(const unsigned char* key, size_t keylen); + void SetIV(uint64_t iv); + void Seek(uint64_t pos); + void Output(unsigned char* output, size_t bytes); +}; + +#endif // BITCOIN_CRYPTO_CHACHA20_H diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 7110e3db40428..4dd93e9785898 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/rfc6979_hmac_sha256.h" +#include "crypto/chacha20.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" @@ -65,6 +66,19 @@ void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const s TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout)); } +void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout) +{ + std::vector key = ParseHex(hexkey); + ChaCha20 rng(key.data(), key.size()); + rng.SetIV(nonce); + rng.Seek(seek); + std::vector out = ParseHex(hexout); + std::vector outres; + outres.resize(out.size()); + rng.Output(outres.data(), outres.size()); + BOOST_CHECK(out == outres); +} + std::string LongTestString(void) { std::string ret; for (int i=0; i<200000; i++) { @@ -307,4 +321,35 @@ BOOST_AUTO_TEST_CASE(rfc6979_hmac_sha256) ("7597887cbd76321f32e30440679a22cf7f8d9d2eac390e581fea091ce202ba94")); } + +BOOST_AUTO_TEST_CASE(chacha20_testvector) +{ + // Test vector from RFC 7539 + TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1, + "224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cb" + "a40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a" + "832c89c167eacd901d7e2bf363"); + + // Test vectors from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0, 0, + "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b" + "8f41518a11cc387b669b2ee6586"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000001", 0, 0, + "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d79" + "2b1c43fea817e9ad275ae546963"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0, + "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b52770" + "62eb7a0433e445f41e3"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 1, 0, + "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc4" + "97a0b466e7d6bbdb0041b2f586b"); + TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0, + "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3b" + "e59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc1" + "18be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5" + "a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5" + "360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78" + "fab78c9"); +} + BOOST_AUTO_TEST_SUITE_END() From 027dc205598c8dc2f094119a26d5eb9acb755ad4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 15 Feb 2017 17:45:22 -0800 Subject: [PATCH 017/132] Switch FastRandomContext to ChaCha20 --- src/Makefile.test.include | 5 +++ src/addrman.cpp | 8 ++--- src/addrman.h | 11 +++++-- src/random.cpp | 33 ++++++++++--------- src/random.h | 66 ++++++++++++++++++++++++++++++++++---- src/test/addrman_tests.cpp | 9 +++--- src/test/random_tests.cpp | 21 +++++++++++- src/test/test_phore.cpp | 3 +- src/test/test_random.h | 8 ++++- 9 files changed, 128 insertions(+), 36 deletions(-) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 677f010cfb0c2..e9ef137159ce3 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -56,6 +56,11 @@ BITCOIN_TESTS =\ test/multisig_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ + test/policyestimator_tests.cpp \ + test/pow_tests.cpp \ + test/prevector_tests.cpp \ + test/raii_event_tests.cpp \ + test/random_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ test/sanity_tests.cpp \ diff --git a/src/addrman.cpp b/src/addrman.cpp index e982950d83ec7..699ba4e19a20f 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -346,8 +346,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT); int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvTried[nKBucket][nKBucketPos] == -1) { - nKBucket = (nKBucket + insecure_rand.rand32()) % ADDRMAN_TRIED_BUCKET_COUNT; - nKBucketPos = (nKBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; + nKBucket = (nKBucket + insecure_rand.randbits(ADDRMAN_TRIED_BUCKET_COUNT_LOG2)) % ADDRMAN_TRIED_BUCKET_COUNT; + nKBucketPos = (nKBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE; } int nId = vvTried[nKBucket][nKBucketPos]; assert(mapInfo.count(nId) == 1); @@ -363,8 +363,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvNew[nUBucket][nUBucketPos] == -1) { - nUBucket = (nUBucket + insecure_rand.rand32()) % ADDRMAN_NEW_BUCKET_COUNT; - nUBucketPos = (nUBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; + nUBucket = (nUBucket + insecure_rand.randbits(ADDRMAN_NEW_BUCKET_COUNT_LOG2)) % ADDRMAN_NEW_BUCKET_COUNT; + nUBucketPos = (nUBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE; } int nId = vvNew[nUBucket][nUBucketPos]; assert(mapInfo.count(nId) == 1); diff --git a/src/addrman.h b/src/addrman.h index 8022b969d8e18..442cb1d161697 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -130,13 +130,13 @@ class CAddrInfo : public CAddress */ //! total number of buckets for tried addresses -#define ADDRMAN_TRIED_BUCKET_COUNT 256 +#define ADDRMAN_TRIED_BUCKET_COUNT_LOG2 8 //! total number of buckets for new addresses -#define ADDRMAN_NEW_BUCKET_COUNT 1024 +#define ADDRMAN_NEW_BUCKET_COUNT_LOG2 10 //! maximum allowed number of entries in buckets for new and tried addresses -#define ADDRMAN_BUCKET_SIZE 64 +#define ADDRMAN_BUCKET_SIZE_LOG2 6 //! over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8 @@ -165,6 +165,11 @@ class CAddrInfo : public CAddress //! the maximum number of nodes to return in a getaddr call #define ADDRMAN_GETADDR_MAX 2500 +//! Convenience +#define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2) +#define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2) +#define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2) + /** * Stochastical (IP) address manager */ diff --git a/src/random.cpp b/src/random.cpp index ff667bf49d134..dfd51b07796b5 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -255,22 +255,16 @@ uint256 GetRandHash() return hash; } -FastRandomContext::FastRandomContext(bool fDeterministic) +void FastRandomContext::RandomSeed() { - // The seed values have some unlikely fixed points which we avoid. - if (fDeterministic) { - Rz = Rw = 11; - } else { - uint32_t tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while (tmp == 0 || tmp == 0x9068ffffU); - Rz = tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while (tmp == 0 || tmp == 0x464fffffU); - Rw = tmp; - } + uint256 seed = GetRandHash(); + rng.SetKey(seed.begin(), 32); + requires_seed = false; +} + +FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0) +{ + rng.SetKey(seed.begin(), 32); } bool Random_SanityCheck() @@ -303,3 +297,12 @@ bool Random_SanityCheck() } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ } + +FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) +{ + if (!fDeterministic) { + return; + } + uint256 seed; + rng.SetKey(seed.begin(), 32); +} diff --git a/src/random.h b/src/random.h index 75417d1d0466c..b2d0374750300 100644 --- a/src/random.h +++ b/src/random.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_RANDOM_H #define BITCOIN_RANDOM_H +#include "crypto/chacha20.h" #include "uint256.h" #include @@ -33,17 +34,68 @@ void GetStrongRandBytes(unsigned char* buf, int num); * This class is not thread-safe. */ class FastRandomContext { +private: + bool requires_seed; + ChaCha20 rng; + + unsigned char bytebuf[64]; + int bytebuf_size; + + uint64_t bitbuf; + int bitbuf_size; + + void RandomSeed(); + + void FillByteBuffer() + { + if (requires_seed) { + RandomSeed(); + } + rng.Output(bytebuf, sizeof(bytebuf)); + bytebuf_size = sizeof(bytebuf); + } + + void FillBitBuffer() + { + bitbuf = rand64(); + bitbuf_size = 64; + } + public: - explicit FastRandomContext(bool fDeterministic=false); + explicit FastRandomContext(bool fDeterministic = false); + + /** Initialize with explicit seed (only for testing) */ + explicit FastRandomContext(const uint256& seed); - uint32_t rand32() { - Rz = 36969 * (Rz & 65535) + (Rz >> 16); - Rw = 18000 * (Rw & 65535) + (Rw >> 16); - return (Rw << 16) + Rz; + /** Generate a random 64-bit integer. */ + uint64_t rand64() + { + if (bytebuf_size < 8) FillByteBuffer(); + uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size); + bytebuf_size -= 8; + return ret; } - uint32_t Rz; - uint32_t Rw; + /** Generate a random (bits)-bit integer. */ + uint64_t randbits(int bits) { + if (bits == 0) { + return 0; + } else if (bits > 32) { + return rand64() >> (64 - bits); + } else { + if (bitbuf_size < bits) FillBitBuffer(); + uint64_t ret = bitbuf & (~(uint64_t)0 >> (64 - bits)); + bitbuf >>= bits; + bitbuf_size -= bits; + return ret; + } + } + + /** Generate a random 32-bit integer. */ + uint32_t rand32() { return randbits(32); } + + /** Generate a random boolean. */ + bool randbool() { return randbits(1); } }; /* Number of random bytes returned by GetOSRand. diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 72477d57555cb..77405ffee0e0b 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -179,10 +179,11 @@ BOOST_AUTO_TEST_CASE(addrman_select) BOOST_CHECK(addrman.size() == 7); // Test 12: Select pulls from new and tried regardless of port number. - BOOST_CHECK(addrman.Select().ToString() == "250.4.6.6:8333"); - BOOST_CHECK(addrman.Select().ToString() == "250.3.2.2:9999"); - BOOST_CHECK(addrman.Select().ToString() == "250.3.3.3:9999"); - BOOST_CHECK(addrman.Select().ToString() == "250.4.4.4:8333"); + std::set ports; + for (int i = 0; i < 20; ++i) { + ports.insert(addrman.Select().GetPort()); + } + BOOST_CHECK_EQUAL(ports.size(), 3); } BOOST_AUTO_TEST_CASE(addrman_new_collisions) diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index d2c46c0daabc3..31b993cd382d4 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -15,5 +15,24 @@ BOOST_AUTO_TEST_CASE(osrandom_tests) BOOST_CHECK(Random_SanityCheck()); } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_CASE(fastrandom_tests) +{ + // Check that deterministic FastRandomContexts are deterministic + FastRandomContext ctx1(true); + FastRandomContext ctx2(true); + + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); + BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + // Check that a nondeterministic ones are not + FastRandomContext ctx3; + FastRandomContext ctx4; + BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/test_phore.cpp b/src/test/test_phore.cpp index a213a10a08fcf..42cbffe333011 100644 --- a/src/test/test_phore.cpp +++ b/src/test/test_phore.cpp @@ -21,7 +21,8 @@ CClientUIInterface uiInterface; CWallet* pwalletMain; -FastRandomContext insecure_rand_ctx(true); +uint256 insecure_rand_seed = GetRandHash(); +FastRandomContext insecure_rand_ctx(insecure_rand_seed); extern bool fPrintToConsole; extern void noui_connect(); diff --git a/src/test/test_random.h b/src/test/test_random.h index e61b92b7bce94..d1fae70458c7d 100644 --- a/src/test/test_random.h +++ b/src/test/test_random.h @@ -8,11 +8,17 @@ #include "random.h" +extern uint256 insecure_rand_seed; extern FastRandomContext insecure_rand_ctx; static inline void seed_insecure_rand(bool fDeterministic = false) { - insecure_rand_ctx = FastRandomContext(fDeterministic); + if (fDeterministic) { + insecure_rand_seed = uint256(); + } else { + insecure_rand_seed = GetRandHash(); + } + insecure_rand_ctx = FastRandomContext(insecure_rand_seed); } static inline uint32_t insecure_rand(void) From 07ac7dbb98d94925161f87c81e6f6921ad1e32a1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 17 Feb 2017 16:32:16 -0800 Subject: [PATCH 018/132] Introduce FastRandomContext::randbool() --- src/random.h | 22 ++++------------------ src/wallet/wallet.cpp | 2 +- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/random.h b/src/random.h index b2d0374750300..c682143c18c3f 100644 --- a/src/random.h +++ b/src/random.h @@ -76,26 +76,12 @@ class FastRandomContext { return ret; } - /** Generate a random (bits)-bit integer. */ - uint64_t randbits(int bits) { - if (bits == 0) { - return 0; - } else if (bits > 32) { - return rand64() >> (64 - bits); - } else { - if (bitbuf_size < bits) FillBitBuffer(); - uint64_t ret = bitbuf & (~(uint64_t)0 >> (64 - bits)); - bitbuf >>= bits; - bitbuf_size -= bits; - return ret; - } + bool randbool() { + return rand32() & 1; } - /** Generate a random 32-bit integer. */ - uint32_t rand32() { return randbits(32); } - - /** Generate a random boolean. */ - bool randbool() { return randbits(1); } + uint32_t Rz; + uint32_t Rw; }; /* Number of random bytes returned by GetOSRand. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 311d9b7637398..f3742cdd9417f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2005,7 +2005,7 @@ static void ApproximateBestSubset(std::vector= nTargetValue) { From b769766b7c9cc13aafd112a09e8341c8e8c7c637 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 25 Feb 2017 12:16:58 -0800 Subject: [PATCH 019/132] Add a FastRandomContext::randrange and use it --- configure.ac | 16 ++++++++++++++++ src/Makefile.test.include | 4 ---- src/crypto/common.h | 21 +++++++++++++++++++++ src/net.h | 2 +- src/random.h | 19 +++++++++++++++++-- src/test/crypto_tests.cpp | 23 +++++++++++++++++++++++ src/test/random_tests.cpp | 17 ++++++++++++++++- 7 files changed, 94 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 5a86b163d3fa5..121427c2e5a2e 100644 --- a/configure.ac +++ b/configure.ac @@ -746,6 +746,22 @@ AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64],,, AC_CHECK_DECLS([__builtin_clz, __builtin_clzl, __builtin_clzll]) +dnl Check for MSG_NOSIGNAL +AC_MSG_CHECKING(for MSG_NOSIGNAL) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[ int f = MSG_NOSIGNAL; ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MSG_NOSIGNAL, 1,[Define this symbol if you have MSG_NOSIGNAL]) ], + [ AC_MSG_RESULT(no)] +) + +dnl Check for MSG_DONTWAIT +AC_MSG_CHECKING(for MSG_DONTWAIT) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[ int f = MSG_DONTWAIT; ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MSG_DONTWAIT, 1,[Define this symbol if you have MSG_DONTWAIT]) ], + [ AC_MSG_RESULT(no)] +) + dnl Check for malloc_info (for memory statistics information in getmemoryinfo) AC_MSG_CHECKING(for getmemoryinfo) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], diff --git a/src/Makefile.test.include b/src/Makefile.test.include index e9ef137159ce3..c506a5d9ee6bd 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -56,10 +56,6 @@ BITCOIN_TESTS =\ test/multisig_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ - test/policyestimator_tests.cpp \ - test/pow_tests.cpp \ - test/prevector_tests.cpp \ - test/raii_event_tests.cpp \ test/random_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ diff --git a/src/crypto/common.h b/src/crypto/common.h index 8d5452d15129f..f585f2fea3421 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -113,4 +113,25 @@ void static inline WriteBE64(unsigned char* ptr, uint64_t x) #endif } +/** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */ +uint64_t static inline CountBits(uint64_t x) +{ +#ifdef HAVE_DECL___BUILTIN_CLZL + if (sizeof(unsigned long) >= sizeof(uint64_t)) { + return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; + } +#endif +#ifdef HAVE_DECL___BUILTIN_CLZLL + if (sizeof(unsigned long long) >= sizeof(uint64_t)) { + return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; + } +#endif + int ret = 0; + while (x) { + x >>= 1; + ++ret; + } + return ret; +} + #endif // BITCOIN_CRYPTO_COMMON_H diff --git a/src/net.h b/src/net.h index af3e6f9a4e60c..75d57560e65e6 100644 --- a/src/net.h +++ b/src/net.h @@ -449,7 +449,7 @@ class CNode // after addresses were pushed. if (addr.IsValid() && !setAddrKnown.count(addr)) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { - vAddrToSend[insecure_rand.rand32() % vAddrToSend.size()] = _addr; + vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr; } else { vAddrToSend.push_back(addr); } diff --git a/src/random.h b/src/random.h index c682143c18c3f..e520b9c7c2827 100644 --- a/src/random.h +++ b/src/random.h @@ -7,6 +7,7 @@ #define BITCOIN_RANDOM_H #include "crypto/chacha20.h" +#include "crypto/common.h" #include "uint256.h" #include @@ -80,8 +81,22 @@ class FastRandomContext { return rand32() & 1; } - uint32_t Rz; - uint32_t Rw; + /** Generate a random integer in the range [0..range). */ + uint64_t randrange(uint64_t range) + { + --range; + int bits = CountBits(range); + while (true) { + uint64_t ret = randbits(bits); + if (ret <= range) return ret; + } + } + + /** Generate a random 32-bit integer. */ + uint32_t rand32() { return randbits(32); } + + /** Generate a random boolean. */ + bool randbool() { return randbits(1); } }; /* Number of random bytes returned by GetOSRand. diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 4dd93e9785898..4b5107cb36779 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -11,6 +11,7 @@ #include "crypto/hmac_sha256.h" #include "crypto/hmac_sha512.h" #include "test_random.h" +#include "random.h" #include "utilstrencodings.h" #include "test/test_phore.h" @@ -352,4 +353,26 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector) "fab78c9"); } +BOOST_AUTO_TEST_CASE(countbits_tests) +{ + FastRandomContext ctx; + for (int i = 0; i <= 64; ++i) { + if (i == 0) { + // Check handling of zero. + BOOST_CHECK_EQUAL(CountBits(0), 0); + } else if (i < 10) { + for (uint64_t j = 1 << (i - 1); (j >> i) == 0; ++j) { + // Exhaustively test up to 10 bits + BOOST_CHECK_EQUAL(CountBits(j), i); + } + } else { + for (int k = 0; k < 1000; k++) { + // Randomly test 1000 samples of each length above 10 bits. + uint64_t j = ((uint64_t)1) << (i - 1) | ctx.randbits(i - 1); + BOOST_CHECK_EQUAL(CountBits(j), i); + } + } + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 31b993cd382d4..27b5f5c5685dd 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -4,7 +4,7 @@ #include "random.h" -#include "test/test_bitcoin.h" +#include "test/test_pivx.h" #include @@ -35,4 +35,19 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal } +BOOST_AUTO_TEST_CASE(fastrandom_randbits) +{ + FastRandomContext ctx1; + FastRandomContext ctx2; + for (int bits = 0; bits < 63; ++bits) { + for (int j = 0; j < 1000; ++j) { + uint64_t rangebits = ctx1.randbits(bits); + BOOST_CHECK_EQUAL(rangebits >> bits, 0); + uint64_t range = ((uint64_t)1) << bits | rangebits; + uint64_t rand = ctx2.randrange(range); + BOOST_CHECK(rand < range); + } + } +} + BOOST_AUTO_TEST_SUITE_END() From 9ae9d618626feb29b20cf8607611c0d730e439e4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 2 May 2017 18:21:33 -0700 Subject: [PATCH 020/132] Use hardware timestamps in RNG seeding --- src/random.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index dfd51b07796b5..be15415c59e96 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -16,6 +16,7 @@ #include #include +#include #ifndef WIN32 #include @@ -45,15 +46,22 @@ static void RandFailure() static inline int64_t GetPerformanceCounter() { - int64_t nCounter = 0; -#ifdef WIN32 - QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); + // Read the hardware time stamp counter when available. + // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information. +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + return __rdtsc(); +#elif !defined(_MSC_VER) && defined(__i386__) + uint64_t r = 0; + __asm__ volatile ("rdtsc" : "=A"(r)); // Constrain the r variable to the eax:edx pair. + return r; +#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__)) + uint64_t r1 = 0, r2 = 0; + __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx. + return (r2 << 32) | r1; #else - timeval t; - gettimeofday(&t, NULL); - nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec); + // Fall back to using C++11 clock (usually microsecond or nanosecond precision) + return std::chrono::high_resolution_clock::now().time_since_epoch().count(); #endif - return nCounter; } void RandAddSeed() From 961f49bc837dbb5db7138e70c9ee3322e9f2dad5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 5 May 2017 11:32:06 -0700 Subject: [PATCH 021/132] Test that GetPerformanceCounter() increments --- src/random.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/random.cpp b/src/random.cpp index be15415c59e96..4ff421215ae80 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef WIN32 #include @@ -277,6 +278,8 @@ FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false) bool Random_SanityCheck() { + uint64_t start = GetPerformanceCounter(); + /* This does not measure the quality of randomness, but it does test that * OSRandom() overwrites all 32 bytes of the output given a maximum * number of tries. @@ -303,7 +306,14 @@ bool Random_SanityCheck() tries += 1; } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); - return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ + if (num_overwritten != NUM_OS_RANDOM_BYTES) return false; /* If this failed, bailed out after too many tries */ + + // Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep. + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + uint64_t stop = GetPerformanceCounter(); + if (stop == start) return false; + + return true; } FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) From 74372d1f6fa5f617617565ba3fd6fead6837759d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 5 May 2017 11:45:37 -0700 Subject: [PATCH 022/132] Use sanity check timestamps as entropy --- src/random.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/random.cpp b/src/random.cpp index 4ff421215ae80..d0c0ef152b7b7 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -313,6 +313,10 @@ bool Random_SanityCheck() uint64_t stop = GetPerformanceCounter(); if (stop == start) return false; + // We called GetPerformanceCounter. Use it as entropy. + RAND_add((const unsigned char*)&start, sizeof(start), 1); + RAND_add((const unsigned char*)&stop, sizeof(stop), 1); + return true; } From 2447d226e40bebe359ec773d404f75d7ec728c49 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 22 May 2017 16:01:29 -0400 Subject: [PATCH 023/132] Add internal method to add new random data to our internal RNG state --- src/random.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/random.cpp b/src/random.cpp index d0c0ef152b7b7..1acc9ff526227 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -207,6 +207,22 @@ static std::mutex cs_rng_state; static unsigned char rng_state[32] = {0}; static uint64_t rng_counter = 0; +static void AddDataToRng(void* data, size_t len) { + CSHA512 hasher; + hasher.Write((const unsigned char*)&len, sizeof(len)); + hasher.Write((const unsigned char*)data, len); + unsigned char buf[64]; + { + std::unique_lock lock(cs_rng_state); + hasher.Write(rng_state, sizeof(rng_state)); + hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter)); + ++rng_counter; + hasher.Finalize(buf); + memcpy(rng_state, buf + 32, 32); + } + memory_cleanse(buf, 64); +} + void GetStrongRandBytes(unsigned char* out, int num) { assert(num <= 32); From 556addc52d8cf153f9d58412c00f0a76d9a1101c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 22 May 2017 16:01:52 -0400 Subject: [PATCH 024/132] Add perf counter data to GetStrongRandBytes state in scheduler --- src/random.cpp | 17 +++++++++++++++++ src/random.h | 7 +++++++ src/scheduler.cpp | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/src/random.cpp b/src/random.cpp index 1acc9ff526227..6e8b7e515e1af 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -203,6 +203,23 @@ void GetRandBytes(unsigned char* buf, int num) } } +static void AddDataToRng(void* data, size_t len); + +void RandAddSeedSleep() +{ + int64_t nPerfCounter1 = GetPerformanceCounter(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + int64_t nPerfCounter2 = GetPerformanceCounter(); + + // Combine with and update state + AddDataToRng(&nPerfCounter1, sizeof(nPerfCounter1)); + AddDataToRng(&nPerfCounter2, sizeof(nPerfCounter2)); + + memory_cleanse(&nPerfCounter1, sizeof(nPerfCounter1)); + memory_cleanse(&nPerfCounter2, sizeof(nPerfCounter2)); +} + + static std::mutex cs_rng_state; static unsigned char rng_state[32] = {0}; static uint64_t rng_counter = 0; diff --git a/src/random.h b/src/random.h index e520b9c7c2827..c3a4e341d912d 100644 --- a/src/random.h +++ b/src/random.h @@ -23,6 +23,13 @@ uint64_t GetRand(uint64_t nMax); int GetRandInt(int nMax); uint256 GetRandHash(); +/** + * Add a little bit of randomness to the output of GetStrongRangBytes. + * This sleeps for a millisecond, so should only be called when there is + * no other work to be done. + */ +void RandAddSeedSleep(); + /** * Function to gather random data from multiple sources, failing whenever any * of those source fail to provide a result. diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 52777b61f96c8..20ee0d5339fe2 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -4,6 +4,7 @@ #include "scheduler.h" +#include "random.h" #include "reverselock.h" #include @@ -37,6 +38,11 @@ void CScheduler::serviceQueue() // is called. while (!shouldStop()) { try { + if (!shouldStop() && taskQueue.empty()) { + reverse_lock > rlock(lock); + // Use this chance to get a tiny bit more entropy + RandAddSeedSleep(); + } while (!shouldStop() && taskQueue.empty()) { // Wait until there is something to do. newTaskScheduled.wait(lock); From 3eba0f39ec0a2255e3e68c0a395d478d61e301c2 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 17 Jul 2017 13:14:53 -0400 Subject: [PATCH 025/132] random: only use getentropy on openbsd --- src/random.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/random.cpp b/src/random.cpp index 6e8b7e515e1af..5f8fc7e6320ad 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -167,10 +167,12 @@ void GetOSRand(unsigned char *ent32) RandFailure(); } } -#elif defined(HAVE_GETENTROPY) +#elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__) /* On OpenBSD this can return up to 256 bytes of entropy, will return an * error if more are requested. * The call cannot return less than the requested number of bytes. + getentropy is explicitly limited to openbsd here, as a similar (but not + the same) function may exist on other platforms via glibc. */ if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { RandFailure(); From f859bdf97b43fe07d7ee913a313dcead511aac09 Mon Sep 17 00:00:00 2001 From: warrows Date: Tue, 2 Jul 2019 18:09:52 +0000 Subject: [PATCH 026/132] [Random] Fix compilation --- src/Makefile.test.include | 1 + src/netbase.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index c506a5d9ee6bd..efaaf69a49de8 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -69,6 +69,7 @@ BITCOIN_TESTS =\ test/sighash_tests.cpp \ test/sigopcount_tests.cpp \ test/skiplist_tests.cpp \ + test/test_random.h \ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ diff --git a/src/netbase.cpp b/src/netbase.cpp index 443d7bb8f51b0..82269558f584c 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -16,6 +16,8 @@ #include "util.h" #include "utilstrencodings.h" +#include + #ifdef HAVE_GETADDRINFO_A #include #endif From 061a21eb34d6515092e899eee44cfa99f1e58c1e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 2 May 2017 11:04:31 -0700 Subject: [PATCH 027/132] Add FastRandomContext::rand256() and ::randbytes() FastRandomContext now provides all functionality that the real Rand* functions provide. --- src/random.cpp | 20 ++++++++++++++++++++ src/random.h | 6 ++++++ src/test/random_tests.cpp | 7 +++++++ 3 files changed, 33 insertions(+) diff --git a/src/random.cpp b/src/random.cpp index 5f8fc7e6320ad..8c1437290b324 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -306,6 +306,26 @@ void FastRandomContext::RandomSeed() requires_seed = false; } +uint256 FastRandomContext::rand256() +{ + if (bytebuf_size < 32) { + FillByteBuffer(); + } + uint256 ret; + memcpy(ret.begin(), bytebuf + 64 - bytebuf_size, 32); + bytebuf_size -= 32; + return ret; +} + +std::vector FastRandomContext::randbytes(size_t len) +{ + std::vector ret(len); + if (len > 0) { + rng.Output(&ret[0], len); + } + return ret; +} + FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0) { rng.SetKey(seed.begin(), 32); diff --git a/src/random.h b/src/random.h index c3a4e341d912d..4d8ac23580452 100644 --- a/src/random.h +++ b/src/random.h @@ -99,9 +99,15 @@ class FastRandomContext { } } + /** Generate random bytes. */ + std::vector randbytes(size_t len); + /** Generate a random 32-bit integer. */ uint32_t rand32() { return randbits(32); } + /** generate a random uint256. */ + uint256 rand256(); + /** Generate a random boolean. */ bool randbool() { return randbits(1); } }; diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 27b5f5c5685dd..1d4c055c6474d 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -25,14 +25,21 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.randbytes(17) == ctx2.randbytes(17)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); + BOOST_CHECK(ctx1.randbytes(128) == ctx2.randbytes(128)); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); + BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50)); // Check that a nondeterministic ones are not FastRandomContext ctx3; FastRandomContext ctx4; BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal + BOOST_CHECK(ctx3.rand256() != ctx4.rand256()); + BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7)); } BOOST_AUTO_TEST_CASE(fastrandom_randbits) From 49e45dafc52411c3d55b5b5338fec93fd47ba053 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 23 May 2017 15:00:46 -0700 Subject: [PATCH 028/132] Add various insecure_rand wrappers for tests --- src/test/test_phore.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/test_phore.h b/src/test/test_phore.h index 6d1fe37aca2ec..62edb6504fd4d 100644 --- a/src/test/test_phore.h +++ b/src/test/test_phore.h @@ -6,6 +6,13 @@ #include #include +static inline uint32_t insecure_rand() { return insecure_rand_ctx.rand32(); } +static inline uint256 insecure_rand256() { return insecure_rand_ctx.rand256(); } +static inline uint64_t insecure_randbits(int bits) { return insecure_rand_ctx.randbits(bits); } +static inline uint64_t insecure_randrange(uint64_t range) { return insecure_rand_ctx.randrange(range); } +static inline bool insecure_randbool() { return insecure_rand_ctx.randbool(); } +static inline std::vector insecure_randbytes(size_t len) { return insecure_rand_ctx.randbytes(len); } + /** Basic testing setup. * This just configures logging and chain parameters. */ From 6407a409477f7d0dce3861d5bb86663e3ceb6c90 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 23 May 2017 15:09:30 -0700 Subject: [PATCH 029/132] Merge test_random.h into test_bitcoin.h --- src/Makefile.test.include | 1 - src/test/coins_tests.cpp | 1 - src/test/crypto_tests.cpp | 1 - src/test/pmt_tests.cpp | 1 - src/test/sighash_tests.cpp | 1 - src/test/skiplist_tests.cpp | 1 - src/test/test_phore.h | 18 ++++++++++++++++++ src/test/test_random.h | 29 ----------------------------- src/test/util_tests.cpp | 1 - 9 files changed, 18 insertions(+), 36 deletions(-) delete mode 100644 src/test/test_random.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index efaaf69a49de8..c506a5d9ee6bd 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -69,7 +69,6 @@ BITCOIN_TESTS =\ test/sighash_tests.cpp \ test/sigopcount_tests.cpp \ test/skiplist_tests.cpp \ - test/test_random.h \ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index d31c47fb88b9e..5ae90468c91bb 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "coins.h" -#include "test_random.h" #include "uint256.h" #include "test/test_phore.h" diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 4b5107cb36779..6a5f15fafaeb2 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -10,7 +10,6 @@ #include "crypto/sha512.h" #include "crypto/hmac_sha256.h" #include "crypto/hmac_sha512.h" -#include "test_random.h" #include "random.h" #include "utilstrencodings.h" #include "test/test_phore.h" diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 55056963c93ad..8073f12d065d4 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -9,7 +9,6 @@ #include "version.h" #include "test/test_phore.h" #include "test_random.h" - #include #include diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index b83b2ff5b1993..901150a095404 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -5,7 +5,6 @@ #include "consensus/validation.h" #include "data/sighash.json.h" #include "main.h" -#include "test_random.h" #include "serialize.h" #include "script/script.h" #include "script/interpreter.h" diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 571d208b07f3d..6e1bfada7dfbb 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "main.h" -#include "test_random.h" #include "util.h" #include "test/test_phore.h" diff --git a/src/test/test_phore.h b/src/test/test_phore.h index 62edb6504fd4d..5a4c657871b99 100644 --- a/src/test/test_phore.h +++ b/src/test/test_phore.h @@ -6,6 +6,24 @@ #include #include +extern uint256 insecure_rand_seed; +extern FastRandomContext insecure_rand_ctx; + +static inline void seed_insecure_rand(bool fDeterministic = false) +{ + if (fDeterministic) { + insecure_rand_seed = uint256(); + } else { + insecure_rand_seed = GetRandHash(); + } + insecure_rand_ctx = FastRandomContext(insecure_rand_seed); +} + +static inline uint32_t insecure_rand(void) +{ + return insecure_rand_ctx.rand32(); +} + static inline uint32_t insecure_rand() { return insecure_rand_ctx.rand32(); } static inline uint256 insecure_rand256() { return insecure_rand_ctx.rand256(); } static inline uint64_t insecure_randbits(int bits) { return insecure_rand_ctx.randbits(bits); } diff --git a/src/test/test_random.h b/src/test/test_random.h deleted file mode 100644 index d1fae70458c7d..0000000000000 --- a/src/test/test_random.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-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. - -#ifndef BITCOIN_TEST_RANDOM_H -#define BITCOIN_TEST_RANDOM_H - -#include "random.h" - -extern uint256 insecure_rand_seed; -extern FastRandomContext insecure_rand_ctx; - -static inline void seed_insecure_rand(bool fDeterministic = false) -{ - if (fDeterministic) { - insecure_rand_seed = uint256(); - } else { - insecure_rand_seed = GetRandHash(); - } - insecure_rand_ctx = FastRandomContext(insecure_rand_seed); -} - -static inline uint32_t insecure_rand(void) -{ - return insecure_rand_ctx.rand32(); -} - -#endif diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 796d1bca2da36..00ab27bd48480 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -6,7 +6,6 @@ #include "clientversion.h" #include "primitives/transaction.h" -#include "test_random.h" #include "sync.h" #include "utilstrencodings.h" #include "utilmoneystr.h" From 4edb3421a80274a0b265710adeb38d589be58835 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jun 2017 11:34:55 -0700 Subject: [PATCH 030/132] Replace more rand() % NUM by randranges --- src/test/coins_tests.cpp | 602 +++++++++++++++++++++++++++++++++++- src/test/crypto_tests.cpp | 2 +- src/test/pmt_tests.cpp | 4 +- src/test/sighash_tests.cpp | 4 +- src/test/skiplist_tests.cpp | 6 +- 5 files changed, 608 insertions(+), 10 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 5ae90468c91bb..82acf215dcae2 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { // Do a random modification. { - uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration. + uint256 txid = txids[insecure_randrange(txids.size())]; // txid we're going to modify in this iteration. CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); BOOST_CHECK(coins == *entry); @@ -173,6 +173,606 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) BOOST_CHECK(updated_an_entry); BOOST_CHECK(found_an_entry); BOOST_CHECK(missed_an_entry); + +// Store of all necessary tx and undo data for next test +typedef std::map> UtxoData; +UtxoData utxoData; + +UtxoData::iterator FindRandomFrom(const std::set &utxoSet) { + assert(utxoSet.size()); + auto utxoSetIt = utxoSet.lower_bound(COutPoint(insecure_rand256(), 0)); + if (utxoSetIt == utxoSet.end()) { + utxoSetIt = utxoSet.begin(); + } + auto utxoDataIt = utxoData.find(*utxoSetIt); + assert(utxoDataIt != utxoData.end()); + return utxoDataIt; +} + + +// This test is similar to the previous test +// except the emphasis is on testing the functionality of UpdateCoins +// random txs are created and UpdateCoins is used to update the cache stack +// In particular it is tested that spending a duplicate coinbase tx +// has the expected effect (the other duplicate is overwitten at all cache levels) +BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) +{ + bool spent_a_duplicate_coinbase = false; + // A simple map to track what we expect the cache stack to represent. + std::map result; + + // The cache stack. + CCoinsViewTest base; // A CCoinsViewTest at the bottom. + std::vector stack; // A stack of CCoinsViewCaches on top. + stack.push_back(new CCoinsViewCacheTest(&base)); // Start with one cache. + + // Track the txids we've used in various sets + std::set coinbase_coins; + std::set disconnected_coins; + std::set duplicate_coins; + std::set utxoset; + + for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { + uint32_t randiter = insecure_rand(); + + // 19/20 txs add a new transaction + if (randiter % 20 < 19) { + CMutableTransaction tx; + tx.vin.resize(1); + tx.vout.resize(1); + tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate + tx.vout[0].scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting + unsigned int height = insecure_rand(); + Coin old_coin; + + // 2/20 times create a new coinbase + if (randiter % 20 < 2 || coinbase_coins.size() < 10) { + // 1/10 of those times create a duplicate coinbase + if (insecure_randrange(10) == 0 && coinbase_coins.size()) { + auto utxod = FindRandomFrom(coinbase_coins); + // Reuse the exact same coinbase + tx = std::get<0>(utxod->second); + // shouldn't be available for reconnection if its been duplicated + disconnected_coins.erase(utxod->first); + + duplicate_coins.insert(utxod->first); + } + else { + coinbase_coins.insert(COutPoint(tx.GetHash(), 0)); + } + assert(CTransaction(tx).IsCoinBase()); + } + + // 17/20 times reconnect previous or add a regular tx + else { + + COutPoint prevout; + // 1/20 times reconnect a previously disconnected tx + if (randiter % 20 == 2 && disconnected_coins.size()) { + auto utxod = FindRandomFrom(disconnected_coins); + tx = std::get<0>(utxod->second); + prevout = tx.vin[0].prevout; + if (!CTransaction(tx).IsCoinBase() && !utxoset.count(prevout)) { + disconnected_coins.erase(utxod->first); + continue; + } + + // If this tx is already IN the UTXO, then it must be a coinbase, and it must be a duplicate + if (utxoset.count(utxod->first)) { + assert(CTransaction(tx).IsCoinBase()); + assert(duplicate_coins.count(utxod->first)); + } + disconnected_coins.erase(utxod->first); + } + + // 16/20 times create a regular tx + else { + auto utxod = FindRandomFrom(utxoset); + prevout = utxod->first; + + // Construct the tx to spend the coins of prevouthash + tx.vin[0].prevout = prevout; + assert(!CTransaction(tx).IsCoinBase()); + } + // In this simple test coins only have two states, spent or unspent, save the unspent state to restore + old_coin = result[prevout]; + // Update the expected result of prevouthash to know these coins are spent + result[prevout].Clear(); + + utxoset.erase(prevout); + + // The test is designed to ensure spending a duplicate coinbase will work properly + // if that ever happens and not resurrect the previously overwritten coinbase + if (duplicate_coins.count(prevout)) { + spent_a_duplicate_coinbase = true; + } + + } + // Update the expected result to know about the new output coins + assert(tx.vout.size() == 1); + const COutPoint outpoint(tx.GetHash(), 0); + result[outpoint] = Coin(tx.vout[0], height, CTransaction(tx).IsCoinBase()); + + // Call UpdateCoins on the top cache + CTxUndo undo; + UpdateCoins(tx, *(stack.back()), undo, height); + + // Update the utxo set for future spends + utxoset.insert(outpoint); + + // Track this tx and undo info to use later + utxoData.emplace(outpoint, std::make_tuple(tx,undo,old_coin)); + } else if (utxoset.size()) { + //1/20 times undo a previous transaction + auto utxod = FindRandomFrom(utxoset); + + CTransaction &tx = std::get<0>(utxod->second); + CTxUndo &undo = std::get<1>(utxod->second); + Coin &orig_coin = std::get<2>(utxod->second); + + // Update the expected result + // Remove new outputs + result[utxod->first].Clear(); + // If not coinbase restore prevout + if (!tx.IsCoinBase()) { + result[tx.vin[0].prevout] = orig_coin; + } + + // Disconnect the tx from the current UTXO + // See code in DisconnectBlock + // remove outputs + stack.back()->SpendCoin(utxod->first); + // restore inputs + if (!tx.IsCoinBase()) { + const COutPoint &out = tx.vin[0].prevout; + Coin coin = undo.vprevout[0]; + ApplyTxInUndo(std::move(coin), *(stack.back()), out); + } + // Store as a candidate for reconnection + disconnected_coins.insert(utxod->first); + + // Update the utxoset + utxoset.erase(utxod->first); + if (!tx.IsCoinBase()) + utxoset.insert(tx.vin[0].prevout); + } + + // Once every 1000 iterations and at the end, verify the full cache. + if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + for (auto it = result.begin(); it != result.end(); it++) { + bool have = stack.back()->HaveCoin(it->first); + const Coin& coin = stack.back()->AccessCoin(it->first); + BOOST_CHECK(have == !coin.IsSpent()); + BOOST_CHECK(coin == it->second); + } + } + + // One every 10 iterations, remove a random entry from the cache + if (utxoset.size() > 1 && insecure_randrange(30) == 0) { + stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); + } + if (disconnected_coins.size() > 1 && insecure_randrange(30) == 0) { + stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); + } + if (duplicate_coins.size() > 1 && insecure_randrange(30) == 0) { + stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); + } + + if (insecure_randrange(100) == 0) { + // Every 100 iterations, flush an intermediate cache + if (stack.size() > 1 && insecure_randrange(2) == 0) { + unsigned int flushIndex = insecure_randrange(stack.size() - 1); + stack[flushIndex]->Flush(); + } + } + if (insecure_randrange(100) == 0) { + // Every 100 iterations, change the cache stack. + if (stack.size() > 0 && insecure_randrange(2) == 0) { + stack.back()->Flush(); + delete stack.back(); + stack.pop_back(); + } + if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { + CCoinsView* tip = &base; + if (stack.size() > 0) { + tip = stack.back(); + } + stack.push_back(new CCoinsViewCacheTest(tip)); + } + } + } + + // Clean up the stack. + while (stack.size() > 0) { + delete stack.back(); + stack.pop_back(); + } + + // Verify coverage. + BOOST_CHECK(spent_a_duplicate_coinbase); +} + +BOOST_AUTO_TEST_CASE(ccoins_serialization) +{ + // Good example + CDataStream ss1(ParseHex("97f23c835800816115944e077fe7c803cfa57f29b36bf87c1d35"), SER_DISK, CLIENT_VERSION); + Coin cc1; + ss1 >> cc1; + BOOST_CHECK_EQUAL(cc1.fCoinBase, false); + BOOST_CHECK_EQUAL(cc1.nHeight, 203998); + BOOST_CHECK_EQUAL(cc1.out.nValue, 60000000000ULL); + BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); + + // Good example + CDataStream ss2(ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4"), SER_DISK, CLIENT_VERSION); + Coin cc2; + ss2 >> cc2; + BOOST_CHECK_EQUAL(cc2.fCoinBase, true); + BOOST_CHECK_EQUAL(cc2.nHeight, 120891); + BOOST_CHECK_EQUAL(cc2.out.nValue, 110397); + BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); + + // Smallest possible example + CDataStream ss3(ParseHex("000006"), SER_DISK, CLIENT_VERSION); + Coin cc3; + ss3 >> cc3; + BOOST_CHECK_EQUAL(cc3.fCoinBase, false); + BOOST_CHECK_EQUAL(cc3.nHeight, 0); + BOOST_CHECK_EQUAL(cc3.out.nValue, 0); + BOOST_CHECK_EQUAL(cc3.out.scriptPubKey.size(), 0); + + // scriptPubKey that ends beyond the end of the stream + CDataStream ss4(ParseHex("000007"), SER_DISK, CLIENT_VERSION); + try { + Coin cc4; + ss4 >> cc4; + BOOST_CHECK_MESSAGE(false, "We should have thrown"); + } catch (const std::ios_base::failure& e) { + } + + // Very large scriptPubKey (3*10^9 bytes) past the end of the stream + CDataStream tmp(SER_DISK, CLIENT_VERSION); + uint64_t x = 3000000000ULL; + tmp << VARINT(x); + BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); + CDataStream ss5(ParseHex("00008a95c0bb00"), SER_DISK, CLIENT_VERSION); + try { + Coin cc5; + ss5 >> cc5; + BOOST_CHECK_MESSAGE(false, "We should have thrown"); + } catch (const std::ios_base::failure& e) { + } +} + +const static COutPoint OUTPOINT; +const static CAmount PRUNED = -1; +const static CAmount ABSENT = -2; +const static CAmount FAIL = -3; +const static CAmount VALUE1 = 100; +const static CAmount VALUE2 = 200; +const static CAmount VALUE3 = 300; +const static char DIRTY = CCoinsCacheEntry::DIRTY; +const static char FRESH = CCoinsCacheEntry::FRESH; +const static char NO_ENTRY = -1; + +const static auto FLAGS = {char(0), FRESH, DIRTY, char(DIRTY | FRESH)}; +const static auto CLEAN_FLAGS = {char(0), FRESH}; +const static auto ABSENT_FLAGS = {NO_ENTRY}; + +void SetCoinsValue(CAmount value, Coin& coin) +{ + assert(value != ABSENT); + coin.Clear(); + assert(coin.IsSpent()); + if (value != PRUNED) { + coin.out.nValue = value; + coin.nHeight = 1; + assert(!coin.IsSpent()); + } +} + +size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags) +{ + if (value == ABSENT) { + assert(flags == NO_ENTRY); + return 0; + } + assert(flags != NO_ENTRY); + CCoinsCacheEntry entry; + entry.flags = flags; + SetCoinsValue(value, entry.coin); + auto inserted = map.emplace(OUTPOINT, std::move(entry)); + assert(inserted.second); + return inserted.first->second.coin.DynamicMemoryUsage(); +} + +void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags) +{ + auto it = map.find(OUTPOINT); + if (it == map.end()) { + value = ABSENT; + flags = NO_ENTRY; + } else { + if (it->second.coin.IsSpent()) { + value = PRUNED; + } else { + value = it->second.coin.out.nValue; + } + flags = it->second.flags; + assert(flags != NO_ENTRY); + } +} + +void WriteCoinsViewEntry(CCoinsView& view, CAmount value, char flags) +{ + CCoinsMap map; + InsertCoinsMapEntry(map, value, flags); + view.BatchWrite(map, {}); +} + +class SingleEntryCacheTest +{ +public: + SingleEntryCacheTest(CAmount base_value, CAmount cache_value, char cache_flags) + { + WriteCoinsViewEntry(base, base_value, base_value == ABSENT ? NO_ENTRY : DIRTY); + cache.usage() += InsertCoinsMapEntry(cache.map(), cache_value, cache_flags); + } + + CCoinsView root; + CCoinsViewCacheTest base{&root}; + CCoinsViewCacheTest cache{&base}; +}; + +void CheckAccessCoin(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags) +{ + SingleEntryCacheTest test(base_value, cache_value, cache_flags); + test.cache.AccessCoin(OUTPOINT); + test.cache.SelfTest(); + + CAmount result_value; + char result_flags; + GetCoinsMapEntry(test.cache.map(), result_value, result_flags); + BOOST_CHECK_EQUAL(result_value, expected_value); + BOOST_CHECK_EQUAL(result_flags, expected_flags); +} + +BOOST_AUTO_TEST_CASE(ccoins_access) +{ + /* Check AccessCoin behavior, requesting a coin from a cache view layered on + * top of a base view, and checking the resulting entry in the cache after + * the access. + * + * Base Cache Result Cache Result + * Value Value Value Flags Flags + */ + CheckAccessCoin(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY ); + CheckAccessCoin(ABSENT, PRUNED, PRUNED, 0 , 0 ); + CheckAccessCoin(ABSENT, PRUNED, PRUNED, FRESH , FRESH ); + CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY ); + CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH); + CheckAccessCoin(ABSENT, VALUE2, VALUE2, 0 , 0 ); + CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH ); + CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY ); + CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); + CheckAccessCoin(PRUNED, ABSENT, PRUNED, NO_ENTRY , FRESH ); + CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 ); + CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH ); + CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY ); + CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH); + CheckAccessCoin(PRUNED, VALUE2, VALUE2, 0 , 0 ); + CheckAccessCoin(PRUNED, VALUE2, VALUE2, FRESH , FRESH ); + CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY ); + CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); + CheckAccessCoin(VALUE1, ABSENT, VALUE1, NO_ENTRY , 0 ); + CheckAccessCoin(VALUE1, PRUNED, PRUNED, 0 , 0 ); + CheckAccessCoin(VALUE1, PRUNED, PRUNED, FRESH , FRESH ); + CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY ); + CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH); + CheckAccessCoin(VALUE1, VALUE2, VALUE2, 0 , 0 ); + CheckAccessCoin(VALUE1, VALUE2, VALUE2, FRESH , FRESH ); + CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY ); + CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); +} + +void CheckSpendCoins(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags) +{ + SingleEntryCacheTest test(base_value, cache_value, cache_flags); + test.cache.SpendCoin(OUTPOINT); + test.cache.SelfTest(); + + CAmount result_value; + char result_flags; + GetCoinsMapEntry(test.cache.map(), result_value, result_flags); + BOOST_CHECK_EQUAL(result_value, expected_value); + BOOST_CHECK_EQUAL(result_flags, expected_flags); +}; + +BOOST_AUTO_TEST_CASE(ccoins_spend) +{ + /* Check SpendCoin behavior, requesting a coin from a cache view layered on + * top of a base view, spending, and then checking + * the resulting entry in the cache after the modification. + * + * Base Cache Result Cache Result + * Value Value Value Flags Flags + */ + CheckSpendCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY ); + CheckSpendCoins(ABSENT, PRUNED, PRUNED, 0 , DIRTY ); + CheckSpendCoins(ABSENT, PRUNED, ABSENT, FRESH , NO_ENTRY ); + CheckSpendCoins(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY ); + CheckSpendCoins(ABSENT, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY ); + CheckSpendCoins(ABSENT, VALUE2, PRUNED, 0 , DIRTY ); + CheckSpendCoins(ABSENT, VALUE2, ABSENT, FRESH , NO_ENTRY ); + CheckSpendCoins(ABSENT, VALUE2, PRUNED, DIRTY , DIRTY ); + CheckSpendCoins(ABSENT, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY ); + CheckSpendCoins(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY ); + CheckSpendCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY ); + CheckSpendCoins(PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY ); + CheckSpendCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY ); + CheckSpendCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY ); + CheckSpendCoins(PRUNED, VALUE2, PRUNED, 0 , DIRTY ); + CheckSpendCoins(PRUNED, VALUE2, ABSENT, FRESH , NO_ENTRY ); + CheckSpendCoins(PRUNED, VALUE2, PRUNED, DIRTY , DIRTY ); + CheckSpendCoins(PRUNED, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY ); + CheckSpendCoins(VALUE1, ABSENT, PRUNED, NO_ENTRY , DIRTY ); + CheckSpendCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY ); + CheckSpendCoins(VALUE1, PRUNED, ABSENT, FRESH , NO_ENTRY ); + CheckSpendCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY ); + CheckSpendCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY ); + CheckSpendCoins(VALUE1, VALUE2, PRUNED, 0 , DIRTY ); + CheckSpendCoins(VALUE1, VALUE2, ABSENT, FRESH , NO_ENTRY ); + CheckSpendCoins(VALUE1, VALUE2, PRUNED, DIRTY , DIRTY ); + CheckSpendCoins(VALUE1, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY ); +} + +void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags, bool coinbase) +{ + SingleEntryCacheTest test(base_value, cache_value, cache_flags); + + CAmount result_value; + char result_flags; + try { + CTxOut output; + output.nValue = modify_value; + test.cache.AddCoin(OUTPOINT, Coin(std::move(output), 1, coinbase), coinbase); + test.cache.SelfTest(); + GetCoinsMapEntry(test.cache.map(), result_value, result_flags); + } catch (std::logic_error& e) { + result_value = FAIL; + result_flags = NO_ENTRY; + } + + BOOST_CHECK_EQUAL(result_value, expected_value); + BOOST_CHECK_EQUAL(result_flags, expected_flags); +} + +// Simple wrapper for CheckAddCoinBase function above that loops through +// different possible base_values, making sure each one gives the same results. +// This wrapper lets the coins_add test below be shorter and less repetitive, +// while still verifying that the CoinsViewCache::AddCoin implementation +// ignores base values. +template +void CheckAddCoin(Args&&... args) +{ + for (CAmount base_value : {ABSENT, PRUNED, VALUE1}) + CheckAddCoinBase(base_value, std::forward(args)...); +} + +BOOST_AUTO_TEST_CASE(ccoins_add) +{ + /* Check AddCoin behavior, requesting a new coin from a cache view, + * writing a modification to the coin, and then checking the resulting + * entry in the cache after the modification. Verify behavior with the + * with the AddCoin potential_overwrite argument set to false, and to true. + * + * Cache Write Result Cache Result potential_overwrite + * Value Value Value Flags Flags + */ + CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false); + CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true ); + CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false); + CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true ); + CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false); + CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true ); + CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , false); + CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true ); + CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false); + CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true ); + CheckAddCoin(VALUE2, VALUE3, FAIL , 0 , NO_ENTRY , false); + CheckAddCoin(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true ); + CheckAddCoin(VALUE2, VALUE3, FAIL , FRESH , NO_ENTRY , false); + CheckAddCoin(VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true ); + CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY , NO_ENTRY , false); + CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY , DIRTY , true ); + CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY|FRESH, NO_ENTRY , false); + CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true ); +} + +void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected_value, char parent_flags, char child_flags, char expected_flags) +{ + SingleEntryCacheTest test(ABSENT, parent_value, parent_flags); + + CAmount result_value; + char result_flags; + try { + WriteCoinsViewEntry(test.cache, child_value, child_flags); + test.cache.SelfTest(); + GetCoinsMapEntry(test.cache.map(), result_value, result_flags); + } catch (std::logic_error& e) { + result_value = FAIL; + result_flags = NO_ENTRY; + } + + BOOST_CHECK_EQUAL(result_value, expected_value); + BOOST_CHECK_EQUAL(result_flags, expected_flags); +} + +BOOST_AUTO_TEST_CASE(ccoins_write) +{ + /* Check BatchWrite behavior, flushing one entry from a child cache to a + * parent cache, and checking the resulting entry in the parent cache + * after the write. + * + * Parent Child Result Parent Child Result + * Value Value Value Flags Flags Flags + */ + CheckWriteCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY , NO_ENTRY ); + CheckWriteCoins(ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY , DIRTY ); + CheckWriteCoins(ABSENT, PRUNED, ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY , DIRTY ); + CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY|FRESH, DIRTY|FRESH); + CheckWriteCoins(PRUNED, ABSENT, PRUNED, 0 , NO_ENTRY , 0 ); + CheckWriteCoins(PRUNED, ABSENT, PRUNED, FRESH , NO_ENTRY , FRESH ); + CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY , NO_ENTRY , DIRTY ); + CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH); + CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY , DIRTY ); + CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY|FRESH, DIRTY ); + CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY ); + CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY ); + CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY|FRESH, DIRTY ); + CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY ); + CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY , DIRTY ); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY ); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY ); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY ); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH); + CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH); + CheckWriteCoins(VALUE1, ABSENT, VALUE1, 0 , NO_ENTRY , 0 ); + CheckWriteCoins(VALUE1, ABSENT, VALUE1, FRESH , NO_ENTRY , FRESH ); + CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY , NO_ENTRY , DIRTY ); + CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH); + CheckWriteCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY , DIRTY ); + CheckWriteCoins(VALUE1, PRUNED, FAIL , 0 , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(VALUE1, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY ); + CheckWriteCoins(VALUE1, PRUNED, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY ); + CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY ); + CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(VALUE1, VALUE2, VALUE2, 0 , DIRTY , DIRTY ); + CheckWriteCoins(VALUE1, VALUE2, FAIL , 0 , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(VALUE1, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH); + CheckWriteCoins(VALUE1, VALUE2, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY ); + CheckWriteCoins(VALUE1, VALUE2, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY ); + CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH); + CheckWriteCoins(VALUE1, VALUE2, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY ); + + // The checks above omit cases where the child flags are not DIRTY, since + // they would be too repetitive (the parent cache is never updated in these + // cases). The loop below covers these cases and makes sure the parent cache + // is always left unchanged. + for (CAmount parent_value : {ABSENT, PRUNED, VALUE1}) + for (CAmount child_value : {ABSENT, PRUNED, VALUE2}) + for (char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS) + for (char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS) + CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags); +>>>>>>> 3ecabae36... Replace more rand() % NUM by randranges } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 6a5f15fafaeb2..64ae4f649ced4 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -37,7 +37,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) { Hasher hasher(h); size_t pos = 0; while (pos < in.size()) { - size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1); + size_t len = insecure_randrange((in.size() - pos + 1) / 2 + 1); hasher.Write((unsigned char*)&in[pos], len); pos += len; if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 8073f12d065d4..98a28cfd9b7a7 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -19,8 +19,8 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree public: // flip one bit in one of the hashes - this should break the authentication void Damage() { - unsigned int n = rand() % vHash.size(); - int bit = rand() % 256; + unsigned int n = insecure_randrange(vHash.size()); + int bit = insecure_randrange(256); uint256 &hash = vHash[n]; hash ^= ((uint256)1 << bit); } diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 901150a095404..e6b2cc147a161 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -87,7 +87,7 @@ void static RandomScript(CScript &script) { script = CScript(); int ops = (insecure_rand() % 10); for (int i=0; i Date: Wed, 7 Jun 2017 11:34:58 -0700 Subject: [PATCH 031/132] Replace rand() & ((1 << N) - 1) with randbits(N) --- src/test/pmt_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 98a28cfd9b7a7..32b44dff523b4 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) std::vector vMatch(nTx, false); std::vector vMatchTxid1; for (unsigned int j=0; j Date: Sat, 6 Jul 2019 11:04:43 +0200 Subject: [PATCH 032/132] [Random / tests] scripted-diff: use insecure_rand256/randrange more -BEGIN VERIFY SCRIPT- sed -i "s/\::iterator it; - it = mapOrphanTransactions.lower_bound(GetRandHash()); + it = mapOrphanTransactions.lower_bound(insecure_rand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); return it->second.tx; @@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.hash = insecure_rand256(); tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 82acf215dcae2..1be378746097a 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -26,7 +26,7 @@ class CCoinsViewTest : public CCoinsView return false; } coins = it->second; - if (coins.IsPruned() && insecure_rand() % 2 == 0) { + if (coins.IsPruned() && insecure_randrange(2) == 0) { // Randomly return false in case of an empty entry. return false; } @@ -45,7 +45,7 @@ class CCoinsViewTest : public CCoinsView { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) { map_[it->first] = it->second.coins; - if (it->second.coins.IsPruned() && insecure_rand() % 3 == 0) { + if (it->second.coins.IsPruned() && insecure_randrange(3) == 0) { // Randomly delete empty entries on write. map_.erase(it->first); } @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) std::vector txids; txids.resize(NUM_SIMULATION_ITERATIONS / 8); for (unsigned int i = 0; i < txids.size(); i++) { - txids[i] = GetRandHash(); + txids[i] = insecure_rand256(); } for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); BOOST_CHECK(coins == *entry); - if (insecure_rand() % 5 == 0 || coins.IsPruned()) { + if (insecure_randrange(5) == 0 || coins.IsPruned()) { if (coins.IsPruned()) { added_an_entry = true; } else { @@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { @@ -137,14 +137,14 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } } - if (insecure_rand() % 100 == 0) { + if (insecure_randrange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_rand() % 2 == 0) { + if (stack.size() > 0 && insecure_randrange(2) == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) { + if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index e6b2cc147a161..6a85a785c2d3d 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -85,7 +85,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un void static RandomScript(CScript &script) { static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR}; script = CScript(); - int ops = (insecure_rand() % 10); + int ops = (insecure_randrange(10)); for (int i=0; i Date: Tue, 9 May 2017 15:13:00 -0700 Subject: [PATCH 033/132] Use rdrand as entropy source on supported platforms --- src/init.cpp | 1 + src/random.cpp | 68 +++++++++++++++++++++++++++++++++++++++++ src/random.h | 3 ++ src/test/test_phore.cpp | 1 + 4 files changed, 73 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index cdefed9effa97..cb9b090914602 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1014,6 +1014,7 @@ bool AppInit2(const std::vector& words) // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // Initialize elliptic curve code + RandomInit(); ECC_Start(); globalVerifyHandle.reset(new ECCVerifyHandle()); diff --git a/src/random.cpp b/src/random.cpp index 8c1437290b324..1f76af8f53936 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -65,6 +65,64 @@ static inline int64_t GetPerformanceCounter() #endif } + +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +static std::atomic hwrand_initialized{false}; +static bool rdrand_supported = false; +static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; +static void RDRandInit() +{ + //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. + // Avoid clobbering ebx, as that is used for PIC on x86. + uint32_t eax, tmp, ecx, edx; + __asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1)); + if (ecx & CPUID_F1_ECX_RDRAND) { + LogPrintf("Using RdRand as entropy source\n"); + rdrand_supported = true; + } + hwrand_initialized.store(true); +} +#else +static void RDRandInit() {} +#endif + +static bool GetHWRand(unsigned char* ent32) { +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) + assert(hwrand_initialized.load(std::memory_order_relaxed)); + if (rdrand_supported) { + uint8_t ok; + // Not all assemblers support the rdrand instruction, write it in hex. +#ifdef __i386__ + for (int iter = 0; iter < 4; ++iter) { + uint32_t r1, r2; + __asm__ volatile (".byte 0x0f, 0xc7, 0xf0;" // rdrand %eax + ".byte 0x0f, 0xc7, 0xf2;" // rdrand %edx + "setc %2" : + "=a"(r1), "=d"(r2), "=q"(ok) :: "cc"); + if (!ok) return false; + WriteLE32(ent32 + 8 * iter, r1); + WriteLE32(ent32 + 8 * iter + 4, r2); + } +#else + uint64_t r1, r2, r3, r4; + __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax + "0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx + "0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx + "0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx + "setc %4" : + "=a"(r1), "=b"(r2), "=c"(r3), "=d"(r4), "=q"(ok) :: "cc"); + if (!ok) return false; + WriteLE64(ent32, r1); + WriteLE64(ent32 + 8, r2); + WriteLE64(ent32 + 16, r3); + WriteLE64(ent32 + 24, r4); +#endif + return true; + } +#endif + return false; +} + void RandAddSeed() { // Seed with CPU performance counter @@ -257,6 +315,11 @@ void GetStrongRandBytes(unsigned char* out, int num) GetOSRand(buf); hasher.Write(buf, 32); + // Third source: HW RNG, if available. + if (GetHWRand(buf)) { + hasher.Write(buf, 32); + } + // Combine with and update state { std::unique_lock lock(cs_rng_state); @@ -383,3 +446,8 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete uint256 seed; rng.SetKey(seed.begin(), 32); } + +void RandomInit() +{ + RDRandInit(); +} diff --git a/src/random.h b/src/random.h index 4d8ac23580452..43f6593571b90 100644 --- a/src/random.h +++ b/src/random.h @@ -129,4 +129,7 @@ void GetOSRand(unsigned char *ent32); */ bool Random_SanityCheck(); +/** Initialize the RNG. */ +void RandomInit(); + #endif // BITCOIN_RANDOM_H diff --git a/src/test/test_phore.cpp b/src/test/test_phore.cpp index f50a90f7a01b4..67ed8b305aea5 100644 --- a/src/test/test_phore.cpp +++ b/src/test/test_phore.cpp @@ -29,6 +29,7 @@ extern void noui_connect(); BasicTestingSetup::BasicTestingSetup() { + RandomInit(); ECC_Start(); SetupEnvironment(); fPrintToDebugLog = false; // don't want to write to debug.log file From 81774fdbbd645dd95b0f9622902ba3ed4a6c7ff7 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 16 Jun 2017 14:43:35 -0400 Subject: [PATCH 034/132] random: fix crash on some 64bit platforms rbx needs to be stashed in a 64bit register on 64bit platforms. With this crash in particular, it was holding a stack canary which was not properly restored after the cpuid. Split out the x86+PIC case so that x86_64 doesn't have to worry about it. --- src/random.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 1f76af8f53936..9531c8739a045 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -72,10 +72,16 @@ static bool rdrand_supported = false; static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; static void RDRandInit() { - //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. + uint32_t eax, ecx, edx; +#if defined(__i386__) && ( defined(__PIC__) || defined(__PIE__)) // Avoid clobbering ebx, as that is used for PIC on x86. - uint32_t eax, tmp, ecx, edx; + uint32_t tmp; __asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1)); +#else + uint32_t ebx; + __asm__ ("cpuid": "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); +#endif + //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. if (ecx & CPUID_F1_ECX_RDRAND) { LogPrintf("Using RdRand as entropy source\n"); rdrand_supported = true; From b1f402c0c22d3a64c9dd0bac58bb350a82faf97f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Jul 2017 16:43:05 -0700 Subject: [PATCH 035/132] Use cpuid intrinsics instead of asm code --- src/random.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 9531c8739a045..48425c85b0b37 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -36,6 +36,10 @@ #include +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#include +#endif + #include #include @@ -72,17 +76,8 @@ static bool rdrand_supported = false; static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; static void RDRandInit() { - uint32_t eax, ecx, edx; -#if defined(__i386__) && ( defined(__PIC__) || defined(__PIE__)) - // Avoid clobbering ebx, as that is used for PIC on x86. - uint32_t tmp; - __asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1)); -#else - uint32_t ebx; - __asm__ ("cpuid": "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); -#endif - //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. - if (ecx & CPUID_F1_ECX_RDRAND) { + uint32_t eax, ebx, ecx, edx; + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) { LogPrintf("Using RdRand as entropy source\n"); rdrand_supported = true; } From b9bab594cab1a4b56266cf5575ddff453cb10064 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 14 Jul 2017 12:17:33 -0700 Subject: [PATCH 036/132] Clarify entropy source --- src/random.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/random.cpp b/src/random.cpp index 48425c85b0b37..46601dd037d79 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -78,7 +78,7 @@ static void RDRandInit() { uint32_t eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) { - LogPrintf("Using RdRand as entropy source\n"); + LogPrintf("Using RdRand as an additional entropy source\n"); rdrand_supported = true; } hwrand_initialized.store(true); From c0653cdabf4dccbf41d5c5e65c8fd1c952fd8d71 Mon Sep 17 00:00:00 2001 From: warrows Date: Sat, 6 Jul 2019 11:24:52 +0200 Subject: [PATCH 037/132] [Random / tests] scripted-diff: Use randbits/bool instead of randrange -BEGIN VERIFY SCRIPT- sed -i 's/insecure_randbits(1)/insecure_randbool()/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(2)/insecure_randbool()/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(4)/insecure_randbits(2)/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(32)/insecure_randbits(5)/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(256)/insecure_randbits(8)/g' src/test/*_tests.cpp -END VERIFY SCRIPT- --- src/test/coins_tests.cpp | 12 ++++++------ src/test/pmt_tests.cpp | 2 +- src/test/sighash_tests.cpp | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 1be378746097a..a7369ed03b833 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -26,7 +26,7 @@ class CCoinsViewTest : public CCoinsView return false; } coins = it->second; - if (coins.IsPruned() && insecure_randrange(2) == 0) { + if (coins.IsPruned() && insecure_randbool() == 0) { // Randomly return false in case of an empty entry. return false; } @@ -139,12 +139,12 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) if (insecure_randrange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randrange(2) == 0) { + if (stack.size() > 0 && insecure_randbool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { + if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); @@ -360,19 +360,19 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) if (insecure_randrange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_randrange(2) == 0) { + if (stack.size() > 1 && insecure_randbool() == 0) { unsigned int flushIndex = insecure_randrange(stack.size() - 1); stack[flushIndex]->Flush(); } } if (insecure_randrange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randrange(2) == 0) { + if (stack.size() > 0 && insecure_randbool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { + if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 32b44dff523b4..f25c9d4053105 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -20,7 +20,7 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree // flip one bit in one of the hashes - this should break the authentication void Damage() { unsigned int n = insecure_randrange(vHash.size()); - int bit = insecure_randrange(256); + int bit = insecure_randbits(8); uint256 &hash = vHash[n]; hash ^= ((uint256)1 << bit); } diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 6a85a785c2d3d..4b7ac90a1a8f7 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -94,16 +94,16 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { tx.nVersion = insecure_rand(); tx.vin.clear(); tx.vout.clear(); - tx.nLockTime = (insecure_randrange(2)) ? insecure_rand() : 0; - int ins = (insecure_randrange(4)) + 1; - int outs = fSingle ? ins : (insecure_randrange(4)) + 1; + tx.nLockTime = (insecure_randbool()) ? insecure_rand() : 0; + int ins = (insecure_randbits(2)) + 1; + int outs = fSingle ? ins : (insecure_randbits(2)) + 1; for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); txin.prevout.hash = insecure_rand256(); - txin.prevout.n = insecure_randrange(4); + txin.prevout.n = insecure_randbits(2); RandomScript(txin.scriptSig); - txin.nSequence = (insecure_randrange(2)) ? insecure_rand() : (unsigned int)-1; + txin.nSequence = (insecure_randbool()) ? insecure_rand() : (unsigned int)-1; } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); From e0b48c3cc16033c7f42c4b74d5057ab9780d4c8d Mon Sep 17 00:00:00 2001 From: warrows Date: Sat, 6 Jul 2019 11:28:16 +0200 Subject: [PATCH 038/132] [Rand/test] scripted-diff: Use new naming style for insecure_rand* functions -BEGIN VERIFY SCRIPT- sed -i 's/\::iterator it; - it = mapOrphanTransactions.lower_bound(insecure_rand256()); + it = mapOrphanTransactions.lower_bound(InsecureRand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); return it->second.tx; @@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = insecure_rand256(); + tx.vin[0].prevout.hash = InsecureRand256(); tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index a7369ed03b833..765922cdc25ca 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -26,7 +26,7 @@ class CCoinsViewTest : public CCoinsView return false; } coins = it->second; - if (coins.IsPruned() && insecure_randbool() == 0) { + if (coins.IsPruned() && InsecureRandBool() == 0) { // Randomly return false in case of an empty entry. return false; } @@ -45,7 +45,7 @@ class CCoinsViewTest : public CCoinsView { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) { map_[it->first] = it->second.coins; - if (it->second.coins.IsPruned() && insecure_randrange(3) == 0) { + if (it->second.coins.IsPruned() && InsecureRandRange(3) == 0) { // Randomly delete empty entries on write. map_.erase(it->first); } @@ -96,25 +96,25 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) std::vector txids; txids.resize(NUM_SIMULATION_ITERATIONS / 8); for (unsigned int i = 0; i < txids.size(); i++) { - txids[i] = insecure_rand256(); + txids[i] = InsecureRand256(); } for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { // Do a random modification. { - uint256 txid = txids[insecure_randrange(txids.size())]; // txid we're going to modify in this iteration. + uint256 txid = txids[InsecureRandRange(txids.size())]; // txid we're going to modify in this iteration. CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); BOOST_CHECK(coins == *entry); - if (insecure_randrange(5) == 0 || coins.IsPruned()) { + if (InsecureRandRange(5) == 0 || coins.IsPruned()) { if (coins.IsPruned()) { added_an_entry = true; } else { updated_an_entry = true; } - coins.nVersion = insecure_rand(); + coins.nVersion = InsecureRand32(); coins.vout.resize(1); - coins.vout[0].nValue = insecure_rand(); + coins.vout[0].nValue = InsecureRand32(); *entry = coins; } else { coins.Clear(); @@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { @@ -137,14 +137,14 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } } - if (insecure_randrange(100) == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randbool() == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); @@ -180,7 +180,7 @@ UtxoData utxoData; UtxoData::iterator FindRandomFrom(const std::set &utxoSet) { assert(utxoSet.size()); - auto utxoSetIt = utxoSet.lower_bound(COutPoint(insecure_rand256(), 0)); + auto utxoSetIt = utxoSet.lower_bound(COutPoint(InsecureRand256(), 0)); if (utxoSetIt == utxoSet.end()) { utxoSetIt = utxoSet.begin(); } @@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) std::set utxoset; for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { - uint32_t randiter = insecure_rand(); + uint32_t randiter = InsecureRand32(); // 19/20 txs add a new transaction if (randiter % 20 < 19) { @@ -221,14 +221,14 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) tx.vin.resize(1); tx.vout.resize(1); tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate - tx.vout[0].scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting - unsigned int height = insecure_rand(); + tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting + unsigned int height = InsecureRand32(); Coin old_coin; // 2/20 times create a new coinbase if (randiter % 20 < 2 || coinbase_coins.size() < 10) { // 1/10 of those times create a duplicate coinbase - if (insecure_randrange(10) == 0 && coinbase_coins.size()) { + if (InsecureRandRange(10) == 0 && coinbase_coins.size()) { auto utxod = FindRandomFrom(coinbase_coins); // Reuse the exact same coinbase tx = std::get<0>(utxod->second); @@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (auto it = result.begin(); it != result.end(); it++) { bool have = stack.back()->HaveCoin(it->first); const Coin& coin = stack.back()->AccessCoin(it->first); @@ -348,31 +348,31 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // One every 10 iterations, remove a random entry from the cache - if (utxoset.size() > 1 && insecure_randrange(30) == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); + if (utxoset.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); } - if (disconnected_coins.size() > 1 && insecure_randrange(30) == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); + if (disconnected_coins.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); } - if (duplicate_coins.size() > 1 && insecure_randrange(30) == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); + if (duplicate_coins.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); } - if (insecure_randrange(100) == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_randbool() == 0) { - unsigned int flushIndex = insecure_randrange(stack.size() - 1); + if (stack.size() > 1 && InsecureRandBool() == 0) { + unsigned int flushIndex = InsecureRandRange(stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_randrange(100) == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randbool() == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 64ae4f649ced4..7bb1e06df44b1 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -37,7 +37,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) { Hasher hasher(h); size_t pos = 0; while (pos < in.size()) { - size_t len = insecure_randrange((in.size() - pos + 1) / 2 + 1); + size_t len = InsecureRandRange((in.size() - pos + 1) / 2 + 1); hasher.Write((unsigned char*)&in[pos], len); pos += len; if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index f25c9d4053105..af2d1bb663478 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -19,8 +19,8 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree public: // flip one bit in one of the hashes - this should break the authentication void Damage() { - unsigned int n = insecure_randrange(vHash.size()); - int bit = insecure_randbits(8); + unsigned int n = InsecureRandRange(vHash.size()); + int bit = InsecureRandBits(8); uint256 &hash = vHash[n]; hash ^= ((uint256)1 << bit); } @@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) std::vector vMatch(nTx, false); std::vector vMatchTxid1; for (unsigned int j=0; j insecure_randbytes(size_t len) { return insecure_rand_ctx.randbytes(len); } +static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); } +static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); } +static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); } +static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); } +static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); } +static inline std::vector InsecureRandBytes(size_t len) { return insecure_rand_ctx.randbytes(len); } /** Basic testing setup. * This just configures logging and chain parameters. diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 00ab27bd48480..d8540c9d3cccb 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -242,7 +242,7 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) int i; int count=0; - seed_insecure_rand(true); + SeedInsecureRand(true); for (int mod=2;mod<11;mod++) { @@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) { uint32_t rval; do{ - rval=insecure_rand()&mask; + rval=InsecureRand32()&mask; }while(rval>=(uint32_t)mod); count += rval==0; } From a45ff277dbd40de92b5b9342c814fbbe1656b690 Mon Sep 17 00:00:00 2001 From: warrows Date: Sat, 6 Jul 2019 12:04:57 +0200 Subject: [PATCH 039/132] [Tests] Fix compilation Some mistakes where done while backporting https://github.com/bitcoin/bitcoin/pull/10321 Compilation is fixed here --- src/test/coins_tests.cpp | 600 ------------------------------------ src/test/skiplist_tests.cpp | 2 + src/test/test_phore.h | 5 - 3 files changed, 2 insertions(+), 605 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 765922cdc25ca..24f21bfd4cbad 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -173,606 +173,6 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) BOOST_CHECK(updated_an_entry); BOOST_CHECK(found_an_entry); BOOST_CHECK(missed_an_entry); - -// Store of all necessary tx and undo data for next test -typedef std::map> UtxoData; -UtxoData utxoData; - -UtxoData::iterator FindRandomFrom(const std::set &utxoSet) { - assert(utxoSet.size()); - auto utxoSetIt = utxoSet.lower_bound(COutPoint(InsecureRand256(), 0)); - if (utxoSetIt == utxoSet.end()) { - utxoSetIt = utxoSet.begin(); - } - auto utxoDataIt = utxoData.find(*utxoSetIt); - assert(utxoDataIt != utxoData.end()); - return utxoDataIt; -} - - -// This test is similar to the previous test -// except the emphasis is on testing the functionality of UpdateCoins -// random txs are created and UpdateCoins is used to update the cache stack -// In particular it is tested that spending a duplicate coinbase tx -// has the expected effect (the other duplicate is overwitten at all cache levels) -BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) -{ - bool spent_a_duplicate_coinbase = false; - // A simple map to track what we expect the cache stack to represent. - std::map result; - - // The cache stack. - CCoinsViewTest base; // A CCoinsViewTest at the bottom. - std::vector stack; // A stack of CCoinsViewCaches on top. - stack.push_back(new CCoinsViewCacheTest(&base)); // Start with one cache. - - // Track the txids we've used in various sets - std::set coinbase_coins; - std::set disconnected_coins; - std::set duplicate_coins; - std::set utxoset; - - for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { - uint32_t randiter = InsecureRand32(); - - // 19/20 txs add a new transaction - if (randiter % 20 < 19) { - CMutableTransaction tx; - tx.vin.resize(1); - tx.vout.resize(1); - tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate - tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting - unsigned int height = InsecureRand32(); - Coin old_coin; - - // 2/20 times create a new coinbase - if (randiter % 20 < 2 || coinbase_coins.size() < 10) { - // 1/10 of those times create a duplicate coinbase - if (InsecureRandRange(10) == 0 && coinbase_coins.size()) { - auto utxod = FindRandomFrom(coinbase_coins); - // Reuse the exact same coinbase - tx = std::get<0>(utxod->second); - // shouldn't be available for reconnection if its been duplicated - disconnected_coins.erase(utxod->first); - - duplicate_coins.insert(utxod->first); - } - else { - coinbase_coins.insert(COutPoint(tx.GetHash(), 0)); - } - assert(CTransaction(tx).IsCoinBase()); - } - - // 17/20 times reconnect previous or add a regular tx - else { - - COutPoint prevout; - // 1/20 times reconnect a previously disconnected tx - if (randiter % 20 == 2 && disconnected_coins.size()) { - auto utxod = FindRandomFrom(disconnected_coins); - tx = std::get<0>(utxod->second); - prevout = tx.vin[0].prevout; - if (!CTransaction(tx).IsCoinBase() && !utxoset.count(prevout)) { - disconnected_coins.erase(utxod->first); - continue; - } - - // If this tx is already IN the UTXO, then it must be a coinbase, and it must be a duplicate - if (utxoset.count(utxod->first)) { - assert(CTransaction(tx).IsCoinBase()); - assert(duplicate_coins.count(utxod->first)); - } - disconnected_coins.erase(utxod->first); - } - - // 16/20 times create a regular tx - else { - auto utxod = FindRandomFrom(utxoset); - prevout = utxod->first; - - // Construct the tx to spend the coins of prevouthash - tx.vin[0].prevout = prevout; - assert(!CTransaction(tx).IsCoinBase()); - } - // In this simple test coins only have two states, spent or unspent, save the unspent state to restore - old_coin = result[prevout]; - // Update the expected result of prevouthash to know these coins are spent - result[prevout].Clear(); - - utxoset.erase(prevout); - - // The test is designed to ensure spending a duplicate coinbase will work properly - // if that ever happens and not resurrect the previously overwritten coinbase - if (duplicate_coins.count(prevout)) { - spent_a_duplicate_coinbase = true; - } - - } - // Update the expected result to know about the new output coins - assert(tx.vout.size() == 1); - const COutPoint outpoint(tx.GetHash(), 0); - result[outpoint] = Coin(tx.vout[0], height, CTransaction(tx).IsCoinBase()); - - // Call UpdateCoins on the top cache - CTxUndo undo; - UpdateCoins(tx, *(stack.back()), undo, height); - - // Update the utxo set for future spends - utxoset.insert(outpoint); - - // Track this tx and undo info to use later - utxoData.emplace(outpoint, std::make_tuple(tx,undo,old_coin)); - } else if (utxoset.size()) { - //1/20 times undo a previous transaction - auto utxod = FindRandomFrom(utxoset); - - CTransaction &tx = std::get<0>(utxod->second); - CTxUndo &undo = std::get<1>(utxod->second); - Coin &orig_coin = std::get<2>(utxod->second); - - // Update the expected result - // Remove new outputs - result[utxod->first].Clear(); - // If not coinbase restore prevout - if (!tx.IsCoinBase()) { - result[tx.vin[0].prevout] = orig_coin; - } - - // Disconnect the tx from the current UTXO - // See code in DisconnectBlock - // remove outputs - stack.back()->SpendCoin(utxod->first); - // restore inputs - if (!tx.IsCoinBase()) { - const COutPoint &out = tx.vin[0].prevout; - Coin coin = undo.vprevout[0]; - ApplyTxInUndo(std::move(coin), *(stack.back()), out); - } - // Store as a candidate for reconnection - disconnected_coins.insert(utxod->first); - - // Update the utxoset - utxoset.erase(utxod->first); - if (!tx.IsCoinBase()) - utxoset.insert(tx.vin[0].prevout); - } - - // Once every 1000 iterations and at the end, verify the full cache. - if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { - for (auto it = result.begin(); it != result.end(); it++) { - bool have = stack.back()->HaveCoin(it->first); - const Coin& coin = stack.back()->AccessCoin(it->first); - BOOST_CHECK(have == !coin.IsSpent()); - BOOST_CHECK(coin == it->second); - } - } - - // One every 10 iterations, remove a random entry from the cache - if (utxoset.size() > 1 && InsecureRandRange(30) == 0) { - stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); - } - if (disconnected_coins.size() > 1 && InsecureRandRange(30) == 0) { - stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); - } - if (duplicate_coins.size() > 1 && InsecureRandRange(30) == 0) { - stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); - } - - if (InsecureRandRange(100) == 0) { - // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && InsecureRandBool() == 0) { - unsigned int flushIndex = InsecureRandRange(stack.size() - 1); - stack[flushIndex]->Flush(); - } - } - if (InsecureRandRange(100) == 0) { - // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && InsecureRandBool() == 0) { - stack.back()->Flush(); - delete stack.back(); - stack.pop_back(); - } - if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { - CCoinsView* tip = &base; - if (stack.size() > 0) { - tip = stack.back(); - } - stack.push_back(new CCoinsViewCacheTest(tip)); - } - } - } - - // Clean up the stack. - while (stack.size() > 0) { - delete stack.back(); - stack.pop_back(); - } - - // Verify coverage. - BOOST_CHECK(spent_a_duplicate_coinbase); -} - -BOOST_AUTO_TEST_CASE(ccoins_serialization) -{ - // Good example - CDataStream ss1(ParseHex("97f23c835800816115944e077fe7c803cfa57f29b36bf87c1d35"), SER_DISK, CLIENT_VERSION); - Coin cc1; - ss1 >> cc1; - BOOST_CHECK_EQUAL(cc1.fCoinBase, false); - BOOST_CHECK_EQUAL(cc1.nHeight, 203998); - BOOST_CHECK_EQUAL(cc1.out.nValue, 60000000000ULL); - BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); - - // Good example - CDataStream ss2(ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4"), SER_DISK, CLIENT_VERSION); - Coin cc2; - ss2 >> cc2; - BOOST_CHECK_EQUAL(cc2.fCoinBase, true); - BOOST_CHECK_EQUAL(cc2.nHeight, 120891); - BOOST_CHECK_EQUAL(cc2.out.nValue, 110397); - BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); - - // Smallest possible example - CDataStream ss3(ParseHex("000006"), SER_DISK, CLIENT_VERSION); - Coin cc3; - ss3 >> cc3; - BOOST_CHECK_EQUAL(cc3.fCoinBase, false); - BOOST_CHECK_EQUAL(cc3.nHeight, 0); - BOOST_CHECK_EQUAL(cc3.out.nValue, 0); - BOOST_CHECK_EQUAL(cc3.out.scriptPubKey.size(), 0); - - // scriptPubKey that ends beyond the end of the stream - CDataStream ss4(ParseHex("000007"), SER_DISK, CLIENT_VERSION); - try { - Coin cc4; - ss4 >> cc4; - BOOST_CHECK_MESSAGE(false, "We should have thrown"); - } catch (const std::ios_base::failure& e) { - } - - // Very large scriptPubKey (3*10^9 bytes) past the end of the stream - CDataStream tmp(SER_DISK, CLIENT_VERSION); - uint64_t x = 3000000000ULL; - tmp << VARINT(x); - BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); - CDataStream ss5(ParseHex("00008a95c0bb00"), SER_DISK, CLIENT_VERSION); - try { - Coin cc5; - ss5 >> cc5; - BOOST_CHECK_MESSAGE(false, "We should have thrown"); - } catch (const std::ios_base::failure& e) { - } -} - -const static COutPoint OUTPOINT; -const static CAmount PRUNED = -1; -const static CAmount ABSENT = -2; -const static CAmount FAIL = -3; -const static CAmount VALUE1 = 100; -const static CAmount VALUE2 = 200; -const static CAmount VALUE3 = 300; -const static char DIRTY = CCoinsCacheEntry::DIRTY; -const static char FRESH = CCoinsCacheEntry::FRESH; -const static char NO_ENTRY = -1; - -const static auto FLAGS = {char(0), FRESH, DIRTY, char(DIRTY | FRESH)}; -const static auto CLEAN_FLAGS = {char(0), FRESH}; -const static auto ABSENT_FLAGS = {NO_ENTRY}; - -void SetCoinsValue(CAmount value, Coin& coin) -{ - assert(value != ABSENT); - coin.Clear(); - assert(coin.IsSpent()); - if (value != PRUNED) { - coin.out.nValue = value; - coin.nHeight = 1; - assert(!coin.IsSpent()); - } -} - -size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags) -{ - if (value == ABSENT) { - assert(flags == NO_ENTRY); - return 0; - } - assert(flags != NO_ENTRY); - CCoinsCacheEntry entry; - entry.flags = flags; - SetCoinsValue(value, entry.coin); - auto inserted = map.emplace(OUTPOINT, std::move(entry)); - assert(inserted.second); - return inserted.first->second.coin.DynamicMemoryUsage(); -} - -void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags) -{ - auto it = map.find(OUTPOINT); - if (it == map.end()) { - value = ABSENT; - flags = NO_ENTRY; - } else { - if (it->second.coin.IsSpent()) { - value = PRUNED; - } else { - value = it->second.coin.out.nValue; - } - flags = it->second.flags; - assert(flags != NO_ENTRY); - } -} - -void WriteCoinsViewEntry(CCoinsView& view, CAmount value, char flags) -{ - CCoinsMap map; - InsertCoinsMapEntry(map, value, flags); - view.BatchWrite(map, {}); -} - -class SingleEntryCacheTest -{ -public: - SingleEntryCacheTest(CAmount base_value, CAmount cache_value, char cache_flags) - { - WriteCoinsViewEntry(base, base_value, base_value == ABSENT ? NO_ENTRY : DIRTY); - cache.usage() += InsertCoinsMapEntry(cache.map(), cache_value, cache_flags); - } - - CCoinsView root; - CCoinsViewCacheTest base{&root}; - CCoinsViewCacheTest cache{&base}; -}; - -void CheckAccessCoin(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags) -{ - SingleEntryCacheTest test(base_value, cache_value, cache_flags); - test.cache.AccessCoin(OUTPOINT); - test.cache.SelfTest(); - - CAmount result_value; - char result_flags; - GetCoinsMapEntry(test.cache.map(), result_value, result_flags); - BOOST_CHECK_EQUAL(result_value, expected_value); - BOOST_CHECK_EQUAL(result_flags, expected_flags); -} - -BOOST_AUTO_TEST_CASE(ccoins_access) -{ - /* Check AccessCoin behavior, requesting a coin from a cache view layered on - * top of a base view, and checking the resulting entry in the cache after - * the access. - * - * Base Cache Result Cache Result - * Value Value Value Flags Flags - */ - CheckAccessCoin(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY ); - CheckAccessCoin(ABSENT, PRUNED, PRUNED, 0 , 0 ); - CheckAccessCoin(ABSENT, PRUNED, PRUNED, FRESH , FRESH ); - CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY ); - CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH); - CheckAccessCoin(ABSENT, VALUE2, VALUE2, 0 , 0 ); - CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH ); - CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY ); - CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); - CheckAccessCoin(PRUNED, ABSENT, PRUNED, NO_ENTRY , FRESH ); - CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 ); - CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH ); - CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY ); - CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH); - CheckAccessCoin(PRUNED, VALUE2, VALUE2, 0 , 0 ); - CheckAccessCoin(PRUNED, VALUE2, VALUE2, FRESH , FRESH ); - CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY ); - CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); - CheckAccessCoin(VALUE1, ABSENT, VALUE1, NO_ENTRY , 0 ); - CheckAccessCoin(VALUE1, PRUNED, PRUNED, 0 , 0 ); - CheckAccessCoin(VALUE1, PRUNED, PRUNED, FRESH , FRESH ); - CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY ); - CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH); - CheckAccessCoin(VALUE1, VALUE2, VALUE2, 0 , 0 ); - CheckAccessCoin(VALUE1, VALUE2, VALUE2, FRESH , FRESH ); - CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY ); - CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); -} - -void CheckSpendCoins(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags) -{ - SingleEntryCacheTest test(base_value, cache_value, cache_flags); - test.cache.SpendCoin(OUTPOINT); - test.cache.SelfTest(); - - CAmount result_value; - char result_flags; - GetCoinsMapEntry(test.cache.map(), result_value, result_flags); - BOOST_CHECK_EQUAL(result_value, expected_value); - BOOST_CHECK_EQUAL(result_flags, expected_flags); -}; - -BOOST_AUTO_TEST_CASE(ccoins_spend) -{ - /* Check SpendCoin behavior, requesting a coin from a cache view layered on - * top of a base view, spending, and then checking - * the resulting entry in the cache after the modification. - * - * Base Cache Result Cache Result - * Value Value Value Flags Flags - */ - CheckSpendCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY ); - CheckSpendCoins(ABSENT, PRUNED, PRUNED, 0 , DIRTY ); - CheckSpendCoins(ABSENT, PRUNED, ABSENT, FRESH , NO_ENTRY ); - CheckSpendCoins(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY ); - CheckSpendCoins(ABSENT, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY ); - CheckSpendCoins(ABSENT, VALUE2, PRUNED, 0 , DIRTY ); - CheckSpendCoins(ABSENT, VALUE2, ABSENT, FRESH , NO_ENTRY ); - CheckSpendCoins(ABSENT, VALUE2, PRUNED, DIRTY , DIRTY ); - CheckSpendCoins(ABSENT, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY ); - CheckSpendCoins(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY ); - CheckSpendCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY ); - CheckSpendCoins(PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY ); - CheckSpendCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY ); - CheckSpendCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY ); - CheckSpendCoins(PRUNED, VALUE2, PRUNED, 0 , DIRTY ); - CheckSpendCoins(PRUNED, VALUE2, ABSENT, FRESH , NO_ENTRY ); - CheckSpendCoins(PRUNED, VALUE2, PRUNED, DIRTY , DIRTY ); - CheckSpendCoins(PRUNED, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY ); - CheckSpendCoins(VALUE1, ABSENT, PRUNED, NO_ENTRY , DIRTY ); - CheckSpendCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY ); - CheckSpendCoins(VALUE1, PRUNED, ABSENT, FRESH , NO_ENTRY ); - CheckSpendCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY ); - CheckSpendCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY ); - CheckSpendCoins(VALUE1, VALUE2, PRUNED, 0 , DIRTY ); - CheckSpendCoins(VALUE1, VALUE2, ABSENT, FRESH , NO_ENTRY ); - CheckSpendCoins(VALUE1, VALUE2, PRUNED, DIRTY , DIRTY ); - CheckSpendCoins(VALUE1, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY ); -} - -void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags, bool coinbase) -{ - SingleEntryCacheTest test(base_value, cache_value, cache_flags); - - CAmount result_value; - char result_flags; - try { - CTxOut output; - output.nValue = modify_value; - test.cache.AddCoin(OUTPOINT, Coin(std::move(output), 1, coinbase), coinbase); - test.cache.SelfTest(); - GetCoinsMapEntry(test.cache.map(), result_value, result_flags); - } catch (std::logic_error& e) { - result_value = FAIL; - result_flags = NO_ENTRY; - } - - BOOST_CHECK_EQUAL(result_value, expected_value); - BOOST_CHECK_EQUAL(result_flags, expected_flags); -} - -// Simple wrapper for CheckAddCoinBase function above that loops through -// different possible base_values, making sure each one gives the same results. -// This wrapper lets the coins_add test below be shorter and less repetitive, -// while still verifying that the CoinsViewCache::AddCoin implementation -// ignores base values. -template -void CheckAddCoin(Args&&... args) -{ - for (CAmount base_value : {ABSENT, PRUNED, VALUE1}) - CheckAddCoinBase(base_value, std::forward(args)...); -} - -BOOST_AUTO_TEST_CASE(ccoins_add) -{ - /* Check AddCoin behavior, requesting a new coin from a cache view, - * writing a modification to the coin, and then checking the resulting - * entry in the cache after the modification. Verify behavior with the - * with the AddCoin potential_overwrite argument set to false, and to true. - * - * Cache Write Result Cache Result potential_overwrite - * Value Value Value Flags Flags - */ - CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false); - CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true ); - CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false); - CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true ); - CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false); - CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true ); - CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , false); - CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true ); - CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false); - CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true ); - CheckAddCoin(VALUE2, VALUE3, FAIL , 0 , NO_ENTRY , false); - CheckAddCoin(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true ); - CheckAddCoin(VALUE2, VALUE3, FAIL , FRESH , NO_ENTRY , false); - CheckAddCoin(VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true ); - CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY , NO_ENTRY , false); - CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY , DIRTY , true ); - CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY|FRESH, NO_ENTRY , false); - CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true ); -} - -void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected_value, char parent_flags, char child_flags, char expected_flags) -{ - SingleEntryCacheTest test(ABSENT, parent_value, parent_flags); - - CAmount result_value; - char result_flags; - try { - WriteCoinsViewEntry(test.cache, child_value, child_flags); - test.cache.SelfTest(); - GetCoinsMapEntry(test.cache.map(), result_value, result_flags); - } catch (std::logic_error& e) { - result_value = FAIL; - result_flags = NO_ENTRY; - } - - BOOST_CHECK_EQUAL(result_value, expected_value); - BOOST_CHECK_EQUAL(result_flags, expected_flags); -} - -BOOST_AUTO_TEST_CASE(ccoins_write) -{ - /* Check BatchWrite behavior, flushing one entry from a child cache to a - * parent cache, and checking the resulting entry in the parent cache - * after the write. - * - * Parent Child Result Parent Child Result - * Value Value Value Flags Flags Flags - */ - CheckWriteCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY , NO_ENTRY ); - CheckWriteCoins(ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY , DIRTY ); - CheckWriteCoins(ABSENT, PRUNED, ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY , DIRTY ); - CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY|FRESH, DIRTY|FRESH); - CheckWriteCoins(PRUNED, ABSENT, PRUNED, 0 , NO_ENTRY , 0 ); - CheckWriteCoins(PRUNED, ABSENT, PRUNED, FRESH , NO_ENTRY , FRESH ); - CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY , NO_ENTRY , DIRTY ); - CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH); - CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY , DIRTY ); - CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY|FRESH, DIRTY ); - CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY ); - CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY ); - CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY|FRESH, DIRTY ); - CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY ); - CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY , DIRTY ); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY ); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY ); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY ); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH); - CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH); - CheckWriteCoins(VALUE1, ABSENT, VALUE1, 0 , NO_ENTRY , 0 ); - CheckWriteCoins(VALUE1, ABSENT, VALUE1, FRESH , NO_ENTRY , FRESH ); - CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY , NO_ENTRY , DIRTY ); - CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH); - CheckWriteCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY , DIRTY ); - CheckWriteCoins(VALUE1, PRUNED, FAIL , 0 , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(VALUE1, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY ); - CheckWriteCoins(VALUE1, PRUNED, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY ); - CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY ); - CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(VALUE1, VALUE2, VALUE2, 0 , DIRTY , DIRTY ); - CheckWriteCoins(VALUE1, VALUE2, FAIL , 0 , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(VALUE1, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH); - CheckWriteCoins(VALUE1, VALUE2, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY ); - CheckWriteCoins(VALUE1, VALUE2, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY ); - CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH); - CheckWriteCoins(VALUE1, VALUE2, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY ); - - // The checks above omit cases where the child flags are not DIRTY, since - // they would be too repetitive (the parent cache is never updated in these - // cases). The loop below covers these cases and makes sure the parent cache - // is always left unchanged. - for (CAmount parent_value : {ABSENT, PRUNED, VALUE1}) - for (CAmount child_value : {ABSENT, PRUNED, VALUE2}) - for (char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS) - for (char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS) - CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags); ->>>>>>> 3ecabae36... Replace more rand() % NUM by randranges } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 8c569c58e89d0..1caf13b017a91 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -98,3 +98,5 @@ BOOST_AUTO_TEST_CASE(getlocator_test) } } } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/test_phore.h b/src/test/test_phore.h index 0c9fce8941d4b..f2b9124879914 100644 --- a/src/test/test_phore.h +++ b/src/test/test_phore.h @@ -19,11 +19,6 @@ static inline void SeedInsecureRand(bool fDeterministic = false) insecure_rand_ctx = FastRandomContext(insecure_rand_seed); } -static inline uint32_t InsecureRand32(void) -{ - return insecure_rand_ctx.rand32(); -} - static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); } static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); } static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); } From 6d7add226ca4fa2c155c38c7a402236e46beb895 Mon Sep 17 00:00:00 2001 From: Dag Robole Date: Sat, 15 Jul 2017 21:34:52 +0200 Subject: [PATCH 040/132] Fix resource leak --- src/random.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/random.cpp b/src/random.cpp index 46601dd037d79..0d1c28b2c8070 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -186,6 +186,7 @@ void GetDevURandom(unsigned char *ent32) do { ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { + close(f); RandFailure(); } have += n; From b36d0c9834dc6bd5ab33b61aef32191e1000740f Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 16 Jul 2017 14:56:43 +0200 Subject: [PATCH 041/132] Add attribute [[noreturn]] (C++11) to functions that will not return Rationale: * Reduce the number of false positives from static analyzers * Potentially enable additional compiler optimizations --- src/random.cpp | 4 ++-- src/test/test_phore.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 0d1c28b2c8070..69e440e8a5d86 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -43,10 +43,10 @@ #include #include -static void RandFailure() +[[noreturn]] static void RandFailure() { LogPrintf("Failed to read randomness, aborting\n"); - abort(); + std::abort(); } static inline int64_t GetPerformanceCounter() diff --git a/src/test/test_phore.cpp b/src/test/test_phore.cpp index 50147054b01e3..b4ec3300079fb 100644 --- a/src/test/test_phore.cpp +++ b/src/test/test_phore.cpp @@ -87,14 +87,14 @@ TestingSetup::~TestingSetup() boost::filesystem::remove_all(pathTemp); } -void Shutdown(void* parg) +[[noreturn]] void Shutdown(void* parg) { - exit(0); + std::exit(0); } -void StartShutdown() +[[noreturn]] void StartShutdown() { - exit(0); + std::exit(0); } bool ShutdownRequested() From 0cb30583b0c40abf8ac954ce4bded146e8f87e1f Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Thu, 27 Jul 2017 15:34:09 +0300 Subject: [PATCH 042/132] Check if sys/random.h is required for getentropy on OSX. --- configure.ac | 8 ++++++++ src/random.cpp | 14 +++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 121427c2e5a2e..cb2eb6d6168c4 100644 --- a/configure.ac +++ b/configure.ac @@ -834,6 +834,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [ AC_MSG_RESULT(no)] ) +AC_MSG_CHECKING(for getentropy via random.h) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], + [[ getentropy(nullptr, 32) ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GETENTROPY_RAND, 1,[Define this symbol if the BSD getentropy system call is available with sys/random.h]) ], + [ AC_MSG_RESULT(no)] +) + AC_MSG_CHECKING(for sysctl KERN_ARND) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], diff --git a/src/random.cpp b/src/random.cpp index 69e440e8a5d86..7a790018328bc 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -27,9 +27,12 @@ #include #include #endif -#ifdef HAVE_GETENTROPY +#if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)) #include #endif +#if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) +#include +#endif #ifdef HAVE_SYSCTL_ARND #include #endif @@ -237,6 +240,15 @@ void GetOSRand(unsigned char *ent32) if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { RandFailure(); } +#elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) + // We need a fallback for OSX < 10.12 + if (&getentropy != NULL) { + if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { + RandFailure(); + } + } else { + GetDevURandom(ent32); + } #elif defined(HAVE_SYSCTL_ARND) /* FreeBSD and similar. It is possible for the call to return less * bytes than requested, so need to read in a loop. From 7b599447a7456fa8d8be7f833edba11fa7efaf3d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 31 Oct 2018 14:25:11 -0700 Subject: [PATCH 043/132] Bugfix: randbytes should seed when needed (non reachable issue) --- src/random.cpp | 1 + src/test/random_tests.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 7a790018328bc..c2f7f6c33d030 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -396,6 +396,7 @@ uint256 FastRandomContext::rand256() std::vector FastRandomContext::randbytes(size_t len) { + if (requires_seed) RandomSeed(); std::vector ret(len); if (len > 0) { rng.Output(&ret[0], len); diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 1d4c055c6474d..1627c08a9bbb4 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -35,11 +35,18 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50)); // Check that a nondeterministic ones are not - FastRandomContext ctx3; - FastRandomContext ctx4; - BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal - BOOST_CHECK(ctx3.rand256() != ctx4.rand256()); - BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7)); + { + FastRandomContext ctx3, ctx4; + BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal + } + { + FastRandomContext ctx3, ctx4; + BOOST_CHECK(ctx3.rand256() != ctx4.rand256()); + } + { + FastRandomContext ctx3, ctx4; + BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7)); + } } BOOST_AUTO_TEST_CASE(fastrandom_randbits) From 6d83e0ecbee184913cc05b987b70d335bc381c96 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 31 Oct 2018 15:41:13 -0700 Subject: [PATCH 044/132] Do not permit copying FastRandomContexts --- src/random.cpp | 14 ++++++++++++++ src/random.h | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/src/random.cpp b/src/random.cpp index c2f7f6c33d030..28663840178a1 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -462,6 +462,20 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete rng.SetKey(seed.begin(), 32); } +FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from) noexcept +{ + requires_seed = from.requires_seed; + rng = from.rng; + std::copy(std::begin(from.bytebuf), std::end(from.bytebuf), std::begin(bytebuf)); + bytebuf_size = from.bytebuf_size; + bitbuf = from.bitbuf; + bitbuf_size = from.bitbuf_size; + from.requires_seed = true; + from.bytebuf_size = 0; + from.bitbuf_size = 0; + return *this; +} + void RandomInit() { RDRandInit(); diff --git a/src/random.h b/src/random.h index 43f6593571b90..9c235547b3249 100644 --- a/src/random.h +++ b/src/random.h @@ -75,6 +75,14 @@ class FastRandomContext { /** Initialize with explicit seed (only for testing) */ explicit FastRandomContext(const uint256& seed); + // Do not permit copying a FastRandomContext (move it, or create a new one to get reseeded). + FastRandomContext(const FastRandomContext&) = delete; + FastRandomContext(FastRandomContext&&) = delete; + FastRandomContext& operator=(const FastRandomContext&) = delete; + + /** Move a FastRandomContext. If the original one is used again, it will be reseeded. */ + FastRandomContext& operator=(FastRandomContext&& from) noexcept; + /** Generate a random 64-bit integer. */ uint64_t rand64() { From 28605a3cb8c1c948ca4be0083016853bd343b7fc Mon Sep 17 00:00:00 2001 From: warrows Date: Tue, 9 Jul 2019 15:21:52 +0200 Subject: [PATCH 045/132] [Random] Add a missing include --- src/random.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/random.cpp b/src/random.cpp index 28663840178a1..7796c69d34495 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -40,6 +40,7 @@ #include #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#include #include #endif From 965554f0ebddb083e5421257713ad852454a9ba8 Mon Sep 17 00:00:00 2001 From: warrows Date: Thu, 1 Aug 2019 09:54:07 +0200 Subject: [PATCH 046/132] [Refactor] Use arrays instead of unic vars in Chacha20 Makes the code shorter and more concise. Might allow for some compiler optimisations. --- src/crypto/chacha20.cpp | 110 +++++++++++----------------------------- 1 file changed, 29 insertions(+), 81 deletions(-) diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp index 816ae870e138a..70c472b74b9d8 100644 --- a/src/crypto/chacha20.cpp +++ b/src/crypto/chacha20.cpp @@ -73,105 +73,53 @@ void ChaCha20::Seek(uint64_t pos) void ChaCha20::Output(unsigned char* c, size_t bytes) { - uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; - uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; - unsigned char *ctarget = NULL; + uint32_t x[16]; + uint32_t j[16]; + unsigned char *ctarget = nullptr; unsigned char tmp[64]; unsigned int i; if (!bytes) return; - j0 = input[0]; - j1 = input[1]; - j2 = input[2]; - j3 = input[3]; - j4 = input[4]; - j5 = input[5]; - j6 = input[6]; - j7 = input[7]; - j8 = input[8]; - j9 = input[9]; - j10 = input[10]; - j11 = input[11]; - j12 = input[12]; - j13 = input[13]; - j14 = input[14]; - j15 = input[15]; + for (uint32_t i=0; i<16; i++) { + j[i] = input[i]; + } for (;;) { if (bytes < 64) { ctarget = c; c = tmp; } - x0 = j0; - x1 = j1; - x2 = j2; - x3 = j3; - x4 = j4; - x5 = j5; - x6 = j6; - x7 = j7; - x8 = j8; - x9 = j9; - x10 = j10; - x11 = j11; - x12 = j12; - x13 = j13; - x14 = j14; - x15 = j15; + for (uint32_t i=0; i<16; i++) { + x[i] = j[i]; + } for (i = 20;i > 0;i -= 2) { - QUARTERROUND( x0, x4, x8,x12) - QUARTERROUND( x1, x5, x9,x13) - QUARTERROUND( x2, x6,x10,x14) - QUARTERROUND( x3, x7,x11,x15) - QUARTERROUND( x0, x5,x10,x15) - QUARTERROUND( x1, x6,x11,x12) - QUARTERROUND( x2, x7, x8,x13) - QUARTERROUND( x3, x4, x9,x14) + QUARTERROUND( x[0], x[4], x[8],x[12]) + QUARTERROUND( x[1], x[5], x[9],x[13]) + QUARTERROUND( x[2], x[6],x[10],x[14]) + QUARTERROUND( x[3], x[7],x[11],x[15]) + QUARTERROUND( x[0], x[5],x[10],x[15]) + QUARTERROUND( x[1], x[6],x[11],x[12]) + QUARTERROUND( x[2], x[7], x[8],x[13]) + QUARTERROUND( x[3], x[4], x[9],x[14]) + } + for (uint32_t i=0; i<16; i++) { + x[i] += j[i]; + } + + ++j[12]; + if (!j[12]) ++j[13]; + + for (uint32_t i=0; i<16; i++) { + WriteLE32(c + 4*i, x[i]); } - x0 += j0; - x1 += j1; - x2 += j2; - x3 += j3; - x4 += j4; - x5 += j5; - x6 += j6; - x7 += j7; - x8 += j8; - x9 += j9; - x10 += j10; - x11 += j11; - x12 += j12; - x13 += j13; - x14 += j14; - x15 += j15; - - ++j12; - if (!j12) ++j13; - - WriteLE32(c + 0, x0); - WriteLE32(c + 4, x1); - WriteLE32(c + 8, x2); - WriteLE32(c + 12, x3); - WriteLE32(c + 16, x4); - WriteLE32(c + 20, x5); - WriteLE32(c + 24, x6); - WriteLE32(c + 28, x7); - WriteLE32(c + 32, x8); - WriteLE32(c + 36, x9); - WriteLE32(c + 40, x10); - WriteLE32(c + 44, x11); - WriteLE32(c + 48, x12); - WriteLE32(c + 52, x13); - WriteLE32(c + 56, x14); - WriteLE32(c + 60, x15); if (bytes <= 64) { if (bytes < 64) { for (i = 0;i < bytes;++i) ctarget[i] = c[i]; } - input[12] = j12; - input[13] = j13; + input[12] = j[12]; + input[13] = j[13]; return; } bytes -= 64; From e5c5183c9e3464367ce2f8e28760f1e67d9f2ec4 Mon Sep 17 00:00:00 2001 From: warrows Date: Thu, 1 Aug 2019 10:12:28 +0200 Subject: [PATCH 047/132] [Log] Replace a string by the function name in a log --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index c1974fd38e29e..0e725dd03196d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -236,7 +236,7 @@ void AdvertizeLocal(CNode* pnode) addrLocal.SetIP(pnode->addrLocal); } if (addrLocal.IsRoutable()) { - LogPrintf("AdvertizeLocal: advertising address %s\n", addrLocal.ToString()); + LogPrintf("%s: advertising address %s\n", __func__, addrLocal.ToString()); FastRandomContext insecure_rand; pnode->PushAddress(addrLocal, insecure_rand); } From 2a620f6f4a065b5c34b1cca157453126fd0bd24c Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Thu, 26 Mar 2020 11:30:09 -0600 Subject: [PATCH 048/132] Fixes and some clean up --- src/random.h | 15 +++++++++++++-- src/rpc/masternode-budget.cpp | 7 ++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/random.h b/src/random.h index 9c235547b3249..b034bdd12ef1d 100644 --- a/src/random.h +++ b/src/random.h @@ -92,8 +92,19 @@ class FastRandomContext { return ret; } - bool randbool() { - return rand32() & 1; + /** Generate a random (bits)-bit integer. */ + uint64_t randbits(int bits) { + if (bits == 0) { + return 0; + } else if (bits > 32) { + return rand64() >> (64 - bits); + } else { + if (bitbuf_size < bits) FillBitBuffer(); + uint64_t ret = bitbuf & (~(uint64_t)0 >> (64 - bits)); + bitbuf >>= bits; + bitbuf_size -= bits; + return ret; + } } /** Generate a random integer in the range [0..range). */ diff --git a/src/rpc/masternode-budget.cpp b/src/rpc/masternode-budget.cpp index 4899cbb0075f3..016385ed84dce 100644 --- a/src/rpc/masternode-budget.cpp +++ b/src/rpc/masternode-budget.cpp @@ -50,7 +50,7 @@ void budgetToJSON(CBudgetProposal* pbudgetProposal, UniValue& bObj) } void checkBudgetInputs(const UniValue& params, std::string &strProposalName, std::string &strURL, - int &nPaymentCount, int &nBlockStart, CAmount &nAmount) + int &nPaymentCount, int &nBlockStart, CTxDestination &address, CAmount &nAmount) { int nBlockMin = 0; CBlockIndex* pindexPrev = chainActive.Tip(); @@ -86,6 +86,7 @@ void checkBudgetInputs(const UniValue& params, std::string &strProposalName, std if (nBlockEnd < pindexPrev->nHeight) throw std::runtime_error("Invalid ending block, starting block + (payment_cycle*payments) must be more than current height."); + address = DecodeDestination(params[4].get_str()); if (!IsValidDestinationString(params[4].get_str())) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Phore address"); @@ -122,7 +123,7 @@ UniValue preparebudget(const UniValue& params, bool fHelp) std::string strURL; int nPaymentCount; int nBlockStart; - CTxDestination address = DecodeDestination(params[4].get_str()); + CTxDestination address; CAmount nAmount; checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, nAmount); @@ -183,7 +184,7 @@ UniValue submitbudget(const UniValue& params, bool fHelp) std::string strURL; int nPaymentCount; int nBlockStart; - CTxDestination address = DecodeDestination(params[4].get_str()); + CTxDestination address; CAmount nAmount; checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, nAmount); From 9cd8cf0d1585b1ffe9c5bd64a051dfac2951cbfc Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Thu, 26 Mar 2020 13:29:36 -0600 Subject: [PATCH 049/132] [Compilation] Pass caught exceptions by reference --- src/main.cpp | 4 ++-- src/net.cpp | 2 +- src/phore-cli.cpp | 2 +- src/phore-tx.cpp | 2 +- src/test/benchmark_zerocoin.cpp | 23 +++++++++++------------ src/test/libzerocoin_tests.cpp | 12 ++++++------ src/util.h | 2 +- src/wallet/walletdb.cpp | 4 ++-- 8 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 86667fab6d14e..f67851a990c0a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1728,7 +1728,7 @@ bool ReadTransaction(CTransaction& tx, const CDiskTxPos &pos, uint256 &hashBlock file >> header; fseek(file.Get(), pos.nTxOffset, SEEK_CUR); file >> tx; - } catch (std::exception &e) { + } catch (std::exception& e) { return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); } hashBlock = header.GetHash(); @@ -6810,7 +6810,7 @@ bool ProcessMessages(CNode* pfrom) } else { PrintExceptionContinue(&e, "ProcessMessages()"); } - } catch (boost::thread_interrupted) { + } catch (boost::thread_interrupted&) { throw; } catch (std::exception& e) { PrintExceptionContinue(&e, "ProcessMessages()"); diff --git a/src/net.cpp b/src/net.cpp index 0e725dd03196d..a482316dd71ac 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1187,7 +1187,7 @@ void ThreadMapPort() MilliSleep(20 * 60 * 1000); // Refresh every 20 minutes } - } catch (boost::thread_interrupted) { + } catch (boost::thread_interrupted&) { r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r); freeUPNPDevlist(devlist); diff --git a/src/phore-cli.cpp b/src/phore-cli.cpp index c31fa8ac608cb..9768c5ce3d5ae 100644 --- a/src/phore-cli.cpp +++ b/src/phore-cli.cpp @@ -274,7 +274,7 @@ int CommandLineRPC(int argc, char* argv[]) throw; } } while (fWait); - } catch (boost::thread_interrupted) { + } catch (boost::thread_interrupted&) { throw; } catch (std::exception& e) { strPrint = std::string("error: ") + e.what(); diff --git a/src/phore-tx.cpp b/src/phore-tx.cpp index e795a42613d64..a5e8abe1de220 100644 --- a/src/phore-tx.cpp +++ b/src/phore-tx.cpp @@ -613,7 +613,7 @@ static int CommandLineRawTx(int argc, char* argv[]) OutputTx(tx); } - catch (boost::thread_interrupted) { + catch (boost::thread_interrupted&) { throw; } catch (std::exception& e) { strPrint = std::string("error: ") + e.what(); diff --git a/src/test/benchmark_zerocoin.cpp b/src/test/benchmark_zerocoin.cpp index fce0061c760f3..443b802f72506 100644 --- a/src/test/benchmark_zerocoin.cpp +++ b/src/test/benchmark_zerocoin.cpp @@ -184,12 +184,12 @@ Testb_GenerateGroupParams() for (count = 0; count < 1; count++) { - try { - group = deriveIntegerGroupParams(calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (std::runtime_error e) { - cout << "Caught exception " << e.what() << endl; - return false; - } + try { + group = deriveIntegerGroupParams(calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); + } catch (std::runtime_error& e) { + cout << "Caught exception " << e.what() << endl; + return false; + } // Now perform some simple tests on the resulting parameters if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { @@ -219,11 +219,11 @@ Testb_ParamGen() ZerocoinParams testParams(gGetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); timer.stop(); - cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - } catch (runtime_error e) { - cout << e.what() << endl; - result = false; - } + cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; + } catch (std::runtime_error& e) { + cout << e.what() << endl; + result = false; + } return result; } @@ -411,4 +411,3 @@ BOOST_AUTO_TEST_CASE(benchmark_test) Testb_RunAllTests(); } BOOST_AUTO_TEST_SUITE_END() - diff --git a/src/test/libzerocoin_tests.cpp b/src/test/libzerocoin_tests.cpp index 02e6484778f34..9138e52bf915f 100644 --- a/src/test/libzerocoin_tests.cpp +++ b/src/test/libzerocoin_tests.cpp @@ -157,7 +157,7 @@ Test_GenerateGroupParams() try { group = deriveIntegerGroupParams(calculateSeed(GetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (std::runtime_error e) { + } catch (std::runtime_error& e) { std::cout << "Caught exception " << e.what() << endl; return false; } @@ -187,7 +187,7 @@ Test_ParamGen() try { // Instantiating testParams runs the parameter generation code ZerocoinParams testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); - } catch (runtime_error e) { + } catch (std::runtime_error& e) { std::cout << e.what() << endl; result = false; } @@ -250,7 +250,7 @@ Test_Accumulator() return false; } - } catch (runtime_error e) { + } catch (std::runtime_error& e) { return false; } @@ -306,7 +306,7 @@ Test_EqualityPoK() return false; } - } catch (runtime_error &e) { + } catch (std::runtime_error &e) { return false; } } @@ -378,7 +378,7 @@ bool Test_InvalidCoin() return false; } - } catch (runtime_error &e) { + } catch (std::runtime_error &e) { std::cout << "Caught exception: " << e.what() << endl; return false; } @@ -433,7 +433,7 @@ Test_MintAndSpend() gSerialNumberSize = ceil((double)serialNumber.bitSize() / 8.0); return ret; - } catch (runtime_error &e) { + } catch (std::runtime_error &e) { std::cout << e.what() << endl; return false; } diff --git a/src/util.h b/src/util.h index d45091469ebb1..3eacaf810b427 100644 --- a/src/util.h +++ b/src/util.h @@ -245,7 +245,7 @@ void TraceThread(const char* name, Callable func) LogPrintf("%s thread start\n", name); func(); LogPrintf("%s thread exit\n", name); - } catch (boost::thread_interrupted) { + } catch (boost::thread_interrupted&) { LogPrintf("%s thread interrupt\n", name); throw; } catch (std::exception& e) { diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index b62659cbe9aa2..f375cf42ecccd 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -757,7 +757,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) LogPrintf("%s\n", strErr); } pcursor->close(); - } catch (boost::thread_interrupted) { + } catch (boost::thread_interrupted&) { throw; } catch (...) { result = DB_CORRUPT; @@ -850,7 +850,7 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, std::vector& vTxHash } } pcursor->close(); - } catch (boost::thread_interrupted) { + } catch (boost::thread_interrupted&) { throw; } catch (...) { result = DB_CORRUPT; From 284978f6b590d7350e605eec2f8a9660b6562821 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Thu, 26 Mar 2020 13:32:13 -0600 Subject: [PATCH 050/132] [Refactor] Add const qualifier to exception catching --- src/init.cpp | 10 +++++----- src/main.cpp | 20 ++++++++++---------- src/masternode-budget.cpp | 6 +++--- src/masternode-payments.cpp | 6 +++--- src/masternodeman.cpp | 6 +++--- src/miner.cpp | 4 ++-- src/net.cpp | 8 ++++---- src/phore-cli.cpp | 10 +++++----- src/phore-tx.cpp | 8 ++++---- src/phored.cpp | 4 ++-- src/qt/intro.cpp | 4 ++-- src/qt/phore.cpp | 14 +++++++------- src/qt/rpcconsole.cpp | 6 +++--- src/rpc/mining.cpp | 2 +- src/rpc/server.cpp | 6 +++--- src/test/alert_tests.cpp | 2 +- src/test/benchmark_zerocoin.cpp | 4 ++-- src/test/libzerocoin_tests.cpp | 12 ++++++------ src/test/zerocoin_implementation_tests.cpp | 2 +- src/txdb.cpp | 6 +++--- src/util.cpp | 6 +++--- src/util.h | 10 +++++----- src/wallet/rpcwallet.cpp | 2 +- src/wallet/walletdb.cpp | 6 +++--- 24 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index cb9b090914602..aa02e857d4700 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1112,7 +1112,7 @@ bool AppInit2(const std::vector& words) try { boost::filesystem::copy_file(sourceFile, backupFile); LogPrintf("Creating backup of %s -> %s\n", sourceFile, backupFile); - } catch (boost::filesystem::filesystem_error& error) { + } catch (const boost::filesystem::filesystem_error& error) { LogPrintf("Failed to create backup %s\n", error.what()); } #else @@ -1148,7 +1148,7 @@ bool AppInit2(const std::vector& words) try { boost::filesystem::remove(file.second); LogPrintf("Old backup deleted: %s\n", file.second); - } catch (boost::filesystem::filesystem_error& error) { + } catch (const boost::filesystem::filesystem_error& error) { LogPrintf("Failed to delete backup %s\n", error.what()); } } @@ -1186,7 +1186,7 @@ bool AppInit2(const std::vector& words) boost::filesystem::remove_all(zerocoinDir); LogPrintf("-resync: folder deleted: %s\n", zerocoinDir.string().c_str()); } - } catch (boost::filesystem::filesystem_error& error) { + } catch (const boost::filesystem::filesystem_error& error) { LogPrintf("Failed to delete blockchain folders %s\n", error.what()); } } @@ -1201,7 +1201,7 @@ bool AppInit2(const std::vector& words) try { boost::filesystem::rename(pathDatabase, pathDatabaseBak); LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string()); - } catch (boost::filesystem::filesystem_error& error) { + } catch (const boost::filesystem::filesystem_error& error) { // failure is ok (well, not really, but it's not worse than what we started with) } @@ -1570,7 +1570,7 @@ bool AppInit2(const std::vector& words) fVerifyingBlocks = false; break; } - } catch (std::exception& e) { + } catch (const std::exception& e) { if (fDebug) LogPrintf("%s\n", e.what()); strLoadError = _("Error opening block database"); fVerifyingBlocks = false; diff --git a/src/main.cpp b/src/main.cpp index f67851a990c0a..2ae77874599b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1728,7 +1728,7 @@ bool ReadTransaction(CTransaction& tx, const CDiskTxPos &pos, uint256 &hashBlock file >> header; fseek(file.Get(), pos.nTxOffset, SEEK_CUR); file >> tx; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); } hashBlock = header.GetHash(); @@ -1988,7 +1988,7 @@ bool GetTransaction(const uint256& hash, CTransaction& txOut, uint256& hashBlock file >> header; fseek(file.Get(), postx.nTxOffset, SEEK_CUR); file >> txOut; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } hashBlock = header.GetHash(); @@ -2069,7 +2069,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) // Read block try { filein >> block; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } @@ -4601,7 +4601,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, return state.Error("Failed to write block"); if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("AcceptBlock() : ReceivedBlockTransactions failed"); - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { return state.Error(std::string("System error: ") + e.what()); } @@ -5205,7 +5205,7 @@ bool InitBlockIndex() return error("LoadBlockIndex() : genesis block cannot be activated"); // Force a chainstate write so that when we VerifyDB in a moment, it doesnt check stale data return FlushStateToDisk(state, FLUSH_STATE_ALWAYS); - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); } } @@ -5302,11 +5302,11 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp) mapBlocksUnknownParent.erase(it); } } - } catch (std::exception& e) { + } catch (const std::exception& e) { LogPrintf("%s : Deserialize or I/O error - %s", __func__, e.what()); } } - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { AbortNode(std::string("System error: ") + e.what()); } if (nLoaded > 0) @@ -6810,9 +6810,9 @@ bool ProcessMessages(CNode* pfrom) } else { PrintExceptionContinue(&e, "ProcessMessages()"); } - } catch (boost::thread_interrupted&) { + } catch (const boost::thread_interrupted&) { throw; - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, "ProcessMessages()"); } catch (...) { PrintExceptionContinue(NULL, "ProcessMessages()"); @@ -7100,7 +7100,7 @@ bool CBlockUndo::ReadFromDisk(const CDiskBlockPos& pos, const uint256& hashBlock try { filein >> *this; filein >> hashChecksum; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } diff --git a/src/masternode-budget.cpp b/src/masternode-budget.cpp index 6d152aee65419..a27ee33547729 100644 --- a/src/masternode-budget.cpp +++ b/src/masternode-budget.cpp @@ -306,7 +306,7 @@ bool CBudgetDB::Write(const CBudgetManager& objToSave) // Write and commit header, data try { fileout << ssObj; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Serialize or I/O error - %s", __func__, e.what()); } fileout.fclose(); @@ -343,7 +343,7 @@ CBudgetDB::ReadResult CBudgetDB::Read(CBudgetManager& objToLoad, bool fDryRun) try { filein.read((char*)&vchData[0], dataSize); filein >> hashIn; - } catch (std::exception& e) { + } catch (const std::exception& e) { error("%s : Deserialize or I/O error - %s", __func__, e.what()); return HashReadError; } @@ -383,7 +383,7 @@ CBudgetDB::ReadResult CBudgetDB::Read(CBudgetManager& objToLoad, bool fDryRun) // de-serialize data into CBudgetManager object ssObj >> objToLoad; - } catch (std::exception& e) { + } catch (const std::exception& e) { objToLoad.Clear(); error("%s : Deserialize or I/O error - %s", __func__, e.what()); return IncorrectFormat; diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index ab1110452494b..993866ec8ace9 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -55,7 +55,7 @@ bool CMasternodePaymentDB::Write(const CMasternodePayments& objToSave) // Write and commit header, data try { fileout << ssObj; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Serialize or I/O error - %s", __func__, e.what()); } fileout.fclose(); @@ -90,7 +90,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments& try { filein.read((char*)&vchData[0], dataSize); filein >> hashIn; - } catch (std::exception& e) { + } catch (const std::exception& e) { error("%s : Deserialize or I/O error - %s", __func__, e.what()); return HashReadError; } @@ -129,7 +129,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments& // de-serialize data into CMasternodePayments object ssObj >> objToLoad; - } catch (std::exception& e) { + } catch (const std::exception& e) { objToLoad.Clear(); error("%s : Deserialize or I/O error - %s", __func__, e.what()); return IncorrectFormat; diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 25fbd81cc0f09..198091feb549c 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -73,7 +73,7 @@ bool CMasternodeDB::Write(const CMasternodeMan& mnodemanToSave) // Write and commit header, data try { fileout << ssMasternodes; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Serialize or I/O error - %s", __func__, e.what()); } // FileCommit(fileout); @@ -110,7 +110,7 @@ CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad, bo try { filein.read((char*)&vchData[0], dataSize); filein >> hashIn; - } catch (std::exception& e) { + } catch (const std::exception& e) { error("%s : Deserialize or I/O error - %s", __func__, e.what()); return HashReadError; } @@ -148,7 +148,7 @@ CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad, bo } // de-serialize data into CMasternodeMan object ssMasternodes >> mnodemanToLoad; - } catch (std::exception& e) { + } catch (const std::exception& e) { mnodemanToLoad.Clear(); error("%s : Deserialize or I/O error - %s", __func__, e.what()); return IncorrectFormat; diff --git a/src/miner.cpp b/src/miner.cpp index 3623b3d9ecd06..67b9c629e8f31 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -783,7 +783,7 @@ void static ThreadBitcoinMiner(void* parg) try { BitcoinMiner(pwallet, false); boost::this_thread::interruption_point(); - } catch (std::exception& e) { + } catch (const std::exception& e) { LogPrintf("ThreadBitcoinMiner() exception"); } catch (...) { LogPrintf("ThreadBitcoinMiner() exception"); @@ -828,7 +828,7 @@ void ThreadStakeMinter() try { BitcoinMiner(pwallet, true); boost::this_thread::interruption_point(); - } catch (std::exception& e) { + } catch (const std::exception& e) { LogPrintf("ThreadStakeMinter() exception \n"); ThreadStakeMinter(); } catch (...) { diff --git a/src/net.cpp b/src/net.cpp index a482316dd71ac..2ed4dbb5b40dd 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1187,7 +1187,7 @@ void ThreadMapPort() MilliSleep(20 * 60 * 1000); // Refresh every 20 minutes } - } catch (boost::thread_interrupted&) { + } catch (const boost::thread_interrupted&) { r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r); freeUPNPDevlist(devlist); @@ -1980,7 +1980,7 @@ bool CAddrDB::Write(const CAddrMan& addr) // Write and commit header, data try { fileout << ssPeers; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Serialize or I/O error - %s", __func__, e.what()); } FileCommit(fileout.Get()); @@ -2011,7 +2011,7 @@ bool CAddrDB::Read(CAddrMan& addr) try { filein.read((char*)&vchData[0], dataSize); filein >> hashIn; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } filein.fclose(); @@ -2034,7 +2034,7 @@ bool CAddrDB::Read(CAddrMan& addr) // de-serialize address data into one CAddrMan object ssPeers >> addr; - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } diff --git a/src/phore-cli.cpp b/src/phore-cli.cpp index 9768c5ce3d5ae..5777af77f48f1 100644 --- a/src/phore-cli.cpp +++ b/src/phore-cli.cpp @@ -91,7 +91,7 @@ static bool AppInitRPC(int argc, char* argv[]) } try { ReadConfigFile(mapArgs, mapMultiArgs); - } catch (std::exception& e) { + } catch (const std::exception& e) { fprintf(stderr, "Error reading configuration file: %s\n", e.what()); return false; } @@ -274,9 +274,9 @@ int CommandLineRPC(int argc, char* argv[]) throw; } } while (fWait); - } catch (boost::thread_interrupted&) { + } catch (const boost::thread_interrupted&) { throw; - } catch (std::exception& e) { + } catch (const std::exception& e) { strPrint = std::string("error: ") + e.what(); nRet = EXIT_FAILURE; } catch (...) { @@ -301,7 +301,7 @@ int main(int argc, char* argv[]) try { if (!AppInitRPC(argc, argv)) return EXIT_FAILURE; - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInitRPC()"); return EXIT_FAILURE; } catch (...) { @@ -312,7 +312,7 @@ int main(int argc, char* argv[]) int ret = EXIT_FAILURE; try { ret = CommandLineRPC(argc, argv); - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, "CommandLineRPC()"); } catch (...) { PrintExceptionContinue(NULL, "CommandLineRPC()"); diff --git a/src/phore-tx.cpp b/src/phore-tx.cpp index a5e8abe1de220..a9da47d69e61a 100644 --- a/src/phore-tx.cpp +++ b/src/phore-tx.cpp @@ -613,9 +613,9 @@ static int CommandLineRawTx(int argc, char* argv[]) OutputTx(tx); } - catch (boost::thread_interrupted&) { + catch (const boost::thread_interrupted&) { throw; - } catch (std::exception& e) { + } catch (const std::exception& e) { strPrint = std::string("error: ") + e.what(); nRet = EXIT_FAILURE; } catch (...) { @@ -636,7 +636,7 @@ int main(int argc, char* argv[]) try { if (!AppInitRawTx(argc, argv)) return EXIT_FAILURE; - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInitRawTx()"); return EXIT_FAILURE; } catch (...) { @@ -647,7 +647,7 @@ int main(int argc, char* argv[]) int ret = EXIT_FAILURE; try { ret = CommandLineRawTx(argc, argv); - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, "CommandLineRawTx()"); } catch (...) { PrintExceptionContinue(NULL, "CommandLineRawTx()"); diff --git a/src/phored.cpp b/src/phored.cpp index 31c7237c0a476..3bb7f46934451 100644 --- a/src/phored.cpp +++ b/src/phored.cpp @@ -90,7 +90,7 @@ bool AppInit(int argc, char* argv[]) } try { ReadConfigFile(mapArgs, mapMultiArgs); - } catch (std::exception& e) { + } catch (const std::exception& e) { fprintf(stderr, "Error reading configuration file: %s\n", e.what()); return false; } @@ -136,7 +136,7 @@ bool AppInit(int argc, char* argv[]) std::vector words; fRet = AppInit2(words); - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInit()"); } catch (...) { PrintExceptionContinue(NULL, "AppInit()"); diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 9dbe6902b3bcc..236e69a38eded 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -94,7 +94,7 @@ void FreespaceChecker::check() replyMessage = tr("Path already exists, and is not a directory."); } } - } catch (fs::filesystem_error& e) { + } catch (const fs::filesystem_error& e) { /* Parent directory does not exist or is not accessible */ replyStatus = ST_ERROR; replyMessage = tr("Cannot create data directory here."); @@ -173,7 +173,7 @@ bool Intro::pickDataDirectory() try { TryCreateDirectory(GUIUtil::qstringToBoostPath(dataDir)); break; - } catch (fs::filesystem_error& e) { + } catch (const fs::filesystem_error& e) { QMessageBox::critical(0, tr("Phore Core"), tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir)); /* fall through, back to choosing screen */ diff --git a/src/qt/phore.cpp b/src/qt/phore.cpp index a3eee4171e301..c053f67f784cc 100644 --- a/src/qt/phore.cpp +++ b/src/qt/phore.cpp @@ -171,7 +171,7 @@ public slots: bool execute_restart; /// Pass fatal exception message to UI thread - void handleRunawayException(std::exception* e); + void handleRunawayException(const std::exception* e); std::vector words; }; @@ -243,7 +243,7 @@ BitcoinCore::BitcoinCore(std::vector& wordlist) : QObject(), words( { } -void BitcoinCore::handleRunawayException(std::exception* e) +void BitcoinCore::handleRunawayException(const std::exception* e) { PrintExceptionContinue(e, "Runaway exception"); emit runawayException(QString::fromStdString(strMiscWarning)); @@ -257,7 +257,7 @@ void BitcoinCore::initialize() qDebug() << __func__ << ": Running AppInit2 in thread"; int rv = AppInit2(words); emit initializeResult(rv); - } catch (std::exception& e) { + } catch (const std::exception& e) { handleRunawayException(&e); } catch (...) { handleRunawayException(NULL); @@ -278,7 +278,7 @@ void BitcoinCore::restart(QStringList args) QProcess::startDetached(QApplication::applicationFilePath(), args); qDebug() << __func__ << ": Restart initiated..."; QApplication::quit(); - } catch (std::exception& e) { + } catch (const std::exception& e) { handleRunawayException(&e); } catch (...) { handleRunawayException(NULL); @@ -294,7 +294,7 @@ void BitcoinCore::shutdown() Shutdown(); qDebug() << __func__ << ": Shutdown finished"; emit shutdownResult(1); - } catch (std::exception& e) { + } catch (const std::exception& e) { handleRunawayException(&e); } catch (...) { handleRunawayException(NULL); @@ -585,7 +585,7 @@ int main(int argc, char* argv[]) } try { ReadConfigFile(mapArgs, mapMultiArgs); - } catch (std::exception& e) { + } catch (const std::exception& e) { QMessageBox::critical(0, QObject::tr("Phore Core"), QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what())); return 0; @@ -658,7 +658,7 @@ int main(int argc, char* argv[]) app.exec(); app.requestShutdown(); app.exec(); - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, "Runaway exception"); app.handleRunawayException(QString::fromStdString(strMiscWarning)); } catch (...) { diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ae0279131a49b..3c88fd0050918 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -237,17 +237,17 @@ void RPCExecutor::request(const QString& command) strPrint = result.write(2); emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); - } catch (UniValue& objError) { + } catch (const UniValue& objError) { try // Nice formatting for standard-format error { int code = find_value(objError, "code").get_int(); std::string message = find_value(objError, "message").get_str(); emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")"); - } catch (std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message + } catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message { // Show raw JSON object emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write())); } - } catch (std::exception& e) { + } catch (const std::exception& e) { emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what())); } } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 272b3703be6b1..4f092d3b7f9b1 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -172,7 +172,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp) CBlockTemplate* pblocktemplate; try { pblocktemplate = CreateNewBlock(scriptPubKey, pwalletMain, false); - } catch(std::runtime_error err) { + } catch(const std::runtime_error err) { throw JSONRPCError(RPC_MISC_ERROR, err.what()); } CBlock* pblock = &pblocktemplate->block; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index dd274fb617c0e..975a9379ee6a2 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -216,7 +216,7 @@ std::string CRPCTable::help(std::string strCommand) const rpcfn_type pfn = pcmd->actor; if (setDone.insert(pfn).second) (*pfn)(params, true); - } catch (std::exception& e) { + } catch (const std::exception& e) { // Help text is returned in an exception std::string strHelp = std::string(e.what()); if (strCommand == "") { @@ -566,7 +566,7 @@ static UniValue JSONRPCExecOne(const UniValue& req) rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id); } catch (const UniValue& objError) { rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id); - } catch (std::exception& e) { + } catch (const std::exception& e) { rpc_result = JSONRPCReplyObj(NullUniValue, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); } @@ -602,7 +602,7 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms try { // Execute return pcmd->actor(params, false); - } catch (std::exception& e) { + } catch (const std::exception& e) { throw JSONRPCError(RPC_MISC_ERROR, e.what()); } diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 5ca519f0c855f..58702dc19b60f 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -94,7 +94,7 @@ struct ReadAlerts : public TestingSetup alerts.push_back(alert); } } - catch (std::exception) { } + catch (const std::exception) { } } ~ReadAlerts() { } diff --git a/src/test/benchmark_zerocoin.cpp b/src/test/benchmark_zerocoin.cpp index 443b802f72506..c5c9f15127f4c 100644 --- a/src/test/benchmark_zerocoin.cpp +++ b/src/test/benchmark_zerocoin.cpp @@ -186,7 +186,7 @@ Testb_GenerateGroupParams() try { group = deriveIntegerGroupParams(calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { cout << "Caught exception " << e.what() << endl; return false; } @@ -220,7 +220,7 @@ Testb_ParamGen() timer.stop(); cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { cout << e.what() << endl; result = false; } diff --git a/src/test/libzerocoin_tests.cpp b/src/test/libzerocoin_tests.cpp index 9138e52bf915f..c0cfaf84d9edb 100644 --- a/src/test/libzerocoin_tests.cpp +++ b/src/test/libzerocoin_tests.cpp @@ -157,7 +157,7 @@ Test_GenerateGroupParams() try { group = deriveIntegerGroupParams(calculateSeed(GetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { std::cout << "Caught exception " << e.what() << endl; return false; } @@ -187,7 +187,7 @@ Test_ParamGen() try { // Instantiating testParams runs the parameter generation code ZerocoinParams testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { std::cout << e.what() << endl; result = false; } @@ -250,7 +250,7 @@ Test_Accumulator() return false; } - } catch (std::runtime_error& e) { + } catch (const std::runtime_error& e) { return false; } @@ -306,7 +306,7 @@ Test_EqualityPoK() return false; } - } catch (std::runtime_error &e) { + } catch (const std::runtime_error &e) { return false; } } @@ -378,7 +378,7 @@ bool Test_InvalidCoin() return false; } - } catch (std::runtime_error &e) { + } catch (const std::runtime_error &e) { std::cout << "Caught exception: " << e.what() << endl; return false; } @@ -433,7 +433,7 @@ Test_MintAndSpend() gSerialNumberSize = ceil((double)serialNumber.bitSize() / 8.0); return ret; - } catch (std::runtime_error &e) { + } catch (const std::runtime_error &e) { std::cout << e.what() << endl; return false; } diff --git a/src/test/zerocoin_implementation_tests.cpp b/src/test/zerocoin_implementation_tests.cpp index 378e85f793204..aa20753007b97 100644 --- a/src/test/zerocoin_implementation_tests.cpp +++ b/src/test/zerocoin_implementation_tests.cpp @@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(zcparams_test) SelectParams(CBaseChainParams::MAIN); ZerocoinParams *ZCParams = Params().Zerocoin_Params(); (void)ZCParams; - } catch(std::exception& e) { + } catch(const std::exception& e) { fPassed = false; std::cout << e.what() << "\n"; } diff --git a/src/txdb.cpp b/src/txdb.cpp index a7cf2e96419f8..36ad7bc21d83c 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -165,7 +165,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats& stats) const ss << VARINT(0); } pcursor->Next(); - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } } @@ -332,7 +332,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts() } else { break; // if shutdown requested or finished loading block index } - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } } @@ -428,7 +428,7 @@ bool CZerocoinDB::WipeCoins(std::string strType) } else { break; // if shutdown requested or finished loading block index } - } catch (std::exception& e) { + } catch (const std::exception& e) { return error("%s : Deserialize or I/O error - %s", __func__, e.what()); } } diff --git a/src/util.cpp b/src/util.cpp index 58515ca5d86bf..e53c07f417de2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -503,7 +503,7 @@ std::string HelpMessageOpt(const std::string &option, const std::string &message std::string("\n\n"); } -static std::string FormatException(std::exception* pex, const char* pszThread) +static std::string FormatException(const std::exception* pex, const char* pszThread) { #ifdef WIN32 char pszModule[MAX_PATH] = ""; @@ -519,7 +519,7 @@ static std::string FormatException(std::exception* pex, const char* pszThread) "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread); } -void PrintExceptionContinue(std::exception* pex, const char* pszThread) +void PrintExceptionContinue(const std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); LogPrintf("\n\n************************\n%s\n", message); @@ -689,7 +689,7 @@ bool TryCreateDirectory(const boost::filesystem::path& p) { try { return boost::filesystem::create_directory(p); - } catch (boost::filesystem::filesystem_error) { + } catch (const boost::filesystem::filesystem_error) { if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p)) throw; } diff --git a/src/util.h b/src/util.h index 3eacaf810b427..9de5951ffb958 100644 --- a/src/util.h +++ b/src/util.h @@ -95,7 +95,7 @@ template std::string FormatStringFromLogArgs(const char *fmt, std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \ try { \ _log_msg_ = tfm::format(format, TINYFORMAT_PASSARGS(n)); \ - } catch (std::runtime_error &e) { \ + } catch (const std::runtime_error &e) { \ _log_msg_ = "Error \"" + std::string(e.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(format, TINYFORMAT_PASSARGS(n));\ } \ return LogPrintStr(_log_msg_); \ @@ -107,7 +107,7 @@ template std::string FormatStringFromLogArgs(const char *fmt, std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \ try { \ _log_msg_ = tfm::format(format, TINYFORMAT_PASSARGS(n)); \ - } catch (std::runtime_error &e) { \ + } catch (const std::runtime_error &e) { \ _log_msg_ = "Error \"" + std::string(e.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(format, TINYFORMAT_PASSARGS(n));\ } \ LogPrintStr(std::string("ERROR: ") + _log_msg_ + "\n"); \ @@ -133,7 +133,7 @@ static inline bool error(const char* format) double double_safe_addition(double fValue, double fIncrement); double double_safe_multiplication(double fValue, double fmultiplicator); -void PrintExceptionContinue(std::exception* pex, const char* pszThread); +void PrintExceptionContinue(const std::exception* pex, const char* pszThread); void ParseParameters(int argc, const char* const argv[]); void FileCommit(FILE* fileout); bool TruncateFile(FILE* file, unsigned int length); @@ -245,10 +245,10 @@ void TraceThread(const char* name, Callable func) LogPrintf("%s thread start\n", name); func(); LogPrintf("%s thread exit\n", name); - } catch (boost::thread_interrupted&) { + } catch (const boost::thread_interrupted&) { LogPrintf("%s thread interrupt\n", name); throw; - } catch (std::exception& e) { + } catch (const std::exception& e) { PrintExceptionContinue(&e, name); throw; } catch (...) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9f4fd263f5563..12dbfd897fc41 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3512,7 +3512,7 @@ void static SearchThread(CzPHRWallet* zwallet, int nCountStart, int nCountEnd) zwallet->AddToMintPool(std::make_pair(hashPubcoin, i), true); walletDB.WriteMintPoolPair(hashSeed, hashPubcoin, i); } - } catch (std::exception& e) { + } catch (const std::exception& e) { LogPrintf("SearchThread() exception"); } catch (...) { LogPrintf("SearchThread() exception"); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index f375cf42ecccd..805d0f618fe25 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -757,7 +757,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) LogPrintf("%s\n", strErr); } pcursor->close(); - } catch (boost::thread_interrupted&) { + } catch (const boost::thread_interrupted&) { throw; } catch (...) { result = DB_CORRUPT; @@ -850,7 +850,7 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, std::vector& vTxHash } } pcursor->close(); - } catch (boost::thread_interrupted&) { + } catch (const boost::thread_interrupted&) { throw; } catch (...) { result = DB_CORRUPT; @@ -1027,7 +1027,7 @@ bool BackupWallet(const CWallet& wallet, const boost::filesystem::path& strDest, boost::filesystem::remove(entry->second); LogPrintf("Old backup deleted: %s\n", (*entry).second); } - } catch (boost::filesystem::filesystem_error& error) { + } catch (const boost::filesystem::filesystem_error& error) { std::string strMessage = strprintf("Failed to delete backup %s\n", error.what()); LogPrint(nullptr, strMessage.data()); NotifyBacked(wallet, false, strMessage); From 79eef0ab3350cb8c70ab8018779d04a2b4dda9cb Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Sat, 21 Sep 2019 15:00:45 -0700 Subject: [PATCH 051/132] Update `crypto/common.h` functions to use compat endian header --- src/crypto/common.h | 120 ++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 77 deletions(-) diff --git a/src/crypto/common.h b/src/crypto/common.h index f585f2fea3421..6906ee7807b27 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -1,127 +1,93 @@ -// Copyright (c) 2014 The Bitcoin developers +// Copyright (c) 2014-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CRYPTO_COMMON_H #define BITCOIN_CRYPTO_COMMON_H +#if defined(HAVE_CONFIG_H) +#include +#endif + #include +#include -#if defined(HAVE_ENDIAN_H) -#include -#endif +#include + +uint16_t static inline ReadLE16(const unsigned char* ptr) +{ + uint16_t x; + memcpy((char*)&x, ptr, 2); + return le16toh(x); +} 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 + uint32_t x; + memcpy((char*)&x, ptr, 4); + return le32toh(x); } 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 + uint64_t x; + memcpy((char*)&x, ptr, 8); + return le64toh(x); +} + +void static inline WriteLE16(unsigned char* ptr, uint16_t x) +{ + uint16_t v = htole16(x); + memcpy(ptr, (char*)&v, 2); } 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 + uint32_t v = htole32(x); + memcpy(ptr, (char*)&v, 4); } 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 + uint64_t v = htole64(x); + memcpy(ptr, (char*)&v, 8); } 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 + uint32_t x; + memcpy((char*)&x, ptr, 4); + return be32toh(x); } 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 + uint64_t x; + memcpy((char*)&x, ptr, 8); + return be64toh(x); } 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 + uint32_t v = htobe32(x); + memcpy(ptr, (char*)&v, 4); } 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 + uint64_t v = htobe64(x); + memcpy(ptr, (char*)&v, 8); } /** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */ uint64_t static inline CountBits(uint64_t x) { -#ifdef HAVE_DECL___BUILTIN_CLZL +#if HAVE_DECL___BUILTIN_CLZL if (sizeof(unsigned long) >= sizeof(uint64_t)) { return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; } #endif -#ifdef HAVE_DECL___BUILTIN_CLZLL +#if HAVE_DECL___BUILTIN_CLZLL if (sizeof(unsigned long long) >= sizeof(uint64_t)) { return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; } @@ -134,4 +100,4 @@ uint64_t static inline CountBits(uint64_t x) return ret; } -#endif // BITCOIN_CRYPTO_COMMON_H +#endif // BITCOIN_CRYPTO_COMMON_H \ No newline at end of file From 9b8d98f0a6579366368b968f2e1e2909ee0bfa4f Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 14:51:15 +0200 Subject: [PATCH 052/132] [Refactor] refactor/fix CSporkManager and CSporkMessage classes - move ProcessSpork, GetSporkValue, IsSporkActive, ExecuteSpork and mapSporksActive to CSporkManager - move Sign, CheckSignature, Relay to CSporkMessage - move ReprocessBlocks out of sporks to main.cpp - rename DisconnectBlocksAndReprocess to DisconnectBlocks - bugfix: only set strMasterPrivKey if spork signature produced by that key was verified successfully - few log format changes, cleaned up includes --- src/activemasternode.cpp | 4 +- src/init.cpp | 2 +- src/main.cpp | 49 ++++++-- src/main.h | 3 +- src/masternode-payments.cpp | 19 +-- src/masternode-sync.cpp | 4 +- src/masternodeman.cpp | 8 +- src/miner.cpp | 2 +- src/qt/privacydialog.cpp | 9 +- src/qt/walletmodel.cpp | 8 +- src/rpc/misc.cpp | 4 +- src/spork.cpp | 244 +++++++++++++++--------------------- src/spork.h | 45 +++---- src/swifttx.cpp | 6 +- src/wallet/rpcwallet.cpp | 13 +- src/wallet/wallet.cpp | 4 +- 16 files changed, 211 insertions(+), 213 deletions(-) diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 5611b67f063d5..505d4a3602ccb 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -198,7 +198,7 @@ bool CActiveMasternode::SendMasternodePing(std::string& errorMessage) * AFTER MIGRATION TO V12 IS DONE */ - if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return true; + if (sporkManager.IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return true; // for migration purposes ping our node on old masternodes network too std::string retErrorMessage; std::vector vchMasterNodeSignature; @@ -300,7 +300,7 @@ bool CActiveMasternode::CreateBroadcast(CTxIn vin, CService service, CKey keyCol * AFTER MIGRATION TO V12 IS DONE */ - if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return true; + if (sporkManager.IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return true; // for migration purposes inject our node in old masternodes' list too std::string retErrorMessage; std::vector vchMasterNodeSignature; diff --git a/src/init.cpp b/src/init.cpp index aa02e857d4700..b3faf8b1415eb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1435,7 +1435,7 @@ bool AppInit2(const std::vector& words) // Phore: load previous sessions sporks if we have them. uiInterface.InitMessage(_("Loading sporks...")); - LoadSporksFromDB(); + sporkManager.LoadSporksFromDB(); uiInterface.InitMessage(_("Loading block index...")); std::string strBlockIndexError = ""; diff --git a/src/main.cpp b/src/main.cpp index 2ae77874599b1..7e1a8393388e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1467,7 +1467,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa *pfMissingInputs = false; //Temporarily disable zerocoin for maintenance - if (GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE) && tx.ContainsZerocoins()) + if (sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE) && tx.ContainsZerocoins()) return state.DoS(10, error("AcceptToMemoryPool : Zerocoin transactions are temporarily disabled for maintenance"), REJECT_INVALID, "bad-tx"); if (!CheckTransaction(tx, chainActive.Height() >= Params().Zerocoin_StartHeight(), true, state, GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < chainActive.Tip()->nTime)) { @@ -2936,7 +2936,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin nInputs += tx.vin.size(); //Temporarily disable zerocoin transactions for maintenance - if (block.nTime > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE) && !IsInitialBlockDownload() && tx.ContainsZerocoins()) { + if (block.nTime > sporkManager.GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE) && !IsInitialBlockDownload() && tx.ContainsZerocoins()) { return state.DoS(100, error("ConnectBlock() : zerocoin transactions are currently in maintenance mode")); } if (tx.IsZerocoinSpend()) { @@ -3444,19 +3444,50 @@ bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock* return true; } -bool DisconnectBlocksAndReprocess(int blocks) +bool DisconnectBlocks(int blocks) { LOCK(cs_main); CValidationState state; - LogPrintf("DisconnectBlocksAndReprocess: Got command to replay %d blocks\n", blocks); + LogPrintf("%s: Got command to replay %d blocks\n", __func__, blocks); for (int i = 0; i <= blocks; i++) DisconnectTip(state, false); return true; } +void ReprocessBlocks(int nBlocks) +{ + std::map::iterator it = mapRejectedBlocks.begin(); + while (it != mapRejectedBlocks.end()) { + //use a window twice as large as is usual for the nBlocks we want to reset + if ((*it).second > GetTime() - (nBlocks * 60 * 5)) { + BlockMap::iterator mi = mapBlockIndex.find((*it).first); + if (mi != mapBlockIndex.end() && (*mi).second) { + LOCK(cs_main); + + CBlockIndex* pindex = (*mi).second; + LogPrintf("%s - %s\n", __func__, (*it).first.ToString()); + + CValidationState state; + ReconsiderBlock(state, pindex); + } + } + ++it; + } + + CValidationState state; + { + LOCK(cs_main); + DisconnectBlocks(nBlocks); + } + + if (state.IsValid()) { + ActivateBestChain(state); + } +} + /* DisconnectBlockAndInputs @@ -4094,7 +4125,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo } // ----------- swiftTX transaction scanning ----------- - if (IsSporkActive(SPORK_3_SWIFTTX_BLOCK_FILTERING)) { + if (sporkManager.IsSporkActive(SPORK_3_SWIFTTX_BLOCK_FILTERING)) { for (const CTransaction& tx : block.vtx) { if (!tx.IsCoinBase()) { //only reject blocks when it's based on complete consensus @@ -6703,7 +6734,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR budget.ProcessMessage(pfrom, strCommand, vRecv); masternodePayments.ProcessMessageMasternodePayments(pfrom, strCommand, vRecv); ProcessMessageSwiftTX(pfrom, strCommand, vRecv); - ProcessSpork(pfrom, strCommand, vRecv); + sporkManager.ProcessSpork(pfrom, strCommand, vRecv); masternodeSync.ProcessMessage(pfrom, strCommand, vRecv); } @@ -6717,8 +6748,10 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR // it was the one which was commented out int ActiveProtocol() { - if (IsSporkActive(SPORK_14_NEW_PROTOCOL_ENFORCEMENT)) - return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT; + // SPORK_14 is used for 70917 (v3.4+) + if (sporkManager.IsSporkActive(SPORK_14_NEW_PROTOCOL_ENFORCEMENT)) + return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT; + return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; } diff --git a/src/main.h b/src/main.h index 3a887efc52a98..9e17996c87ccb 100644 --- a/src/main.h +++ b/src/main.h @@ -521,7 +521,8 @@ bool FindTransactionsByDestination(const CTxDestination &dest, std::set Params().LAST_POW_BLOCK() ? block.vtx[1] : block.vtx[0]); //check if it's a budget block - if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) { + if (sporkManager.IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) { if (budget.IsBudgetPaymentBlock(nBlockHeight)) { transactionStatus = budget.IsTransactionValid(txNew, nBlockHeight); if (transactionStatus == TrxValidationStatus::Valid) { @@ -244,7 +244,7 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight) if (transactionStatus == TrxValidationStatus::Invalid) { LogPrint("masternode","Invalid budget payment detected %s\n", txNew.ToString().c_str()); - if (IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT)) + if (sporkManager.IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT)) return false; LogPrint("masternode","Budget enforcement is disabled, accepting block\n"); @@ -262,7 +262,7 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight) return true; LogPrint("masternode","Invalid mn payment detected %s\n", txNew.ToString().c_str()); - if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) + if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) return false; LogPrint("masternode","Masternode payment enforcement is disabled, accepting block\n"); @@ -275,7 +275,7 @@ void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStak CBlockIndex* pindexPrev = chainActive.Tip(); if (!pindexPrev) return; - if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(pindexPrev->nHeight + 1)) { + if (sporkManager.IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(pindexPrev->nHeight + 1)) { budget.FillBlockPayee(txNew, nFees, fProofOfStake); } else { masternodePayments.FillBlockPayee(txNew, nFees, fProofOfStake); @@ -284,7 +284,7 @@ void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStak std::string GetRequiredPaymentsString(int nBlockHeight) { - if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nBlockHeight)) { + if (sporkManager.IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nBlockHeight)) { return budget.GetRequiredPaymentsString(nBlockHeight); } else { return masternodePayments.GetRequiredPaymentsString(nBlockHeight); @@ -347,7 +347,10 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFe int CMasternodePayments::GetMinMasternodePaymentsProto() { - return ActiveProtocol(); + if (sporkManager.IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) + return ActiveProtocol(); // Allow only updated peers + else + return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; // Also allow old peers as long as they are allowed to run } void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) @@ -526,7 +529,7 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew) CAmount nReward = GetBlockValue(nBlockHeight); - if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { + if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { // Get a stable number of masternodes by ignoring newly activated (< 8000 sec old) masternodes nMasternode_Drift_Count = mnodeman.stable_size() + Params().MasternodeCountDrift(); } diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index ee46c99f4bcee..242e95feedcee 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -309,7 +309,7 @@ void CMasternodeSync::Process() // timeout if (lastMasternodeList == 0 && (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3 || GetTime() - nAssetSyncStarted > MASTERNODE_SYNC_TIMEOUT * 5)) { - if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { + if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { LogPrintf("CMasternodeSync::Process - ERROR - Sync has failed, will retry later\n"); RequestedMasternodeAssets = MASTERNODE_SYNC_FAILED; RequestedMasternodeAttempt = 0; @@ -340,7 +340,7 @@ void CMasternodeSync::Process() // timeout if (lastMasternodeWinner == 0 && (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3 || GetTime() - nAssetSyncStarted > MASTERNODE_SYNC_TIMEOUT * 5)) { - if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { + if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { LogPrintf("CMasternodeSync::Process - ERROR - Sync has failed, will retry later\n"); RequestedMasternodeAssets = MASTERNODE_SYNC_FAILED; RequestedMasternodeAttempt = 0; diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 198091feb549c..14c0308a000a1 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -359,7 +359,7 @@ int CMasternodeMan::stable_size () if (mn.protocolVersion < nMinProtocol) { continue; // Skip obsolete versions } - if (IsSporkActive (SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { + if (sporkManager.IsSporkActive (SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { nMasternode_Age = GetAdjustedTime() - mn.sigTime; if ((nMasternode_Age) < nMasternode_Min_Age) { continue; // Skip masternodes younger than (default) 8000 sec (MUST be > MASTERNODE_REMOVAL_SECONDS) @@ -608,7 +608,7 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, in continue; // Skip obsolete versions } - if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { + if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { nMasternode_Age = GetAdjustedTime() - mn.sigTime; if ((nMasternode_Age) < nMasternode_Min_Age) { if (fDebug) LogPrint("masternode","Skipping just activated Masternode. Age: %ld\n", nMasternode_Age); @@ -857,7 +857,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData // Light version for OLD MASSTERNODES - fake pings, no self-activation else if (strCommand == NetMsgType::DSEE) { //ObfuScation Election Entry - if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return; + if (sporkManager.IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return; CTxIn vin; CService addr; @@ -1064,7 +1064,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData else if (strCommand == NetMsgType::DSEEP) { //ObfuScation Election Entry Ping - if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return; + if (sporkManager.IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return; CTxIn vin; std::vector vchSig; diff --git a/src/miner.cpp b/src/miner.cpp index 67b9c629e8f31..f76f25c3529e0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -225,7 +225,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet, if (tx.IsCoinBase() || tx.IsCoinStake() || !IsFinalTx(tx, nHeight)){ continue; } - if(GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE) && tx.ContainsZerocoins()){ + if(sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE) && tx.ContainsZerocoins()){ continue; } diff --git a/src/qt/privacydialog.cpp b/src/qt/privacydialog.cpp index 1df70161ab53c..7d35285f86a09 100644 --- a/src/qt/privacydialog.cpp +++ b/src/qt/privacydialog.cpp @@ -162,7 +162,7 @@ void PrivacyDialog::on_pushButtonMintzPHR_clicked() if (!walletModel || !walletModel->getOptionsModel()) return; - if(GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) { + if(sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) { QMessageBox::information(this, tr("Mint Zerocoin"), tr("zPHR is currently undergoing maintenance."), QMessageBox::Ok, QMessageBox::Ok); @@ -272,7 +272,7 @@ void PrivacyDialog::on_pushButtonSpendzPHR_clicked() if (!walletModel || !walletModel->getOptionsModel() || !pwalletMain) return; - if(GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) { + if(sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) { QMessageBox::information(this, tr("Mint Zerocoin"), tr("zPHR is currently undergoing maintenance."), QMessageBox::Ok, QMessageBox::Ok); return; @@ -738,8 +738,9 @@ void PrivacyDialog::keyPressEvent(QKeyEvent* event) void PrivacyDialog::updateSPORK16Status() { // Update/enable labels, buttons and tooltips depending on the current SPORK_16 status - bool fButtonsEnabled = ui->pushButtonMintzPHR->isEnabled(); - bool fMaintenanceMode = GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE); + //bool fButtonsEnabled = ui->pushButtonMintzPIV->isEnabled(); + bool fButtonsEnabled = false; + bool fMaintenanceMode = sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE); if (fMaintenanceMode && fButtonsEnabled) { // Mint zPHR ui->pushButtonMintzPHR->setEnabled(false); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e5d1d02bbc795..31ceb827b2c37 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -325,8 +325,8 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact CReserveKey* keyChange = transaction.getPossibleKeyChange(); - if (recipients[0].useSwiftTX && total > GetSporkValue(SPORK_5_MAX_VALUE) * COIN) { - emit message(tr("Send Coins"), tr("SwiftX doesn't support sending values that high yet. Transactions are currently limited to %1 PHR.").arg(GetSporkValue(SPORK_5_MAX_VALUE)), + if (recipients[0].useSwiftTX && total > sporkManager.GetSporkValue(SPORK_5_MAX_VALUE) * COIN) { + emit message(tr("Send Coins"), tr("SwiftX doesn't support sending values that high yet. Transactions are currently limited to %1 PIV.").arg(sporkManager.GetSporkValue(SPORK_5_MAX_VALUE)), CClientUIInterface::MSG_ERROR); return TransactionCreationFailed; } @@ -334,8 +334,8 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl, recipients[0].inputType, recipients[0].useSwiftTX); transaction.setTransactionFee(nFeeRequired); - if (recipients[0].useSwiftTX && newTx->GetValueOut() > GetSporkValue(SPORK_5_MAX_VALUE) * COIN) { - emit message(tr("Send Coins"), tr("SwiftX doesn't support sending values that high yet. Transactions are currently limited to %1 PHR.").arg(GetSporkValue(SPORK_5_MAX_VALUE)), + if (recipients[0].useSwiftTX && newTx->GetValueOut() > sporkManager.GetSporkValue(SPORK_5_MAX_VALUE) * COIN) { + emit message(tr("Send Coins"), tr("SwiftX doesn't support sending values that high yet. Transactions are currently limited to %1 PIV.").arg(sporkManager.GetSporkValue(SPORK_5_MAX_VALUE)), CClientUIInterface::MSG_ERROR); return TransactionCreationFailed; } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index df002b74e0684..3fe4100cf7f59 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -313,14 +313,14 @@ UniValue spork(const UniValue& params, bool fHelp) UniValue ret(UniValue::VOBJ); for (int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++) { if (sporkManager.GetSporkNameByID(nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), GetSporkValue(nSporkID))); + ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.GetSporkValue(nSporkID))); } return ret; } else if (params.size() == 1 && params[0].get_str() == "active") { UniValue ret(UniValue::VOBJ); for (int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++) { if (sporkManager.GetSporkNameByID(nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), IsSporkActive(nSporkID))); + ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.IsSporkActive(nSporkID))); } return ret; } else if (params.size() == 2) { diff --git a/src/spork.cpp b/src/spork.cpp index 81c906d5b0ec7..c84852f74d6c7 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -3,18 +3,12 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "spork.h" -#include "base58.h" #include "consensus/validation.h" -#include "key.h" #include "main.h" #include "masternode-budget.h" #include "net.h" -#include "protocol.h" -#include "sync.h" +#include "spork.h" #include "sporkdb.h" -#include "util.h" - class CSporkMessage; class CSporkManager; @@ -22,10 +16,9 @@ class CSporkManager; CSporkManager sporkManager; std::map mapSporks; -std::map mapSporksActive; // Phore: on startup load spork values from previous session if they exist in the sporkDB -void LoadSporksFromDB() +void CSporkManager::LoadSporksFromDB() { for (int i = SPORK_START; i <= SPORK_END; ++i) { // Since not all spork IDs are in use, we have to exclude undefined IDs @@ -57,16 +50,17 @@ void LoadSporksFromDB() } } -void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) +void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { - if (fLiteMode) return; //disable all obfuscation/masternode related functionality + if (fLiteMode) return; // disable all obfuscation/masternode related functionality - if (strCommand == NetMsgType::SPORK) { - //LogPrintf("ProcessSpork::spork\n"); + if (strCommand == "spork") { + //LogPrintf("CSporkManager::spork\n"); CDataStream vMsg(vRecv); CSporkMessage spork; vRecv >> spork; + LOCK(cs_main); if (chainActive.Tip() == NULL) return; // Ignore spork messages about unknown/deleted sporks @@ -85,15 +79,16 @@ void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) LogPrintf("spork - new %s ID %d Time %d bestHeight %d\n", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Tip()->nHeight); - if (!sporkManager.CheckSignature(spork)) { - LogPrintf("spork - invalid signature\n"); + bool fRequireNew = spork.nTimeSigned >= Params().NewSporkStart(); + if (!spork.CheckSignature(fRequireNew)) { + LogPrintf("%s : Invalid Signature\n", __func__); Misbehaving(pfrom->GetId(), 100); return; } mapSporks[hash] = spork; mapSporksActive[spork.nSporkID] = spork; - sporkManager.Relay(spork); + spork.Relay(); // Phore: add to spork database. pSporkDB->WriteSpork(spork.nSporkID, spork); @@ -108,9 +103,31 @@ void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) } } +bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue) +{ + + CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetTime()); + + if(spork.Sign(strMasterPrivKey)){ + spork.Relay(); + mapSporks[spork.GetHash()] = spork; + mapSporksActive[nSporkID] = spork; + return true; + } + + return false; +} + +// grab the spork value, and see if it's off +bool CSporkManager::IsSporkActive(int nSporkID) +{ + int64_t r = GetSporkValue(nSporkID); + if (r == -1) return false; + return r < GetAdjustedTime(); +} // grab the value of the spork on the network, or the default -int64_t GetSporkValue(int nSporkID) +int64_t CSporkManager::GetSporkValue(int nSporkID) { int64_t r = -1; @@ -138,166 +155,107 @@ int64_t GetSporkValue(int nSporkID) return r; } -// grab the spork value, and see if it's off -bool IsSporkActive(int nSporkID) +int CSporkManager::GetSporkIDByName(std::string strName) { - if (Params().NetworkID() == CBaseChainParams::REGTEST) { - if(nSporkID == SPORK_13_ENABLE_SUPERBLOCKS) { - return true; - } - } - int64_t r = GetSporkValue(nSporkID); - if (r == -1) return false; - return r < GetTime(); -} + if (strName == "SPORK_2_SWIFTTX") return SPORK_2_SWIFTTX; + if (strName == "SPORK_3_SWIFTTX_BLOCK_FILTERING") return SPORK_3_SWIFTTX_BLOCK_FILTERING; + if (strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE; + if (strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING; + if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT; + if (strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT; + if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES; + if (strName == "SPORK_13_ENABLE_SUPERBLOCKS") return SPORK_13_ENABLE_SUPERBLOCKS; + if (strName == "SPORK_14_NEW_PROTOCOL_ENFORCEMENT") return SPORK_14_NEW_PROTOCOL_ENFORCEMENT; + //if (strName == "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2") return SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2; + if (strName == "SPORK_16_ZEROCOIN_MAINTENANCE_MODE") return SPORK_16_ZEROCOIN_MAINTENANCE_MODE; + if (strName == "SPORK_17_SEGWIT_ACTIVATION") return SPORK_17_SEGWIT_ACTIVATION; + //if (strName == "SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3") return SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3; + if (strName == "SPORK_19_SEGWIT_ON_COINBASE") return SPORK_19_SEGWIT_ON_COINBASE_DEFAULT; + + return -1; +} -void ReprocessBlocks(int nBlocks) +std::string CSporkManager::GetSporkNameByID(int id) { - std::map::iterator it = mapRejectedBlocks.begin(); - while (it != mapRejectedBlocks.end()) { - //use a window twice as large as is usual for the nBlocks we want to reset - if ((*it).second > GetTime() - (nBlocks * 60 * 5)) { - BlockMap::iterator mi = mapBlockIndex.find((*it).first); - if (mi != mapBlockIndex.end() && (*mi).second) { - LOCK(cs_main); - - CBlockIndex* pindex = (*mi).second; - LogPrintf("ReprocessBlocks - %s\n", (*it).first.ToString()); - - CValidationState state; - ReconsiderBlock(state, pindex); - } - } - ++it; - } - - CValidationState state; - { - LOCK(cs_main); - DisconnectBlocksAndReprocess(nBlocks); - } + if (id == SPORK_2_SWIFTTX) return "SPORK_2_SWIFTTX"; + if (id == SPORK_3_SWIFTTX_BLOCK_FILTERING) return "SPORK_3_SWIFTTX_BLOCK_FILTERING"; + if (id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE"; + if (id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING"; + if (id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"; + if (id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT"; + if (id == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES"; + if (id == SPORK_13_ENABLE_SUPERBLOCKS) return "SPORK_13_ENABLE_SUPERBLOCKS"; + if (id == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) return "SPORK_14_NEW_PROTOCOL_ENFORCEMENT"; + if (id == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) return "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2"; + if (id == SPORK_16_ZEROCOIN_MAINTENANCE_MODE) return "SPORK_16_ZEROCOIN_MAINTENANCE_MODE"; - if (state.IsValid()) { - ActivateBestChain(state); - } + return "Unknown"; } -bool CSporkManager::CheckSignature(CSporkMessage& spork) +bool CSporkManager::SetPrivKey(std::string strPrivKey) { - //note: need to investigate why this is failing - std::string strMessage = std::to_string(spork.nSporkID) + std::to_string(spork.nValue) + std::to_string(spork.nTimeSigned); - CPubKey pubkeynew(ParseHex(Params().SporkKey())); - std::string errorMessage = ""; - if (obfuScationSigner.VerifyMessage(pubkeynew, spork.vchSig, strMessage, errorMessage)) { + CSporkMessage spork; + + spork.Sign(strPrivKey); + + const bool fRequireNew = GetTime() >= Params().NewSporkStart(); + if (spork.CheckSignature(fRequireNew)) { + // Test signing successful, proceed + LogPrintf("%s : -- Successfully initialized as spork signer\n", __func__); + strMasterPrivKey = strPrivKey; return true; } return false; } -bool CSporkManager::Sign(CSporkMessage& spork) +bool CSporkMessage::Sign(std::string strSignKey) { - std::string strMessage = std::to_string(spork.nSporkID) + std::to_string(spork.nValue) + std::to_string(spork.nTimeSigned); + std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned); - CKey key2; - CPubKey pubkey2; + CKey key; + CPubKey pubkey; std::string errorMessage = ""; - if (!obfuScationSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2)) { - LogPrintf("CMasternodePayments::Sign - ERROR: Invalid masternodeprivkey: '%s'\n", errorMessage); - return false; + if (!obfuScationSigner.SetKey(strSignKey, errorMessage, key, pubkey)) { + return error("%s : SetKey error: '%s'\n", __func__, errorMessage); } - if (!obfuScationSigner.SignMessage(strMessage, errorMessage, spork.vchSig, key2)) { - LogPrintf("CMasternodePayments::Sign - Sign message failed"); - return false; + if (!obfuScationSigner.SignMessage(strMessage, errorMessage, vchSig, key)) { + return error("%s : Sign message failed", __func__); } - if (!obfuScationSigner.VerifyMessage(pubkey2, spork.vchSig, strMessage, errorMessage)) { - LogPrintf("CMasternodePayments::Sign - Verify message failed"); - return false; + if (!obfuScationSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)) { + return error("%s : Verify message failed", __func__); } return true; } -bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue) +bool CSporkMessage::CheckSignature(bool fRequireNew) { - CSporkMessage msg; - msg.nSporkID = nSporkID; - msg.nValue = nValue; - msg.nTimeSigned = GetTime(); - - if (Sign(msg)) { - Relay(msg); - mapSporks[msg.GetHash()] = msg; - mapSporksActive[nSporkID] = msg; - return true; - } - - return false; -} - -void CSporkManager::Relay(CSporkMessage& msg) -{ - CInv inv(MSG_SPORK, msg.GetHash()); - RelayInv(inv); -} - -bool CSporkManager::SetPrivKey(std::string strPrivKey) -{ - CSporkMessage msg; - - // Test signing successful, proceed - strMasterPrivKey = strPrivKey; + //note: need to investigate why this is failing + std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned); + CPubKey pubkeynew(ParseHex(Params().SporkPubKey())); + std::string errorMessage = ""; - Sign(msg); + bool fValidWithNewKey = obfuScationSigner.VerifyMessage(pubkeynew, vchSig, strMessage, errorMessage); - if (CheckSignature(msg)) { - LogPrintf("CSporkManager::SetPrivKey - Successfully initialized as spork signer\n"); - return true; - } else { + if (fRequireNew && !fValidWithNewKey) return false; + + // See if window is open that allows for old spork key to sign messages + if (!fValidWithNewKey && GetAdjustedTime() < Params().RejectOldSporkKey()) { + CPubKey pubkeyold(ParseHex(Params().SporkPubKeyOld())); + return obfuScationSigner.VerifyMessage(pubkeyold, vchSig, strMessage, errorMessage); } + return fValidWithNewKey; } -int CSporkManager::GetSporkIDByName(std::string strName) +void CSporkMessage::Relay() { - if (strName == "SPORK_2_SWIFTTX") return SPORK_2_SWIFTTX; - if (strName == "SPORK_3_SWIFTTX_BLOCK_FILTERING") return SPORK_3_SWIFTTX_BLOCK_FILTERING; - if (strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE; - if (strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING; - if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT; - if (strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT; - if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES; - if (strName == "SPORK_13_ENABLE_SUPERBLOCKS") return SPORK_13_ENABLE_SUPERBLOCKS; - if (strName == "SPORK_14_NEW_PROTOCOL_ENFORCEMENT") return SPORK_14_NEW_PROTOCOL_ENFORCEMENT; - //if (strName == "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2") return SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2; - if (strName == "SPORK_16_ZEROCOIN_MAINTENANCE_MODE") return SPORK_16_ZEROCOIN_MAINTENANCE_MODE; - if (strName == "SPORK_17_SEGWIT_ACTIVATION") return SPORK_17_SEGWIT_ACTIVATION; - //if (strName == "SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3") return SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3; - if (strName == "SPORK_19_SEGWIT_ON_COINBASE") return SPORK_19_SEGWIT_ON_COINBASE_DEFAULT; - - return -1; + CInv inv(MSG_SPORK, GetHash()); + RelayInv(inv); } -std::string CSporkManager::GetSporkNameByID(int id) -{ - if (id == SPORK_2_SWIFTTX) return "SPORK_2_SWIFTTX"; - if (id == SPORK_3_SWIFTTX_BLOCK_FILTERING) return "SPORK_3_SWIFTTX_BLOCK_FILTERING"; - if (id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE"; - if (id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING"; - if (id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"; - if (id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT"; - if (id == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES"; - if (id == SPORK_13_ENABLE_SUPERBLOCKS) return "SPORK_13_ENABLE_SUPERBLOCKS"; - if (id == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) return "SPORK_14_NEW_PROTOCOL_ENFORCEMENT"; - //if (id == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) return "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2"; - if (id == SPORK_16_ZEROCOIN_MAINTENANCE_MODE) return "SPORK_16_ZEROCOIN_MAINTENANCE_MODE"; - if (id == SPORK_17_SEGWIT_ACTIVATION) return "SPORK_17_SEGWIT_ACTIVATION"; - //if (id == SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3) return "SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3"; - if (id == SPORK_19_SEGWIT_ON_COINBASE) return "SPORK_19_SEGWIT_ON_COINBASE"; - - return "Unknown"; -} diff --git a/src/spork.h b/src/spork.h index 341a11e449edc..e411a50b92586 100644 --- a/src/spork.h +++ b/src/spork.h @@ -7,6 +7,7 @@ #define SPORK_H #include "base58.h" +#include "hash.h" #include "key.h" #include "main.h" #include "net.h" @@ -62,33 +63,31 @@ class CSporkMessage; class CSporkManager; extern std::map mapSporks; -extern std::map mapSporksActive; extern CSporkManager sporkManager; -void LoadSporksFromDB(); -void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); -int64_t GetSporkValue(int nSporkID); -bool IsSporkActive(int nSporkID); -void ReprocessBlocks(int nBlocks); - // -// Spork Class -// Keeps track of all of the network spork settings +// Spork Classes +// Keep track of all of the network spork settings // class CSporkMessage { +private: + + public: std::vector vchSig; int nSporkID; int64_t nValue; int64_t nTimeSigned; - uint256 GetHash() - { - uint256 n = HashQuark(BEGIN(nSporkID), END(nTimeSigned)); - return n; - } + CSporkMessage(int nSporkID, int64_t nValue, int64_t nTimeSigned) : nSporkID(nSporkID), nValue(nValue), nTimeSigned(nTimeSigned) {} + CSporkMessage() : nSporkID(0), nValue(0), nTimeSigned(0) {} + + uint256 GetHash() { return HashQuark(BEGIN(nSporkID), END(nTimeSigned)); } + bool Sign(std::string strSignKey); + bool CheckSignature(bool fRequireNew = false); + void Relay(); ADD_SERIALIZE_METHODS; @@ -108,19 +107,23 @@ class CSporkManager private: std::vector vchSig; std::string strMasterPrivKey; + std::map mapSporksActive; public: - CSporkManager() - { - } + CSporkManager() {} + void LoadSporksFromDB(); + + void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); + int64_t GetSporkValue(int nSporkID); + void ExecuteSpork(int nSporkID, int nValue); + bool UpdateSpork(int nSporkID, int64_t nValue); + + bool IsSporkActive(int nSporkID); std::string GetSporkNameByID(int id); int GetSporkIDByName(std::string strName); - bool UpdateSpork(int nSporkID, int64_t nValue); + bool SetPrivKey(std::string strPrivKey); - bool CheckSignature(CSporkMessage& spork); - bool Sign(CSporkMessage& spork); - void Relay(CSporkMessage& msg); }; #endif diff --git a/src/swifttx.cpp b/src/swifttx.cpp index b519e39443580..673daaee43423 100644 --- a/src/swifttx.cpp +++ b/src/swifttx.cpp @@ -40,7 +40,7 @@ int nCompleteTXLocks; void ProcessMessageSwiftTX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if (fLiteMode) return; //disable all obfuscation/masternode related functionality - if (!IsSporkActive(SPORK_2_SWIFTTX)) return; + if (!sporkManager.IsSporkActive(SPORK_2_SWIFTTX)) return; if (!masternodeSync.IsBlockchainSynced()) return; if (strCommand == NetMsgType::IX) { @@ -200,7 +200,7 @@ bool IsIXTXValid(const CTransaction& txCollateral) } } - if (nValueOut > GetSporkValue(SPORK_5_MAX_VALUE) * COIN) { + if (nValueOut > sporkManager.GetSporkValue(SPORK_5_MAX_VALUE) * COIN) { LogPrint("swiftx", "IsIXTXValid - Transaction value too high - %s\n", txCollateral.ToString().c_str()); return false; } @@ -464,7 +464,7 @@ void CleanTransactionLocksList() int GetTransactionLockSignatures(uint256 txHash) { if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2; - if (!IsSporkActive(SPORK_2_SWIFTTX)) return -1; + if (!sporkManager.IsSporkActive(SPORK_2_SWIFTTX)) return -1; std::map::iterator it = mapTxLocks.find(txHash); if(it != mapTxLocks.end()) return it->second.CountSignatures(); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 12dbfd897fc41..1cd0b7d493d30 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2759,7 +2759,8 @@ UniValue mintzerocoin(const UniValue& params, bool fHelp) } int64_t nTime = GetTimeMillis(); - if(GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) + + if(sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) throw JSONRPCError(RPC_WALLET_ERROR, "zPHR is currently disabled due to maintenance."); EnsureWalletIsUnlocked(true); @@ -2866,19 +2867,17 @@ UniValue spendzerocoin(const UniValue& params, bool fHelp) HelpExampleRpc("spendzerocoin", "5000 false true 100 \"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\"")); LOCK2(cs_main, pwalletMain->cs_wallet); - - if(GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) - throw JSONRPCError(RPC_WALLET_ERROR, "zPHR is currently disabled due to maintenance."); - int64_t nTimeStart = GetTimeMillis(); + if(sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) + throw JSONRPCError(RPC_WALLET_ERROR, "zPIV is currently disabled due to maintenance."); + EnsureWalletIsUnlocked(); CAmount nAmount = AmountFromValue(params[0]); // Spending amount bool fMintChange = params[1].get_bool(); // Mint change to zPHR bool fMinimizeChange = params[2].get_bool(); // Minimize change int nSecurityLevel = params[3].get_int(); // Security level - CTxDestination address = CNoDestination(); // Optional sending address. Dummy initialization here. if (params.size() == 5) { // Destination address was supplied as params[4]. Optional parameters MUST be at the end @@ -3567,4 +3566,4 @@ UniValue searchdzphr(const UniValue& params, bool fHelp) //todo: better response return "done"; -} +} \ No newline at end of file diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f3742cdd9417f..70429a5695942 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3528,7 +3528,7 @@ bool CWallet::LoadDestData(const CTxDestination& dest, const std::string& key, c void CWallet::AutoZeromint() { // Don't bother Autominting if Zerocoin Protocol isn't active - if (GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) return; + if (sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) return; // Wait until blockchain + masternodes are fully synced and wallet is unlocked. if (!masternodeSync.IsSynced() || IsLocked()){ @@ -3955,7 +3955,7 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee, bool int CMerkleTx::GetTransactionLockSignatures() const { if (fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2; - if (!IsSporkActive(SPORK_2_SWIFTTX)) return -3; + if (!sporkManager.IsSporkActive(SPORK_2_SWIFTTX)) return -3; if (!fEnableSwiftTX) return -1; //compile consessus vote From 827d25bf669ac30998d05247e9a4e4402e6b670d Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 15:29:32 +0200 Subject: [PATCH 053/132] [Spork] Protect CSporkManager with critical section --- src/spork.cpp | 41 +++++++++++++++++++++++++++-------------- src/spork.h | 1 + 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/spork.cpp b/src/spork.cpp index c84852f74d6c7..26839281efd77 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -52,28 +52,33 @@ void CSporkManager::LoadSporksFromDB() void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { - if (fLiteMode) return; // disable all obfuscation/masternode related functionality + if (fLiteMode || chainActive.Tip() == nullptr) return; // disable all obfuscation/masternode related functionality if (strCommand == "spork") { - //LogPrintf("CSporkManager::spork\n"); - CDataStream vMsg(vRecv); + CSporkMessage spork; vRecv >> spork; - LOCK(cs_main); - if (chainActive.Tip() == NULL) return; - // Ignore spork messages about unknown/deleted sporks std::string strSpork = sporkManager.GetSporkNameByID(spork.nSporkID); if (strSpork == "Unknown") return; uint256 hash = spork.GetHash(); - if (mapSporksActive.count(spork.nSporkID)) { - if (mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned) { - if (fDebug) LogPrintf("spork - seen %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight); - return; + { + LOCK(cs); + if (mapSporksActive.count(spork.nSporkID)) { + // spork is active + if (mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned) { + // spork in memory has been signed more recently + if (fDebug) LogPrintf("%s : seen %s block %d \n", __func__, hash.ToString(), chainActive.Tip()->nHeight); + return; + } else { + // update active spork + if (fDebug) LogPrintf("%s : got updated spork %s block %d \n", __func__, hash.ToString(), chainActive.Tip()->nHeight); + } } else { - if (fDebug) LogPrintf("spork - got updated spork %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight); + // spork is not active + if (fDebug) LogPrintf("%s : got new spork %s block %d \n", __func__, hash.ToString(), chainActive.Tip()->nHeight); } } @@ -81,19 +86,24 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr bool fRequireNew = spork.nTimeSigned >= Params().NewSporkStart(); if (!spork.CheckSignature(fRequireNew)) { + LOCK(cs_main); LogPrintf("%s : Invalid Signature\n", __func__); Misbehaving(pfrom->GetId(), 100); return; } - mapSporks[hash] = spork; - mapSporksActive[spork.nSporkID] = spork; + { + LOCK(cs); + mapSporks[hash] = spork; + mapSporksActive[spork.nSporkID] = spork; + } spork.Relay(); // Phore: add to spork database. pSporkDB->WriteSpork(spork.nSporkID, spork); } - if (strCommand == NetMsgType::GETSPORKS) { + if (strCommand == "getsporks") { + LOCK(cs); std::map::iterator it = mapSporksActive.begin(); while (it != mapSporksActive.end()) { @@ -110,6 +120,7 @@ bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue) if(spork.Sign(strMasterPrivKey)){ spork.Relay(); + LOCK(cs); mapSporks[spork.GetHash()] = spork; mapSporksActive[nSporkID] = spork; return true; @@ -129,6 +140,7 @@ bool CSporkManager::IsSporkActive(int nSporkID) // grab the value of the spork on the network, or the default int64_t CSporkManager::GetSporkValue(int nSporkID) { + LOCK(cs); int64_t r = -1; if (mapSporksActive.count(nSporkID)) { @@ -201,6 +213,7 @@ bool CSporkManager::SetPrivKey(std::string strPrivKey) const bool fRequireNew = GetTime() >= Params().NewSporkStart(); if (spork.CheckSignature(fRequireNew)) { + LOCK(cs); // Test signing successful, proceed LogPrintf("%s : -- Successfully initialized as spork signer\n", __func__); strMasterPrivKey = strPrivKey; diff --git a/src/spork.h b/src/spork.h index e411a50b92586..4343419a4317a 100644 --- a/src/spork.h +++ b/src/spork.h @@ -105,6 +105,7 @@ class CSporkMessage class CSporkManager { private: + CCriticalSection cs; std::vector vchSig; std::string strMasterPrivKey; std::map mapSporksActive; From 0fba7c16aecb9a3af695ff870335f8db3d78b7ef Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 15:55:57 +0200 Subject: [PATCH 054/132] [Spork] CSporkManager class serialization --- src/spork.cpp | 12 ++++++++++++ src/spork.h | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/spork.cpp b/src/spork.cpp index 26839281efd77..55222acd39786 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -17,6 +17,12 @@ CSporkManager sporkManager; std::map mapSporks; +void CSporkManager::Clear() +{ + strMasterPrivKey = ""; + mapSporksActive.clear(); +} + // Phore: on startup load spork values from previous session if they exist in the sporkDB void CSporkManager::LoadSporksFromDB() { @@ -223,6 +229,12 @@ bool CSporkManager::SetPrivKey(std::string strPrivKey) return false; } +std::string CSporkManager::ToString() const +{ + LOCK(cs); + return strprintf("Sporks: %llu", mapSporksActive.size()); +} + bool CSporkMessage::Sign(std::string strSignKey) { std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned); diff --git a/src/spork.h b/src/spork.h index 4343419a4317a..04d2d242b478c 100644 --- a/src/spork.h +++ b/src/spork.h @@ -105,14 +105,23 @@ class CSporkMessage class CSporkManager { private: - CCriticalSection cs; - std::vector vchSig; + mutable CCriticalSection cs; std::string strMasterPrivKey; std::map mapSporksActive; public: CSporkManager() {} + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { + READWRITE(mapSporksActive); + // we don't serialize private key to prevent its leakage + } + + void Clear(); void LoadSporksFromDB(); void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); @@ -125,6 +134,7 @@ class CSporkManager int GetSporkIDByName(std::string strName); bool SetPrivKey(std::string strPrivKey); + std::string ToString() const; }; #endif From 12cc9728d523377b4b352170b26b5415bb3fe092 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 16:31:15 +0200 Subject: [PATCH 055/132] [Spork] Do not accept sporks signed too far into the future --- src/spork.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/spork.cpp b/src/spork.cpp index 55222acd39786..b0f69dc6f5e01 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -69,6 +69,14 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr std::string strSpork = sporkManager.GetSporkNameByID(spork.nSporkID); if (strSpork == "Unknown") return; + // Do not accept sporks signed way too far into the future + if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) { + LOCK(cs_main); + LogPrintf("%s -- ERROR: too far into the future\n", __func__); + Misbehaving(pfrom->GetId(), 100); + return; + } + uint256 hash = spork.GetHash(); { LOCK(cs); From 03533a4f8a91637145e98cec7e71eb6314f5c1a3 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 16:41:02 +0200 Subject: [PATCH 056/132] [Spork] Remove unused SPORK_7_MASTERNODE_SCANNING --- src/spork.cpp | 3 --- src/spork.h | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/spork.cpp b/src/spork.cpp index b0f69dc6f5e01..3fa53d728fdc8 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -163,7 +163,6 @@ int64_t CSporkManager::GetSporkValue(int nSporkID) if (nSporkID == SPORK_2_SWIFTTX) r = SPORK_2_SWIFTTX_DEFAULT; if (nSporkID == SPORK_3_SWIFTTX_BLOCK_FILTERING) r = SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT; if (nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT; - if (nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING_DEFAULT; if (nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT; if (nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT; if (nSporkID == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) r = SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT; @@ -187,7 +186,6 @@ int CSporkManager::GetSporkIDByName(std::string strName) if (strName == "SPORK_2_SWIFTTX") return SPORK_2_SWIFTTX; if (strName == "SPORK_3_SWIFTTX_BLOCK_FILTERING") return SPORK_3_SWIFTTX_BLOCK_FILTERING; if (strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE; - if (strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING; if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT; if (strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT; if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES; @@ -207,7 +205,6 @@ std::string CSporkManager::GetSporkNameByID(int id) if (id == SPORK_2_SWIFTTX) return "SPORK_2_SWIFTTX"; if (id == SPORK_3_SWIFTTX_BLOCK_FILTERING) return "SPORK_3_SWIFTTX_BLOCK_FILTERING"; if (id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE"; - if (id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING"; if (id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"; if (id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT"; if (id == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES"; diff --git a/src/spork.h b/src/spork.h index 04d2d242b478c..5c21c01cf88cf 100644 --- a/src/spork.h +++ b/src/spork.h @@ -29,7 +29,6 @@ #define SPORK_2_SWIFTTX 10001 #define SPORK_3_SWIFTTX_BLOCK_FILTERING 10002 #define SPORK_5_MAX_VALUE 10004 -#define SPORK_7_MASTERNODE_SCANNING 10006 #define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT 10007 #define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT 10008 #define SPORK_10_MASTERNODE_PAY_UPDATED_NODES 10009 @@ -45,8 +44,7 @@ #define SPORK_2_SWIFTTX_DEFAULT 978307200 //2001-1-1 #define SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT 1424217600 //2015-2-18 -#define SPORK_5_MAX_VALUE_DEFAULT 1000 //1000 PHR -#define SPORK_7_MASTERNODE_SCANNING_DEFAULT 978307200 //2001-1-1 +#define SPORK_5_MAX_VALUE_DEFAULT 1000 //1000 PIV #define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT 4070908800 //OFF #define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT 4070908800 //OFF #define SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT 4070908800 //OFF From 6f072294e841c2a408c81a3668e3a733ad0421ec Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 16:41:52 +0200 Subject: [PATCH 057/132] [Spork] Remove unused SPORK_11 and SPORK_12 --- src/spork.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/spork.h b/src/spork.h index 5c21c01cf88cf..7a5f2407587a8 100644 --- a/src/spork.h +++ b/src/spork.h @@ -32,8 +32,6 @@ #define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT 10007 #define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT 10008 #define SPORK_10_MASTERNODE_PAY_UPDATED_NODES 10009 -//#define SPORK_11_LOCK_INVALID_UTXO 10010 -//#define SPORK_12_RECONSIDER_BLOCKS 10011 #define SPORK_13_ENABLE_SUPERBLOCKS 10012 #define SPORK_14_NEW_PROTOCOL_ENFORCEMENT 10013 //#define SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2 10014 @@ -48,7 +46,6 @@ #define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT 4070908800 //OFF #define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT 4070908800 //OFF #define SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT 4070908800 //OFF -//#define SPORK_11_LOCK_INVALID_UTXO_DEFAULT 4070908800 //OFF - NOTE: this is block height not time! #define SPORK_13_ENABLE_SUPERBLOCKS_DEFAULT 4070908800 //OFF #define SPORK_14_NEW_PROTOCOL_ENFORCEMENT_DEFAULT 4070908800 //OFF //#define SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2_DEFAULT 4070908800 //OFF From 87dd5252a92a995ad331d4dbd531f2003625bf0f Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 18:54:22 +0200 Subject: [PATCH 058/132] [Spork] Define SporkId enum (with its serialization) --- src/Makefile.am | 1 + src/rpc/misc.cpp | 13 ++++++++----- src/serialize.h | 18 ++++++++++++++++++ src/spork.cpp | 24 ++++++++++++------------ src/spork.h | 42 ++++++++++-------------------------------- src/sporkdb.cpp | 6 +++--- src/sporkdb.h | 6 +++--- src/sporkid.h | 33 +++++++++++++++++++++++++++++++++ 8 files changed, 88 insertions(+), 55 deletions(-) create mode 100644 src/sporkid.h diff --git a/src/Makefile.am b/src/Makefile.am index 435e18e115271..cc0cb95935dc1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -156,6 +156,7 @@ BITCOIN_CORE_H = \ support/allocators/zeroafterfree.h \ spork.h \ sporkdb.h \ + sporkid.h \ streams.h \ support/cleanse.h \ sync.h \ diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 3fe4100cf7f59..e7a4e4151cded 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -309,23 +309,26 @@ class DescribeAddressVisitor : public boost::static_visitor */ UniValue spork(const UniValue& params, bool fHelp) { + SporkId nSporkID; if (params.size() == 1 && params[0].get_str() == "show") { UniValue ret(UniValue::VOBJ); - for (int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++) { - if (sporkManager.GetSporkNameByID(nSporkID) != "Unknown") + for (int i = SPORK_START; i <= SPORK_END; i++) { + nSporkID = (SporkId) i; + if (sporkManager.GetSporkNameByID((SporkId) nSporkID) != "Unknown") ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.GetSporkValue(nSporkID))); } return ret; } else if (params.size() == 1 && params[0].get_str() == "active") { UniValue ret(UniValue::VOBJ); - for (int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++) { + for (int i = SPORK_START; i <= SPORK_END; i++) { + nSporkID = (SporkId) i; if (sporkManager.GetSporkNameByID(nSporkID) != "Unknown") ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.IsSporkActive(nSporkID))); } return ret; } else if (params.size() == 2) { - int nSporkID = sporkManager.GetSporkIDByName(params[0].get_str()); - if (nSporkID == -1) { + nSporkID = sporkManager.GetSporkIDByName(params[0].get_str()); + if (nSporkID == SPORK_INVALID) { return "Invalid spork name"; } diff --git a/src/serialize.h b/src/serialize.h index 3d9350a564d83..d9013fbec8e3b 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -20,6 +20,7 @@ #include #include "libzerocoin/Denominations.h" #include "libzerocoin/SpendType.h" +#include "sporkid.h" class CScript; @@ -290,6 +291,23 @@ inline void Unserialize(Stream& s, libzerocoin::SpendType & a, int, int = 0) a = static_cast(f); } +// Serialization for SporkId +inline unsigned int GetSerializeSize(SporkId sporkID, int, int = 0) { return sizeof(SporkId); } +template +inline void Serialize(Stream& s, SporkId sporkID, int, int = 0) +{ + int32_t f = static_cast(sporkID); + WRITEDATA(s, f); +} + +template +inline void Unserialize(Stream& s, SporkId& sporkID, int, int = 0) +{ + int32_t f=0; + READDATA(s, f); + sporkID = (SporkId) f; +} + /** * Compact Size * size < 253 -- 1 byte diff --git a/src/spork.cpp b/src/spork.cpp index 3fa53d728fdc8..9d75098b1d549 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -26,16 +26,16 @@ void CSporkManager::Clear() // Phore: on startup load spork values from previous session if they exist in the sporkDB void CSporkManager::LoadSporksFromDB() { + SporkId id; for (int i = SPORK_START; i <= SPORK_END; ++i) { + id = (SporkId) i; // Since not all spork IDs are in use, we have to exclude undefined IDs - std::string strSpork = sporkManager.GetSporkNameByID(i); - if (strSpork == "Unknown") { - LogPrintf("%s : unknown spork ID %d\n", __func__, i); - continue; - } + std::string strSpork = sporkManager.GetSporkNameByID(id); + if (strSpork == "Unknown") continue; + // attempt to read spork from sporkDB CSporkMessage spork; - if (!pSporkDB->ReadSpork(i, spork)) { + if (!pSporkDB->ReadSpork(id, spork)) { LogPrintf("%s : no previous value for %s found in database\n", __func__, strSpork); continue; } @@ -127,7 +127,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr } } -bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue) +bool CSporkManager::UpdateSpork(SporkId nSporkID, int64_t nValue) { CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetTime()); @@ -144,7 +144,7 @@ bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue) } // grab the spork value, and see if it's off -bool CSporkManager::IsSporkActive(int nSporkID) +bool CSporkManager::IsSporkActive(SporkId nSporkID) { int64_t r = GetSporkValue(nSporkID); if (r == -1) return false; @@ -152,7 +152,7 @@ bool CSporkManager::IsSporkActive(int nSporkID) } // grab the value of the spork on the network, or the default -int64_t CSporkManager::GetSporkValue(int nSporkID) +int64_t CSporkManager::GetSporkValue(SporkId nSporkID) { LOCK(cs); int64_t r = -1; @@ -180,7 +180,7 @@ int64_t CSporkManager::GetSporkValue(int nSporkID) return r; } -int CSporkManager::GetSporkIDByName(std::string strName) +SporkId CSporkManager::GetSporkIDByName(std::string strName) { if (strName == "SPORK_2_SWIFTTX") return SPORK_2_SWIFTTX; @@ -197,10 +197,10 @@ int CSporkManager::GetSporkIDByName(std::string strName) //if (strName == "SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3") return SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3; if (strName == "SPORK_19_SEGWIT_ON_COINBASE") return SPORK_19_SEGWIT_ON_COINBASE_DEFAULT; - return -1; + return SPORK_INVALID; } -std::string CSporkManager::GetSporkNameByID(int id) +std::string CSporkManager::GetSporkNameByID(SporkId id) { if (id == SPORK_2_SWIFTTX) return "SPORK_2_SWIFTTX"; if (id == SPORK_3_SWIFTTX_BLOCK_FILTERING) return "SPORK_3_SWIFTTX_BLOCK_FILTERING"; diff --git a/src/spork.h b/src/spork.h index 7a5f2407587a8..4c25b60db267f 100644 --- a/src/spork.h +++ b/src/spork.h @@ -11,35 +11,13 @@ #include "key.h" #include "main.h" #include "net.h" +#include "sporkid.h" #include "sync.h" #include "util.h" #include "obfuscation.h" #include "protocol.h" -/* - Don't ever reuse these IDs for other sporks - - This would result in old clients getting confused about which spork is for what - - Sporks 11,12, and 16 to be removed with 1st zerocoin release -*/ -#define SPORK_START 10001 -#define SPORK_END 10018 - -#define SPORK_2_SWIFTTX 10001 -#define SPORK_3_SWIFTTX_BLOCK_FILTERING 10002 -#define SPORK_5_MAX_VALUE 10004 -#define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT 10007 -#define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT 10008 -#define SPORK_10_MASTERNODE_PAY_UPDATED_NODES 10009 -#define SPORK_13_ENABLE_SUPERBLOCKS 10012 -#define SPORK_14_NEW_PROTOCOL_ENFORCEMENT 10013 -//#define SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2 10014 -#define SPORK_16_ZEROCOIN_MAINTENANCE_MODE 10015 -#define SPORK_17_SEGWIT_ACTIVATION 10016 -//#define SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3 10017 -#define SPORK_19_SEGWIT_ON_COINBASE 10018 - #define SPORK_2_SWIFTTX_DEFAULT 978307200 //2001-1-1 #define SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT 1424217600 //2015-2-18 #define SPORK_5_MAX_VALUE_DEFAULT 1000 //1000 PIV @@ -72,12 +50,12 @@ class CSporkMessage public: std::vector vchSig; - int nSporkID; + SporkId nSporkID; int64_t nValue; int64_t nTimeSigned; - CSporkMessage(int nSporkID, int64_t nValue, int64_t nTimeSigned) : nSporkID(nSporkID), nValue(nValue), nTimeSigned(nTimeSigned) {} - CSporkMessage() : nSporkID(0), nValue(0), nTimeSigned(0) {} + CSporkMessage(SporkId nSporkID, int64_t nValue, int64_t nTimeSigned) : nSporkID(nSporkID), nValue(nValue), nTimeSigned(nTimeSigned) {} + CSporkMessage() : nSporkID((SporkId)0), nValue(0), nTimeSigned(0) {} uint256 GetHash() { return HashQuark(BEGIN(nSporkID), END(nTimeSigned)); } bool Sign(std::string strSignKey); @@ -120,13 +98,13 @@ class CSporkManager void LoadSporksFromDB(); void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); - int64_t GetSporkValue(int nSporkID); - void ExecuteSpork(int nSporkID, int nValue); - bool UpdateSpork(int nSporkID, int64_t nValue); + int64_t GetSporkValue(SporkId nSporkID); + void ExecuteSpork(SporkId nSporkID, int nValue); + bool UpdateSpork(SporkId nSporkID, int64_t nValue); - bool IsSporkActive(int nSporkID); - std::string GetSporkNameByID(int id); - int GetSporkIDByName(std::string strName); + bool IsSporkActive(SporkId nSporkID); + std::string GetSporkNameByID(SporkId id); + SporkId GetSporkIDByName(std::string strName); bool SetPrivKey(std::string strPrivKey); std::string ToString() const; diff --git a/src/sporkdb.cpp b/src/sporkdb.cpp index 79be1dc7a78ad..c957cca8aceae 100644 --- a/src/sporkdb.cpp +++ b/src/sporkdb.cpp @@ -7,19 +7,19 @@ CSporkDB::CSporkDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "sporks", nCacheSize, fMemory, fWipe) {} -bool CSporkDB::WriteSpork(const int nSporkId, const CSporkMessage& spork) +bool CSporkDB::WriteSpork(const SporkId nSporkId, const CSporkMessage& spork) { LogPrintf("Wrote spork %s to database\n", sporkManager.GetSporkNameByID(nSporkId)); return Write(nSporkId, spork); } -bool CSporkDB::ReadSpork(const int nSporkId, CSporkMessage& spork) +bool CSporkDB::ReadSpork(const SporkId nSporkId, CSporkMessage& spork) { return Read(nSporkId, spork); } -bool CSporkDB::SporkExists(const int nSporkId) +bool CSporkDB::SporkExists(const SporkId nSporkId) { return Exists(nSporkId); } diff --git a/src/sporkdb.h b/src/sporkdb.h index 9d44110227e79..49de00f94cfaa 100644 --- a/src/sporkdb.h +++ b/src/sporkdb.h @@ -19,9 +19,9 @@ class CSporkDB : public CLevelDBWrapper void operator=(const CSporkDB&); public: - bool WriteSpork(const int nSporkId, const CSporkMessage& spork); - bool ReadSpork(const int nSporkId, CSporkMessage& spork); - bool SporkExists(const int nSporkId); + bool WriteSpork(const SporkId nSporkId, const CSporkMessage& spork); + bool ReadSpork(const SporkId nSporkId, CSporkMessage& spork); + bool SporkExists(const SporkId nSporkId); }; diff --git a/src/sporkid.h b/src/sporkid.h new file mode 100644 index 0000000000000..4f218cedfb276 --- /dev/null +++ b/src/sporkid.h @@ -0,0 +1,33 @@ +// Copyright (c) 2014-2016 The Dash developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef SPORKID_H +#define SPORKID_H + +/* + Don't ever reuse these IDs for other sporks + - This would result in old clients getting confused about which spork is for what +*/ + +enum SporkId : int32_t { + SPORK_2_SWIFTTX = 10001, + SPORK_3_SWIFTTX_BLOCK_FILTERING = 10002, + SPORK_5_MAX_VALUE = 10004, + SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT = 10007, + SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT = 10008, + SPORK_10_MASTERNODE_PAY_UPDATED_NODES = 10009, + SPORK_13_ENABLE_SUPERBLOCKS = 10012, + SPORK_14_NEW_PROTOCOL_ENFORCEMENT = 10013, + //SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2 = 10014, + SPORK_16_ZEROCOIN_MAINTENANCE_MODE = 10015, + SPORK_17_SEGWIT_ACTIVATION = 10016, + //SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3 = 10017, + SPORK_19_SEGWIT_ON_COINBASE = 10018, + + SPORK_START = SPORK_2_SWIFTTX, + SPORK_END = SPORK_19_SEGWIT_ON_COINBASE, + SPORK_INVALID = -1 +}; + +#endif From cadd04821d529d6ac149e70bef31a6a609e147f9 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 19:45:05 +0200 Subject: [PATCH 059/132] [Spork] Introduce CSporkDef and remove if/else blocks --- src/spork.cpp | 99 +++++++++++++++++++++++++-------------------------- src/spork.h | 20 +++-------- src/sporkid.h | 10 ++++++ 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/src/spork.cpp b/src/spork.cpp index 9d75098b1d549..fb21af52b6435 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -17,6 +17,32 @@ CSporkManager sporkManager; std::map mapSporks; +#define MAKE_SPORK_DEF(name, defaultValue) CSporkDef(name, defaultValue, #name) + +std::vector sporkDefs = { + MAKE_SPORK_DEF(SPORK_2_SWIFTTX, 0), // ON + MAKE_SPORK_DEF(SPORK_3_SWIFTTX_BLOCK_FILTERING, 0), // ON + MAKE_SPORK_DEF(SPORK_5_MAX_VALUE, 1000), // 1000 PIV + MAKE_SPORK_DEF(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_10_MASTERNODE_PAY_UPDATED_NODES, 0), // OFF + MAKE_SPORK_DEF(SPORK_13_ENABLE_SUPERBLOCKS, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_14_NEW_PROTOCOL_ENFORCEMENT, 4070908800ULL), // OFF + //MAKE_SPORK_DEF(SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_16_ZEROCOIN_MAINTENANCE_MODE, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_17_SEGWIT_ACTIVATION, 4070908800ULL), // OFF + //MAKE_SPORK_DEF(SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_19_SEGWIT_ON_COINBASE, 4070908800ULL), // OFF +}; + +CSporkManager::CSporkManager() +{ + for (auto& sporkDef : sporkDefs) { + sporkDefsById.emplace(sporkDef.sporkId, &sporkDef); + sporkDefsByName.emplace(sporkDef.name, &sporkDef); + } +} + void CSporkManager::Clear() { strMasterPrivKey = ""; @@ -146,74 +172,47 @@ bool CSporkManager::UpdateSpork(SporkId nSporkID, int64_t nValue) // grab the spork value, and see if it's off bool CSporkManager::IsSporkActive(SporkId nSporkID) { - int64_t r = GetSporkValue(nSporkID); - if (r == -1) return false; - return r < GetAdjustedTime(); + return GetSporkValue(nSporkID) < GetAdjustedTime(); } // grab the value of the spork on the network, or the default int64_t CSporkManager::GetSporkValue(SporkId nSporkID) { LOCK(cs); - int64_t r = -1; if (mapSporksActive.count(nSporkID)) { - r = mapSporksActive[nSporkID].nValue; + return mapSporksActive[nSporkID].nValue; + } else { - if (nSporkID == SPORK_2_SWIFTTX) r = SPORK_2_SWIFTTX_DEFAULT; - if (nSporkID == SPORK_3_SWIFTTX_BLOCK_FILTERING) r = SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT; - if (nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT; - if (nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT; - if (nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT; - if (nSporkID == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) r = SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT; - if (nSporkID == SPORK_13_ENABLE_SUPERBLOCKS) r = SPORK_13_ENABLE_SUPERBLOCKS_DEFAULT; - if (nSporkID == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) r = SPORK_14_NEW_PROTOCOL_ENFORCEMENT_DEFAULT; - //if (nSporkID == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) r = SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2_DEFAULT; - if (nSporkID == SPORK_16_ZEROCOIN_MAINTENANCE_MODE) r = SPORK_16_ZEROCOIN_MAINTENANCE_MODE_DEFAULT; - if (nSporkID == SPORK_17_SEGWIT_ACTIVATION) r = SPORK_17_SEGWIT_ACTIVATION_DEFAULT; - //if (nSporkID == SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3) r = SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3_DEFAULT; - if (nSporkID == SPORK_19_SEGWIT_ON_COINBASE) r = SPORK_19_SEGWIT_ON_COINBASE_DEFAULT; - - if (r == -1) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID); + auto it = sporkDefsById.find(nSporkID); + if (it != sporkDefsById.end()) { + return it->second->defaultValue; + } else { + LogPrintf("%s : Unknown Spork %d\n", __func__, nSporkID); + } } - return r; + return -1; } SporkId CSporkManager::GetSporkIDByName(std::string strName) { - - if (strName == "SPORK_2_SWIFTTX") return SPORK_2_SWIFTTX; - if (strName == "SPORK_3_SWIFTTX_BLOCK_FILTERING") return SPORK_3_SWIFTTX_BLOCK_FILTERING; - if (strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE; - if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT; - if (strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT; - if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES; - if (strName == "SPORK_13_ENABLE_SUPERBLOCKS") return SPORK_13_ENABLE_SUPERBLOCKS; - if (strName == "SPORK_14_NEW_PROTOCOL_ENFORCEMENT") return SPORK_14_NEW_PROTOCOL_ENFORCEMENT; - //if (strName == "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2") return SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2; - if (strName == "SPORK_16_ZEROCOIN_MAINTENANCE_MODE") return SPORK_16_ZEROCOIN_MAINTENANCE_MODE; - if (strName == "SPORK_17_SEGWIT_ACTIVATION") return SPORK_17_SEGWIT_ACTIVATION; - //if (strName == "SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3") return SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3; - if (strName == "SPORK_19_SEGWIT_ON_COINBASE") return SPORK_19_SEGWIT_ON_COINBASE_DEFAULT; - - return SPORK_INVALID; + auto it = sporkDefsByName.find(strName); + if (it == sporkDefsByName.end()) { + LogPrintf("%s -- Unknown Spork name '%s'\n", __func__, strName); + return SPORK_INVALID; + } + return it->second->sporkId; } -std::string CSporkManager::GetSporkNameByID(SporkId id) +std::string CSporkManager::GetSporkNameByID(SporkId nSporkID) { - if (id == SPORK_2_SWIFTTX) return "SPORK_2_SWIFTTX"; - if (id == SPORK_3_SWIFTTX_BLOCK_FILTERING) return "SPORK_3_SWIFTTX_BLOCK_FILTERING"; - if (id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE"; - if (id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"; - if (id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT"; - if (id == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES"; - if (id == SPORK_13_ENABLE_SUPERBLOCKS) return "SPORK_13_ENABLE_SUPERBLOCKS"; - if (id == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) return "SPORK_14_NEW_PROTOCOL_ENFORCEMENT"; - if (id == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) return "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2"; - if (id == SPORK_16_ZEROCOIN_MAINTENANCE_MODE) return "SPORK_16_ZEROCOIN_MAINTENANCE_MODE"; - - return "Unknown"; + auto it = sporkDefsById.find(nSporkID); + if (it == sporkDefsById.end()) { + LogPrint("%s -- Unknown Spork ID %d\n", __func__, nSporkID); + return "Unknown"; + } + return it->second->name; } bool CSporkManager::SetPrivKey(std::string strPrivKey) diff --git a/src/spork.h b/src/spork.h index 4c25b60db267f..ba5ad8e29a43b 100644 --- a/src/spork.h +++ b/src/spork.h @@ -6,6 +6,8 @@ #ifndef SPORK_H #define SPORK_H +#include + #include "base58.h" #include "hash.h" #include "key.h" @@ -18,20 +20,6 @@ #include "obfuscation.h" #include "protocol.h" -#define SPORK_2_SWIFTTX_DEFAULT 978307200 //2001-1-1 -#define SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT 1424217600 //2015-2-18 -#define SPORK_5_MAX_VALUE_DEFAULT 1000 //1000 PIV -#define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT 4070908800 //OFF -#define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT 4070908800 //OFF -#define SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT 4070908800 //OFF -#define SPORK_13_ENABLE_SUPERBLOCKS_DEFAULT 4070908800 //OFF -#define SPORK_14_NEW_PROTOCOL_ENFORCEMENT_DEFAULT 4070908800 //OFF -//#define SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2_DEFAULT 4070908800 //OFF -#define SPORK_16_ZEROCOIN_MAINTENANCE_MODE_DEFAULT 4070908800 //OFF -#define SPORK_17_SEGWIT_ACTIVATION_DEFAULT 4070908800 //OFF -//#define SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3_DEFAULT 4070908800 //OFF -#define SPORK_19_SEGWIT_ON_COINBASE_DEFAULT 4070908800 //OFF - class CSporkMessage; class CSporkManager; @@ -80,10 +68,12 @@ class CSporkManager private: mutable CCriticalSection cs; std::string strMasterPrivKey; + std::unordered_map sporkDefsById; + std::unordered_map sporkDefsByName; std::map mapSporksActive; public: - CSporkManager() {} + CSporkManager(); ADD_SERIALIZE_METHODS; diff --git a/src/sporkid.h b/src/sporkid.h index 4f218cedfb276..0d45038188893 100644 --- a/src/sporkid.h +++ b/src/sporkid.h @@ -30,4 +30,14 @@ enum SporkId : int32_t { SPORK_INVALID = -1 }; +// Default values +struct CSporkDef +{ + CSporkDef(): sporkId(SPORK_INVALID), defaultValue(0) {} + CSporkDef(SporkId id, int64_t val, std::string n): sporkId(id), defaultValue(val), name(n) {} + SporkId sporkId; + int64_t defaultValue; + std::string name; +}; + #endif From 219a1ee9038c3c580dff7d2fc71887360e1d1f40 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 19:53:19 +0200 Subject: [PATCH 060/132] [Spork] Make CSporkMessage::vchSig private --- src/spork.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/spork.h b/src/spork.h index ba5ad8e29a43b..c1583dc7bc2cd 100644 --- a/src/spork.h +++ b/src/spork.h @@ -34,10 +34,9 @@ extern CSporkManager sporkManager; class CSporkMessage { private: - + std::vector vchSig; public: - std::vector vchSig; SporkId nSporkID; int64_t nValue; int64_t nTimeSigned; From 1fe8c49ca6dc22f3928fe449ce81c6a62bb139b6 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 22:21:26 +0200 Subject: [PATCH 061/132] Fix spork RPC to use new spork defs This also removes the need for SPORK_START/SPORK_END --- src/rpc/misc.cpp | 20 +++++++++----------- src/spork.cpp | 21 ++++++--------------- src/spork.h | 1 + src/sporkid.h | 4 +--- 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index e7a4e4151cded..1c4552b83e320 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -28,6 +28,8 @@ #include +extern std::vector sporkDefs; + /** * @note Do not add or change anything in the information returned by this @@ -309,27 +311,23 @@ class DescribeAddressVisitor : public boost::static_visitor */ UniValue spork(const UniValue& params, bool fHelp) { - SporkId nSporkID; if (params.size() == 1 && params[0].get_str() == "show") { UniValue ret(UniValue::VOBJ); - for (int i = SPORK_START; i <= SPORK_END; i++) { - nSporkID = (SporkId) i; - if (sporkManager.GetSporkNameByID((SporkId) nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.GetSporkValue(nSporkID))); + for (const auto& sporkDef : sporkDefs) { + ret.push_back(Pair(sporkDef.name, sporkManager.GetSporkValue(sporkDef.sporkId))); } return ret; } else if (params.size() == 1 && params[0].get_str() == "active") { UniValue ret(UniValue::VOBJ); - for (int i = SPORK_START; i <= SPORK_END; i++) { - nSporkID = (SporkId) i; - if (sporkManager.GetSporkNameByID(nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.IsSporkActive(nSporkID))); + for (const auto& sporkDef : sporkDefs) { + ret.push_back(Pair(sporkDef.name, sporkManager.IsSporkActive(sporkDef.sporkId))); } return ret; } else if (params.size() == 2) { - nSporkID = sporkManager.GetSporkIDByName(params[0].get_str()); + // advanced mode, update spork values + SporkId nSporkID = sporkManager.GetSporkIDByName(params[0].get_str()); if (nSporkID == SPORK_INVALID) { - return "Invalid spork name"; + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid spork name"); } // SPORK VALUE diff --git a/src/spork.cpp b/src/spork.cpp index fb21af52b6435..5daa11f101944 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -10,12 +10,6 @@ #include "spork.h" #include "sporkdb.h" -class CSporkMessage; -class CSporkManager; - -CSporkManager sporkManager; - -std::map mapSporks; #define MAKE_SPORK_DEF(name, defaultValue) CSporkDef(name, defaultValue, #name) @@ -35,6 +29,9 @@ std::vector sporkDefs = { MAKE_SPORK_DEF(SPORK_19_SEGWIT_ON_COINBASE, 4070908800ULL), // OFF }; +CSporkManager sporkManager; +std::map mapSporks; + CSporkManager::CSporkManager() { for (auto& sporkDef : sporkDefs) { @@ -52,17 +49,11 @@ void CSporkManager::Clear() // Phore: on startup load spork values from previous session if they exist in the sporkDB void CSporkManager::LoadSporksFromDB() { - SporkId id; - for (int i = SPORK_START; i <= SPORK_END; ++i) { - id = (SporkId) i; - // Since not all spork IDs are in use, we have to exclude undefined IDs - std::string strSpork = sporkManager.GetSporkNameByID(id); - if (strSpork == "Unknown") continue; - + for (const auto& sporkDef : sporkDefs) { // attempt to read spork from sporkDB CSporkMessage spork; - if (!pSporkDB->ReadSpork(id, spork)) { - LogPrintf("%s : no previous value for %s found in database\n", __func__, strSpork); + if (!pSporkDB->ReadSpork(sporkDef.sporkId, spork)) { + LogPrintf("%s : no previous value for %s found in database\n", __func__, sporkDef.name); continue; } diff --git a/src/spork.h b/src/spork.h index c1583dc7bc2cd..a07450ea71a29 100644 --- a/src/spork.h +++ b/src/spork.h @@ -23,6 +23,7 @@ class CSporkMessage; class CSporkManager; +extern std::vector sporkDefs; extern std::map mapSporks; extern CSporkManager sporkManager; diff --git a/src/sporkid.h b/src/sporkid.h index 0d45038188893..1d2590d609c1b 100644 --- a/src/sporkid.h +++ b/src/sporkid.h @@ -24,9 +24,7 @@ enum SporkId : int32_t { SPORK_17_SEGWIT_ACTIVATION = 10016, //SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3 = 10017, SPORK_19_SEGWIT_ON_COINBASE = 10018, - - SPORK_START = SPORK_2_SWIFTTX, - SPORK_END = SPORK_19_SEGWIT_ON_COINBASE, + SPORK_INVALID = -1 }; From 662b4b6636c5de08c5216878bb0493839838b12f Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 22:25:57 +0200 Subject: [PATCH 062/132] [Core] ReprocessBlocks: adjust to PIVX blocktime --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 7e1a8393388e6..b5b41a31f94b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3462,7 +3462,7 @@ void ReprocessBlocks(int nBlocks) std::map::iterator it = mapRejectedBlocks.begin(); while (it != mapRejectedBlocks.end()) { //use a window twice as large as is usual for the nBlocks we want to reset - if ((*it).second > GetTime() - (nBlocks * 60 * 5)) { + if ((*it).second > GetTime() - (nBlocks * Params().TargetSpacing() * 2)) { BlockMap::iterator mi = mapBlockIndex.find((*it).first); if (mi != mapBlockIndex.end() && (*mi).second) { LOCK(cs_main); From f1d7b5213d1f49140909f4cc3d8586199a8fd38a Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 10 Sep 2019 23:56:41 +0200 Subject: [PATCH 063/132] [Tests] spork functional test: check spork value after node restart --- src/sporkid.h | 2 +- test/functional/rpc_spork.py | 93 ++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100755 test/functional/rpc_spork.py diff --git a/src/sporkid.h b/src/sporkid.h index 1d2590d609c1b..2e0377d08f96c 100644 --- a/src/sporkid.h +++ b/src/sporkid.h @@ -24,7 +24,7 @@ enum SporkId : int32_t { SPORK_17_SEGWIT_ACTIVATION = 10016, //SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3 = 10017, SPORK_19_SEGWIT_ON_COINBASE = 10018, - + SPORK_INVALID = -1 }; diff --git a/test/functional/rpc_spork.py b/test/functional/rpc_spork.py new file mode 100755 index 0000000000000..0eac7fc38539d --- /dev/null +++ b/test/functional/rpc_spork.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The PIVX developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# -*- coding: utf-8 -*- + +from time import sleep + +from test_framework.mininode import network_thread_start +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import connect_nodes_bi, p2p_port +from fake_stake.util import TestNode + + +class PHORE_RPCSporkTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 2 + self.extra_args = [['-staking=1']] * self.num_nodes + self.extra_args[0].append('-sporkkey=932HEevBSujW2ud7RfB1YF91AFygbBRQj3de3LyaCRqNzKKgWXi') + + + def setup_network(self): + ''' Can't rely on syncing all the nodes when staking=1 + :param: + :return: + ''' + self.setup_nodes() + for i in range(self.num_nodes - 1): + for j in range(i+1, self.num_nodes): + connect_nodes_bi(self.nodes, i, j) + + def init_test(self): + ''' Initializes test parameters + :param: + :return: + ''' + title = "*** Starting %s ***" % self.__class__.__name__ + underline = "-" * len(title) + self.log.info("\n\n%s\n%s\n%s\n", title, underline, self.description) + + # Setup the p2p connections and start up the network thread. + self.test_nodes = [] + for i in range(self.num_nodes): + self.test_nodes.append(TestNode()) + self.test_nodes[i].peer_connect('127.0.0.1', p2p_port(i)) + + network_thread_start() # Start up network handling in another thread + self.node = self.nodes[0] + + # Let the test nodes get in sync + for i in range(self.num_nodes): + self.test_nodes[i].wait_for_verack() + + + def printDict(self, d): + self.log.info("{") + for k in d: + self.log.info(" %s = %d" % (k, d[k])) + self.log.info("}") + + + def run_test(self): + self.description = "Performs tests on the Spork RPC" + # check spork values: + sporks = self.nodes[1].spork("show") + self.printDict(sporks) + active = self.nodes[1].spork("active") + assert(not active["SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"]) + # activate SPORK 8 + new_value = 1563253447 + res = self.nodes[0].spork("SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT", new_value) + assert(res == "success") + sleep(1) + self.sync_all() + sporks = self.nodes[1].spork("show") + self.printDict(sporks) + assert(sporks["SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"] == new_value) + active = self.nodes[0].spork("active") + assert (active["SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"]) + self.log.info("Stopping nodes...") + self.stop_nodes() + self.log.info("Restarting node 1...") + self.start_node(1, []) + sporks = self.nodes[1].spork("show") + self.printDict(sporks) + assert (sporks["SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT"] == new_value) + + + +if __name__ == '__main__': + PIVX_RPCSporkTest().main() + From 1e1ecfe5d093fa557fb90d92473458d005f1c835 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 11 Sep 2019 18:31:24 +0200 Subject: [PATCH 064/132] [Spork] fix CSporkManager maps --- src/spork.cpp | 2 +- src/spork.h | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/spork.cpp b/src/spork.cpp index 5daa11f101944..de8f570eb87a3 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -135,7 +135,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr } if (strCommand == "getsporks") { LOCK(cs); - std::map::iterator it = mapSporksActive.begin(); + std::map::iterator it = mapSporksActive.begin(); while (it != mapSporksActive.end()) { pfrom->PushMessage(NetMsgType::SPORK, it->second); diff --git a/src/spork.h b/src/spork.h index a07450ea71a29..0f6370f3b1fce 100644 --- a/src/spork.h +++ b/src/spork.h @@ -6,8 +6,6 @@ #ifndef SPORK_H #define SPORK_H -#include - #include "base58.h" #include "hash.h" #include "key.h" @@ -68,9 +66,9 @@ class CSporkManager private: mutable CCriticalSection cs; std::string strMasterPrivKey; - std::unordered_map sporkDefsById; - std::unordered_map sporkDefsByName; - std::map mapSporksActive; + std::map sporkDefsById; + std::map sporkDefsByName; + std::map mapSporksActive; public: CSporkManager(); From 94e04a115b548a48a1d71c30a187672b632f3766 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Mon, 23 Sep 2019 18:28:56 +0200 Subject: [PATCH 065/132] [Trivial] rename DisconnectBlocks argument for consistency --- src/main.cpp | 10 +++++----- src/main.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b5b41a31f94b5..cb43cde35090a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3444,15 +3444,15 @@ bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock* return true; } -bool DisconnectBlocks(int blocks) +bool DisconnectBlocks(int nBlocks) { LOCK(cs_main); CValidationState state; - - LogPrintf("%s: Got command to replay %d blocks\n", __func__, blocks); - for (int i = 0; i <= blocks; i++) - DisconnectTip(state, false); + + LogPrintf("%s: Got command to replay %d blocks\n", __func__, nBlocks); + for (int i = 0; i <= nBlocks; i++) + DisconnectTip(state); return true; } diff --git a/src/main.h b/src/main.h index 9e17996c87ccb..717e15cba03ae 100644 --- a/src/main.h +++ b/src/main.h @@ -521,7 +521,7 @@ bool FindTransactionsByDestination(const CTxDestination &dest, std::set Date: Mon, 23 Sep 2019 18:31:37 +0200 Subject: [PATCH 066/132] [Trivial] Align the format of the log messages in kernel.cpp --- src/spork.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/spork.cpp b/src/spork.cpp index de8f570eb87a3..db1f0f4bd2af5 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -89,7 +89,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr // Do not accept sporks signed way too far into the future if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) { LOCK(cs_main); - LogPrintf("%s -- ERROR: too far into the future\n", __func__); + LogPrintf("%s : ERROR: too far into the future\n", __func__); Misbehaving(pfrom->GetId(), 100); return; } @@ -190,7 +190,7 @@ SporkId CSporkManager::GetSporkIDByName(std::string strName) { auto it = sporkDefsByName.find(strName); if (it == sporkDefsByName.end()) { - LogPrintf("%s -- Unknown Spork name '%s'\n", __func__, strName); + LogPrintf("%s : Unknown Spork name '%s'\n", __func__, strName); return SPORK_INVALID; } return it->second->sporkId; @@ -200,7 +200,7 @@ std::string CSporkManager::GetSporkNameByID(SporkId nSporkID) { auto it = sporkDefsById.find(nSporkID); if (it == sporkDefsById.end()) { - LogPrint("%s -- Unknown Spork ID %d\n", __func__, nSporkID); + LogPrint("%s : Unknown Spork ID %d\n", __func__, nSporkID); return "Unknown"; } return it->second->name; @@ -216,7 +216,7 @@ bool CSporkManager::SetPrivKey(std::string strPrivKey) if (spork.CheckSignature(fRequireNew)) { LOCK(cs); // Test signing successful, proceed - LogPrintf("%s : -- Successfully initialized as spork signer\n", __func__); + LogPrintf("%s : Successfully initialized as spork signer\n", __func__); strMasterPrivKey = strPrivKey; return true; } From 01b248ab3044c22c12dfad0a0200b666049ff5c4 Mon Sep 17 00:00:00 2001 From: furszy Date: Fri, 27 Sep 2019 13:13:23 -0300 Subject: [PATCH 067/132] [Startup] Don't continue loading the wallet if the shutdown was requested. --- src/init.cpp | 15 ++++++++++++--- src/main.cpp | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b3faf8b1415eb..b7cea374a8f25 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1404,7 +1404,7 @@ bool AppInit2(const std::vector& words) nCoinCacheSize = nTotalCache / 300; // coins in memory require around 300 bytes bool fLoaded = false; - while (!fLoaded) { + while (!fLoaded && !ShutdownRequested()) { bool fReset = fReindex; std::string strLoadError; @@ -1432,6 +1432,9 @@ bool AppInit2(const std::vector& words) if (fReindex) pblocktree->WriteReindexing(true); + + // End loop if shutdown was requested + if (ShutdownRequested()) break; // Phore: load previous sessions sporks if we have them. uiInterface.InitMessage(_("Loading sporks...")); @@ -1440,6 +1443,7 @@ bool AppInit2(const std::vector& words) uiInterface.InitMessage(_("Loading block index...")); std::string strBlockIndexError = ""; if (!LoadBlockIndex(strBlockIndexError)) { + if (ShutdownRequested()) break; strLoadError = _("Error loading block database"); strLoadError = strprintf("%s : %s", strLoadError, strBlockIndexError); break; @@ -1581,7 +1585,7 @@ bool AppInit2(const std::vector& words) fLoaded = true; } while (false); - if (!fLoaded) { + if (!fLoaded && !ShutdownRequested()) { // first suggest a reindex if (!fReset) { bool fRet = uiInterface.ThreadSafeMessageBox( @@ -1603,7 +1607,7 @@ bool AppInit2(const std::vector& words) // As LoadBlockIndex can take several minutes, it's possible the user // requested to kill the GUI during the last operation. If so, exit. // As the program has not fully started yet, Shutdown() is possibly overkill. - if (fRequestShutdown) { + if (ShutdownRequested()) { LogPrintf("Shutdown requested. Exiting.\n"); return false; } @@ -1973,6 +1977,11 @@ bool AppInit2(const std::vector& words) threadGroup.create_thread(boost::bind(&ThreadCheckObfuScationPool)); + if (ShutdownRequested()) { + LogPrintf("Shutdown requested. Exiting.\n"); + return false; + } + // ********************************************************* Step 11: start node if (!CheckDiskSpace()) diff --git a/src/main.cpp b/src/main.cpp index cb43cde35090a..49b20c0b67fdd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3449,7 +3449,7 @@ bool DisconnectBlocks(int nBlocks) LOCK(cs_main); CValidationState state; - + LogPrintf("%s: Got command to replay %d blocks\n", __func__, nBlocks); for (int i = 0; i <= nBlocks; i++) DisconnectTip(state); From a5adc16a74e652b842f84a7afafb0cc5973a1881 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Sun, 29 Sep 2019 23:48:59 +0200 Subject: [PATCH 068/132] [Trivial] Get rid of compiler warnings --- src/init.cpp | 3 +-- src/utilstrencodings.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b7cea374a8f25..c01f6c8e419cd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1083,8 +1083,6 @@ bool AppInit2(const std::vector& words) return InitError(_("Unable to start HTTP server. See debug log for details.")); } - int64_t nStart; - // ********************************************************* Step 5: Backup wallet and verify wallet database integrity #ifdef ENABLE_WALLET if (!fDisableWallet) { @@ -1404,6 +1402,7 @@ bool AppInit2(const std::vector& words) nCoinCacheSize = nTotalCache / 300; // coins in memory require around 300 bytes bool fLoaded = false; + int64_t nStart = GetTimeMillis(); while (!fLoaded && !ShutdownRequested()) { bool fReset = fReindex; std::string strLoadError; diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index cf0b9c3e2f1d0..05b8d9edceae0 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -55,7 +55,7 @@ bool validateURL(std::string strURL, std::string& strErr, unsigned int maxSize) // check fronts bool found = false; - for (int i=0; i < reqPre.size() && !found; i++) { + for (int i=0; i < (int) reqPre.size() && !found; i++) { if (strURL.find(reqPre[i]) == 0) found = true; } if ((!found) && (reqPre.size() > 0)) { From 46190057fb0fcaae156f6814d39f7756fe7e79f3 Mon Sep 17 00:00:00 2001 From: warrows Date: Thu, 19 Sep 2019 21:36:21 +0200 Subject: [PATCH 069/132] [Travis] Lower timeout for the full test suite Set the build timeout for the longest job to 21mn 40sec. Set the build timeout for the other jobs back to 33 mn and 20 sec. This should avoid global 50 mn timeout on the longest job and avoid having to restart other jobs needlessly. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 069342f113a8a..9f02bef30f6ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,7 +66,8 @@ script: - export CONTINUE=1 - if [ $SECONDS -gt 1200 ]; then export CONTINUE=0; fi # Likely the depends build took very long - if [ $CONTINUE = "1" ]; then set -o errexit; source .travis/test_06_script_a.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi - - if [ $SECONDS -gt 1500 ]; then export CONTINUE=0; fi # Likely the build took very long; The tests take about 1000s, so we should abort if we have less than 50*60-1000=2000s left + - if [ -z ${BUILD_TIMEOUT+x} ] && [ $SECONDS -gt $BUILD_TIMEOUT ]; then export CONTINUE=0; fi + - if [ $SECONDS -gt 2000 ]; then export CONTINUE=0; fi # Likely the build took very long; The tests take about 1000s, so we should abort if we have less than 50*60-1000=2000s left - if [ $CONTINUE = "1" ]; then set -o errexit; source .travis/test_06_script_b.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi after_script: - echo $TRAVIS_COMMIT_RANGE From d644f6c06df0daca5fc5a00180ce47e390a02ac4 Mon Sep 17 00:00:00 2001 From: furszy Date: Sun, 29 Sep 2019 12:44:32 -0300 Subject: [PATCH 070/132] [Startup][Refactor][Backport] * OS memory allocation fail handler. * OS signal handler registration method created to remove code duplication. * AppInitBasicSetup() method created, organizing better the setup step of the wallet initialization. --- src/init.cpp | 64 ++++++++++++++++++++++++++++++++++++---------------- src/init.h | 6 +++++ 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index c01f6c8e419cd..dce1f6a6649f5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -301,7 +301,7 @@ void Shutdown() */ void HandleSIGTERM(int) { - fRequestShutdown = true; + StartShutdown(); } void HandleSIGHUP(int) @@ -309,6 +309,17 @@ void HandleSIGHUP(int) fReopenDebugLog = true; } +#ifndef WIN32 +static void registerSignalHandler(int signal, void(*handler)(int)) +{ + struct sigaction sa; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(signal, &sa, nullptr); +} +#endif + bool static Bind(const CService& addr, unsigned int flags) { @@ -734,10 +745,20 @@ bool AppInitServers() return true; } -/** Initialize phore. - * @pre Parameters should be parsed and config file should be read. - */ -bool AppInit2(const std::vector& words) +[[noreturn]] static void new_handler_terminate() +{ + // Rather than throwing std::bad-alloc if allocation fails, terminate + // immediately to (try to) avoid chain corruption. + // Since LogPrintf may itself allocate memory, set the handler directly + // to terminate first. + std::set_new_handler(std::terminate); + LogPrintf("Error: Out of memory. Terminating.\n"); + + // The log was successful, terminate now. + std::terminate(); +}; + +bool AppInitBasicSetup() { // ********************************************************* Step 1: setup #ifdef _MSC_VER @@ -750,7 +771,7 @@ bool AppInit2(const std::vector& words) _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); #endif #ifdef WIN32 -// Enable Data Execution Prevention (DEP) + // Enable Data Execution Prevention (DEP) // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008 // A failure is non-critical and needs no further attention! #ifndef PROCESS_DEP_ENABLE @@ -776,26 +797,31 @@ bool AppInit2(const std::vector& words) umask(077); } - - // Clean shutdown on SIGTERM - struct sigaction sa; - sa.sa_handler = HandleSIGTERM; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); + // Clean shutdown on SIGTERMx + registerSignalHandler(SIGTERM, HandleSIGTERM); + registerSignalHandler(SIGINT, HandleSIGTERM); // Reopen debug.log on SIGHUP - struct sigaction sa_hup; - sa_hup.sa_handler = HandleSIGHUP; - sigemptyset(&sa_hup.sa_mask); - sa_hup.sa_flags = 0; - sigaction(SIGHUP, &sa_hup, NULL); + registerSignalHandler(SIGHUP, HandleSIGHUP); // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly signal(SIGPIPE, SIG_IGN); #endif + std::set_new_handler(new_handler_terminate); + + return true; +} + +/** Initialize phore. + * @pre Parameters should be parsed and config file should be read. + */ +bool AppInit2(const std::vector& words) +{ + // ********************************************************* Step 1: setup + if (!AppInitBasicSetup()) + return false; + // ********************************************************* Step 2: parameter interactions // Set this early so that parameter interactions go to console fPrintToConsole = GetBoolArg("-printtoconsole", false); diff --git a/src/init.h b/src/init.h index 671b4810d4fb5..e98bc14491f00 100644 --- a/src/init.h +++ b/src/init.h @@ -29,6 +29,12 @@ void Shutdown(); void PrepareShutdown(); bool AppInit2(const std::vector& words); +/** Initialize PIVX core: Basic context setup. + * @note This can be done before daemonization. Do not call Shutdown() if this function fails. + * @pre Parameters should be parsed and config file should be read. + */ +bool AppInitBasicSetup(); + /** The help message mode determines what help message to show */ enum HelpMessageMode { HMM_BITCOIND, From b0fdf4f1e6b239ec5ab588663284484002225935 Mon Sep 17 00:00:00 2001 From: furszy Date: Sun, 29 Sep 2019 14:09:23 -0300 Subject: [PATCH 071/132] [Logging][Startup] * Stop loading block indexes on wallet startup if shutdown was requested. * Wallet loading, wallet rescan and block index load time logged in a more understandable way. --- src/init.cpp | 17 ++++++++--------- src/main.cpp | 3 +++ src/util.cpp | 1 - src/util.h | 1 - 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index dce1f6a6649f5..a4750c48002c1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -948,7 +948,6 @@ bool AppInit2(const std::vector& words) else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS) nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS; - fServer = GetBoolArg("-server", false); setvbuf(stdout, NULL, _IOLBF, 0); /// ***TODO*** do we still need this after -printtoconsole is gone? // Staking needs a CWallet instance, so make sure wallet is enabled @@ -1103,7 +1102,7 @@ bool AppInit2(const std::vector& words) * that the server is there and will be ready later). Warmup mode will * be disabled when initialisation is finished. */ - if (fServer) { + if (GetBoolArg("-server", false)) { uiInterface.InitMessage.connect(SetRPCWarmupStatus); if (!AppInitServers()) return InitError(_("Unable to start HTTP server. See debug log for details.")); @@ -1435,8 +1434,9 @@ bool AppInit2(const std::vector& words) uiInterface.InitMessage(_("Loading block index...")); - nStart = GetTimeMillis(); do { + const int64_t load_block_index_start_time = GetTimeMillis(); + try { UnloadBlockIndex(); delete pcoinsTip; @@ -1608,6 +1608,7 @@ bool AppInit2(const std::vector& words) fVerifyingBlocks = false; fLoaded = true; + LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time); } while (false); if (!fLoaded && !ShutdownRequested()) { @@ -1636,7 +1637,6 @@ bool AppInit2(const std::vector& words) LogPrintf("Shutdown requested. Exiting.\n"); return false; } - LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); @@ -1672,7 +1672,7 @@ bool AppInit2(const std::vector& words) uiInterface.InitMessage(_("Loading wallet...")); fVerifyingBlocks = true; - nStart = GetTimeMillis(); + const int64_t nWalletStartTime = GetTimeMillis(); bool fFirstRun = true; pwalletMain = new CWallet(strWalletFile); DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); @@ -1741,8 +1741,7 @@ bool AppInit2(const std::vector& words) } LogPrintf("%s", strErrors.str()); - LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); - + LogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nWalletStartTime); zwalletMain = new CzPHRWallet(pwalletMain->strWalletFile); pwalletMain->setZWallet(zwalletMain); @@ -1762,9 +1761,9 @@ bool AppInit2(const std::vector& words) if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { uiInterface.InitMessage(_("Rescanning...")); LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); - nStart = GetTimeMillis(); + const int64_t nWalletRescanTime = GetTimeMillis(); pwalletMain->ScanForWalletTransactions(pindexRescan, true); - LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); + LogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nWalletRescanTime); pwalletMain->SetBestChain(chainActive.GetLocator()); nWalletDBUpdated++; diff --git a/src/main.cpp b/src/main.cpp index 49b20c0b67fdd..8961dd628a48b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4915,6 +4915,9 @@ bool static LoadBlockIndexDB(std::string& strError) } std::sort(vSortedByHeight.begin(), vSortedByHeight.end()); for (const PAIRTYPE(int, CBlockIndex*) & item : vSortedByHeight) { + // Stop if shutdown was requested + if (ShutdownRequested()) return false; + CBlockIndex* pindex = item.second; pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); if (pindex->nStatus & BLOCK_HAVE_DATA) { diff --git a/src/util.cpp b/src/util.cpp index e53c07f417de2..20cebdfe48460 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -116,7 +116,6 @@ bool fDebug = false; bool fPrintToConsole = false; bool fPrintToDebugLog = true; bool fDaemon = false; -bool fServer = false; std::string strMiscWarning; bool fLogTimestamps = false; bool fLogIPs = false; diff --git a/src/util.h b/src/util.h index 9de5951ffb958..5f8f457026d8b 100644 --- a/src/util.h +++ b/src/util.h @@ -63,7 +63,6 @@ extern std::map > mapMultiArgs; extern bool fDebug; extern bool fPrintToConsole; extern bool fPrintToDebugLog; -extern bool fServer; extern std::string strMiscWarning; extern bool fLogTimestamps; extern bool fLogIPs; From 8b0283ebf721eeb0d7f16f013c1d663fb4879ee7 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 2 Oct 2019 13:22:38 -0300 Subject: [PATCH 072/132] [Startup][Wallet] Don't continue rescanning the wallet if shutdown was requested. --- src/init.cpp | 5 ++++- src/wallet/wallet.cpp | 9 ++++++++- src/wallet/wallet.h | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a4750c48002c1..5444d4cedefe2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1762,7 +1762,10 @@ bool AppInit2(const std::vector& words) uiInterface.InitMessage(_("Rescanning...")); LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); const int64_t nWalletRescanTime = GetTimeMillis(); - pwalletMain->ScanForWalletTransactions(pindexRescan, true); + if (pwalletMain->ScanForWalletTransactions(pindexRescan, true, true) == -1) { + LogPrintf("Shutdown requested over the txs scan. Exiting.\n"); + return false; + } LogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nWalletRescanTime); pwalletMain->SetBestChain(chainActive.GetLocator()); nWalletDBUpdated++; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 70429a5695942..46bc385945128 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1510,8 +1510,9 @@ bool CWalletTx::WriteToDisk() * Scan the block chain (starting in pindexStart) for transactions * from or to us. If fUpdate is true, found transactions that already * exist in the wallet will be updated. + * @returns -1 if process was cancelled or the number of tx added to the wallet. */ -int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) +int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, bool fromStartup) { int ret = 0; int64_t nNow = GetTime(); @@ -1537,6 +1538,12 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); + if (fromStartup) { + if (ShutdownRequested()) { + return -1; + } + } + CBlock block; ReadBlockFromDisk(block, pindex); for (CTransaction& tx : block.vtx) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 152d0465e6f87..31fc94c860243 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -548,7 +548,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void SyncTransaction(const CTransaction& tx, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); void EraseFromWallet(const uint256& hash); - int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); + int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, bool fromStartup = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(); CAmount GetBalance() const; From 5187ee4e8b8e0a0f999fd112344610cac3675800 Mon Sep 17 00:00:00 2001 From: furszy Date: Thu, 3 Oct 2019 10:50:04 -0300 Subject: [PATCH 073/132] [Trivial] Use error() instead of LogPrintf + return false. --- src/init.cpp | 3 +-- src/wallet/wallet.cpp | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 5444d4cedefe2..87b665784b66c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1763,8 +1763,7 @@ bool AppInit2(const std::vector& words) LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); const int64_t nWalletRescanTime = GetTimeMillis(); if (pwalletMain->ScanForWalletTransactions(pindexRescan, true, true) == -1) { - LogPrintf("Shutdown requested over the txs scan. Exiting.\n"); - return false; + return error("Shutdown requested over the txs scan. Exiting."); } LogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nWalletRescanTime); pwalletMain->SetBestChain(chainActive.GetLocator()); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 46bc385945128..1dc6773670aef 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1538,10 +1538,8 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); - if (fromStartup) { - if (ShutdownRequested()) { - return -1; - } + if (fromStartup && ShutdownRequested()) { + return -1; } CBlock block; From 9fcb920e21c4c675eb17936eac0ccf5d1f01bc16 Mon Sep 17 00:00:00 2001 From: cevap Date: Tue, 28 May 2019 18:45:08 +0200 Subject: [PATCH 074/132] add snapcraft support to pivx, static build Description =========== Enables support for automatic build and release process of pivx snap on snapcraft.io, as well as the ability to create a snap package on launchpad. Build is performed with prebuilding all dependencies for each architecture, current version builds each version on same architecture, it is possible to build for separate architectures on a specific one. Snap builds are in general auto updated and if users stay on a specific channel, with each relaunch latest version of set channel is launched. PIVX Snap build status: https://build.snapcraft.io/user/cevap/PIVX PIVX's public store page: https://snapcraft.io/pivx Getting started: https://docs.snapcraft.io/getting-started/3876 Snap FAQ/Documentation: https://docs.snapcraft.io/ Publishing process: https://docs.snapcraft.io/releasing-your-app/6795 Datafolder and how to launch ============================ PIVX's snap default datafolder: `~/snap/pivx/common/.pivx` launch QT from terminal: - `pivx.qt` - `pivx.qt-testnet`, equals `pivx.qt --testnet` - `pivx.qt-regtest`, equals `pivx.qt --regtest launch daemon from terminal: - `pivx.daemon` - `pivx.daemon-testnet`, equals `pivx.daemon --testnet` - `pivx.daemon-regtest`, equals `pivx.daemon --regtest use cli: - `pivx.cli` - `pivx.cli-testnet`, equals `pivx.cli --testnet` - `pivx.cli-regtest`, equals `pivx.cli --regtest` tx: - pivx.tx tests: - pivx.test - pivx.testqt About snapcraft config ====================== Execution environment for this snap is core18 and strict confinement. For more info about base, confinment ...: https://docs.snapcraft.io/snapcraft-top-level-metadata/8334 Additional fixes and features ============================= - [x] Daemon icons for all networks - [x] QT icons patch (includes patching of icons) - [x] Add workaround for ppc64el and QT - [x] additional patches - [x] add test_pivx and test_pivx-qt - [x] snap has access to several ressources like network or home folder - [x] tests (for now only make check at the end) - [x] customizable script - [x] script in simple, readble manner Installation process ==================== On most installations, you do not need to specify `--channel=`, it can be done by writting channel directly: `--edge` without `channel=`. Official documenation is with --channel and so is this installation guide by that. Install pivx from snap (stable channel): sudo snap install pivx Install pivx from specific channel (example: edge) sudo snap install --channel=edge pivx How to update snap from another channel: sudo snap refresh --channel=edge pivx Uninstall pivx from system (!!!WARNING!!! it removes pivx's snap datafolder) sudo snap remove pivx --- build-aux/snap/local/desktop/pivx-qt.desktop | 15 + build-aux/snap/local/desktop/pivx-qt.ico | Bin 0 -> 53158 bytes .../local/desktop/pivx-qt_regtest.desktop | 15 + .../snap/local/desktop/pivx-qt_regtest.ico | Bin 0 -> 53158 bytes .../local/desktop/pivx-qt_testnet.desktop | 15 + .../snap/local/desktop/pivx-qt_testnet.ico | Bin 0 -> 53158 bytes build-aux/snap/local/desktop/pivxd.desktop | 15 + build-aux/snap/local/desktop/pivxd.ico | Bin 0 -> 53158 bytes .../snap/local/desktop/pivxd_regtest.desktop | 15 + .../snap/local/desktop/pivxd_regtest.ico | Bin 0 -> 53158 bytes .../snap/local/desktop/pivxd_testnet.desktop | 15 + .../snap/local/desktop/pivxd_testnet.ico | Bin 0 -> 53158 bytes .../local/patches/X001-default_data_dir.patch | 13 + .../patches/X002-fix-bdb-tmp-folder.patch | 36 +++ .../X003-fix-use-snap-instead-of-dirty.patch | 25 ++ build-aux/snap/snapcraft.yaml | 299 ++++++++++++++++++ contrib/devtools/lint-whitespace.sh | 4 +- 17 files changed, 465 insertions(+), 2 deletions(-) create mode 100644 build-aux/snap/local/desktop/pivx-qt.desktop create mode 100755 build-aux/snap/local/desktop/pivx-qt.ico create mode 100644 build-aux/snap/local/desktop/pivx-qt_regtest.desktop create mode 100755 build-aux/snap/local/desktop/pivx-qt_regtest.ico create mode 100644 build-aux/snap/local/desktop/pivx-qt_testnet.desktop create mode 100755 build-aux/snap/local/desktop/pivx-qt_testnet.ico create mode 100755 build-aux/snap/local/desktop/pivxd.desktop create mode 100755 build-aux/snap/local/desktop/pivxd.ico create mode 100755 build-aux/snap/local/desktop/pivxd_regtest.desktop create mode 100755 build-aux/snap/local/desktop/pivxd_regtest.ico create mode 100755 build-aux/snap/local/desktop/pivxd_testnet.desktop create mode 100755 build-aux/snap/local/desktop/pivxd_testnet.ico create mode 100644 build-aux/snap/local/patches/X001-default_data_dir.patch create mode 100644 build-aux/snap/local/patches/X002-fix-bdb-tmp-folder.patch create mode 100644 build-aux/snap/local/patches/X003-fix-use-snap-instead-of-dirty.patch create mode 100644 build-aux/snap/snapcraft.yaml diff --git a/build-aux/snap/local/desktop/pivx-qt.desktop b/build-aux/snap/local/desktop/pivx-qt.desktop new file mode 100644 index 0000000000000..8c137c03ac71b --- /dev/null +++ b/build-aux/snap/local/desktop/pivx-qt.desktop @@ -0,0 +1,15 @@ +# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html + +[Desktop Entry] +Encoding=UTF-8 +Name=PIVX Core +Comment=PIVX Core QT main network +GenericName=PIVX Digital Currency QT client main network +Exec=pivx.qt %u +Terminal=false +Type=Application +Icon=${SNAP}/pivx-qt.ico +MimeType=x-scheme-handler/piv; +Categories=X-Office;X-Finance; +Keywords=internet;pivx;zpiv;piv;core;wallet;qt;main;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; +Version=3.2.99 diff --git a/build-aux/snap/local/desktop/pivx-qt.ico b/build-aux/snap/local/desktop/pivx-qt.ico new file mode 100755 index 0000000000000000000000000000000000000000..5db4fb4989bd8f3dc92a377aac02b3e5c35d9315 GIT binary patch literal 53158 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 a4Jz?tuQOK@++}987U`m>v%8h9|Nb9>kPEi} literal 0 HcmV?d00001 diff --git a/build-aux/snap/local/desktop/pivx-qt_testnet.desktop b/build-aux/snap/local/desktop/pivx-qt_testnet.desktop new file mode 100644 index 0000000000000..d55dca27436e5 --- /dev/null +++ b/build-aux/snap/local/desktop/pivx-qt_testnet.desktop @@ -0,0 +1,15 @@ +# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html + +[Desktop Entry] +Encoding=UTF-8 +Name=PIVX Core +Comment=PIVX Core QT test network +GenericName=PIVX Digital Currency QT client testnet network +Exec=pivx.qt-testnet %u +Terminal=false +Type=Application +Icon=${SNAP}/pivx-qt_testnet.ico +MimeType=x-scheme-handler/piv; +Categories=X-Office;X-Finance; +Keywords=internet;pivx;zpiv;tpiv;core;wallet;qt;testnet;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; +Version=3.2.99 diff --git a/build-aux/snap/local/desktop/pivx-qt_testnet.ico b/build-aux/snap/local/desktop/pivx-qt_testnet.ico new file mode 100755 index 0000000000000000000000000000000000000000..a4892e2c1352d24566be7ed6d72c679dec052af1 GIT binary patch literal 53158 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 literal 0 HcmV?d00001 diff --git a/build-aux/snap/local/desktop/pivxd.desktop b/build-aux/snap/local/desktop/pivxd.desktop new file mode 100755 index 0000000000000..c916cdb933517 --- /dev/null +++ b/build-aux/snap/local/desktop/pivxd.desktop @@ -0,0 +1,15 @@ +# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html + +[Desktop Entry] +Encoding=UTF-8 +Name=PIVX Core Daemon SNAP +Comment=main +GenericName=PIVX Digital Currency Daemon Client main network +Exec=pivx.daemon %u +Terminal=true +Type=Application +Icon=${SNAP}/pivxd.ico +MimeType=x-scheme-handler/piv; +Categories=X-Office;X-Finance; +Keywords=internet;pivx;zpiv;core;wallet;daemon;main;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; +Version=3.2.99 diff --git a/build-aux/snap/local/desktop/pivxd.ico b/build-aux/snap/local/desktop/pivxd.ico new file mode 100755 index 0000000000000000000000000000000000000000..80d3b36945ae65226df597245931e7f8ad9e32cf GIT binary patch literal 53158 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 Vv@f@b5UY-odB5G|p08cq{|}};?-2k1 literal 0 HcmV?d00001 diff --git a/build-aux/snap/local/desktop/pivxd_regtest.desktop b/build-aux/snap/local/desktop/pivxd_regtest.desktop new file mode 100755 index 0000000000000..da31a04a0602d --- /dev/null +++ b/build-aux/snap/local/desktop/pivxd_regtest.desktop @@ -0,0 +1,15 @@ +# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html + +[Desktop Entry] +Encoding=UTF-8 +Name=PIVX Core Daemon SNAP +Comment=regtest +GenericName=PIVX Digital Currency Daemon Client regression test network +Exec=pivx.daemon-regtest %u +Terminal=true +Type=Application +Icon=${SNAP}/pivxd_regtest.ico +MimeType=x-scheme-handler/piv; +Categories=X-Office;X-Finance; +Keywords=internet;pivx;zpiv;core;wallet;daemon;regtest;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; +Version=3.2.99 diff --git a/build-aux/snap/local/desktop/pivxd_regtest.ico b/build-aux/snap/local/desktop/pivxd_regtest.ico new file mode 100755 index 0000000000000000000000000000000000000000..72802e471d00df7a0e39e97ab31044a2a5509029 GIT binary patch literal 53158 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 Jr%Ltb{{aka)8qgE literal 0 HcmV?d00001 diff --git a/build-aux/snap/local/desktop/pivxd_testnet.desktop b/build-aux/snap/local/desktop/pivxd_testnet.desktop new file mode 100755 index 0000000000000..8ffe7d3effb95 --- /dev/null +++ b/build-aux/snap/local/desktop/pivxd_testnet.desktop @@ -0,0 +1,15 @@ +# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html + +[Desktop Entry] +Encoding=UTF-8 +Name=PIVX Core Daemon SNAP +Comment=testnet +GenericName=PIVX Digital Currency Daemon Client testnet network +Exec=pivx.daemon-testnet %u +Terminal=true +Type=Application +Icon=${SNAP}/pivxd_testnet.ico +MimeType=x-scheme-handler/piv; +Categories=X-Office;X-Finance; +Keywords=internet;pivx;zpiv;core;wallet;daemon;testnet;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; +Version=3.2.99 diff --git a/build-aux/snap/local/desktop/pivxd_testnet.ico b/build-aux/snap/local/desktop/pivxd_testnet.ico new file mode 100755 index 0000000000000000000000000000000000000000..0f7d5b609cb9619316bd0b0659a42d8fdd3a8996 GIT binary patch literal 53158 zcmeI52Y6Lgw#OGmumGVBf?$FJhy@5z719f!qN1RHsIh=x!QOEQjx&ye=+Ht5HIrYUUPw>w_pNX5v+q88ul?U^uie)X zsUfwcVMD%+i&;R;|sQbm*`Nma$-l|07|M`Fa+qj+*(s=s&{_s{4XGW|vn;k9pWJb$f%cA8s z`u~6K-{?&9T!AFcojYg3b3Ys*3DHt_Mx;b0M9C{Nqh(xjw7j`AN?uqNCDF@b3Wgr(bAOn;$}w4n=_&$8UGO_o)@M@%WI_b(2_`LmT;Lk`Eb1Z z^_EP{w?6MYHX~a8$UA$cN6Aj;FNB}s`8)jk=0(fzmqf|%Wsy?<^wum_8dt&z@Aibo z691USpB5pn^3HnFJ3Tu}j?asdualx>Z&sAN3?AJY@s7p2y1W<8`;+xuXMQiviIUZ6 zQSwzbX~O#<=pZ<}&-)?vchyf`VdOQ{`TnVy5%NM-xIDfzQeMxFl0Q)HT$4tmd{D^y zQ}liE{g!%L%R5O>Dl`thpQP-2$-mI|DZ_WEk+PY%Z)8Wx%S)prgZKBq%LC-U5t`sF zf66drPNaOxyZeZ@g7>m;S7%4aj7)GR{8Pwl{=7dGjQ5+0RY28Zu8Ilz(_aSfHmqkdc zB@uGvD&n}mXFZ?&`HcLKcT|onpDyE?pHDxzy~y#^bLAf=K9^sKW5sv4B4@)yehd)F zt1FUQ%Qw=vux#{95M>F6R9_Y6uOOd}wyI$z{j=wL_NRZl@H+eNf4cl7!G}HHU(f#R z%4<%9v`&wZYxA9Y@)xI$w&E8D9-3C(&Ky^s`aB~>+Mt)-K%R4H|ErN-)g{+ke5ek- zR35DN)&2YN&rNz$qogUi{2AK7dh$;r|Dm*@fy=dRs$M{c(uP{=J9#T-xp>fLe|{SO z+^=U{?@tSt+T?pXZ8#HJK>srU>VsZ*3trwvFNTnR3^+_dH)X)n{j|p`G#w?YZTZ53 z#{UI*viiPRedTKM`~#Fle>H@BL&$dm`5uBypMb0V*`&GA5(*Ck;AH_kyuTzI*)aM4 zB>(>J?+q`7@t|?F+~>|Y>Ti0C+?)_8$>jNauK z!NWXsbFh`Jy54?PoEf2v7b0a2`45GLkjFvIhkoP~I(W~N2zj6X_v*8k{1p$alLz79 zF646R@>s`Mr_lVJ?U=N+zlewWIn%N5{eD`MWKRs2rnpP_PjRsRbGf{C5?MJxKXHV< zrawHquq0X@*1WZDz5Raq_y5VH!BUI1H4)7FlTNZ*`rl8BlLO7c?4 zGb>UKQ`ZMQ&?@qdCj7mO5UG3S?|<_(|2s&3i>LhmNck!6(&Q-l2K{%0v~>(-#$g`w zXADuC`J)G$WJJox$kjU1T@9^4@8t4)0KDCCScUu-TmHz^lEho3@v`31G9y&lq=ie6 zQf8>M1B*fMuoT^6=b_m0XS{rZa_?fCHJ3bQS)}7Y%0D(eRBp(I@GrOFP%QZ~_c+Oz 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 KnB^-`_x}N$2)1(o literal 0 HcmV?d00001 diff --git a/build-aux/snap/local/patches/X001-default_data_dir.patch b/build-aux/snap/local/patches/X001-default_data_dir.patch new file mode 100644 index 0000000000000..a98fc039ec3db --- /dev/null +++ b/build-aux/snap/local/patches/X001-default_data_dir.patch @@ -0,0 +1,13 @@ +diff --git a/src/util.cpp b/src/util.cpp +index bd44c328c..455e990d7 100644 +--- a/src/util.cpp ++++ b/src/util.cpp +@@ -433,7 +433,7 @@ boost::filesystem::path GetDefaultDataDir() + return GetSpecialFolderPath(CSIDL_APPDATA) / "PIVX"; + #else + fs::path pathRet; +- char* pszHome = getenv("HOME"); ++ char* pszHome = getenv("SNAP_USER_COMMON"); + if (pszHome == NULL || strlen(pszHome) == 0) + pathRet = fs::path("/"); + else diff --git a/build-aux/snap/local/patches/X002-fix-bdb-tmp-folder.patch b/build-aux/snap/local/patches/X002-fix-bdb-tmp-folder.patch new file mode 100644 index 0000000000000..b561f58569831 --- /dev/null +++ b/build-aux/snap/local/patches/X002-fix-bdb-tmp-folder.patch @@ -0,0 +1,36 @@ +From dcfe31b190ab8a28f2617914afdf15c6be2a74d2 Mon Sep 17 00:00:00 2001 +From: cevap +Date: Mon, 4 Feb 2019 07:41:47 +0100 +Subject: [PATCH] fix-bdb-tmp-folder + +--- + depends/packages/bdb.mk | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk +index 6c9876c..291111c 100644 +--- a/depends/packages/bdb.mk ++++ b/depends/packages/bdb.mk +@@ -13,6 +13,19 @@ $(package)_cxxflags=-std=c++11 + endef + + define $(package)_preprocess_cmds ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' csharp/DatabaseEnvironment.cs && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' csharp/DatabaseEnvironmentConfig.cs && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' csharp/doc/libdb_dotnet48.XML && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' docs/api_reference/C/envset_tmp_dir.html && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' docs/api_reference/CXX/envset_tmp_dir.html && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' docs/csharp/html/F_BerkeleyDB_DatabaseEnvironmentConfig_TempDir.htm && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' docs/csharp/html/P_BerkeleyDB_DatabaseEnvironment_TempDir.htm && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' docs/java/com/sleepycat/db/EnvironmentConfig.html && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' docs/programmer_reference/test.html && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' java/src/com/sleepycat/db/EnvironmentConfig.java && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' os/os_tmpdir.c && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' php_db4/samples/simple_counter.php && \ ++ sed -i.old 's/\/var\/tmp/$HOME\/snap\/pivx\/common\/var\/tmp/g' php_db4/samples/transactional_counter.php && \ + sed -i.old 's/__atomic_compare_exchange/__atomic_compare_exchange_db/' dbinc/atomic.h && \ + sed -i.old 's/atomic_init/atomic_init_db/' dbinc/atomic.h mp/mp_region.c mp/mp_mvcc.c mp/mp_fget.c mutex/mut_method.c mutex/mut_tas.c && \ + cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub dist +-- +2.17.1 + diff --git a/build-aux/snap/local/patches/X003-fix-use-snap-instead-of-dirty.patch b/build-aux/snap/local/patches/X003-fix-use-snap-instead-of-dirty.patch new file mode 100644 index 0000000000000..755604057a67c --- /dev/null +++ b/build-aux/snap/local/patches/X003-fix-use-snap-instead-of-dirty.patch @@ -0,0 +1,25 @@ +From ec230421e7107448ca9ac2421eb702924e12a879 Mon Sep 17 00:00:00 2001 +From: observerdev +Date: Thu, 11 Apr 2019 00:12:00 +0200 +Subject: [PATCH] fix-use-snap-instead--of-dirty + +--- + share/genbuild.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/share/genbuild.sh b/share/genbuild.sh +index 519cc6e..de56b8d 100755 +--- a/share/genbuild.sh ++++ b/share/genbuild.sh +@@ -37,7 +37,7 @@ if [ "${BITCOIN_GENBUILD_NO_GIT}" != "1" -a -e "$(which git 2>/dev/null)" -a "$( + + # otherwise generate suffix from git, i.e. string like "59887e8-dirty" + SUFFIX=$(git rev-parse --short HEAD) +- git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-dirty" ++ git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-snap" + + # get a string like "2012-04-10 16:27:19 +0200" + LAST_COMMIT_DATE="$(git log -n 1 --format="%ci")" +-- +2.17.1 + diff --git a/build-aux/snap/snapcraft.yaml b/build-aux/snap/snapcraft.yaml new file mode 100644 index 0000000000000..66bcff9b77539 --- /dev/null +++ b/build-aux/snap/snapcraft.yaml @@ -0,0 +1,299 @@ +# Copyright (c) 2018-2019 The Ion developers +# Copyright (c) 2019 The PIVX developers +name: pivx +base: core18 +version: 3.2.99 +summary: PIVX (Private – Instant – Verified – Transaction) +description: | + PIVX is an MIT licensed, + open source, blockchain-based cryptocurrency with + ultra fast transactions, low fees, high network decentralization, and + Zero Knowledge cryptography proofs for industry-leading + transaction anonymity. + + - [Download](https://pivx.org/wp-content/uploads/2018/10/PIVX-White.pdf) PIVX White Paper PDF +grade: devel +confinement: strict +apps: + daemon: + command: pivxd + plugs: [network, network-bind, home, removable-media] + desktop: pivxd.desktop + environment: + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + daemon-testnet: + command: pivxd --testnet + plugs: [network, network-bind, home, removable-media] + desktop: pivxd_testnet.desktop + environment: + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + daemon-regtest: + command: pivxd --regtest + plugs: [network, network-bind, home, removable-media] + desktop: pivxd_regtest.desktop + environment: + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + qt: + command: pivx-qt + plugs: [network, network-bind, network-status, unity7, desktop, desktop-legacy, wayland, x11, mir, opengl, home, gsettings, removable-media, screen-inhibit-control, pulseaudio, media-hub] + desktop: pivx-qt.desktop + environment: + QT_XKB_CONFIG_ROOT: $SNAP_USER_DATA:$SNAP/usr/share:$QT_XKB_CONFIG_ROOT + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + qt-testnet: + command: pivx-qt --testnet + plugs: [network, network-bind, network-status, unity7, desktop, desktop-legacy, wayland, x11, mir, opengl, home, gsettings, removable-media, screen-inhibit-control, pulseaudio, media-hub] + desktop: pivx-qt_testnet.desktop + environment: + QT_XKB_CONFIG_ROOT: $SNAP_USER_DATA:$SNAP/usr/share:$QT_XKB_CONFIG_ROOT + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + qt-regtest: + command: pivx-qt --regtest + plugs: [network, network-bind, network-status, unity7, desktop, desktop-legacy, wayland, x11, mir, opengl, home, gsettings, removable-media, screen-inhibit-control, pulseaudio, media-hub] + desktop: pivx-qt_regtest.desktop + environment: + QT_XKB_CONFIG_ROOT: $SNAP_USER_DATA:$SNAP/usr/share:$QT_XKB_CONFIG_ROOT + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + cli: + command: pivx-cli + plugs: [network, network-bind, home, removable-media] + environment: + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + cli-testnet: + command: pivx-cli --testnet + plugs: [network, network-bind, home, removable-media] + environment: + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + cli-regtest: + command: pivx-cli --regtest + plugs: [network, network-bind, home, removable-media] + environment: + XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + tx: + command: pivx-tx + plugs: [home] + test: + command: test_pivx + plugs: [home] + testqt: + command: test_pivx-qt + plugs: [home] +parts: + pivx: + source: https://github.com/PIVX-Project/PIVX + source-type: git + source-tag: master + plugin: nil + override-build: | + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "CUSTOM SETTINGS" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + # use override prefix if binaries differ from project name, for ion it does, + # project is called ioncore because ion exists already as package. For anybody + # offering non official release and using own SNAP, this variable should be used + # default value is "false", to enable it, use your projects binary prefix + OVERRIDEBINPREFIX="false" + OVERRIDEDATADIR="false" + OVERRIDECONF="${OVERRIDEDATADIR}" + COPYCONF=0 # copy example config into users data folder, 1 = enabled + JOBS=4 # 0 means off and make will run without -j + PATCH=1 # 1 = enabled + SPLASHPNGS=0 # patch pngs to differ visaully from those installed from self compilation or other source like deb + FIXPPCBUILD=1 # if ppc builds fail due to failed qt, apps part will return error and build will fail, 1 = enabled + EXTRALOG=1 # prints env and all installed files at the end of current script + RUNTESTS=1 # run make check after post install part + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "SET OVERRIDE VARIABLES IF SET" # checks OVERRIDEBINPREFIX, OVERRIDEDATADIR and OVERRIDECONF + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + if [ $OVERRIDEBINPREFIX = "false" ]; then + BINPREF="${SNAPCRAFT_PROJECT_NAME}" + else + BINPREF="${OVERRIDEBINPREFIX}" + fi + if [ $OVERRIDEDATADIR = "false" ]; then + DATADIR="${SNAPCRAFT_PROJECT_NAME}" + else + DATADIR="${OVERRIDEDATADIR}" + fi + if [ $OVERRIDECONF = "false" ]; then + CONF="${SNAPCRAFT_PROJECT_NAME}" + else + CONF="${OVERRIDECONF}" + fi + echo "BINPREF VARIABLE - ${BINPREF}" + echo "DATADIR VARIABLE - ${DATADIR}" + echo "CONF VARIABLE - ${CONF}" + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "OVERRIDE ARCHITECTURE" # applies currently only on i386, for i386 architecture, we will use i686-linux-gnu to compile dependencies + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + if [ $SNAPCRAFT_ARCH_TRIPLET = "i386-linux-gnu" ]; then + HOST="i686-linux-gnu" + else + HOST="${SNAPCRAFT_ARCH_TRIPLET}" + fi + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "APPLY PATCHES ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # patches which have to be applied for compilation, replace splash screen + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + cd ${SNAPCRAFT_PART_BUILD} + if [ $PATCH = 1 ]; then + echo "apply patches:" + git apply $SNAPCRAFT_PART_BUILD/build-aux/snap/local/patches/X001-default_data_dir.patch + git apply $SNAPCRAFT_PART_BUILD/build-aux/snap/local/patches/X002-fix-bdb-tmp-folder.patch + git apply $SNAPCRAFT_PART_BUILD/build-aux/snap/local/patches/X003-fix-use-snap-instead-of-dirty.patch + sed -i 's/tar --strip-components/tar --no-same-owner --strip-components/' ${SNAPCRAFT_PART_BUILD}/depends/funcs.mk + else + echo "APPLY .patch files during compilation is disabled, skipping" + fi + if [ $SPLASHPNGS = 1 ]; then + echo "replace splash screen with snapcrafts" + mv -f $SNAPCRAFT_PART_BUILD/contrib/snap/images/splash.png $SNAPCRAFT_PART_BUILD/src/qt/res/images/splash.png + mv -f $SNAPCRAFT_PART_BUILD/contrib/snap/images/splash_regtest.png $SNAPCRAFT_PART_BUILD/src/qt/res/images/splash_regtest.png + mv -f $SNAPCRAFT_PART_BUILD/contrib/snap/images/splash_testnet.png $SNAPCRAFT_PART_BUILD/src/qt/res/images/splash_testnet.png + mv -f $SNAPCRAFT_PART_BUILD/contrib/snap/icons/favicon.ico $SNAPCRAFT_PART_BUILD/share/pixmaps/favicon.ico + mv -f $SNAPCRAFT_PART_BUILD/contrib/snap/icons/favicon_testnet.ico $SNAPCRAFT_PART_BUILD/share/pixmaps/favicon_testnet.ico + mv -f $SNAPCRAFT_PART_BUILD/contrib/snap/icons/favicon_regtest.ico $SNAPCRAFT_PART_BUILD/share/pixmaps/favicon_regtest.ico + mv -f $SNAPCRAFT_PART_BUILD/build-aux/snap/local/desktop/${BINPREF}.png $SNAPCRAFT_PART_BUILD/src/qt/res/icons/${BINPREF}.png + mv -f $SNAPCRAFT_PART_BUILD/build-aux/snap/local/desktop/${BINPREF}_testnet.png $SNAPCRAFT_PART_BUILD/src/qt/res/icons/${BINPREF}_testnet.png + mv -f $SNAPCRAFT_PART_BUILD/build-aux/snap/local/desktop/${BINPREF}_regtest.png $SNAPCRAFT_PART_BUILD/src/qt/res/icons/${BINPREF}_regtest.png + else + echo "patch icons and images is disabled, skipping" + fi + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "BUILD DEPENDENCIES" + echo "PRECOMPILE ${SNAPCRAFT_ARCH_TRIPLET} DEPENDENCIES FOR ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # cd to depends folder, download and precompile + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + cd ${SNAPCRAFT_PART_BUILD}/depends + make download-linux + if [ $JOBS = 0 ]; then + make + else + make -j${JOBS} HOST=${HOST} + fi + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "CONFIGURATION OF ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # run configure with prefix to include depends + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + cd ${SNAPCRAFT_PART_BUILD} + echo "Configure and build ${BINPREF}" + ./autogen.sh + ./configure --prefix=`pwd`/depends/${HOST} + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "COMPILATION OF ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # run make to compile using -j + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + if [ $JOBS = 0 ]; then + make + else + make -j${JOBS} HOST=${HOST} + fi + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "INSTALLATION OF ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # run make install with a prefix where to install + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + make install prefix=${SNAPCRAFT_PART_INSTALL} + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "POST INSTALL SCRIPTS OF ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # run make install with a prefix where to install + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + if [ $FIXPPCBUILD = 1 ]; then + if [ $SNAPCRAFT_ARCH_TRIPLET = "powerpc64le-linux-gnu" ]; then + if [ -e $SNAPCRAFT_PART_BUILD/src/qt/${BINPREF}-qt ]; then + echo "PPC64EL fix - ${BINPREF}-qt exists, fix unrequired" + else + echo "echo ${BINPREF}-qt is not installed" > ${SNAPCRAFT_PART_INSTALL}/usr/bin/${BINPREF}-qt + chmod +x ${SNAPCRAFT_PART_INSTALL}/usr/bin/${BINPREF}-qt + echo "PPC64EL fix - ${BINPREF}-qt does not exist, fix required, dummy as ${BINPREF}-qt" + fi + if [ -e $SNAPCRAFT_PART_BUILD/src/qt/test/test_${BINPREF}-qt ]; then + echo "PPC64EL fix - test_${BINPREF}-qt exists, fix unrequired" + else + echo "echo test_${BINPREF}-qt is not installed" > ${SNAPCRAFT_PART_INSTALL}/usr/bin/test_${BINPREF}-qt + chmod +x ${SNAPCRAFT_PART_INSTALL}/usr/bin/test_${BINPREF}-qt + echo "PPC64EL fix - test_${BINPREF}-qt does not exist, fix required, dummy as test_${BINPREF}-qt" + fi + if [ -e $SNAPCRAFT_PART_BUILD/src/test/test_${BINPREF} ]; then + echo "PPC64EL fix - test_${BINPREF} exists, fix unrequired" + else + echo "echo test_${BINPREF} is not installed" > ${SNAPCRAFT_PART_INSTALL}/usr/bin/test_${BINPREF} + chmod +x ${SNAPCRAFT_PART_INSTALL}/usr/bin/test_${BINPREF} + echo "PPC64EL fix - test_${BINPREF} does not exist, fix required, dummy as test_${BINPREF}" + fi + fi + else + echo "PPC64EL fix disabled, skipping" + fi + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "CONFIG FILE" # create .pivx folder and copy example config - !!!warning!!!: do not copy as pivx.conf + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + mkdir -p ${SNAP_USER_COMMON}/.${DATADIR} + if [ $COPYCONF = 1 ]; then + cp ${SNAPCRAFT_PART_BUILD}/contrib/debian/manpages/${CONF}.conf.5 ${SNAP_USER_COMMON}/.${DATADIR}/${CONF}-example.conf + else + echo "COPY CONFIG FILE disabled, skipping" + fi + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "RUN TESTS" # if tests fail to pass, build and release will fail + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + cd ${SNAPCRAFT_PART_BUILD} + if [ $RUNTESTS = 1 ]; then + make check + else + echo "RUN TESTS disabled, skipping" + fi + echo "-----------------------------------------------" + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + echo "INSTALATION OF ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}-snap has finished" # List installed files and vars when installation is finished + echo "+++++++++++++++++++++++++++++++++++++++++++++++" + if [ $EXTRALOG = 1 ]; then + find ${SNAPCRAFT_PART_INSTALL} -type f + env + else + echo "RUN TESTS disabled, skipping" + fi + echo "-----------------------------------------------+" + build-packages: + - curl + - wget + - gcc + - gcc-8 + - g++ + - g++-8 + - make + - autoconf + - automake + - cmake + - pkg-config + - libtool + - bsdmainutils + - binutils + - python3 + - help2man + - doxygen + stage-packages: + - libxkbcommon0 + - ttf-ubuntu-font-family + - dmz-cursor-theme + - light-themes + - shared-mime-info + - libqt5gui5 + - libgdk-pixbuf2.0-0 + - libqt5svg5 # for loading icon themes which are svg + - locales-all + - qtwayland5 + - ca-certificates + after: + - patches + patches: + source: build-aux/snap/local/patches + plugin: dump + prime: + - -* + desktop: + source: build-aux/snap/local/desktop + plugin: dump \ No newline at end of file diff --git a/contrib/devtools/lint-whitespace.sh b/contrib/devtools/lint-whitespace.sh index 128aa10da5efa..adf43c083cb93 100755 --- a/contrib/devtools/lint-whitespace.sh +++ b/contrib/devtools/lint-whitespace.sh @@ -31,14 +31,14 @@ if [ -z "${TRAVIS_COMMIT_RANGE}" ]; then fi showdiff() { - if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- "." ":(exclude)depends/patches/" ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/"; then + if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- "." ":(exclude)depends/patches/" ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)build-aux/snap/local/patches/"; then echo "Failed to get a diff" exit 1 fi } showcodediff() { - if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- *.cpp *.h *.md *.py *.sh ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/"; then + if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- *.cpp *.h *.md *.py *.sh ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)build-aux/snap/local/patches/"; then echo "Failed to get a diff" exit 1 fi From 543578a0340b41e7e8af111d70cfa2b08302efed Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Sun, 28 Jul 2019 18:37:36 -0700 Subject: [PATCH 075/132] Update for merging --- build-aux/snap/local/desktop/pivx-qt.desktop | 8 +-- build-aux/snap/local/desktop/pivx-qt.ico | Bin 53158 -> 0 bytes .../local/desktop/pivx-qt_regtest.desktop | 15 ------ .../snap/local/desktop/pivx-qt_regtest.ico | Bin 53158 -> 0 bytes .../local/desktop/pivx-qt_testnet.desktop | 6 +-- .../snap/local/desktop/pivx-qt_testnet.ico | Bin 53158 -> 0 bytes build-aux/snap/local/desktop/pivxd.desktop | 6 +-- build-aux/snap/local/desktop/pivxd.ico | Bin 53158 -> 0 bytes .../snap/local/desktop/pivxd_regtest.desktop | 15 ------ .../snap/local/desktop/pivxd_regtest.ico | Bin 53158 -> 0 bytes .../snap/local/desktop/pivxd_testnet.desktop | 6 +-- .../snap/local/desktop/pivxd_testnet.ico | Bin 53158 -> 0 bytes .../local/patches/X001-default_data_dir.patch | 13 ----- build-aux/snap/snapcraft.yaml | 49 +++++++----------- 14 files changed, 33 insertions(+), 85 deletions(-) delete mode 100755 build-aux/snap/local/desktop/pivx-qt.ico delete mode 100644 build-aux/snap/local/desktop/pivx-qt_regtest.desktop delete mode 100755 build-aux/snap/local/desktop/pivx-qt_regtest.ico delete mode 100755 build-aux/snap/local/desktop/pivx-qt_testnet.ico delete mode 100755 build-aux/snap/local/desktop/pivxd.ico delete mode 100755 build-aux/snap/local/desktop/pivxd_regtest.desktop delete mode 100755 build-aux/snap/local/desktop/pivxd_regtest.ico delete mode 100755 build-aux/snap/local/desktop/pivxd_testnet.ico delete mode 100644 build-aux/snap/local/patches/X001-default_data_dir.patch diff --git a/build-aux/snap/local/desktop/pivx-qt.desktop b/build-aux/snap/local/desktop/pivx-qt.desktop index 8c137c03ac71b..48887dbd4fa7f 100644 --- a/build-aux/snap/local/desktop/pivx-qt.desktop +++ b/build-aux/snap/local/desktop/pivx-qt.desktop @@ -5,11 +5,11 @@ Encoding=UTF-8 Name=PIVX Core Comment=PIVX Core QT main network GenericName=PIVX Digital Currency QT client main network -Exec=pivx.qt %u +Exec=pivx-core.qt %u Terminal=false Type=Application -Icon=${SNAP}/pivx-qt.ico -MimeType=x-scheme-handler/piv; +Icon=${SNAP}/share/pixmaps/pivx.png +MimeType=x-scheme-handler/pivx; Categories=X-Office;X-Finance; Keywords=internet;pivx;zpiv;piv;core;wallet;qt;main;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; -Version=3.2.99 +Version=1.0 diff --git a/build-aux/snap/local/desktop/pivx-qt.ico b/build-aux/snap/local/desktop/pivx-qt.ico deleted file mode 100755 index 5db4fb4989bd8f3dc92a377aac02b3e5c35d9315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53158 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 a4Jz?tuQOK@++}987U`m>v%8h9|Nb9>kPEi} diff --git a/build-aux/snap/local/desktop/pivx-qt_testnet.desktop b/build-aux/snap/local/desktop/pivx-qt_testnet.desktop index d55dca27436e5..a2c5c0fc95b3f 100644 --- a/build-aux/snap/local/desktop/pivx-qt_testnet.desktop +++ b/build-aux/snap/local/desktop/pivx-qt_testnet.desktop @@ -5,11 +5,11 @@ Encoding=UTF-8 Name=PIVX Core Comment=PIVX Core QT test network GenericName=PIVX Digital Currency QT client testnet network -Exec=pivx.qt-testnet %u +Exec=pivx-core.qt-testnet %u Terminal=false Type=Application -Icon=${SNAP}/pivx-qt_testnet.ico +Icon=${SNAP}/share/pixmaps/pivx_testnet.png MimeType=x-scheme-handler/piv; Categories=X-Office;X-Finance; Keywords=internet;pivx;zpiv;tpiv;core;wallet;qt;testnet;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; -Version=3.2.99 +Version=1.0 diff --git a/build-aux/snap/local/desktop/pivx-qt_testnet.ico b/build-aux/snap/local/desktop/pivx-qt_testnet.ico deleted file mode 100755 index a4892e2c1352d24566be7ed6d72c679dec052af1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53158 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 diff --git a/build-aux/snap/local/desktop/pivxd.desktop b/build-aux/snap/local/desktop/pivxd.desktop index c916cdb933517..52a34224c9f02 100755 --- a/build-aux/snap/local/desktop/pivxd.desktop +++ b/build-aux/snap/local/desktop/pivxd.desktop @@ -5,11 +5,11 @@ Encoding=UTF-8 Name=PIVX Core Daemon SNAP Comment=main GenericName=PIVX Digital Currency Daemon Client main network -Exec=pivx.daemon %u +Exec=pivx-core.daemon %u Terminal=true Type=Application -Icon=${SNAP}/pivxd.ico +Icon=${SNAP}/share/pixmaps/pivx.png MimeType=x-scheme-handler/piv; Categories=X-Office;X-Finance; Keywords=internet;pivx;zpiv;core;wallet;daemon;main;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; -Version=3.2.99 +Version=1.0 diff --git a/build-aux/snap/local/desktop/pivxd.ico b/build-aux/snap/local/desktop/pivxd.ico deleted file mode 100755 index 80d3b36945ae65226df597245931e7f8ad9e32cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53158 zcmeI5ca&9C_UAVgp{iabsH*o~1*if+L_v@urz)sKR1BC2B4TP2Dkef9ZEBUa1##7nd47)YR|p$E+rqY7v)mUge zl)C;mH#%|m{Q9etgwhpd^Q1frEd7ik3tWl+e$w~|`j|A=onXB#uD0+TsP_=!dhf~o z)26q1H!TA?i}*J}?~~43xSv7a;Qt!>V1Q*Vn_~GVRa!Xk)q5XC(-0&4KZ5tKBK{}P z*Z6-^U}-PH%iq9Z%OK1A>+zQJR=MRbuCH{?M7lmVSO;%ed?) z%eZ2QQ|h${`vF$<(FTg zd7%f2##(Nnrzdy)@MHA9w&FwSeEj|g4bnv?^$AtRMGYxBky%k4Z3tRbQNJs`&nQNc~77nu0S8$OM9MPYsEd4 zj_4QKU$Q(X-jCFyhh?E<2FZ`UC-6A#9P%6kt;Ams(VsZ<5q#W?ZXZkDQ_(}e1CMK~ zkPRpQpMSQU|NB3hgUjCk2FFfeajz=cY z@!{L2S@75h55L&%pChuHs4f)GBg#FPGCvHd->x9fXWV?%?|zH_n@0F}9@&_JTug(9 zJJ8P#4_?|$8npBk2%nXZeGg!{jjC3!2J_pjq#u{#%Yxnszfg8kPm09 zBOVg{ygG;XGkNz~XbPls9DG%7u-H&+S>o>r7Y7e}#v*BspZ~V^vA|a3^21{+Yf7z! z7lOgb%G(qOkwm#V>53SB$Wv6X@fi8KJvR$^1 z!pwm}H;|Vw5#DdA4r;967 zWoP^sycQlG_T}rf|HlY#iT;~H{?81utWUw!OG_?1s13%W{dAw?aXnwPF3-i5?F39KZCM?<4&BiBdt z|Nl+c|NQvRAKd;oZ7F#_4c!L@tKnw}{qYR?*ipw>&S2zWFqn)ak6Q9T=Y~c?$B^$p z@;M%VIdnStUe0qJ?%l+_XfFNl5A<<~e%|dqU!-MT$G4%9nk zj7f?uEsHz{l7BU%HI&~o#(9>0@P5j@9MW8V60+EjJ~^|@%DU=ZkN*AZ|Kj*HzD@M= z;>NoF`te75>8WR;Y3cuBvy}dp+G~vU&Z)rfe@AnV*g2v9|3vx63-`b0_y3(Ww@c>E zvsGs;u^+zwhwa_7udM!f@zQK!B=}+Cr$U*C|Nykp6*TgErwkclJVid^Y8FwsIum zw+_*rYjYduJAd5HP!2yoo*%wa(CNdNQ(T80zmjq5@Ns56y#Hg}15pk?57N1Mo=bmJ zV(CNa59{cM>gk8Ro^1K=)91ZFUwacYDp5H)stkU<{r*Dh*`Kk*GWhgP&>PTItg8-UZ9k2&lu-uOHAAm6wqb2EG?Q^ns?u$X_0@P~ z_juNS^5$RUkSHV*Vw+OltipTeU<)EC`hAge`Oe^R`9h^&DJjWRG zKFToKpO@#4hiNil-us?Q8`WC#ThI&0$OL!~!1F1%4c5a5i{*L0XWrRFyfc|QWY9J= zH&{ykPACfQYr|CubOL2b(eFg2uUy@9zM3SDO_q(cR2Ng=KLGxhP#4eO zP7)v9+PM75{`~wGT517vv}d8U(uw3#1AP$7J2LeZy8kM|Ps0Bq^taeJO+0HoT75-; za$JKf-CtqhB0n$9;eXe^B70|Ga}nuo!YzSD?|Lm(U zJkUD3Gry0^zj##|q_vH%*9OUs6kJor%Ui=vT=QW3a%KV+=W4PsfD4fM_6FmF*KMURm9Vq_MQ|phl z>@T!e)C`_G1^;!lU)td9>^Hmzep;7x2z~CZO@^Z~A0smdoc|#DN3w_ht6;DA9Qflb zOoa5z_@A}i(5-}VUMISa?dRL`ceMO`!?^kL!IstFoQ>Cx{O(*kwg)W&Vs*m zIp>J}1iqSQEyLZ9(1+I$K2K}U5%BF4HKpEogFLo&YIz#1R`4&97avslB8wfp1 z9B0p2`-D8RF1%kEI)s1ecg~M}L0fg&q+~h)MKPv+)SjP{45=Q7znEu*d9p9JL-?26 zplgtu&@+s;w8ox*LeKm8QyuYqL4^O{1m1V{%6xI!oqu7^-sNAxQ8KZ3x(&#ZOvln3 zE6t%?>?1flI~cqEo5Vk77LU_Dn~(Pn!QaK6wH?WBkaHaQ)23Sf^jJb(X7E3IAp2xQ z{1bki_;+>D%N@zT#*mB~KWFVAD%a#Me;6S!#yEL5 z7RElfqnFlKTc1M4UR_lWklKU)y>^v<#${VIw(;i)rtC=uIrr+3vsbJAT1fla&a>7T z>a>p^k^PX?wA8l!_1LcXM`S1KbAO)TC;i7BZ{bAtpjn^F8_BrcISW7^B_79CTJ9*F z!BGDz-dRH&LHI-NyMFB3ng8^!HCKv}9r3UI;NUDPNXKOk8w#+$nC_9D$8o-jctfEJ zAkNk7x3BD#qdnzk`)JGka}58q$uK%3cprSNi%0yA%!eLD_i#qR(M7Q`jl>-#fS9&(qN>;w>?S`7hiU-(Gr*Roiy{!kUlP9`4~R<)qY=K7{B>ST z`XqKdpt7l~T3h4XM))q?Sq9C6s-Phd=gq@fXYbD1ZV#SELmOK&{|#FY_9Oy2PpS2) zr{Mo~+>4ph&t%PSIBSZ9d6t?n)UvvtVnsbqw8GqJRxptKb>{Xo^5>jG=nCizXcBZZ z;d!{JP3N$)oseN;;XBO)YJ>XA#vMv}ZfOM{3cyp#9bUpn3 z9(n@ee3MgW>L2dszvcAL#L1t?xubNCpXTtt+jpMaEqk{h_hsO92t3Zl)maps1APPf z406taQVy*VslHx7=KjFF5c;doz3`;F5$wH0#&Oa^@T#-ftKoey^UEsEjSb@LQZLq@ zyLmjz)!7V}hop+&e^-A0zKH)n&T90?wX_gAX$1Q#rxjS>diZ_>dWX9C68^VISHY{= zC+FDJF#^g`@fH+Hu1)$?>&G2pF5p;_MYRpI;R^iTww?5mx!OH z!VeU`$>bZ$dou4Fj&Z4Wu8$mIa{N5&Ad~#gAtYQKWYY5v z9UjB2*G3j@o$Cr@JzJ{dau$lyP~726+T}ebK1Ze^?{#zCuCCi9N!QEQd(TV93vZUI zaysSJ;VzYL@6PN9UVHiJIlilNS_>gwKXOhB437McAaDeMBM2Np;Lt!oou8i$jZ$^~ zQur}XN- z4ek`hd%ts+xN~q94>vCi4!iWRo<|j1#^tO7zUi(5zQ;Q2ldM%q~AIp0up4&M} z+PS!hhm$`H8w>qeE58!lwFdh)(Y|$9-SKqJkUY=c^$qMbjH^=qAOIZlkuR*dS(%{@R|Gm%t#2U_UUcvhPBkZw7_Z-nhPCc+U!TloL%PAUG z5wmv^o9BT=qhoWAExZ4jeUc3DJ_)&h27R;Lk2`xZ44RH@}20r~U z=u{|Fc3hd&o-od8xcxU{#00yt<}|CDa~}2$LpkVv?n{KUcj(!(&>pqU2Iy>(_HO6X zPluY|rQ^YA=Nua=FLtty0@vl>{|UH%i{G(Rg!?7*AT*7>HoJ1z7^?;IYKUjf4LEzg z!~0@uu7>(pR6f&I&YsU1o}kXkjHM3f1EhnZXCY`0j&53CZG|;lYH;rOC*rN0A?dK> z6O|9!5!fgQoQ=$Ha^>B{-I4c)xc5;DW!8ZEH1Mq&Hd?rIUnH%XI=Kt{>!FYFuj6d| zZ2rrwI-$(Y8eeTU&OTRXP*bS~owvaDPlNWLb4{En3*F?M8B4@thk?`%88uR-F37Cz ze(0RSR!`S}<2Gm`cNT?Zw)Bhi%%mY@*l!4gz#7|P=^LRhd9T5p5yEu7;ThsApe{H< zU^aKm6uW8GIn+Z~=Sg(-WDWJ;?;og#Am=pl=gJODBmA}lI_;ZeqO!;q6?k6=PJfZE z@!|Li7@h;pxz%7Uc^^OM1lcn!B%me71v+H=fk}+ofRDcgnDl z$oqIJA3n+$Tk8Jn0_a5-(?)S8UcCQxNBJVs?lbAQ5w>8`bgMgQzUm>LF_X?z$sU<^ zK2B%&HquAWOf+X`Ux{s-)Z<}4fH_c+Wt;{^?}3LS^SE1iUXP1?*7THVBgR`b`km)q z&|HYSnN7=k0^DQk;uYe}r%v;$hK;pLE9X!L*N>q|YpyWH-({o3WDm2FEVb18NJ@g)>HC9pe^kf=2H+dgbxlwneY? zsd;?)UCt}&p6EIkOO0*RzupTCnSrj6j@OUp!O(B{|F3S`R$<*(8q6&;rsd9aU<7v^ zx}H0s)^0t0k>(C1kZh7^TqK>Oz8PCld1d}G`Tea&t!+~9^W^y{-%!T$PkS;?nLmLp zM%QFdJ7GL?r!mNUfP2V}j(@u`%-ZQcopHScos?IL?z?`*SsEv4-hgd&=S--3?mM`V zyEBtPYQK4N+o0F-R6ML>T`(_0&R*V!eP9!1t))IvYDbK-|FiHLjVFf@CjH;$x~3WR zrLodu@G`carFPZ)t=dY}FJLRqIh*U$0qx*vo~OpE1C{+i{bF&~Gx~KnWn%mn_}0bY z3H-yv!<_S9?+cmaqRF9i&yrJu7g+}BIBGi*|%`U^^|2DRHStojrs5ofF4K| zXE&Yii0_b>ZnE#UBHokmd3@E-F?PeubGXkO?gjSOs2xCzPeb=ix1!?M@^>Wuaq`A4 zS=tqpS^8A+_!!iu205x8I!@Tr7pKb}X0o#S4S2uA-Ge)6Pj^AMj$IjNeW)4fB%5Ds zJk7<&mX91t9h^-agnFZkxI3cpsWV4d8gGBCqv{|Qf9^D}ZXA$}7UA<6x^!qw*+kYU zo%xiof1x>;xw5_(8+m-i!uU##Y_B+bU|ydRi&uL*Z$cN1tEL^?I9qEMVcm&e3;xUx z!Y@yyKaRzrBk+&SlW!f!)|AHdS~vb2I&t>+a;rLi3}c-1qxkRX=3uY5F8+)Bd4c~W zgm)zVs#CRtp=!sg=Pc5Cs@76<_e=BSyC$-h<>yiU_Ws4@hYhMp@Tq%N-yrvQFrH3V z|HT?{HoV_0Jey1L@lWqC{K+2~h}vFy6q{<{b6Gvb20%CT5VoTucC~ST9wB#N*54UqWuyTDsEvd%lhin^>kdx_e>Dd4a1sP;C8df3Zt@1H*} z-_<`#Iau@%$tjMocNDW2jP{BMZv#^olmY44b)1`0Cv@`BU@Mm0s9*fSu_^#^aQH&SC9X-=-^6ug8xre>{)3^SO z@ysXcSKFvh^{`FGJ*@E`XxSHH3-cr9Maf{*9&rw9{26;-W7PR(qShaERwp4zFS*o~ z^>A3@j~yiT#ez&fR4pNRU3*fHhZ*3`#gjX&Q)%h0*;WQgx> zVDl{0kNw&*>OkK&Tmkm_-lo>foHd;m)WuX z+_rF7;IFYg-_P948ku9qwKcfMzN2%zH1mhmh*#r9(n(BQ+$7;l<{i=+rvq;heH~FZ!JOJqW0!g)Im#i zHQ&V2+HmkbaJ_)K>mS<|Wb>B)A81B9IHd7s&3bzo-%CzH4wKT`syi23>3VE5hNo9p zMFabhw2>*CFTqA;Qnq6cY5cWL4^AzW_eSeP^*|eVQQv;{>mzJrrje)4l_b+2ACmY> z@35Y;Mf-l9-T{wB@odTek+u+gQvHHo7s(bZb>qL2lql~*5`XC(_NP8*Pwaj5B{{#+ zuZJqEFpqxVepgo|!d~Hr9R8Ah){sB*_F;uVO9_0E(OrrIj=9nAk7-Pb{$J+Kkq;~U zIV-eP`&F*&zlMvg{xD+}ja!l@^v8N|eVlsq?$jm35uBxK8hnq3_w`Moruu+GPX4uD zNV$a-aw)sw1%s=se|ClC@Qv`~Nq0wSH&zBk~>z9awWg^kof zf8G7m+2ZC9-{Qa)e!*m9w@LiLS#>?9A^yR5->QjiM~4jl?3r)#>3yf1u3o+y4D}ti zW)bH>Zb5&oPeO)upXhb&JWlcB&)n=Z?I$#%d&J`*fxpg1Y0N`;;*D3dr}B35$@x}R zQ}{XUjC@&#&L8OEulX2#{%;PK@sB&+-|ss)O~_uXE@;uS>Xm%f=vzV_{_GWG(01-5 zys7#-=;dE}U*Al1zwg>23|mo88e_f8cc{ue?Bz1%)%RriK1$s7=;!f}z@IVa$F0E7 zk4Mse^|{KEe)kf;Z3lD@-&rfTi2s|CedTq~g^XVuBHkj} z()l9hwC98M;s^!LMb~5Jr{I_}UtjCVzB^yOA_-pnydKo@uk-kkb%ibBD4<`H@*n3E}??q-i1I~$fc>Ex_ z|J9qZ=9B(=ckcOy*6QCxxU_q?+AaOa1I$4RWZ$^6-hZ53HW`~6S>4b#vMn|Tx{P|b zo%^7VFh6>PKJj_V@oHz)L-3~kn-_4o*B-hHKCgpk=6a!8Xb9uC9`60$&UpXy^qC_j zI<_QbQ?l~-(N=N%DC#3Kh5P*(ltX922V;Mh?@5Qwz>hun&@GV80LrEa_0ssBy@cH>*}pn@RJmPIeX3*2Xw``eY~`$Z#&^!Ua`q{e za^_Lq0l4ERlWY%O#Pcd>9nVkk?6)JIl&;}jCm!#<1SyU6q$Qj5m-64KxD#-XW_%jt zK2sWFt(4_6=h-S@48F_3TO_Pkz-t{muRc{aD#P8WpA6_k-d9`c6!)*eUHHrXl5E!A zgWg$2A8;0KIW!2$=RALEiKTUwja%8DoQZv=)5liY<<+NPBRf*wx|0@I`uQ_d&YqMp z2b@YMXBqAc!WQA)0AT~kInVhbuH^W2{u9m{iHlw5@CxVxo@Ya&2E5S&YBc~!BG5_P&NMHta0`sJiE&By1#$Z-Hsef zXGn%6%aUXDoqAq%(n6bIA@&{foc2duA4NLjcz+IQIqeVsI_L?)UxuRhx(Q=$qP1CP z&l9_R2hRRL*fR35amBYl0>1}K?0u$v3~i$>zI7>Hoyh*n7T)=oI(ZG!cP(y)masoC z1NQ`|7|JT8FR!Ezsit0}&t{LDXy;9yVM}XIciN0(*3oC+x*U8xoFno)-_}HIR;7S% zI`SF<$H8DX2|68|FUS2YE;eq%>I)p4{e28!ng_aA>kgUIKWPl{Ah@sOd4BAf8TNGA z^%rl=iwwJC11=BzWb17<*e=DDZT~m0Pvh7W_SXsj$F>uv&49UVG|P^Y>_b0+{|?;C zspFG*XEgqPP!6`WdZ>`nVb@MO)0TlhSabucOz>pQC!e+vqHToE0jsNVZwF)9&v+J6 zznQ2X(R|s#TXDdcGt>Ex;9tW!_!7pS)jA_qX+^n-)(6`ad=ig`f4r~(teatPK3r(s zPoPblik-6S!Shi_*vkGVbr6u=!fsqZ?ZmIQV*RpB^*M2{pB{J)|62T4Gp{>?bJMfH z_dM`rO*!A`8^HJl!rp)q;jHi|))5(Z_Q*DZ`5j=cetH&oACDW1-MfibUN5Y(;P3Gh zbvfrzz+MRLp%3yqmbP*(7}kNO=4yX}+;8p#z5`#`*^Apo2#?kc_^o9l1xtB8g?;%lt(WR-1Q_mT>p5Bu_Rbpfw>SP?`i=3B?0+ifAl8{nu#?U= z*2=+l5%qH$?E)LRX?!0e?JL@czICVmWWT;d=XYcG6u>pwKSp$kv*!E^e%3?tuVY+u zCUQM)suh&z>`5Ja@X7MqSUeAx1MN1(V>182f7epZ-eSvmV4?NYcXlqO9@gT%O#OTU z>6>7*kHB|~X}@;w>P2-nI6sd(Gp7r?{bRU%x^vg7S9UVr=xmC|1C4KU@^7jv$^NhN zok!EZ_pyv2)Wa==vY9;5zI?txE_Rycdd_3j#Z z%|4R9hjppPzfk^e5q~M(J*g3Y&Z_wSRE6h6;v8uI-o16^@c^ctpHf}#^H22ovwZ#@ zK7UW2KP8dB&drPTQ#^n6-ukHDA0F#ZkfuLhKRc<>$&jZ|`et Vv@f@b5UY-odB5G|p08cq{|}};?-2k1 diff --git a/build-aux/snap/local/desktop/pivxd_regtest.desktop b/build-aux/snap/local/desktop/pivxd_regtest.desktop deleted file mode 100755 index da31a04a0602d..0000000000000 --- a/build-aux/snap/local/desktop/pivxd_regtest.desktop +++ /dev/null @@ -1,15 +0,0 @@ -# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - -[Desktop Entry] -Encoding=UTF-8 -Name=PIVX Core Daemon SNAP -Comment=regtest -GenericName=PIVX Digital Currency Daemon Client regression test network -Exec=pivx.daemon-regtest %u -Terminal=true -Type=Application -Icon=${SNAP}/pivxd_regtest.ico -MimeType=x-scheme-handler/piv; -Categories=X-Office;X-Finance; -Keywords=internet;pivx;zpiv;core;wallet;daemon;regtest;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; -Version=3.2.99 diff --git a/build-aux/snap/local/desktop/pivxd_regtest.ico b/build-aux/snap/local/desktop/pivxd_regtest.ico deleted file mode 100755 index 72802e471d00df7a0e39e97ab31044a2a5509029..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53158 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 Jr%Ltb{{aka)8qgE diff --git a/build-aux/snap/local/desktop/pivxd_testnet.desktop b/build-aux/snap/local/desktop/pivxd_testnet.desktop index 8ffe7d3effb95..6cf6a55ab828f 100755 --- a/build-aux/snap/local/desktop/pivxd_testnet.desktop +++ b/build-aux/snap/local/desktop/pivxd_testnet.desktop @@ -5,11 +5,11 @@ Encoding=UTF-8 Name=PIVX Core Daemon SNAP Comment=testnet GenericName=PIVX Digital Currency Daemon Client testnet network -Exec=pivx.daemon-testnet %u +Exec=pivx-core.daemon-testnet %u Terminal=true Type=Application -Icon=${SNAP}/pivxd_testnet.ico +Icon=${SNAP}/share/pixmaps/pivx_testnet.png MimeType=x-scheme-handler/piv; Categories=X-Office;X-Finance; Keywords=internet;pivx;zpiv;core;wallet;daemon;testnet;snap;launchpad;crypto;digital;currency;coin;token;zerocoin; -Version=3.2.99 +Version=1.0 diff --git a/build-aux/snap/local/desktop/pivxd_testnet.ico b/build-aux/snap/local/desktop/pivxd_testnet.ico deleted file mode 100755 index 0f7d5b609cb9619316bd0b0659a42d8fdd3a8996..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53158 zcmeI52Y6Lgw#OGmumGVBf?$FJhy@5z719f!qN1RHsIh=x!QOEQjx&ye=+Ht5HIrYUUPw>w_pNX5v+q88ul?U^uie)X zsUfwcVMD%+i&;R;|sQbm*`Nma$-l|07|M`Fa+qj+*(s=s&{_s{4XGW|vn;k9pWJb$f%cA8s z`u~6K-{?&9T!AFcojYg3b3Ys*3DHt_Mx;b0M9C{Nqh(xjw7j`AN?uqNCDF@b3Wgr(bAOn;$}w4n=_&$8UGO_o)@M@%WI_b(2_`LmT;Lk`Eb1Z z^_EP{w?6MYHX~a8$UA$cN6Aj;FNB}s`8)jk=0(fzmqf|%Wsy?<^wum_8dt&z@Aibo z691USpB5pn^3HnFJ3Tu}j?asdualx>Z&sAN3?AJY@s7p2y1W<8`;+xuXMQiviIUZ6 zQSwzbX~O#<=pZ<}&-)?vchyf`VdOQ{`TnVy5%NM-xIDfzQeMxFl0Q)HT$4tmd{D^y zQ}liE{g!%L%R5O>Dl`thpQP-2$-mI|DZ_WEk+PY%Z)8Wx%S)prgZKBq%LC-U5t`sF zf66drPNaOxyZeZ@g7>m;S7%4aj7)GR{8Pwl{=7dGjQ5+0RY28Zu8Ilz(_aSfHmqkdc zB@uGvD&n}mXFZ?&`HcLKcT|onpDyE?pHDxzy~y#^bLAf=K9^sKW5sv4B4@)yehd)F zt1FUQ%Qw=vux#{95M>F6R9_Y6uOOd}wyI$z{j=wL_NRZl@H+eNf4cl7!G}HHU(f#R z%4<%9v`&wZYxA9Y@)xI$w&E8D9-3C(&Ky^s`aB~>+Mt)-K%R4H|ErN-)g{+ke5ek- zR35DN)&2YN&rNz$qogUi{2AK7dh$;r|Dm*@fy=dRs$M{c(uP{=J9#T-xp>fLe|{SO z+^=U{?@tSt+T?pXZ8#HJK>srU>VsZ*3trwvFNTnR3^+_dH)X)n{j|p`G#w?YZTZ53 z#{UI*viiPRedTKM`~#Fle>H@BL&$dm`5uBypMb0V*`&GA5(*Ck;AH_kyuTzI*)aM4 zB>(>J?+q`7@t|?F+~>|Y>Ti0C+?)_8$>jNauK z!NWXsbFh`Jy54?PoEf2v7b0a2`45GLkjFvIhkoP~I(W~N2zj6X_v*8k{1p$alLz79 zF646R@>s`Mr_lVJ?U=N+zlewWIn%N5{eD`MWKRs2rnpP_PjRsRbGf{C5?MJxKXHV< zrawHquq0X@*1WZDz5Raq_y5VH!BUI1H4)7FlTNZ*`rl8BlLO7c?4 zGb>UKQ`ZMQ&?@qdCj7mO5UG3S?|<_(|2s&3i>LhmNck!6(&Q-l2K{%0v~>(-#$g`w zXADuC`J)G$WJJox$kjU1T@9^4@8t4)0KDCCScUu-TmHz^lEho3@v`31G9y&lq=ie6 zQf8>M1B*fMuoT^6=b_m0XS{rZa_?fCHJ3bQS)}7Y%0D(eRBp(I@GrOFP%QZ~_c+Oz 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 KnB^-`_x}N$2)1(o diff --git a/build-aux/snap/local/patches/X001-default_data_dir.patch b/build-aux/snap/local/patches/X001-default_data_dir.patch deleted file mode 100644 index a98fc039ec3db..0000000000000 --- a/build-aux/snap/local/patches/X001-default_data_dir.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/util.cpp b/src/util.cpp -index bd44c328c..455e990d7 100644 ---- a/src/util.cpp -+++ b/src/util.cpp -@@ -433,7 +433,7 @@ boost::filesystem::path GetDefaultDataDir() - return GetSpecialFolderPath(CSIDL_APPDATA) / "PIVX"; - #else - fs::path pathRet; -- char* pszHome = getenv("HOME"); -+ char* pszHome = getenv("SNAP_USER_COMMON"); - if (pszHome == NULL || strlen(pszHome) == 0) - pathRet = fs::path("/"); - else diff --git a/build-aux/snap/snapcraft.yaml b/build-aux/snap/snapcraft.yaml index 66bcff9b77539..a6bd2315abad1 100644 --- a/build-aux/snap/snapcraft.yaml +++ b/build-aux/snap/snapcraft.yaml @@ -1,8 +1,8 @@ # Copyright (c) 2018-2019 The Ion developers # Copyright (c) 2019 The PIVX developers -name: pivx +name: pivx-core base: core18 -version: 3.2.99 +version: 3.4.99 summary: PIVX (Private – Instant – Verified – Transaction) description: | PIVX is an MIT licensed, @@ -21,18 +21,14 @@ apps: desktop: pivxd.desktop environment: XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + HOME: $SNAP_USER_COMMON daemon-testnet: command: pivxd --testnet plugs: [network, network-bind, home, removable-media] desktop: pivxd_testnet.desktop environment: XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS - daemon-regtest: - command: pivxd --regtest - plugs: [network, network-bind, home, removable-media] - desktop: pivxd_regtest.desktop - environment: - XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + HOME: $SNAP_USER_COMMON qt: command: pivx-qt plugs: [network, network-bind, network-status, unity7, desktop, desktop-legacy, wayland, x11, mir, opengl, home, gsettings, removable-media, screen-inhibit-control, pulseaudio, media-hub] @@ -40,6 +36,7 @@ apps: environment: QT_XKB_CONFIG_ROOT: $SNAP_USER_DATA:$SNAP/usr/share:$QT_XKB_CONFIG_ROOT XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + HOME: $SNAP_USER_COMMON qt-testnet: command: pivx-qt --testnet plugs: [network, network-bind, network-status, unity7, desktop, desktop-legacy, wayland, x11, mir, opengl, home, gsettings, removable-media, screen-inhibit-control, pulseaudio, media-hub] @@ -47,28 +44,19 @@ apps: environment: QT_XKB_CONFIG_ROOT: $SNAP_USER_DATA:$SNAP/usr/share:$QT_XKB_CONFIG_ROOT XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS - qt-regtest: - command: pivx-qt --regtest - plugs: [network, network-bind, network-status, unity7, desktop, desktop-legacy, wayland, x11, mir, opengl, home, gsettings, removable-media, screen-inhibit-control, pulseaudio, media-hub] - desktop: pivx-qt_regtest.desktop - environment: - QT_XKB_CONFIG_ROOT: $SNAP_USER_DATA:$SNAP/usr/share:$QT_XKB_CONFIG_ROOT - XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + HOME: $SNAP_USER_COMMON cli: command: pivx-cli plugs: [network, network-bind, home, removable-media] environment: XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + HOME: $SNAP_USER_COMMON cli-testnet: command: pivx-cli --testnet plugs: [network, network-bind, home, removable-media] environment: XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS - cli-regtest: - command: pivx-cli --regtest - plugs: [network, network-bind, home, removable-media] - environment: - XDG_DATA_DIRS: $SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS + HOME: $SNAP_USER_COMMON tx: command: pivx-tx plugs: [home] @@ -79,7 +67,7 @@ apps: command: test_pivx-qt plugs: [home] parts: - pivx: + pivx-core: source: https://github.com/PIVX-Project/PIVX source-type: git source-tag: master @@ -92,7 +80,7 @@ parts: # project is called ioncore because ion exists already as package. For anybody # offering non official release and using own SNAP, this variable should be used # default value is "false", to enable it, use your projects binary prefix - OVERRIDEBINPREFIX="false" + OVERRIDEBINPREFIX="pivx" OVERRIDEDATADIR="false" OVERRIDECONF="${OVERRIDEDATADIR}" COPYCONF=0 # copy example config into users data folder, 1 = enabled @@ -100,7 +88,7 @@ parts: PATCH=1 # 1 = enabled SPLASHPNGS=0 # patch pngs to differ visaully from those installed from self compilation or other source like deb FIXPPCBUILD=1 # if ppc builds fail due to failed qt, apps part will return error and build will fail, 1 = enabled - EXTRALOG=1 # prints env and all installed files at the end of current script + EXTRALOG=0 # prints env and all installed files at the end of current script RUNTESTS=1 # run make check after post install part echo "-----------------------------------------------" echo "+++++++++++++++++++++++++++++++++++++++++++++++" @@ -140,7 +128,6 @@ parts: cd ${SNAPCRAFT_PART_BUILD} if [ $PATCH = 1 ]; then echo "apply patches:" - git apply $SNAPCRAFT_PART_BUILD/build-aux/snap/local/patches/X001-default_data_dir.patch git apply $SNAPCRAFT_PART_BUILD/build-aux/snap/local/patches/X002-fix-bdb-tmp-folder.patch git apply $SNAPCRAFT_PART_BUILD/build-aux/snap/local/patches/X003-fix-use-snap-instead-of-dirty.patch sed -i 's/tar --strip-components/tar --no-same-owner --strip-components/' ${SNAPCRAFT_PART_BUILD}/depends/funcs.mk @@ -195,6 +182,8 @@ parts: echo "INSTALLATION OF ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # run make install with a prefix where to install echo "+++++++++++++++++++++++++++++++++++++++++++++++" make install prefix=${SNAPCRAFT_PART_INSTALL} + install -m 0644 -D -T $SNAPCRAFT_PART_BUILD/src/qt/res/icons/bitcoin.png $SNAPCRAFT_PART_INSTALL/share/pixmaps/pivx.png + install -m 0644 -D -T $SNAPCRAFT_PART_BUILD/src/qt/res/icons/bitcoin_testnet.png $SNAPCRAFT_PART_INSTALL/share/pixmaps/pivx_testnet.png echo "-----------------------------------------------" echo "+++++++++++++++++++++++++++++++++++++++++++++++" echo "POST INSTALL SCRIPTS OF ${BINPREF}-${SNAPCRAFT_PROJECT_VERSION}" # run make install with a prefix where to install @@ -241,10 +230,12 @@ parts: echo "RUN TESTS" # if tests fail to pass, build and release will fail echo "+++++++++++++++++++++++++++++++++++++++++++++++" cd ${SNAPCRAFT_PART_BUILD} - if [ $RUNTESTS = 1 ]; then - make check - else - echo "RUN TESTS disabled, skipping" + if [ ! $SNAPCRAFT_ARCH_TRIPLET = "s390x-linux-gnu" ]; then + if [ $RUNTESTS = 1 ]; then + make check + else + echo "RUN TESTS disabled, skipping" + fi fi echo "-----------------------------------------------" echo "+++++++++++++++++++++++++++++++++++++++++++++++" @@ -254,7 +245,7 @@ parts: find ${SNAPCRAFT_PART_INSTALL} -type f env else - echo "RUN TESTS disabled, skipping" + echo "EXTRA LOG disabled, skipping" fi echo "-----------------------------------------------+" build-packages: From 214e931d8b719a78a47bd10c51a5807dfbcc2e7b Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 8 Oct 2019 22:29:41 +0200 Subject: [PATCH 076/132] [Script] Introduce constant for maximum CScript length Backports bitcoin/bitcoin f8e6fb1800fbac87e76cdddc074d8f4af585f050 --- src/script/interpreter.cpp | 2 +- src/script/script.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 96f90ebdeb796..56d4deaf18db9 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -269,7 +269,7 @@ bool EvalScript(std::vector >& stack, const CScript& std::vector vfExec; std::vector altstack; set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); - if (script.size() > 10000) + if (script.size() > MAX_SCRIPT_SIZE) return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE); unsigned int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; diff --git a/src/script/script.h b/src/script/script.h index 445628db25325..7e019b768c5ff 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -23,6 +23,8 @@ static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes static const unsigned int MAX_OPS_PER_SCRIPT = 201; static const unsigned int MAX_PUBKEYS_PER_MULTISIG = 20; +// Maximum script length in bytes +static const int MAX_SCRIPT_SIZE = 10000; // Threshold for nLockTime: below this value it is interpreted as block number, // otherwise as UNIX timestamp. From c46e22ba58ae39de116bb2a565c3ed5fa0f35ab5 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 8 Oct 2019 22:35:25 +0200 Subject: [PATCH 077/132] [Script] Treat overly long scriptPubKeys as unspendable Backports bitcoin/bitcoin 4f87af6fc7580912726f9bf833c21e6e1b478e1d --- src/script/script.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/script.h b/src/script/script.h index 7e019b768c5ff..1999a9f970fe1 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -631,7 +631,7 @@ class CScript : public std::vector */ bool IsUnspendable() const { - return (size() > 0 && *begin() == OP_RETURN); + return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE); } std::string ToString() const; From 789a11756470740ee67351492de05b49d779a3e0 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 8 Oct 2019 22:46:56 +0200 Subject: [PATCH 078/132] [Bug] Fix OOM when deserializing UTXO entries with invalid length backports bitcoin/bitcoin 5d0434d13d0145a110c0c93e59edfd7d062f8531 --- src/compressor.h | 10 ++++++++-- src/streams.h | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/compressor.h b/src/compressor.h index 97b5ea0ee1f90..0f25d71c65596 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -91,8 +91,14 @@ class CScriptCompressor return; } nSize -= nSpecialScripts; - script.resize(nSize); - s >> REF(CFlatData(script)); + if (nSize > MAX_SCRIPT_SIZE) { + // Overly long script, replace with a short invalid one + script << OP_RETURN; + s.ignore(nSize); + } else { + script.resize(nSize); + s >> REF(CFlatData(script)); + } } }; diff --git a/src/streams.h b/src/streams.h index e31ec607ea11d..f0554443fdf80 100644 --- a/src/streams.h +++ b/src/streams.h @@ -402,6 +402,21 @@ class CAutoFile return (*this); } + CAutoFile& ignore(size_t nSize) + { + if (!file) + throw std::ios_base::failure("CAutoFile::ignore: file handle is NULL"); + unsigned char data[4096]; + while (nSize > 0) { + size_t nNow = std::min(nSize, sizeof(data)); + if (fread(data, 1, nNow, file) != nNow) + throw std::ios_base::failure(feof(file) ? "CAutoFile::ignore: end of file" : "CAutoFile::read: fread failed"); + nSize -= nNow; + } + return (*this); + } + + CAutoFile& write(const char* pch, size_t nSize) { if (!file) From 01f8c1c901b4c4a88be9e3385b9983a0c7b7eaf7 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 8 Oct 2019 22:47:49 +0200 Subject: [PATCH 079/132] CDataStream::ignore Throw exception instead of assert on negative nSize Backports bitcoin/bitcoin 4bf631e5e48cd4c14c825cdaf7a1bee81e15493d --- src/streams.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/streams.h b/src/streams.h index f0554443fdf80..aa3692909e1f2 100644 --- a/src/streams.h +++ b/src/streams.h @@ -264,7 +264,9 @@ class CDataStream CDataStream& ignore(int nSize) { // Ignore from the beginning of the buffer - assert(nSize >= 0); + if (nSize < 0) { + throw std::ios_base::failure("CDataStream::ignore(): nSize negative"); + } unsigned int nReadPosNext = nReadPos + nSize; if (nReadPosNext >= vch.size()) { if (nReadPosNext > vch.size()) From f522a5bda52998469f4d4caee57aaf444e847a9f Mon Sep 17 00:00:00 2001 From: random-zebra Date: Tue, 8 Oct 2019 23:04:39 +0200 Subject: [PATCH 080/132] [Tests] Add tests for CCoins deserialization Backports bitcoin/bitcoin 1e44169f0e0c334a86b14a22ebc8fec45cec7354 --- src/test/coins_tests.cpp | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 24f21bfd4cbad..51cd8fa9c391f 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -3,8 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "coins.h" +#include "script/standard.h" #include "uint256.h" #include "test/test_phore.h" +#include "utilstrencodings.h" #include #include @@ -175,4 +177,73 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) BOOST_CHECK(missed_an_entry); } +BOOST_AUTO_TEST_CASE(ccoins_serialization) +{ + // Good example + CDataStream ss1(ParseHex("0108835800816115944e077fe7c803cfa57f29b36bf87c1d35b4934b"), SER_DISK, CLIENT_VERSION); + CCoins cc1; + ss1 >> cc1; + BOOST_CHECK_EQUAL(cc1.nVersion, 1); + BOOST_CHECK_EQUAL(cc1.fCoinBase, false); + BOOST_CHECK_EQUAL(cc1.nHeight, 870987); + BOOST_CHECK_EQUAL(cc1.vout.size(), 2); + BOOST_CHECK_EQUAL(cc1.IsAvailable(0), false); + BOOST_CHECK_EQUAL(cc1.IsAvailable(1), true); + BOOST_CHECK_EQUAL(cc1.vout[1].nValue, 60000000000ULL); + BOOST_CHECK_EQUAL(HexStr(cc1.vout[1].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); + + // Good example + CDataStream ss2(ParseHex("0111044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa482d21f"), SER_DISK, CLIENT_VERSION); + CCoins cc2; + ss2 >> cc2; + BOOST_CHECK_EQUAL(cc2.nVersion, 1); + BOOST_CHECK_EQUAL(cc2.fCoinBase, true); + BOOST_CHECK_EQUAL(cc2.nHeight, 59807); + BOOST_CHECK_EQUAL(cc2.vout.size(), 17); + for (int i = 0; i < 17; i++) { + BOOST_CHECK_EQUAL(cc2.IsAvailable(i), i == 4 || i == 16); + } + BOOST_CHECK_EQUAL(cc2.vout[4].nValue, 234925952); + BOOST_CHECK_EQUAL(HexStr(cc2.vout[4].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("61b01caab50f1b8e9c50a5057eb43c2d9563a4ee")))))); + BOOST_CHECK_EQUAL(cc2.vout[16].nValue, 110397); + BOOST_CHECK_EQUAL(HexStr(cc2.vout[16].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); + + // Smallest possible example + CDataStream ssx(SER_DISK, CLIENT_VERSION); + BOOST_CHECK_EQUAL(HexStr(ssx.begin(), ssx.end()), ""); + + CDataStream ss3(ParseHex("0004000600"), SER_DISK, CLIENT_VERSION); + CCoins cc3; + ss3 >> cc3; + BOOST_CHECK_EQUAL(cc3.nVersion, 0); + BOOST_CHECK_EQUAL(cc3.fCoinBase, false); + BOOST_CHECK_EQUAL(cc3.nHeight, 0); + BOOST_CHECK_EQUAL(cc3.vout.size(), 1); + BOOST_CHECK_EQUAL(cc3.IsAvailable(0), true); + BOOST_CHECK_EQUAL(cc3.vout[0].nValue, 0); + BOOST_CHECK_EQUAL(cc3.vout[0].scriptPubKey.size(), 0); + + // scriptPubKey that ends beyond the end of the stream + CDataStream ss4(ParseHex("0004000800"), SER_DISK, CLIENT_VERSION); + try { + CCoins cc4; + ss4 >> cc4; + BOOST_CHECK_MESSAGE(false, "We should have thrown"); + } catch (const std::ios_base::failure& e) { + } + + // Very large scriptPubKey (3*10^9 bytes) past the end of the stream + CDataStream tmp(SER_DISK, CLIENT_VERSION); + uint64_t x = 3000000000ULL; + tmp << VARINT(x); + BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); + CDataStream ss5(ParseHex("0002008a95c0bb0000"), SER_DISK, CLIENT_VERSION); + try { + CCoins cc5; + ss5 >> cc5; + BOOST_CHECK_MESSAGE(false, "We should have thrown"); + } catch (const std::ios_base::failure& e) { + } +} + BOOST_AUTO_TEST_SUITE_END() From 1f787a56cb7ceae68f9c9a6c5e5cbacda28987bb Mon Sep 17 00:00:00 2001 From: warrows Date: Sat, 20 Jul 2019 10:58:13 +0200 Subject: [PATCH 081/132] [Wallet] Do not store Merkle branches in the wallet Backport of https://github.com/bitcoin/bitcoin/pull/6550 Assume that when a wallet transaction has a valid block hash and transaction position in it, the transaction is actually there. We're already trusting wallet data in a much more fundamental way anyway. To prevent backward compatibility issues, a new record is used for storing the block locator in the wallet. Old wallets will see a wallet file synchronized up to the genesis block, and rescan automatically. --- src/chainparams.cpp | 2 +- src/main.cpp | 9 +++++++-- src/miner.cpp | 2 +- src/primitives/block.cpp | 39 ++------------------------------------- src/primitives/block.h | 10 ++++------ src/test/miner_tests.cpp | 2 +- src/test/pmt_tests.cpp | 2 +- src/wallet/wallet.cpp | 14 +------------- src/wallet/wallet.h | 7 +------ src/wallet/walletdb.cpp | 6 ++++-- 10 files changed, 23 insertions(+), 70 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 8f4fd52c80abd..5c2a7ed5e8aac 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -176,7 +176,7 @@ class CMainParams : public CChainParams txNew.vout[0].SetEmpty(); genesis.vtx.push_back(txNew); genesis.hashPrevBlock = 0; - genesis.hashMerkleRoot = genesis.BuildMerkleTree(); + genesis.hashMerkleRoot = genesis.ComputeMerkleRoot(); genesis.nVersion = 1; genesis.nTime = 1505224800; genesis.nBits = 0x207fffff;; diff --git a/src/main.cpp b/src/main.cpp index 8961dd628a48b..319f66de541c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4047,6 +4047,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo { // These are checks that are independent of context. + if (block.fChecked) + return true; + // Check that the header is valid (particularly PoW). This is mostly // redundant with the call in AcceptBlockHeader. if (!CheckBlockHeader(block, state, block.IsProofOfWork())) @@ -4062,7 +4065,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo // Check the merkle root. if (fCheckMerkleRoot) { bool mutated; - uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); + uint256 hashMerkleRoot2 = block.ComputeMerkleRoot(&mutated); if (block.hashMerkleRoot != hashMerkleRoot2) return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); @@ -4175,7 +4178,6 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo } } - unsigned int nSigOps = 0; for (const CTransaction& tx : block.vtx) { nSigOps += GetLegacySigOpCount(tx); @@ -4184,6 +4186,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"), REJECT_INVALID, "bad-blk-sigops", true); + if (fCheckPOW && fCheckMerkleRoot && fCheckSig) + block.fChecked = true; + return true; } diff --git a/src/miner.cpp b/src/miner.cpp index f76f25c3529e0..d0067da950964 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -544,7 +544,7 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned assert(txCoinbase.vin[0].scriptSig.size() <= 100); pblock->vtx[0] = txCoinbase; - pblock->hashMerkleRoot = pblock->BuildMerkleTree(); + pblock->hashMerkleRoot = pblock->ComputeMerkleRoot(); } #ifdef ENABLE_WALLET diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 511a98136ae3b..459548f3cd111 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -22,7 +22,7 @@ uint256 CBlockHeader::GetHash() const return Hash(BEGIN(nVersion), END(nAccumulatorCheckpoint)); } -uint256 CBlock::BuildMerkleTree(bool* fMutated) const +uint256 CBlock::ComputeMerkleRoot(bool* fMutated) const { /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind @@ -59,7 +59,7 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const known ways of changing the transactions without affecting the merkle root. */ - vMerkleTree.clear(); + std::vector vMerkleTree; vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. for (std::vector::const_iterator it(vtx.begin()); it != vtx.end(); ++it) vMerkleTree.push_back(it->GetHash()); @@ -85,37 +85,6 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const return (vMerkleTree.empty() ? uint256() : vMerkleTree.back()); } -std::vector CBlock::GetMerkleBranch(int nIndex) const -{ - if (vMerkleTree.empty()) - BuildMerkleTree(); - std::vector vMerkleBranch; - int j = 0; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) - { - int i = std::min(nIndex^1, nSize-1); - vMerkleBranch.push_back(vMerkleTree[j+i]); - nIndex >>= 1; - j += nSize; - } - return vMerkleBranch; -} - -uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex) -{ - if (nIndex == -1) - return uint256(); - for (std::vector::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it) - { - if (nIndex & 1) - hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); - else - hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); - nIndex >>= 1; - } - return hash; -} - std::string CBlock::ToString() const { std::stringstream s; @@ -130,10 +99,6 @@ std::string CBlock::ToString() const { s << " " << vtx[i].ToString() << "\n"; } - s << " vMerkleTree: "; - for (unsigned int i = 0; i < vMerkleTree.size(); i++) - s << " " << vMerkleTree[i].ToString(); - s << "\n"; return s.str(); } diff --git a/src/primitives/block.h b/src/primitives/block.h index 4193344adb99d..907a24f693a50 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -94,7 +94,7 @@ class CBlock : public CBlockHeader // memory only mutable CScript payee; - mutable std::vector vMerkleTree; + mutable bool fChecked; CBlock() { @@ -121,7 +121,7 @@ class CBlock : public CBlockHeader { CBlockHeader::SetNull(); vtx.clear(); - vMerkleTree.clear(); + fChecked = false; payee = CScript(); vchBlockSig.clear(); } @@ -158,14 +158,12 @@ class CBlock : public CBlockHeader return IsProofOfStake()? std::make_pair(vtx[1].vin[0].prevout, nTime) : std::make_pair(COutPoint(), (unsigned int)0); } - // Build the in-memory merkle tree for this block and return the merkle root. + // Build the merkle tree for this block and return the merkle root. // If non-NULL, *mutated is set to whether mutation was detected in the merkle // tree (a duplication of transactions in the block leading to an identical // merkle root). - uint256 BuildMerkleTree(bool* mutated = NULL) const; + uint256 ComputeMerkleRoot(bool* mutated = NULL) const; - std::vector GetMerkleBranch(int nIndex) const; - static uint256 CheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex); std::string ToString() const; void print() const; }; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 39b0cde8af8cf..e0739d3e0b16a 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) pblock->vtx[0] = CTransaction(txCoinbase); if (txFirst.size() < 2) txFirst.push_back(new CTransaction(pblock->vtx[0])); - pblock->hashMerkleRoot = pblock->BuildMerkleTree(); + pblock->hashMerkleRoot = pblock->ComputeMerkleRoot(); pblock->nNonce = blockinfo[i].nonce; CValidationState state; BOOST_CHECK(ProcessNewBlock(state, NULL, pblock)); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index af2d1bb663478..90d6d87a0e498 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) } // calculate actual merkle root and height - uint256 merkleRoot1 = block.BuildMerkleTree(); + uint256 merkleRoot1 = block.ComputeMerkleRoot(); std::vector vTxid(nTx, 0); for (unsigned int j=0; jhashMerkleRoot) - return 0; - fMerkleVerified = true; - } - pindexRet = pindex; return chainActive.Height() - pindex->nHeight + 1; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 31fc94c860243..7ab2d9bbb18d5 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -815,13 +815,8 @@ class CMerkleTx : public CTransaction public: uint256 hashBlock; - std::vector vMerkleBranch; int nIndex; - // memory only - mutable bool fMerkleVerified; - - CMerkleTx() { Init(); @@ -836,7 +831,6 @@ class CMerkleTx : public CTransaction { hashBlock = 0; nIndex = -1; - fMerkleVerified = false; } ADD_SERIALIZE_METHODS; @@ -844,6 +838,7 @@ class CMerkleTx : public CTransaction template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + std::vector vMerkleBranch; // For compatibility with older versions. READWRITE(*(CTransaction*)this); nVersion = this->nVersion; READWRITE(hashBlock); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 805d0f618fe25..577aaf7a71fe9 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -145,12 +145,14 @@ bool CWalletDB::EraseMultiSig(const CScript& dest) bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { nWalletDBUpdated++; - return Write(std::string("bestblock"), locator); + Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan + return Write(std::string("bestblock_nomerkle"), locator); } bool CWalletDB::ReadBestBlock(CBlockLocator& locator) { - return Read(std::string("bestblock"), locator); + if (Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true; + return Read(std::string("bestblock_nomerkle"), locator); } bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext) From 658050b1af6bb5d502af1cb7691a4b01e36f1a64 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Thu, 26 Mar 2020 21:57:55 -0600 Subject: [PATCH 082/132] Fixes and some clean up --- src/compat/byteswap.h | 2 +- src/compat/endian.h | 2 +- src/crypto/common.h | 2 +- src/main.cpp | 30 +++++++++++++++--------------- src/miner.cpp | 4 ++-- src/wallet/rpcwallet.cpp | 2 +- src/wallet/walletdb.cpp | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h index ae2e080faec02..dd726c772b95d 100644 --- a/src/compat/byteswap.h +++ b/src/compat/byteswap.h @@ -6,7 +6,7 @@ #define BITCOIN_COMPAT_BYTESWAP_H #if defined(HAVE_CONFIG_H) -#include +#include #endif #include diff --git a/src/compat/endian.h b/src/compat/endian.h index df05e029a6c1b..ebcfd1b7c1c52 100644 --- a/src/compat/endian.h +++ b/src/compat/endian.h @@ -6,7 +6,7 @@ #define BITCOIN_COMPAT_ENDIAN_H #if defined(HAVE_CONFIG_H) -#include +#include #endif #include diff --git a/src/crypto/common.h b/src/crypto/common.h index 6906ee7807b27..7759ac662aeec 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -6,7 +6,7 @@ #define BITCOIN_CRYPTO_COMMON_H #if defined(HAVE_CONFIG_H) -#include +#include #endif #include diff --git a/src/main.cpp b/src/main.cpp index 319f66de541c9..26fe604546498 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1470,7 +1470,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa if (sporkManager.IsSporkActive(SPORK_16_ZEROCOIN_MAINTENANCE_MODE) && tx.ContainsZerocoins()) return state.DoS(10, error("AcceptToMemoryPool : Zerocoin transactions are temporarily disabled for maintenance"), REJECT_INVALID, "bad-tx"); - if (!CheckTransaction(tx, chainActive.Height() >= Params().Zerocoin_StartHeight(), true, state, GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < chainActive.Tip()->nTime)) { + if (!CheckTransaction(tx, chainActive.Height() >= Params().Zerocoin_StartHeight(), true, state, sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < chainActive.Tip()->nTime)) { return state.DoS(100, error("AcceptToMemoryPool: : CheckTransaction failed"), REJECT_INVALID, "bad-tx"); } @@ -1516,7 +1516,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa } // Don't accept witness transactions before the final threshold passes - if (!GetBoolArg("-prematurewitness", false) && !tx.wit.IsNull() && !IsSporkActive(SPORK_17_SEGWIT_ACTIVATION)) { + if (!GetBoolArg("-prematurewitness", false) && !tx.wit.IsNull() && !sporkManager.IsSporkActive(SPORK_17_SEGWIT_ACTIVATION)) { return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true); } @@ -1765,7 +1765,7 @@ bool AcceptableInputs(CTxMemPool& pool, CValidationState& state, const CTransact if (pfMissingInputs) *pfMissingInputs = false; - if (!CheckTransaction(tx, chainActive.Height() >= Params().Zerocoin_StartHeight(), true, state, GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < chainActive.Tip()->nTime)) + if (!CheckTransaction(tx, chainActive.Height() >= Params().Zerocoin_StartHeight(), true, state, sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < chainActive.Tip()->nTime)) return error("AcceptableInputs: : CheckTransaction failed"); // Coinbase is only valid in a block, not as a loose transaction @@ -2926,7 +2926,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG; - if (GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < block.nTime) { + if (sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < block.nTime) { flags |= SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; } @@ -3452,7 +3452,7 @@ bool DisconnectBlocks(int nBlocks) LogPrintf("%s: Got command to replay %d blocks\n", __func__, nBlocks); for (int i = 0; i <= nBlocks; i++) - DisconnectTip(state); + DisconnectTip(state, false); return true; } @@ -4101,7 +4101,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo if (block.IsProofOfStake()) { int commitpos = GetWitnessCommitmentIndex(block); if (commitpos >= 0) { - if (IsSporkActive(SPORK_19_SEGWIT_ON_COINBASE)) { + if (sporkManager.IsSporkActive(SPORK_19_SEGWIT_ON_COINBASE)) { if (block.vtx[0].vout.size() != 2) return state.DoS(100, error("CheckBlock() : coinbase output has wrong size for proof-of-stake block")); if (!block.vtx[0].vout[1].scriptPubKey.IsUnspendable()) @@ -4289,7 +4289,7 @@ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPr { int commitpos = GetWitnessCommitmentIndex(block); static const std::vector nonce(32, 0x00); - if (commitpos != -1 && GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexPrev->nTime && block.vtx[0].wit.IsEmpty()) { + if (commitpos != -1 && sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexPrev->nTime && block.vtx[0].wit.IsEmpty()) { block.vtx[0].wit.vtxinwit.resize(1); block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.resize(1); block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0] = nonce; @@ -4308,7 +4308,7 @@ std::vector GenerateCoinbaseCommitment(CBlock& block, const CBloc } } std::vector ret(32, 0x00); - if (fHaveWitness && GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexPrev->nTime) { + if (fHaveWitness && sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexPrev->nTime) { if (commitpos == -1) { uint256 witnessroot = BlockWitnessMerkleRoot(block, NULL); CHash256().Write(witnessroot.begin(), 32).Write(&ret[0], 32).Finalize(witnessroot.begin()); @@ -4367,7 +4367,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn std::vector vBlockSerials; for (const CTransaction& tx : block.vtx) { - if (!CheckTransaction(tx, true, chainActive.Height() + 1 >= Params().Zerocoin_StartHeight(), state, GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < block.nTime)) + if (!CheckTransaction(tx, true, chainActive.Height() + 1 >= Params().Zerocoin_StartHeight(), state, sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < block.nTime)) return error("CheckBlock() : CheckTransaction failed"); // double check that there are no double spent zPHR spends in this block @@ -4415,10 +4415,10 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256(witness root, witness nonce). In case there are // multiple, the last one is used. bool fHaveWitness = false; - if (pindexPrev != nullptr && GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexPrev->nTime) { + if (pindexPrev != nullptr && sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexPrev->nTime) { int commitpos = GetWitnessCommitmentIndex(block); if (commitpos != -1) { - if (!IsSporkActive(SPORK_19_SEGWIT_ON_COINBASE)) { + if (!sporkManager.IsSporkActive(SPORK_19_SEGWIT_ON_COINBASE)) { if (fDebug) { LogPrintf("CheckBlock() : staking-on-segwit is not enabled.\n"); } @@ -5109,7 +5109,7 @@ bool RewindBlockIndex(const CChainParams& params) int nHeight = 1; while (nHeight <= chainActive.Height()) { - if (GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < chainActive[nHeight - 1]->nTime && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) { + if (sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < chainActive[nHeight - 1]->nTime && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) { break; } nHeight++; @@ -5132,7 +5132,7 @@ bool RewindBlockIndex(const CChainParams& params) // to disk before writing the chainstate, resulting in a failure to continue if interrupted. for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) { CBlockIndex* pindexIter = it->second; - if (GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexIter->nTime && !(pindexIter->nStatus & BLOCK_OPT_WITNESS)) { + if (sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) < pindexIter->nTime && !(pindexIter->nStatus & BLOCK_OPT_WITNESS)) { // Reduce validity pindexIter->nStatus = std::min(pindexIter->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (pindexIter->nStatus & ~BLOCK_VALID_MASK); // Remove have-data flags. @@ -6129,7 +6129,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR // doing this will result in the received block being rejected as an orphan in case it is // not a direct successor. if (State(pfrom->GetId())->fHaveWitness && - (GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) > chainActive.Tip()->nTime || State(pfrom->GetId())->fHaveWitness)) { + (sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) > chainActive.Tip()->nTime || State(pfrom->GetId())->fHaveWitness)) { inv.type = MSG_WITNESS_BLOCK; } vToFetch.push_back(inv); @@ -7064,7 +7064,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) NodeId staller = -1; FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); for (CBlockIndex *pindex : vToDownload) { - if (State(pto->GetId())->fHaveWitness || GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) > pindex->pprev->nTime) { + if (State(pto->GetId())->fHaveWitness || sporkManager.GetSporkValue(SPORK_17_SEGWIT_ACTIVATION) > pindex->pprev->nTime) { vGetData.push_back(CInv(State(staller)->fHaveWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK, pindex->GetBlockHash())); MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex); LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), diff --git a/src/miner.cpp b/src/miner.cpp index d0067da950964..971384d8cc674 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -117,7 +117,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet, // -promiscuousmempoolflags is used. // TODO: replace this with a call to main to assess validity of a mempool // transaction (which in most cases can be a no-op). - bool fIncludeWitness = IsSporkActive(SPORK_17_SEGWIT_ACTIVATION); + bool fIncludeWitness = sporkManager.IsSporkActive(SPORK_17_SEGWIT_ACTIVATION); // Make sure to create the correct block version after zerocoin is enabled bool fZerocoinActive = chainActive.Height() >= Params().Zerocoin_StartHeight(); @@ -501,7 +501,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet, pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(pblock->vtx[0]); if (fProofOfStake) { - if (! IsSporkActive(SPORK_19_SEGWIT_ON_COINBASE)) { + if (!sporkManager.IsSporkActive(SPORK_19_SEGWIT_ON_COINBASE)) { bool fHaveWitness = false; for (size_t t = 1; t < pblock->vtx.size(); t++) { if (!pblock->vtx[t].wit.IsNull()) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1cd0b7d493d30..4edb17df4b4a0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1081,7 +1081,7 @@ UniValue addwitnessaddress(const UniValue& params, bool fHelp) throw std::runtime_error(msg); } - if (!IsSporkActive(SPORK_17_SEGWIT_ACTIVATION) && !GetBoolArg("-walletprematurewitness", false)) { + if (!sporkManager.IsSporkActive(SPORK_17_SEGWIT_ACTIVATION) && !GetBoolArg("-walletprematurewitness", false)) { throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network"); } diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 577aaf7a71fe9..bc63ab650e4f9 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -441,7 +441,7 @@ bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CW ssValue >> wtx; CValidationState state; // false because there is no reason to go through the zerocoin checks for our own wallet - if (!(CheckTransaction(wtx, false, false, state, IsSporkActive(SPORK_17_SEGWIT_ACTIVATION)) && (wtx.GetHash() == hash) && state.IsValid())) + if (!(CheckTransaction(wtx, false, false, state, sporkManager.IsSporkActive(SPORK_17_SEGWIT_ACTIVATION)) && (wtx.GetHash() == hash) && state.IsValid())) return false; // Undo serialize changes in 31600 From 7fd7295e2f8a30dc366eb4ae14c7ca9a239d5b9c Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Fri, 27 Mar 2020 16:58:46 -0600 Subject: [PATCH 083/132] [Refactor] Move wallet functions out of header --- src/wallet/wallet.cpp | 296 +++++++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 313 ++++-------------------------------------- 2 files changed, 319 insertions(+), 290 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c8516cef21105..28b3d9a41b662 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4982,3 +4982,299 @@ bool CWallet::DatabaseMint(CDeterministicMint& dMint) return true; } +CWallet::CWallet() +{ + SetNull(); +} + +CWallet::CWallet(std::string strWalletFileIn) +{ +SetNull(); + +strWalletFile = strWalletFileIn; +fFileBacked = true; +} + +~CWallet::CWallet() +{ + delete pwalletdbEncryption; +} + +void CWallet::SetNull() +{ + nWalletVersion = FEATURE_BASE; + nWalletMaxVersion = FEATURE_BASE; + fFileBacked = false; + nMasterKeyMaxID = 0; + pwalletdbEncryption = NULL; + nOrderPosNext = 0; + nNextResend = 0; + nLastResend = 0; + nTimeFirstKey = 0; + fWalletUnlockAnonymizeOnly = false; + fBackupMints = false; + + // Stake Settings + nHashDrift = 45; + nStakeSplitThreshold = 500; + nHashInterval = 22; + nStakeSetUpdateTime = 300; // 5 minutes + + //MultiSend + vMultiSend.clear(); + fMultiSendStake = false; + fMultiSendMasternodeReward = false; + fMultiSendNotify = false; + strMultiSendChangeAddress = ""; + nLastMultiSendHeight = 0; + vDisabledAddresses.clear(); + + //Auto Combine Dust + fCombineDust = false; + nAutoCombineThreshold = 0; +} + +int CWallet::getZeromintPercentage() +{ + return nZeromintPercentage; +} + +void CWallet::setZWallet(CzPHRWallet* zwallet) +{ + zwalletMain = zwallet; + zphrTracker = std::unique_ptr(new CzPHRTracker(strWalletFile)); +} + +CWallet::CzPHRWallet* getZWallet() { return zwalletMain; } + + +bool CWallet::isZeromintEnabled() +{ + return fEnableZeromint; +} + +void CWallet::setZPhrAutoBackups(bool fEnabled) +{ + fBackupMints = fEnabled; +} + +bool CWallet::isMultiSendEnabled() +{ + return fMultiSendMasternodeReward || fMultiSendStake; +} + +void CWallet::setMultiSendDisabled() +{ + fMultiSendMasternodeReward = false; + fMultiSendStake = false; +} + +bool CWallet::CanSupportFeature(enum WalletFeature wf) +{ + AssertLockHeld(cs_wallet); + return nWalletMaxVersion >= wf; +} + +bool CWallet::LoadMinVersion(int nVersion) +{ + AssertLockHeld(cs_wallet); + nWalletVersion = nVersion; + nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); + return true; +} + +isminetype CWallet::IsMine(const CTxOut& txout) const +{ + return ::IsMine(*this, txout.scriptPubKey); +} + +CAmount CWallet::GetChange(const CTxOut& txout) const +{ + if (!MoneyRange(txout.nValue)) + throw std::runtime_error("CWallet::GetChange() : value out of range"); + return (IsChange(txout) ? txout.nValue : 0); +} +bool CWallet::IsMine(const CTransaction& tx) const +{ + for (const CTxOut& txout : tx.vout) + if (IsMine(txout)) + return true; + return false; +} + +bool CWallet::IsFromMe(const CTransaction& tx) const +{ + return (GetDebit(tx, ISMINE_ALL) > 0); +} +CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const +{ + CAmount nDebit = 0; + for (const CTxIn& txin : tx.vin) { + nDebit += GetDebit(txin, filter); + if (!MoneyRange(nDebit)) + throw std::runtime_error("CWallet::GetDebit() : value out of range"); + } + return nDebit; +} +CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) const +{ + CAmount nCredit = 0; + for (const CTxOut& txout : tx.vout) { + nCredit += GetCredit(txout, filter); + if (!MoneyRange(nCredit)) + throw std::runtime_error("CWallet::GetCredit() : value out of range"); + } + return nCredit; +} +CAmount CWallet::GetChange(const CTransaction& tx) const +{ + CAmount nChange = 0; + for (const CTxOut& txout : tx.vout) { + nChange += GetChange(txout); + if (!MoneyRange(nChange)) + throw std::runtime_error("CWallet::GetChange() : value out of range"); + } + return nChange; +} + +void CWallet::Inventory(const uint256& hash) +{ + { + LOCK(cs_wallet); + std::map::iterator mi = mapRequestCount.find(hash); + if (mi != mapRequestCount.end()) + (*mi).second++; + } +} + +unsigned int CWallet::GetKeyPoolSize() { + AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool + return setInternalKeyPool.size() + setExternalKeyPool.size(); +} + +int CWallet::GetVersion() +{ + LOCK(cs_wallet); + return nWalletVersion; +} + +CWalletTx::CWalletTx() +{ + Init(NULL); +} + +CWalletTx::CWalletTx(const CWallet* pwalletIn) +{ + Init(pwalletIn); +} + +CWalletTx::CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn) +{ + Init(pwalletIn); +} + +CWalletTx::CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn) +{ + Init(pwalletIn); +} + +void CWalletTx::Init(const CWallet* pwalletIn) +{ + pwallet = pwalletIn; + mapValue.clear(); + vOrderForm.clear(); + fTimeReceivedIsTxTime = false; + nTimeReceived = 0; + nTimeSmart = 0; + fFromMe = false; + strFromAccount.clear(); + fDebitCached = false; + fCreditCached = false; + fImmatureCreditCached = false; + fAvailableCreditCached = false; + fAnonymizableCreditCached = false; + fAnonymizedCreditCached = false; + fDenomUnconfCreditCached = false; + fDenomConfCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; + fImmatureWatchCreditCached = false; + fAvailableWatchCreditCached = false; + fChangeCached = false; + nDebitCached = 0; + nCreditCached = 0; + nImmatureCreditCached = 0; + nAvailableCreditCached = 0; + nAnonymizableCreditCached = 0; + nAnonymizedCreditCached = 0; + nDenomUnconfCreditCached = 0; + nDenomConfCreditCached = 0; + nWatchDebitCached = 0; + nWatchCreditCached = 0; + nAvailableWatchCreditCached = 0; + nImmatureWatchCreditCached = 0; + nChangeCached = 0; + nOrderPos = -1; +} + +void CWalletTx::MarkDirty() +{ + fCreditCached = false; + fAvailableCreditCached = false; + fAnonymizableCreditCached = false; + fAnonymizedCreditCached = false; + fDenomUnconfCreditCached = false; + fDenomConfCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; + fAvailableWatchCreditCached = false; + fImmatureWatchCreditCached = false; + fDebitCached = false; + fChangeCached = false; +} + +void CWalletTx::BindWallet(CWallet* pwalletIn) +{ + pwallet = pwalletIn; + MarkDirty(); +} + +CAmount CWalletTx::GetChange() const +{ + if (fChangeCached) + return nChangeCached; + nChangeCached = pwallet->GetChange(*this); + fChangeCached = true; + return nChangeCached; +} + +bool CWalletTx::IsFromMe(const isminefilter& filter) const +{ + return (GetDebit(filter) > 0); +} + +bool CWalletTx::IsTrusted() const +{ + // Quick answer in most cases + if (!IsFinalTx(*this)) + return false; + int nDepth = GetDepthInMainChain(); + if (nDepth >= 1) + return true; + if (nDepth < 0) + return false; + if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit + return false; + + // Trusted if all inputs are from us and are in the mempool: + for (const CTxIn& txin : vin) { + // Transactions not sent by us: not trusted + const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash); + if (parent == NULL) + return false; + const CTxOut& parentOut = parent->vout[txin.prevout.n]; + if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) + return false; + } + return true; +} diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7ab2d9bbb18d5..3dd5cc094c6cc 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -318,93 +318,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool fCombineDust; CAmount nAutoCombineThreshold; - CWallet() - { - SetNull(); - } - - CWallet(std::string strWalletFileIn) - { - SetNull(); - - strWalletFile = strWalletFileIn; - fFileBacked = true; - } - - ~CWallet() - { - delete pwalletdbEncryption; - } - - void SetNull() - { - nWalletVersion = FEATURE_BASE; - nWalletMaxVersion = FEATURE_BASE; - fFileBacked = false; - nMasterKeyMaxID = 0; - pwalletdbEncryption = NULL; - nOrderPosNext = 0; - nNextResend = 0; - nLastResend = 0; - nTimeFirstKey = 0; - fWalletUnlockAnonymizeOnly = false; - fBackupMints = false; - - // Stake Settings - nHashDrift = 45; - nStakeSplitThreshold = 500; - nHashInterval = 22; - nStakeSetUpdateTime = 300; // 5 minutes - - //MultiSend - vMultiSend.clear(); - fMultiSendStake = false; - fMultiSendMasternodeReward = false; - fMultiSendNotify = false; - strMultiSendChangeAddress = ""; - nLastMultiSendHeight = 0; - vDisabledAddresses.clear(); - - //Auto Combine Dust - fCombineDust = false; - nAutoCombineThreshold = 0; - } - - int getZeromintPercentage() - { - return nZeromintPercentage; - } - - void setZWallet(CzPHRWallet* zwallet) - { - zwalletMain = zwallet; - zphrTracker = std::unique_ptr(new CzPHRTracker(strWalletFile)); - } - - CzPHRWallet* getZWallet() { return zwalletMain; } - - - bool isZeromintEnabled() - { - return fEnableZeromint; - } - - void setZPhrAutoBackups(bool fEnabled) - { - fBackupMints = fEnabled; - } - - bool isMultiSendEnabled() - { - return fMultiSendMasternodeReward || fMultiSendStake; - } - - void setMultiSendDisabled() - { - fMultiSendMasternodeReward = false; - fMultiSendStake = false; - } - std::map mapWallet; std::list laccentries; @@ -428,11 +341,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface const CWalletTx* GetWalletTx(const uint256& hash) const; //! check whether we are allowed to upgrade (or already support) to the named feature - bool CanSupportFeature(enum WalletFeature wf) - { - AssertLockHeld(cs_wallet); - return nWalletMaxVersion >= wf; - } + bool CanSupportFeature(enum WalletFeature wf); void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed = true, const CCoinControl* coinControl = NULL, bool fIncludeZeroValue = false, AvailableCoinsType nCoinType = ALL_COINS, bool fUseIX = false, int nWatchonlyConfig = 1) const; std::map > AvailableCoinsByAddress(bool fConfirmed = true, CAmount maxCoinValue = 0); @@ -475,13 +384,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface //! Load metadata (used by LoadWallet) bool LoadKeyMetadata(const CPubKey& pubkey, const CKeyMetadata& metadata); - bool LoadMinVersion(int nVersion) - { - AssertLockHeld(cs_wallet); - nWalletVersion = nVersion; - nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); - return true; - } + bool LoadMinVersion(int nVersion); //! Adds an encrypted key to the store, and saves it to disk. bool AddCryptedKey(const CPubKey& vchPubKey, const std::vector& vchCryptedSecret); @@ -609,67 +512,18 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface isminetype IsMine(const CTxIn& txin) const; CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const; - isminetype IsMine(const CTxOut& txout) const - { - return ::IsMine(*this, txout.scriptPubKey); - } + isminetype IsMine(const CTxOut& txout) const; bool IsMyZerocoinSpend(const CBigNum& bnSerial) const; bool IsMyMint(const CBigNum& bnValue) const; - CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const - { - if (!MoneyRange(txout.nValue)) - throw std::runtime_error("CWallet::GetCredit() : value out of range"); - return ((IsMine(txout) & filter) ? txout.nValue : 0); - } + CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const; bool IsChange(const CTxOut& txout) const; - CAmount GetChange(const CTxOut& txout) const - { - if (!MoneyRange(txout.nValue)) - throw std::runtime_error("CWallet::GetChange() : value out of range"); - return (IsChange(txout) ? txout.nValue : 0); - } - bool IsMine(const CTransaction& tx) const - { - for (const CTxOut& txout : tx.vout) - if (IsMine(txout)) - return true; - return false; - } + CAmount GetChange(const CTxOut& txout) const; + bool IsMine(const CTransaction& tx) const; /** should probably be renamed to IsRelevantToMe */ - bool IsFromMe(const CTransaction& tx) const - { - return (GetDebit(tx, ISMINE_ALL) > 0); - } - CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const - { - CAmount nDebit = 0; - for (const CTxIn& txin : tx.vin) { - nDebit += GetDebit(txin, filter); - if (!MoneyRange(nDebit)) - throw std::runtime_error("CWallet::GetDebit() : value out of range"); - } - return nDebit; - } - CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const - { - CAmount nCredit = 0; - for (const CTxOut& txout : tx.vout) { - nCredit += GetCredit(txout, filter); - if (!MoneyRange(nCredit)) - throw std::runtime_error("CWallet::GetCredit() : value out of range"); - } - return nCredit; - } - CAmount GetChange(const CTransaction& tx) const - { - CAmount nChange = 0; - for (const CTxOut& txout : tx.vout) { - nChange += GetChange(txout); - if (!MoneyRange(nChange)) - throw std::runtime_error("CWallet::GetChange() : value out of range"); - } - return nChange; - } + bool IsFromMe(const CTransaction& tx) const; + CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const; + CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; + CAmount GetChange(const CTransaction& tx) const; void SetBestChain(const CBlockLocator& loc); DBErrors LoadWallet(bool& fFirstRunRet); @@ -681,20 +535,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool NewKeyPool(); bool UpdatedTransaction(const uint256& hashTx); - void Inventory(const uint256& hash) - { - { - LOCK(cs_wallet); - std::map::iterator mi = mapRequestCount.find(hash); - if (mi != mapRequestCount.end()) - (*mi).second++; - } - } + void Inventory(const uint256& hash); - unsigned int GetKeyPoolSize() { - AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool - return setInternalKeyPool.size() + setExternalKeyPool.size(); - } + unsigned int GetKeyPoolSize(); bool SetDefaultKey(const CPubKey& vchPubKey); @@ -705,11 +548,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool SetMaxVersion(int nVersion); //! get the current wallet format (the oldest client version guaranteed to understand this wallet) - int GetVersion() - { - LOCK(cs_wallet); - return nWalletVersion; - } + int GetVersion(); /** * HD Wallet Functions @@ -919,64 +758,11 @@ class CWalletTx : public CMerkleTx mutable CAmount nAvailableWatchCreditCached; mutable CAmount nChangeCached; - CWalletTx() - { - Init(NULL); - } - - CWalletTx(const CWallet* pwalletIn) - { - Init(pwalletIn); - } - - CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn) - { - Init(pwalletIn); - } - - CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn) - { - Init(pwalletIn); - } - - void Init(const CWallet* pwalletIn) - { - pwallet = pwalletIn; - mapValue.clear(); - vOrderForm.clear(); - fTimeReceivedIsTxTime = false; - nTimeReceived = 0; - nTimeSmart = 0; - fFromMe = false; - strFromAccount.clear(); - fDebitCached = false; - fCreditCached = false; - fImmatureCreditCached = false; - fAvailableCreditCached = false; - fAnonymizableCreditCached = false; - fAnonymizedCreditCached = false; - fDenomUnconfCreditCached = false; - fDenomConfCreditCached = false; - fWatchDebitCached = false; - fWatchCreditCached = false; - fImmatureWatchCreditCached = false; - fAvailableWatchCreditCached = false; - fChangeCached = false; - nDebitCached = 0; - nCreditCached = 0; - nImmatureCreditCached = 0; - nAvailableCreditCached = 0; - nAnonymizableCreditCached = 0; - nAnonymizedCreditCached = 0; - nDenomUnconfCreditCached = 0; - nDenomConfCreditCached = 0; - nWatchDebitCached = 0; - nWatchCreditCached = 0; - nAvailableWatchCreditCached = 0; - nImmatureWatchCreditCached = 0; - nChangeCached = 0; - nOrderPos = -1; - } + CWalletTx(); + CWalletTx(const CWallet* pwalletIn); + CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn); + CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn); + void Init(const CWallet* pwalletIn); ADD_SERIALIZE_METHODS; @@ -1022,27 +808,8 @@ class CWalletTx : public CMerkleTx } //! make sure balances are recalculated - void MarkDirty() - { - fCreditCached = false; - fAvailableCreditCached = false; - fAnonymizableCreditCached = false; - fAnonymizedCreditCached = false; - fDenomUnconfCreditCached = false; - fDenomConfCreditCached = false; - fWatchDebitCached = false; - fWatchCreditCached = false; - fAvailableWatchCreditCached = false; - fImmatureWatchCreditCached = false; - fDebitCached = false; - fChangeCached = false; - } - - void BindWallet(CWallet* pwalletIn) - { - pwallet = pwalletIn; - MarkDirty(); - } + void MarkDirty(); + void BindWallet(CWallet* pwalletIn); //! filter decides which addresses will count towards the debit CAmount GetDebit(const isminefilter& filter) const; @@ -1057,14 +824,7 @@ class CWalletTx : public CMerkleTx CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache = true) const; CAmount GetLockedWatchOnlyCredit() const; - CAmount GetChange() const - { - if (fChangeCached) - return nChangeCached; - nChangeCached = pwallet->GetChange(*this); - fChangeCached = true; - return nChangeCached; - } + CAmount GetChange() const; void GetAmounts(std::list& listReceived, std::list& listSent, @@ -1074,38 +834,11 @@ class CWalletTx : public CMerkleTx void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived, CAmount& nSent, CAmount& nFee, const isminefilter& filter) const; - bool IsFromMe(const isminefilter& filter) const - { - return (GetDebit(filter) > 0); - } + bool IsFromMe(const isminefilter& filter) const; bool InMempool() const; - bool IsTrusted() const - { - // Quick answer in most cases - if (!IsFinalTx(*this)) - return false; - int nDepth = GetDepthInMainChain(); - if (nDepth >= 1) - return true; - if (nDepth < 0) - return false; - if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit - return false; - - // Trusted if all inputs are from us and are in the mempool: - for (const CTxIn& txin : vin) { - // Transactions not sent by us: not trusted - const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash); - if (parent == NULL) - return false; - const CTxOut& parentOut = parent->vout[txin.prevout.n]; - if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) - return false; - } - return true; - } + bool IsTrusted() const; bool WriteToDisk(); From b76e854f793dc212d8dd045497b926093a8b46b6 Mon Sep 17 00:00:00 2001 From: warrows Date: Wed, 17 Jul 2019 17:43:02 +0200 Subject: [PATCH 084/132] [Wallet] Keep track of explicit wallet conflicts instead of using mempool Backport of https://github.com/bitcoin/bitcoin/pull/7105 (9ac63d6d3056600c1b784da0e6b98f679fa98b6e) --- src/wallet/rpcwallet.cpp | 5 + src/wallet/wallet.cpp | 139 +++++++++++++++---- src/wallet/wallet.h | 10 +- test/functional/wallet_txn_clone.py | 159 ++++++++++++++++++++++ test/functional/wallet_txn_doublespend.py | 147 ++++++++++++++++++++ 5 files changed, 429 insertions(+), 31 deletions(-) create mode 100755 test/functional/wallet_txn_clone.py create mode 100755 test/functional/wallet_txn_doublespend.py diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4edb17df4b4a0..4c6ef3e83c2e8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -56,6 +56,8 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); entry.push_back(Pair("blockindex", wtx.nIndex)); entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime())); + } else { + entry.push_back(Pair("trusted", wtx.IsTrusted())); } uint256 hash = wtx.GetHash(); entry.push_back(Pair("txid", hash.GetHex())); @@ -1429,6 +1431,9 @@ UniValue listtransactions(const UniValue& params, bool fHelp) " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n" " 'receive' category of transactions.\n" " \"bcconfirmations\": n, (numeric) The number of blockchain confirmations for the transaction. Available for 'send'\n" + " 'receive' category of transactions. Negative confirmations indicate the\n" + " transation conflicts with the block chain\n" + " \"trusted\": xxx (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n" " and 'receive' category of transactions.\n" " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n" " category of transactions.\n" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 28b3d9a41b662..85c00b31c8442 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -953,11 +953,18 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) wtx.nTimeReceived = GetAdjustedTime(); wtx.nOrderPos = IncOrderPosNext(); wtx.nTimeSmart = ComputeTimeSmart(wtx); + wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); - AddToSpends(hash); - // wqking -- fix a bug that listtransactions doesn't return recent transactions. - wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); + AddToSpends(hash); + for (const CTxIn& txin : wtx.vin) { + if (mapWallet.count(txin.prevout.hash)) { + CWalletTx& prevtx = mapWallet[txin.prevout.hash]; + if (prevtx.nIndex == -1 && !prevtx.hashBlock.IsNull()) { + MarkConflicted(prevtx.hashBlock, wtx.GetHash()); + } + } + } } bool fUpdated = false; @@ -1011,6 +1018,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { { AssertLockHeld(cs_wallet); + + if (pblock) { + for (const CTxIn& txin : tx.vin) { + std::pair range = mapTxSpends.equal_range(txin.prevout); + while (range.first != range.second) { + if (range.first->second != tx.GetHash()) { + LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pblock->GetHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n); + MarkConflicted(pblock->GetHash(), range.first->second); + } + range.first++; + } + } + } + bool fExisted = mapWallet.count(tx.GetHash()) != 0; if (fExisted && !fUpdate) return false; if (fExisted || IsMine(tx) || IsFromMe(tx)) { @@ -1024,6 +1045,53 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl return false; } +void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) +{ + LOCK2(cs_main, cs_wallet); + + CBlockIndex* pindex; + assert(mapBlockIndex.count(hashBlock)); + pindex = mapBlockIndex[hashBlock]; + int conflictconfirms = 0; + if (chainActive.Contains(pindex)) { + conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1); + } + assert(conflictconfirms < 0); + + // Do not flush the wallet here for performance reasons + CWalletDB walletdb(strWalletFile, "r+", false); + + std::deque todo; + std::set done; + + todo.push_back(hashTx); + + while (!todo.empty()) { + uint256 now = todo.front(); + todo.pop_front(); + done.insert(now); + assert(mapWallet.count(now)); + CWalletTx& wtx = mapWallet[now]; + int currentconfirm = wtx.GetDepthInMainChain(); + if (conflictconfirms < currentconfirm) { + // Block is 'more conflicted' than current confirm; update. + // Mark transaction as conflicted with this block. + wtx.nIndex = -1; + wtx.hashBlock = hashBlock; + wtx.MarkDirty(); + wtx.WriteToDisk(&walletdb); + // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too + TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0)); + while (iter != mapTxSpends.end() && iter->first.hash == now) { + if (!done.count(iter->second)) { + todo.push_back(iter->second); + } + iter++; + } + } + } +} + void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock) { LOCK2(cs_main, cs_wallet); @@ -1615,7 +1683,7 @@ void CWallet::ReacceptWalletTransactions() int nDepth = wtx.GetDepthInMainChain(); - if (!wtx.IsCoinBase() && nDepth < 0 && !wtx.IsCoinStake()) { + if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && nDepth == 0) { // Try to add to memory pool LOCK(mempool.cs); wtx.AcceptToMemoryPool(false); @@ -2374,6 +2442,7 @@ bool CWallet::CreateTransaction(const std::vector >& //a chance at a free transaction. //But mempool inputs might still be in the mempool, so their age stays 0 int age = pcoin.first->GetDepthInMainChain(); + assert(age >= 0); if (age != 0) age += 1; dPriority += (double)nCredit * age; @@ -3892,7 +3961,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block) int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const { - if (hashBlock == 0 || nIndex == -1) + if (hashBlock == 0) return 0; AssertLockHeld(cs_main); @@ -3905,7 +3974,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const return 0; pindexRet = pindex; - return chainActive.Height() - pindex->nHeight + 1; + return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1); } int CMerkleTx::GetDepthInMainChain(const CBlockIndex*& pindexRet, bool enableIX) const @@ -5217,6 +5286,40 @@ void CWalletTx::Init(const CWallet* pwalletIn) nOrderPos = -1; } +bool CWalletTx::IsTrusted() const +{ + // Quick answer in most cases + if (!IsFinalTx(*this)) + return false; + int nDepth = GetDepthInMainChain(); + if (nDepth >= 1) + return true; + if (nDepth < 0) + return false; + if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit + return false; + + // Don't trust unconfirmed transactions from us unless they are in the mempool. + { + LOCK(mempool.cs); + if (!mempool.exists(GetHash())) { + return false; + } + } + + // Trusted if all inputs are from us and are in the mempool: + for (const CTxIn& txin : vin) { + // Transactions not sent by us: not trusted + const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash); + if (parent == NULL) + return false; + const CTxOut& parentOut = parent->vout[txin.prevout.n]; + if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) + return false; + } + return true; +} + void CWalletTx::MarkDirty() { fCreditCached = false; @@ -5253,28 +5356,4 @@ bool CWalletTx::IsFromMe(const isminefilter& filter) const return (GetDebit(filter) > 0); } -bool CWalletTx::IsTrusted() const -{ - // Quick answer in most cases - if (!IsFinalTx(*this)) - return false; - int nDepth = GetDepthInMainChain(); - if (nDepth >= 1) - return true; - if (nDepth < 0) - return false; - if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit - return false; - // Trusted if all inputs are from us and are in the mempool: - for (const CTxIn& txin : vin) { - // Transactions not sent by us: not trusted - const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash); - if (parent == NULL) - return false; - const CTxOut& parentOut = parent->vout[txin.prevout.n]; - if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) - return false; - } - return true; -} diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3dd5cc094c6cc..93d2d8f8a3459 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -225,6 +225,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void AddToSpends(const COutPoint& outpoint, const uint256& wtxid); void AddToSpends(const uint256& wtxid); + /* Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */ + void MarkConflicted(const uint256& hashBlock, const uint256& hashTx); + void SyncMetaData(std::pair); /* HD derive new child key (on internal or external chain) */ void DeriveNewChildKey(const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool fInternal /*= false*/); @@ -654,6 +657,11 @@ class CMerkleTx : public CTransaction public: uint256 hashBlock; + /* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest + * block in the chain we know this or any in-wallet dependency conflicts + * with. Older clients interpret nIndex == -1 as unconfirmed for backward + * compatibility. + */ int nIndex; CMerkleTx() @@ -690,7 +698,7 @@ class CMerkleTx : public CTransaction /** * Return depth of transaction in blockchain: - * -1 : not in blockchain, and not in memory pool (conflicted transaction) + * <0 : conflicts with a transaction this deep in the blockchain * 0 : in memory pool, waiting to be included in a block * >=1 : this many blocks deep in the main chain */ diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py new file mode 100755 index 0000000000000..a30048cd7916d --- /dev/null +++ b/test/functional/wallet_txn_clone.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test the wallet accounts properly when there are cloned transactions with malleated scriptsigs.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +class TxnMallTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 4 + + def add_options(self, parser): + parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", + help="Test double-spend of 1-confirmed transaction") + + def setup_network(self): + # Start with split network: + super(TxnMallTest, self).setup_network() + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) + + def run_test(self): + # All nodes should start with 1,250 BTC: + starting_balance = 6250 + for i in range(4): + assert_equal(self.nodes[i].getbalance(), starting_balance) + self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! + + # Assign coins to foo and bar accounts: + self.nodes[0].settxfee(.001) + + node0_address_foo = self.nodes[0].getnewaddress("foo") + fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, (1219 *5)) + fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) + + node0_address_bar = self.nodes[0].getnewaddress("bar") + fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, (29 *5)) + fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) + + assert_equal(self.nodes[0].getbalance(""), + starting_balance - (1219 * 5) - (29 * 5) + fund_foo_tx["fee"] + fund_bar_tx["fee"]) + + # Coins are sent to node1_address + node1_address = self.nodes[1].getnewaddress("from0") + + # Send tx1, and another transaction tx2 that won't be cloned + txid1 = self.nodes[0].sendfrom("foo", node1_address, (40 * 5), 0) + txid2 = self.nodes[0].sendfrom("bar", node1_address, (20 * 5), 0) + + # Construct a clone of tx1, to be malleated + rawtx1 = self.nodes[0].getrawtransaction(txid1,1) + clone_inputs = [{"txid":rawtx1["vin"][0]["txid"],"vout":rawtx1["vin"][0]["vout"]}] + clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]:float(rawtx1["vout"][0]["value"]), + rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]:float(rawtx1["vout"][1]["value"])} + clone_locktime = rawtx1["locktime"] + clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs, clone_locktime) + + # createrawtransaction randomizes the order of its outputs, so swap them if necessary. + # output 0 is at version+#inputs+input+sigstub+sequence+#outputs + # 40 BTC serialized is 00286bee00000000 + pos0 = 2*(4+1+36+1+4+1) + hex40 = "00286bee00000000" + output_len = 16 + 2 + 2 * int("0x" + clone_raw[pos0 + 16 : pos0 + 16 + 2], 0) + if (rawtx1["vout"][0]["value"] == 40 and clone_raw[pos0 : pos0 + 16] != hex40 or + rawtx1["vout"][0]["value"] != 40 and clone_raw[pos0 : pos0 + 16] == hex40): + output0 = clone_raw[pos0 : pos0 + output_len] + output1 = clone_raw[pos0 + output_len : pos0 + 2 * output_len] + clone_raw = clone_raw[:pos0] + output1 + output0 + clone_raw[pos0 + 2 * output_len:] + + # Use a different signature hash type to sign. This creates an equivalent but malleated clone. + # Don't send the clone anywhere yet + tx1_clone = self.nodes[0].signrawtransaction(clone_raw, None, None, "ALL|ANYONECANPAY") + assert_equal(tx1_clone["complete"], True) + + # Have node0 mine a block, if requested: + if (self.options.mine_block): + self.nodes[0].generate(1) + sync_blocks(self.nodes[0:2]) + + tx1 = self.nodes[0].gettransaction(txid1) + tx2 = self.nodes[0].gettransaction(txid2) + + # Node0's balance should be starting balance, plus 50BTC for another + # matured block, minus tx1 and tx2 amounts, and minus transaction fees: + expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] + if self.options.mine_block: expected += 250 + expected += tx1["amount"] + tx1["fee"] + expected += tx2["amount"] + tx2["fee"] + assert_equal(self.nodes[0].getbalance(), expected) + + # foo and bar accounts should be debited: + assert_equal(self.nodes[0].getbalance("foo", 0), (1219 * 5) + tx1["amount"] + tx1["fee"]) + assert_equal(self.nodes[0].getbalance("bar", 0), (29 * 5) + tx2["amount"] + tx2["fee"]) + + if self.options.mine_block: + assert_equal(tx1["confirmations"], 1) + assert_equal(tx2["confirmations"], 1) + # Node1's "from0" balance should be both transaction amounts: + assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"] + tx2["amount"])) + else: + assert_equal(tx1["confirmations"], 0) + assert_equal(tx2["confirmations"], 0) + + # Send clone and its parent to miner + self.nodes[2].sendrawtransaction(fund_foo_tx["hex"]) + txid1_clone = self.nodes[2].sendrawtransaction(tx1_clone["hex"]) + # mine a block... + self.nodes[2].generate(1) + + # Reconnect the split network, and sync chain: + connect_nodes(self.nodes[1], 2) + connect_nodes(self.nodes[0], 2) + connect_nodes(self.nodes[2], 0) + connect_nodes(self.nodes[2], 1) + + self.nodes[2].sendrawtransaction(fund_bar_tx["hex"]) + self.nodes[2].sendrawtransaction(tx2["hex"]) + self.nodes[2].generate(1) # Mine another block to make sure we sync + sync_blocks(self.nodes) + + # Re-fetch transaction info: + tx1 = self.nodes[0].gettransaction(txid1) + tx1_clone = self.nodes[0].gettransaction(txid1_clone) + tx2 = self.nodes[0].gettransaction(txid2) + + # Verify expected confirmations + assert_equal(tx1["confirmations"], -2) + assert_equal(tx1_clone["confirmations"], 2) + assert_equal(tx2["confirmations"], 1) + + # Check node0's total balance; should be same as before the clone, + 100 BTC for 2 matured, + # less possible orphaned matured subsidy + expected += 500 + if (self.options.mine_block): + expected -= 250 + assert_equal(self.nodes[0].getbalance(), expected) + assert_equal(self.nodes[0].getbalance("*", 0), expected) + + # Check node0's individual account balances. + # "foo" should have been debited by the equivalent clone of tx1 + assert_equal(self.nodes[0].getbalance("foo"), (1219 * 5) + tx1["amount"] + tx1["fee"]) + # "bar" should have been debited by (possibly unconfirmed) tx2 + assert_equal(self.nodes[0].getbalance("bar", 0), (29 * 5) + tx2["amount"] + tx2["fee"]) + # "" should have starting balance, less funding txes, plus subsidies + assert_equal(self.nodes[0].getbalance("", 0), starting_balance + - (1219 * 5) + + fund_foo_tx["fee"] + - (29 * 5) + + fund_bar_tx["fee"] + + 500) + + # Node1's "from0" account balance + assert_equal(self.nodes[1].getbalance("from0", 0), -(tx1["amount"] + tx2["amount"])) + +if __name__ == '__main__': + TxnMallTest().main() + diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py new file mode 100755 index 0000000000000..054486a3af243 --- /dev/null +++ b/test/functional/wallet_txn_doublespend.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2017 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 the wallet accounts properly when there is a double-spend conflict.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import time + +class TxnMallTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 4 + + def add_options(self, parser): + parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", + help="Test double-spend of 1-confirmed transaction") + + def setup_network(self): + # Start with split network: + super().setup_network() + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) + + def run_test(self): + # All nodes should start with 6,250 PIV: + starting_balance = 6250 + for i in range(4): + assert_equal(self.nodes[i].getbalance(), starting_balance) + self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! + + # Assign coins to foo and bar accounts: + node0_address_foo = self.nodes[0].getnewaddress("foo") + fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, (1219 * 5)) + fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) + + node0_address_bar = self.nodes[0].getnewaddress("bar") + fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, (29 * 5)) + fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) + + assert_equal(self.nodes[0].getbalance(""), + starting_balance - (1219 * 5) - (29 * 5) + fund_foo_tx["fee"] + fund_bar_tx["fee"]) + + # Coins are sent to node1_address + node1_address = self.nodes[1].getnewaddress("from0") + + # First: use raw transaction API to send 1240 BTC to node1_address, + # but don't broadcast: + doublespend_fee = Decimal('-.02') + rawtx_input_0 = {} + rawtx_input_0["txid"] = fund_foo_txid + rawtx_input_0["vout"] = find_output(self.nodes[0], fund_foo_txid, (1219 * 5)) + rawtx_input_1 = {} + rawtx_input_1["txid"] = fund_bar_txid + rawtx_input_1["vout"] = find_output(self.nodes[0], fund_bar_txid, (29 * 5)) + inputs = [rawtx_input_0, rawtx_input_1] + change_address = self.nodes[0].getnewaddress() + outputs = {} + outputs[node1_address] = float(1240 * 5) + outputs[change_address] = float((1248 * 5) - (1240 * 5) + doublespend_fee) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + doublespend = self.nodes[0].signrawtransaction(rawtx) + assert_equal(doublespend["complete"], True) + + # Create two spends using 1 50 BTC coin each + txid1 = self.nodes[0].sendfrom("foo", node1_address, (40 * 5), 0) + txid2 = self.nodes[0].sendfrom("bar", node1_address, (20 * 5), 0) + + # Have node0 mine a block: + if (self.options.mine_block): + self.nodes[0].generate(1) + sync_blocks(self.nodes[0:2]) + + tx1 = self.nodes[0].gettransaction(txid1) + tx2 = self.nodes[0].gettransaction(txid2) + + # Node0's balance should be starting balance, plus 50BTC for another + # matured block, minus 40, minus 20, and minus transaction fees: + expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] + if self.options.mine_block: expected += 250 + expected += tx1["amount"] + tx1["fee"] + expected += tx2["amount"] + tx2["fee"] + assert_equal(self.nodes[0].getbalance(), expected) + + # foo and bar accounts should be debited: + assert_equal(self.nodes[0].getbalance("foo", 0), (1219 * 5)+tx1["amount"]+tx1["fee"]) + assert_equal(self.nodes[0].getbalance("bar", 0), (29 * 5)+tx2["amount"]+tx2["fee"]) + + if self.options.mine_block: + assert_equal(tx1["bcconfirmations"], 1) + assert_equal(tx2["bcconfirmations"], 1) + # Node1's "from0" balance should be both transaction amounts: + assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"]+tx2["amount"])) + else: + assert_equal(tx1["bcconfirmations"], 0) + assert_equal(tx2["bcconfirmations"], 0) + + # Now give doublespend and its parents to miner: + self.nodes[2].sendrawtransaction(fund_foo_tx["hex"]) + self.nodes[2].sendrawtransaction(fund_bar_tx["hex"]) + doublespend_txid = self.nodes[2].sendrawtransaction(doublespend["hex"]) + + # mine a block... + self.nodes[2].generate(1) + + # Reconnect the split network, and sync chain: + connect_nodes(self.nodes[1], 2) + connect_nodes(self.nodes[0], 2) + connect_nodes(self.nodes[2], 0) + connect_nodes(self.nodes[2], 1) + self.nodes[2].generate(1) # Mine another block to make sure we sync + sync_blocks(self.nodes) + assert_equal(self.nodes[0].gettransaction(doublespend_txid)["confirmations"], 2) + + # Re-fetch transaction info: + tx1 = self.nodes[0].gettransaction(txid1) + tx2 = self.nodes[0].gettransaction(txid2) + + # Both transactions should be conflicted + assert_equal(tx1["bcconfirmations"], -2) + assert_equal(tx2["bcconfirmations"], -2) + + # Node0's total balance should be starting balance, plus 100BTC for + # two more matured blocks, minus 1240 for the double-spend, plus fees (which are + # negative): + expected = starting_balance + 500 - (1240 * 5) + fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee + assert_equal(self.nodes[0].getbalance(), expected) + assert_equal(self.nodes[0].getbalance("*"), expected) + + # Final "" balance is starting_balance - amount moved to accounts - doublespend + subsidies + + # fees (which are negative) + assert_equal(self.nodes[0].getbalance("foo"), (1219 * 5)) + #assert_equal(self.nodes[0].getbalance("bar"), (29 * 5)) + #assert_equal(self.nodes[0].getbalance(""), starting_balance + # -(1219 * 5) + # - (29 * 5) + # -(1240 * 5) + # + 500 + # + fund_foo_tx["fee"] + # + fund_bar_tx["fee"] + # + doublespend_fee) + + # Node1's "from0" account balance should be just the doublespend: + assert_equal(self.nodes[1].getbalance("from0"), (1240 * 5)) + +if __name__ == '__main__': + TxnMallTest().main() From 4728b29002b9cf2c2793d2e885663bad68b35936 Mon Sep 17 00:00:00 2001 From: warrows Date: Fri, 19 Jul 2019 15:57:41 +0200 Subject: [PATCH 085/132] [Wallet] Do not flush the wallet in AddToWalletIfInvolvingMe(..) Backport of https://github.com/bitcoin/bitcoin/pull/4805 ( commit 44bc988e7becb492a78ed92ea1052f4789012534 ) --- src/init.cpp | 3 ++- src/main.cpp | 4 ++-- src/test/accounting_tests.cpp | 6 +++--- src/wallet/db.cpp | 6 ++++-- src/wallet/db.h | 4 +++- src/wallet/wallet.cpp | 31 ++++++++++++++++++------------- src/wallet/wallet.h | 4 ++-- src/wallet/walletdb.cpp | 2 +- src/wallet/walletdb.h | 2 +- src/zphrwallet.cpp | 5 +++-- 10 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 87b665784b66c..d921fe1c42c74 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1771,6 +1771,7 @@ bool AppInit2(const std::vector& words) // Restore wallet transaction metadata after -zapwallettxes=1 if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") { + CWalletDB walletdb(strWalletFile); for (const CWalletTx& wtxOld : vWtx) { uint256 hash = wtxOld.GetHash(); std::map::iterator mi = pwalletMain->mapWallet.find(hash); @@ -1784,7 +1785,7 @@ bool AppInit2(const std::vector& words) copyTo->fFromMe = copyFrom->fFromMe; copyTo->strFromAccount = copyFrom->strFromAccount; copyTo->nOrderPos = copyFrom->nOrderPos; - copyTo->WriteToDisk(); + copyTo->WriteToDisk(&walletdb); } } } diff --git a/src/main.cpp b/src/main.cpp index 26fe604546498..bed4e06227db4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2790,7 +2790,7 @@ bool UpdateZPHRSupply(const CBlock& block, CBlockIndex* pindex) CWalletTx wtx(pwalletMain, tx); wtx.nTimeReceived = block.GetBlockTime(); wtx.SetMerkleBranch(block); - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, nullptr); setAddedToWallet.insert(txid); } } @@ -3137,7 +3137,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CWalletTx wtx(pwalletMain, tx); wtx.nTimeReceived = pindex->GetBlockTime(); wtx.SetMerkleBranch(block); - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, nullptr); setAddedTx.insert(pSpend.second); } } diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index 924edd10539a1..ed9ed9044dd82 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) pwalletMain->AddAccountingEntry(ae, walletdb); wtx.mapValue["comment"] = "z"; - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, &walletdb); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[0]->nTimeReceived = (unsigned int)1333333335; vpwtx[0]->nOrderPos = -1; @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) --tx.nLockTime; // Just to change the hash :) *static_cast(&wtx) = CTransaction(tx); } - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, &walletdb); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[1]->nTimeReceived = (unsigned int)1333333336; @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) --tx.nLockTime; // Just to change the hash :) *static_cast(&wtx) = CTransaction(tx); } - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, &walletdb); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[2]->nTimeReceived = (unsigned int)1333333329; vpwtx[2]->nOrderPos = -1; diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index fcd7f8fa7652f..7b115531c053a 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -222,10 +222,11 @@ void CDBEnv::CheckpointLSN(const std::string& strFile) } -CDB::CDB(const std::string& strFilename, const char* pszMode, int nSerVersion) : pdb(NULL), activeTxn(NULL) +CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL) { int ret; fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); + fFlushOnClose = fFlushOnCloseIn; if (strFilename.empty()) return; @@ -303,7 +304,8 @@ void CDB::Close() activeTxn = NULL; pdb = NULL; - Flush(); + if (fFlushOnClose) + Flush(); { LOCK(bitdb.cs_db); diff --git a/src/wallet/db.h b/src/wallet/db.h index 7048da49be684..07ba197e8ccac 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -105,7 +105,9 @@ class CDB bool fReadOnly; int nSerVersion; - explicit CDB(const std::string& strFilename, const char* pszMode = "r+", int nSerVersion = CLIENT_VERSION); + bool fFlushOnClose; + + explicit CDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnCloseIn=true); ~CDB() { Close(); } public: diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 85c00b31c8442..91d735b8b370c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -931,7 +931,7 @@ void CWallet::MarkDirty() } } -bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) +bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb) { uint256 hash = wtxIn.GetHash(); @@ -951,10 +951,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) if (fInsertedNew) { if (!wtx.nTimeReceived) wtx.nTimeReceived = GetAdjustedTime(); - wtx.nOrderPos = IncOrderPosNext(); - wtx.nTimeSmart = ComputeTimeSmart(wtx); + wtx.nOrderPos = IncOrderPosNext(pwalletdb); wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); - + wtx.nTimeSmart = ComputeTimeSmart(wtx); AddToSpends(hash); for (const CTxIn& txin : wtx.vin) { @@ -989,7 +988,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) // Write to disk if (fInsertedNew || fUpdated) - if (!wtx.WriteToDisk()) + if (!wtx.WriteToDisk(pwalletdb)) return false; // Break debit/credit balance caches: @@ -1039,7 +1038,11 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl // Get merkle branch if transaction was found in a block if (pblock) wtx.SetMerkleBranch(*pblock); - return AddToWallet(wtx); + // Do not flush the wallet here for performance reasons + // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism + CWalletDB walletdb(strWalletFile, "r+", false); + + return AddToWallet(wtx, false, &walletdb); } } return false; @@ -1568,8 +1571,10 @@ void CWalletTx::GetAccountAmounts(const std::string& strAccount, CAmount& nRecei } -bool CWalletTx::WriteToDisk() +bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb) { + if (pwalletdb) + return pwalletdb->WriteTx(GetHash(), *this); return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this); } @@ -1619,8 +1624,8 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b //If this is a zapwallettx, need to readd zphr if (fCheckZPHR && pindex->nHeight >= Params().Zerocoin_StartHeight()) { std::list listMints; - BlockToZerocoinMintList(block, listMints); - + BlockToZerocoinMintList(block, listMints, true); + CWalletDB walletdb(strWalletFile); for (auto& m : listMints) { if (IsMyMint(m.GetValue())) { LogPrint("zero", "%s: found mint\n", __func__); @@ -1635,7 +1640,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b CWalletTx wtx(pwalletMain, tx); wtx.nTimeReceived = block.GetBlockTime(); wtx.SetMerkleBranch(block); - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, &walletdb); setAddedToWallet.insert(txid); } } @@ -1655,7 +1660,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b wtx.SetMerkleBranch(blockSpend); wtx.nTimeReceived = pindexSpend->nTime; - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, &walletdb); setAddedToWallet.emplace(txidSpend); } } @@ -2793,14 +2798,14 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, std: // This is only to keep the database open to defeat the auto-flush for the // duration of this scope. This is the only place where this optimization // maybe makes sense; please don't do it anywhere else. - CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile, "r") : NULL; + CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile, "r+") : NULL; // Take key pair from key pool so it won't be used again reservekey.KeepKey(); // Add tx to wallet, because if it has change it's also ours, // otherwise just for transaction history. - AddToWallet(wtxNew); + AddToWallet(wtxNew, false, pwalletdb); // Notify that old coins are spent if (!wtxNew.IsZerocoinSpend()) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 93d2d8f8a3459..25eda028e122a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -450,7 +450,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface int64_t IncOrderPosNext(CWalletDB* pwalletdb = NULL); void MarkDirty(); - bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet = false); + bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); void SyncTransaction(const CTransaction& tx, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); void EraseFromWallet(const uint256& hash); @@ -848,7 +848,7 @@ class CWalletTx : public CMerkleTx bool IsTrusted() const; - bool WriteToDisk(); + bool WriteToDisk(CWalletDB *pwalletdb); int64_t GetTxTime() const; int64_t GetComputedTxTime() const; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index bc63ab650e4f9..b5192e53b69ab 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -463,7 +463,7 @@ bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CW if (wtx.nOrderPos == -1) wss.fAnyUnordered = true; - pwallet->AddToWallet(wtx, true); + pwallet->AddToWallet(wtx, true, nullptr); } else if (strType == "acentry") { std::string strAccount; ssKey >> strAccount; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 00fa6c94e2369..3dabff4d910b6 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -131,7 +131,7 @@ class CKeyMetadata class CWalletDB : public CDB { public: - CWalletDB(const std::string& strFilename, const char* pszMode = "r+") : CDB(strFilename, pszMode, CLIENT_VERSION) + CWalletDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnClose = true) : CDB(strFilename, pszMode, fFlushOnClose) { } diff --git a/src/zphrwallet.cpp b/src/zphrwallet.cpp index 4ab1cac104d16..601afb1b51d7a 100644 --- a/src/zphrwallet.cpp +++ b/src/zphrwallet.cpp @@ -265,7 +265,7 @@ void CzPHRWallet::SyncWithChain(bool fGenerateMintPool) //Fill out wtx so that a transaction record can be created wtx.nTimeReceived = pindex->GetBlockTime(); - pwalletMain->AddToWallet(wtx); + pwalletMain->AddToWallet(wtx, false, &walletdb); setAddedTx.insert(txHash); } @@ -321,7 +321,8 @@ bool CzPHRWallet::SetMintSeen(const CBigNum& bnValue, const int& nHeight, const wtx.SetMerkleBranch(block); wtx.nTimeReceived = pindex->nTime; - pwalletMain->AddToWallet(wtx); + CWalletDB walletdb(strWalletFile); + pwalletMain->AddToWallet(wtx, false, &walletdb); } // Add to zphrTracker which also adds to database From 2c9fcc4c0611ff84d7fdb1da0388e4bc14a607db Mon Sep 17 00:00:00 2001 From: warrows Date: Sat, 20 Jul 2019 15:59:20 +0200 Subject: [PATCH 086/132] [Wallet] Switch to a constant-space Merkle root/branch algorithm Backport of https://github.com/bitcoin/bitcoin/pull/6508 This switches the Merkle tree logic for blocks to one that runs in constant (small) space. The old code is moved to tests, and a new test is added that for various combinations of block sizes, transaction positions to compute a branch for, and mutations: * Verifies that the old code and new code agree for the Merkle root. * Verifies that the old code and new code agree for the Merkle branch. * Verifies that the computed Merkle branch is valid. * Verifies that mutations don't change the Merkle root. * Verifies that mutations are correctly detected. --- src/Makefile.am | 1 + src/Makefile.test.include | 1 + src/chainparams.cpp | 3 +- src/consensus/merkle.cpp | 7 +- src/main.cpp | 2 +- src/miner.cpp | 3 +- src/primitives/block.cpp | 63 ------------------ src/primitives/block.h | 6 -- src/test/merkle_tests.cpp | 135 ++++++++++++++++++++++++++++++++++++++ src/test/miner_tests.cpp | 3 +- src/test/pmt_tests.cpp | 4 +- 11 files changed, 147 insertions(+), 81 deletions(-) create mode 100644 src/test/merkle_tests.cpp diff --git a/src/Makefile.am b/src/Makefile.am index cc0cb95935dc1..7bcd946c4ddb7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -104,6 +104,7 @@ BITCOIN_CORE_H = \ consensus/merkle.h \ consensus/validation.h \ compressor.h \ + consensus/merkle.h \ primitives/block.h \ primitives/deterministicmint.h \ primitives/transaction.h \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index c506a5d9ee6bd..6eed4b48e6203 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -52,6 +52,7 @@ BITCOIN_TESTS =\ test/key_tests.cpp \ test/main_tests.cpp \ test/mempool_tests.cpp \ + test/merkle_tests.cpp \ test/mruset_tests.cpp \ test/multisig_tests.cpp \ test/netbase_tests.cpp \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5c2a7ed5e8aac..0b5a42066aee5 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -8,6 +8,7 @@ #include "libzerocoin/Params.h" #include "chainparams.h" +#include "consensus/merkle.h" #include "random.h" #include "util.h" #include "utilstrencodings.h" @@ -176,7 +177,7 @@ class CMainParams : public CChainParams txNew.vout[0].SetEmpty(); genesis.vtx.push_back(txNew); genesis.hashPrevBlock = 0; - genesis.hashMerkleRoot = genesis.ComputeMerkleRoot(); + genesis.hashMerkleRoot = BlockMerkleRoot(genesis); genesis.nVersion = 1; genesis.nTime = 1505224800; genesis.nBits = 0x207fffff;; diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 35f7d2e05a937..c2b0cd787a2f5 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -1,7 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. - #include "merkle.h" #include "hash.h" #include "utilstrencodings.h" @@ -10,13 +9,11 @@ and/or designing a new system that will use merkle trees, keep in mind that the following merkle tree algorithm has a serious flaw related to duplicate txids, resulting in a vulnerability (CVE-2012-2459). - The reason is that if the number of hashes in the list at a given time is odd, the last one is duplicated before computing the next level (which is unusual in Merkle trees). This results in certain sequences of transactions leading to the same merkle root. For example, these two trees: - A A / \ / \ B C B C @@ -24,11 +21,9 @@ D E F D E F F / \ / \ / \ / \ / \ / \ / \ 1 2 3 4 5 6 1 2 3 4 5 6 5 6 - for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and 6 are repeated) result in the same root hash A (because the hash of both of (F) and (F,F) is C). - The vulnerability results from being able to send a block with such a transaction list, with the same merkle root, and the same block hash as the original without duplication, resulting in failed validation. If the @@ -184,4 +179,4 @@ std::vector BlockMerkleBranch(const CBlock& block, uint32_t position) leaves[s] = block.vtx[s].GetHash(); } return ComputeMerkleBranch(leaves, position); -} +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bed4e06227db4..098f10ca8dd72 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4065,7 +4065,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo // Check the merkle root. if (fCheckMerkleRoot) { bool mutated; - uint256 hashMerkleRoot2 = block.ComputeMerkleRoot(&mutated); + uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated); if (block.hashMerkleRoot != hashMerkleRoot2) return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); diff --git a/src/miner.cpp b/src/miner.cpp index 971384d8cc674..8f47db774555e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -11,6 +11,7 @@ #include "amount.h" #include "consensus/validation.h" +#include "consensus/merkle.h" #include "hash.h" #include "main.h" #include "masternode-sync.h" @@ -544,7 +545,7 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned assert(txCoinbase.vin[0].scriptSig.size() <= 100); pblock->vtx[0] = txCoinbase; - pblock->hashMerkleRoot = pblock->ComputeMerkleRoot(); + pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); } #ifdef ENABLE_WALLET diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 459548f3cd111..3aba249d8322c 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -22,69 +22,6 @@ uint256 CBlockHeader::GetHash() const return Hash(BEGIN(nVersion), END(nAccumulatorCheckpoint)); } -uint256 CBlock::ComputeMerkleRoot(bool* fMutated) const -{ - /* WARNING! If you're reading this because you're learning about crypto - and/or designing a new system that will use merkle trees, keep in mind - that the following merkle tree algorithm has a serious flaw related to - duplicate txids, resulting in a vulnerability (CVE-2012-2459). - - The reason is that if the number of hashes in the list at a given time - is odd, the last one is duplicated before computing the next level (which - is unusual in Merkle trees). This results in certain sequences of - transactions leading to the same merkle root. For example, these two - trees: - - A A - / \ / \ - B C B C - / \ | / \ / \ - D E F D E F F - / \ / \ / \ / \ / \ / \ / \ - 1 2 3 4 5 6 1 2 3 4 5 6 5 6 - - for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and - 6 are repeated) result in the same root hash A (because the hash of both - of (F) and (F,F) is C). - - The vulnerability results from being able to send a block with such a - transaction list, with the same merkle root, and the same block hash as - the original without duplication, resulting in failed validation. If the - receiving node proceeds to mark that block as permanently invalid - however, it will fail to accept further unmodified (and thus potentially - valid) versions of the same block. We defend against this by detecting - the case where we would hash two identical hashes at the end of the list - together, and treating that identically to the block having an invalid - merkle root. Assuming no double-SHA256 collisions, this will detect all - known ways of changing the transactions without affecting the merkle - root. - */ - std::vector vMerkleTree; - vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. - for (std::vector::const_iterator it(vtx.begin()); it != vtx.end(); ++it) - vMerkleTree.push_back(it->GetHash()); - int j = 0; - bool mutated = false; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) - { - for (int i = 0; i < nSize; i += 2) - { - int i2 = std::min(i+1, nSize-1); - if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) { - // Two identical hashes at the end of the list at a particular level. - mutated = true; - } - vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), - BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); - } - j += nSize; - } - if (fMutated) { - *fMutated = mutated; - } - return (vMerkleTree.empty() ? uint256() : vMerkleTree.back()); -} - std::string CBlock::ToString() const { std::stringstream s; diff --git a/src/primitives/block.h b/src/primitives/block.h index 907a24f693a50..5fcaf39048c2e 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -158,12 +158,6 @@ class CBlock : public CBlockHeader return IsProofOfStake()? std::make_pair(vtx[1].vin[0].prevout, nTime) : std::make_pair(COutPoint(), (unsigned int)0); } - // Build the merkle tree for this block and return the merkle root. - // If non-NULL, *mutated is set to whether mutation was detected in the merkle - // tree (a duplication of transactions in the block leading to an identical - // merkle root). - uint256 ComputeMerkleRoot(bool* mutated = NULL) const; - std::string ToString() const; void print() const; }; diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp new file mode 100644 index 0000000000000..57536d8478f03 --- /dev/null +++ b/src/test/merkle_tests.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "consensus/merkle.h" +#include "test/test_pivx.h" + +#include + +BOOST_FIXTURE_TEST_SUITE(merkle_tests, TestingSetup) + +// Older version of the merkle root computation code, for comparison. +static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::vector& vMerkleTree) +{ + vMerkleTree.clear(); + vMerkleTree.reserve(block.vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. + for (std::vector::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it) + vMerkleTree.push_back(it->GetHash()); + int j = 0; + bool mutated = false; + for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) + { + for (int i = 0; i < nSize; i += 2) + { + int i2 = std::min(i+1, nSize-1); + if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) { + // Two identical hashes at the end of the list at a particular level. + mutated = true; + } + vMerkleTree.push_back(Hash(vMerkleTree[j+i].begin(), vMerkleTree[j+i].end(), + vMerkleTree[j+i2].begin(), vMerkleTree[j+i2].end())); + } + j += nSize; + } + if (fMutated) { + *fMutated = mutated; + } + return (vMerkleTree.empty() ? uint256() : vMerkleTree.back()); +} + +// Older version of the merkle branch computation code, for comparison. +static std::vector BlockGetMerkleBranch(const CBlock& block, const std::vector& vMerkleTree, int nIndex) +{ + std::vector vMerkleBranch; + int j = 0; + for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) + { + int i = std::min(nIndex^1, nSize-1); + vMerkleBranch.push_back(vMerkleTree[j+i]); + nIndex >>= 1; + j += nSize; + } + return vMerkleBranch; +} + +static inline int ctz(uint32_t i) { + if (i == 0) return 0; + int j = 0; + while (!(i & 1)) { + j++; + i >>= 1; + } + return j; +} + +BOOST_AUTO_TEST_CASE(merkle_test) +{ + for (int i = 0; i < 32; i++) { + // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes. + int ntx = (i <= 16) ? i : 17 + (InsecureRandRange(4000)); + // Try up to 3 mutations. + for (int mutate = 0; mutate <= 3; mutate++) { + int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first. + if (duplicate1 >= ntx) break; // Duplication of the entire tree results in a different root (it adds a level). + int ntx1 = ntx + duplicate1; // The resulting number of transactions after the first duplication. + int duplicate2 = mutate >= 2 ? 1 << ctz(ntx1) : 0; // Likewise for the second mutation. + if (duplicate2 >= ntx1) break; + int ntx2 = ntx1 + duplicate2; + int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; // And for the the third mutation. + if (duplicate3 >= ntx2) break; + int ntx3 = ntx2 + duplicate3; + // Build a block with ntx different transactions. + CBlock block; + block.vtx.resize(ntx); + for (int j = 0; j < ntx; j++) { + CMutableTransaction mtx; + mtx.nLockTime = j; + block.vtx[j] = mtx; + } + // Compute the root of the block before mutating it. + bool unmutatedMutated = false; + uint256 unmutatedRoot = BlockMerkleRoot(block, &unmutatedMutated); + BOOST_CHECK(unmutatedMutated == false); + // Optionally mutate by duplicating the last transactions, resulting in the same merkle root. + block.vtx.resize(ntx3); + for (int j = 0; j < duplicate1; j++) { + block.vtx[ntx + j] = block.vtx[ntx + j - duplicate1]; + } + for (int j = 0; j < duplicate2; j++) { + block.vtx[ntx1 + j] = block.vtx[ntx1 + j - duplicate2]; + } + for (int j = 0; j < duplicate3; j++) { + block.vtx[ntx2 + j] = block.vtx[ntx2 + j - duplicate3]; + } + // Compute the merkle root and merkle tree using the old mechanism. + bool oldMutated = false; + std::vector merkleTree; + uint256 oldRoot = BlockBuildMerkleTree(block, &oldMutated, merkleTree); + // Compute the merkle root using the new mechanism. + bool newMutated = false; + uint256 newRoot = BlockMerkleRoot(block, &newMutated); + BOOST_CHECK(oldRoot == newRoot); + BOOST_CHECK(newRoot == unmutatedRoot); + BOOST_CHECK((newRoot == uint256()) == (ntx == 0)); + BOOST_CHECK(oldMutated == newMutated); + BOOST_CHECK(newMutated == !!mutate); + // If no mutation was done (once for every ntx value), try up to 16 branches. + if (mutate == 0) { + for (int loop = 0; loop < std::min(ntx, 16); loop++) { + // If ntx <= 16, try all branches. Otherise, try 16 random ones. + int mtx = loop; + if (ntx > 16) { + mtx = InsecureRandRange(ntx); + } + std::vector newBranch = BlockMerkleBranch(block, mtx); + std::vector oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); + BOOST_CHECK(oldBranch == newBranch); + BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx].GetHash(), newBranch, mtx) == oldRoot); + } + } + } + } +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index e0739d3e0b16a..08f081149f45f 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -4,6 +4,7 @@ #include "consensus/validation.h" #include "init.h" +#include "consensus/merkle.h" #include "main.h" #include "miner.h" #include "pubkey.h" @@ -82,7 +83,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) pblock->vtx[0] = CTransaction(txCoinbase); if (txFirst.size() < 2) txFirst.push_back(new CTransaction(pblock->vtx[0])); - pblock->hashMerkleRoot = pblock->ComputeMerkleRoot(); + pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); pblock->nNonce = blockinfo[i].nonce; CValidationState state; BOOST_CHECK(ProcessNewBlock(state, NULL, pblock)); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 90d6d87a0e498..2832c06670d5a 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -8,7 +8,7 @@ #include "uint256.h" #include "version.h" #include "test/test_phore.h" -#include "test_random.h" +#include "consensus/merkle.h" #include #include @@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) } // calculate actual merkle root and height - uint256 merkleRoot1 = block.ComputeMerkleRoot(); + uint256 merkleRoot1 = BlockMerkleRoot(block); std::vector vTxid(nTx, 0); for (unsigned int j=0; j Date: Fri, 19 Dec 2014 06:59:16 +0100 Subject: [PATCH 087/132] [Wallet] sort pending wallet transactions before reaccepting During startup, when adding pending wallet transactions, which spend outputs of other pending wallet transactions, back to the memory pool, and when they are added out of order, it appears as if they are orphans with missing inputs. Those transactions are then rejected and flagged as "conflicting" (= not in the memory pool, not in the block chain). To prevent this, transactions are explicitly sorted. --- src/wallet/wallet.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 91d735b8b370c..e1a266a8d9596 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1681,7 +1681,10 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b void CWallet::ReacceptWalletTransactions() { LOCK2(cs_main, cs_wallet); - for (PAIRTYPE(const uint256, CWalletTx) & item : mapWallet) { + std::map mapSorted; + + // Sort pending wallet transactions based on their initial wallet insertion order + for (PAIRTYPE(const uint256, CWalletTx)& item: mapWallet) { const uint256& wtxid = item.first; CWalletTx& wtx = item.second; assert(wtx.GetHash() == wtxid); @@ -1689,11 +1692,18 @@ void CWallet::ReacceptWalletTransactions() int nDepth = wtx.GetDepthInMainChain(); if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && nDepth == 0) { - // Try to add to memory pool - LOCK(mempool.cs); - wtx.AcceptToMemoryPool(false); + mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx)); } } + + // Try to add wallet transactions to memory pool + for (PAIRTYPE(const int64_t, CWalletTx*)& item: mapSorted) + { + CWalletTx& wtx = *(item.second); + + LOCK(mempool.cs); + wtx.AcceptToMemoryPool(false); + } } bool CWalletTx::InMempool() const From 6a0dd8e7bd6552d30872220a895b10c3f3cf1817 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 6 Jan 2016 17:24:30 -0500 Subject: [PATCH 088/132] Make sure conflicted wallet tx's update balances --- src/wallet/wallet.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e1a266a8d9596..5562d193d61bc 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1091,6 +1091,13 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) } iter++; } + // If a transaction changes 'conflicted' state, that changes the balance + // available of the outputs it spends. So force those to be recomputed + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + { + if (mapWallet.count(txin.prevout.hash)) + mapWallet[txin.prevout.hash].MarkDirty(); + } } } } From 62aaf72f2c699288c84a2abc8fee32d73391518e Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 7 Jan 2016 16:31:12 -0500 Subject: [PATCH 089/132] Make wallet descendant searching more efficient --- src/wallet/wallet.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5562d193d61bc..c3520451f6c86 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1064,14 +1064,14 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) // Do not flush the wallet here for performance reasons CWalletDB walletdb(strWalletFile, "r+", false); - std::deque todo; + std::set todo; std::set done; - todo.push_back(hashTx); + todo.insert(hashTx); while (!todo.empty()) { - uint256 now = todo.front(); - todo.pop_front(); + uint256 now = *todo.begin(); + todo.erase(now); done.insert(now); assert(mapWallet.count(now)); CWalletTx& wtx = mapWallet[now]; @@ -1087,7 +1087,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0)); while (iter != mapTxSpends.end() && iter->first.hash == now) { if (!done.count(iter->second)) { - todo.push_back(iter->second); + todo.insert(iter->second); } iter++; } From e23e5e4c0ae815b4e9d55f7cec14a8e880e8ee46 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 7 Jan 2016 16:31:27 -0500 Subject: [PATCH 090/132] Add new rpc call: abandontransaction Unconfirmed transactions that are not in your mempool either due to eviction or other means may be unlikely to be mined. abandontransaction gives the wallet a way to no longer consider as spent the coins that are inputs to such a transaction. All dependent transactions in the wallet will also be marked as abandoned. --- src/rpc/server.cpp | 1 + src/rpc/server.h | 1 + src/wallet/rpcwallet.cpp | 33 ++++++++++++++ src/wallet/wallet.cpp | 94 +++++++++++++++++++++++++++++++++++----- src/wallet/wallet.h | 8 ++++ 5 files changed, 125 insertions(+), 12 deletions(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 975a9379ee6a2..f177ed0c850f5 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -407,6 +407,7 @@ static const CRPCCommand vRPCCommands[] = {"wallet", "getstakingstatus", &getstakingstatus, false, false, true}, {"wallet", "getstakesplitthreshold", &getstakesplitthreshold, false, false, true}, {"wallet", "gettransaction", &gettransaction, false, false, true}, + {"wallet", "abandontransaction", &abandontransaction, false, false, true}, {"wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, false, true}, {"wallet", "getwalletinfo", &getwalletinfo, false, false, true}, {"wallet", "importprivkey", &importprivkey, true, false, true}, diff --git a/src/rpc/server.h b/src/rpc/server.h index de9fc66705372..7aa077cea0238 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -237,6 +237,7 @@ extern UniValue listaddressgroupings(const UniValue& params, bool fHelp); extern UniValue listaccounts(const UniValue& params, bool fHelp); extern UniValue listsinceblock(const UniValue& params, bool fHelp); extern UniValue gettransaction(const UniValue& params, bool fHelp); +extern UniValue abandontransaction(const UniValue& params, bool fHelp); extern UniValue backupwallet(const UniValue& params, bool fHelp); extern UniValue keypoolrefill(const UniValue& params, bool fHelp); extern UniValue walletpassphrase(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4c6ef3e83c2e8..c8ada9fd5c9cd 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1744,6 +1744,39 @@ UniValue gettransaction(const UniValue& params, bool fHelp) return entry; } +UniValue abandontransaction(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw std::runtime_error( + "abandontransaction \"txid\"\n" + "\nMark in-wallet transaction as abandoned\n" + "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n" + "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n" + "It only works on transactions which are not included in a block and are not currently in the mempool.\n" + "It has no effect on transactions which are already conflicted or abandoned.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + ); + + EnsureWalletIsUnlocked(); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + uint256 hash; + hash.SetHex(params[0].get_str()); + + if (!pwalletMain->mapWallet.count(hash)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); + if (!pwalletMain->AbandonTransaction(hash)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment"); + + return NullUniValue; +} + UniValue backupwallet(const UniValue& params, bool fHelp) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c3520451f6c86..d5211738dc0d0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -63,6 +63,8 @@ OutputType g_change_type = OUTPUT_TYPE_NONE; */ CFeeRate CWallet::minTxFee = CFeeRate(10000); +const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + /** @defgroup mapWallet * * @{ @@ -593,8 +595,11 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const for (TxSpends::const_iterator it = range.first; it != range.second; ++it) { const uint256& wtxid = it->second; std::map::const_iterator mit = mapWallet.find(wtxid); - if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) - return true; // Spent + if (mit != mapWallet.end()) { + int depth = mit->second.GetDepthInMainChain(); + if (depth > 0 || (depth == 0 && !mit->second.isAbandoned())) + return true; // Spent + } } return false; } @@ -959,7 +964,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD for (const CTxIn& txin : wtx.vin) { if (mapWallet.count(txin.prevout.hash)) { CWalletTx& prevtx = mapWallet[txin.prevout.hash]; - if (prevtx.nIndex == -1 && !prevtx.hashBlock.IsNull()) { + if (prevtx.nIndex == -1 && !prevtx.hashUnset()) { MarkConflicted(prevtx.hashBlock, wtx.GetHash()); } } @@ -969,7 +974,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD bool fUpdated = false; if (!fInsertedNew) { // Merge - if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock) { + if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock) { + wtx.hashBlock = wtxIn.hashBlock; + fUpdated = true; + } + // If no longer abandoned, update + if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned()) { wtx.hashBlock = wtxIn.hashBlock; fUpdated = true; } @@ -1017,7 +1027,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { { AssertLockHeld(cs_wallet); - + if (pblock) { for (const CTxIn& txin : tx.vin) { std::pair range = mapTxSpends.equal_range(txin.prevout); @@ -1030,7 +1040,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl } } } - + bool fExisted = mapWallet.count(tx.GetHash()) != 0; if (fExisted && !fUpdate) return false; if (fExisted || IsMine(tx) || IsFromMe(tx)) { @@ -1048,6 +1058,63 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl return false; } +bool CWallet::AbandonTransaction(const uint256& hashTx) +{ + LOCK2(cs_main, cs_wallet); + + // Do not flush the wallet here for performance reasons + CWalletDB walletdb(strWalletFile, "r+", false); + + std::set todo; + std::set done; + + // Can't mark abandoned if confirmed or in mempool + assert(mapWallet.count(hashTx)); + CWalletTx& origtx = mapWallet[hashTx]; + if (origtx.GetDepthInMainChain() > 0 || origtx.InMempool()) { + return false; + } + + todo.insert(hashTx); + + while (!todo.empty()) { + uint256 now = *todo.begin(); + todo.erase(now); + done.insert(now); + assert(mapWallet.count(now)); + CWalletTx& wtx = mapWallet[now]; + int currentconfirm = wtx.GetDepthInMainChain(); + // If the orig tx was not in block, none of its spends can be + assert(currentconfirm <= 0); + // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon} + if (currentconfirm == 0 && !wtx.isAbandoned()) { + // If the orig tx was not in block/mempool, none of its spends can be in mempool + assert(!wtx.InMempool()); + wtx.nIndex = -1; + wtx.setAbandoned(); + wtx.MarkDirty(); + wtx.WriteToDisk(&walletdb); + // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too + TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(hashTx, 0)); + while (iter != mapTxSpends.end() && iter->first.hash == now) { + if (!done.count(iter->second)) { + todo.insert(iter->second); + } + iter++; + } + // If a transaction changes 'conflicted' state, that changes the balance + // available of the outputs it spends. So force those to be recomputed + for (const CTxIn& txin: wtx.vin) + { + if (mapWallet.count(txin.prevout.hash)) + mapWallet[txin.prevout.hash].MarkDirty(); + } + } + } + + return true; +} + void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) { LOCK2(cs_main, cs_wallet); @@ -1093,7 +1160,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) } // If a transaction changes 'conflicted' state, that changes the balance // available of the outputs it spends. So force those to be recomputed - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + for (const CTxIn& txin: wtx.vin) { if (mapWallet.count(txin.prevout.hash)) mapWallet[txin.prevout.hash].MarkDirty(); @@ -1232,7 +1299,7 @@ int CWalletTx::GetRequestCount() const LOCK(pwallet->cs_wallet); if (IsCoinBase()) { // Generated block - if (hashBlock != 0) { + if (!hashUnset()) { std::map::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); if (mi != pwallet->mapRequestCount.end()) nRequests = (*mi).second; @@ -1244,7 +1311,7 @@ int CWalletTx::GetRequestCount() const nRequests = (*mi).second; // How about the block it's in? - if (nRequests == 0 && hashBlock != 0) { + if (nRequests == 0 && !hashUnset()) { std::map::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); if (mi != pwallet->mapRequestCount.end()) nRequests = (*mi).second; @@ -1697,9 +1764,12 @@ void CWallet::ReacceptWalletTransactions() assert(wtx.GetHash() == wtxid); int nDepth = wtx.GetDepthInMainChain(); - + if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && nDepth == 0) { mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx)); + // Try to add to memory pool + LOCK(mempool.cs); + wtx.AcceptToMemoryPool(false); } } @@ -1726,7 +1796,7 @@ void CWalletTx::RelayWalletTransaction(std::string strCommand) { LOCK(cs_main); if (!IsCoinBase()) { - if (GetDepthInMainChain() == 0) { + if (GetDepthInMainChain() == 0 && !isAbandoned()) { uint256 hash = GetHash(); LogPrintf("Relaying wtx %s\n", hash.ToString()); @@ -3983,7 +4053,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block) int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const { - if (hashBlock == 0) + if (hashUnset()) return 0; AssertLockHeld(cs_main); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 25eda028e122a..3f74d6cd0aa49 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -569,6 +569,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface //! Get wallet transactions that conflict with given transaction (spend same outputs) std::set GetConflicts(const uint256& txid) const; + /* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */ + bool AbandonTransaction(const uint256& hashTx); + /** * Address book entry changed. * @note called with lock cs_wallet held. @@ -654,6 +657,8 @@ class CMerkleTx : public CTransaction { private: int GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const; + /** Constant used in hashBlock to indicate tx has been abandoned */ + static const uint256 ABANDON_HASH; public: uint256 hashBlock; @@ -717,6 +722,9 @@ class CMerkleTx : public CTransaction bool AcceptToMemoryPool(bool fLimitFree = true, bool fRejectInsaneFee = true, bool ignoreFees = false); int GetTransactionLockSignatures() const; bool IsTransactionLockTimedOut() const; + bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); } + bool isAbandoned() const { return (hashBlock == ABANDON_HASH); } + void setAbandoned() { hashBlock = ABANDON_HASH; } }; /** From 172b90eab378a9b915af3d4ad32c5c553a0df080 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 11 Jan 2016 11:15:41 +0100 Subject: [PATCH 091/132] [Wallet] Call notification signal when a transaction is abandoned --- src/wallet/wallet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d5211738dc0d0..61eff6481b4be 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1094,6 +1094,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) wtx.setAbandoned(); wtx.MarkDirty(); wtx.WriteToDisk(&walletdb); + NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED); // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(hashTx, 0)); while (iter != mapTxSpends.end() && iter->first.hash == now) { From cd11f5d141f205547117f14d202c538e024a22d5 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 9 Dec 2016 13:36:42 -0500 Subject: [PATCH 092/132] Flush wallet after abandontransaction --- src/wallet/wallet.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 61eff6481b4be..0aaee34717fb3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1062,8 +1062,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) { LOCK2(cs_main, cs_wallet); - // Do not flush the wallet here for performance reasons - CWalletDB walletdb(strWalletFile, "r+", false); + CWalletDB walletdb(strWalletFile, "r+"); std::set todo; std::set done; From a0c5ead9acaf61191f8504227a4948252b84a749 Mon Sep 17 00:00:00 2001 From: presstab Date: Fri, 1 Mar 2019 10:56:47 -0700 Subject: [PATCH 093/132] Remove stale wallet transactions on initial load. --- src/init.cpp | 2 +- src/wallet/wallet.cpp | 14 ++++++++++---- src/wallet/wallet.h | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index d921fe1c42c74..08be7a91ac195 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2050,7 +2050,7 @@ bool AppInit2(const std::vector& words) #ifdef ENABLE_WALLET if (pwalletMain) { // Add wallet transactions that aren't already in a block to mapTransactions - pwalletMain->ReacceptWalletTransactions(); + pwalletMain->ReacceptWalletTransactions(/*fFirstLoad*/true); // Run a thread to flush wallet periodically threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile))); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0aaee34717fb3..4266e4bfbce02 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1192,6 +1192,7 @@ void CWallet::EraseFromWallet(const uint256& hash) LOCK(cs_wallet); if (mapWallet.erase(hash)) CWalletDB(strWalletFile).EraseTx(hash); + LogPrintf("%s: Erased wtx %s from wallet\n", __func__, hash.GetHex()); } return; } @@ -1752,7 +1753,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b return ret; } -void CWallet::ReacceptWalletTransactions() +void CWallet::ReacceptWalletTransactions(bool fFirstLoad) { LOCK2(cs_main, cs_wallet); std::map mapSorted; @@ -1764,8 +1765,8 @@ void CWallet::ReacceptWalletTransactions() assert(wtx.GetHash() == wtxid); int nDepth = wtx.GetDepthInMainChain(); - - if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && nDepth == 0) { + + if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && nDepth == 0 && !wtx.isAbandoned()) { mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx)); // Try to add to memory pool LOCK(mempool.cs); @@ -1779,7 +1780,12 @@ void CWallet::ReacceptWalletTransactions() CWalletTx& wtx = *(item.second); LOCK(mempool.cs); - wtx.AcceptToMemoryPool(false); + bool fSuccess = wtx.AcceptToMemoryPool(false); + if (!fSuccess && fFirstLoad && GetTime() - wtx.GetTxTime() > 12*60*60) { + //First load of wallet, failed to accept to mempool, and older than 12 hours... not likely to ever + //make it in to mempool + AbandonTransaction(wtx.GetHash()); + } } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3f74d6cd0aa49..d567593901e38 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -455,7 +455,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); void EraseFromWallet(const uint256& hash); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, bool fromStartup = false); - void ReacceptWalletTransactions(); + void ReacceptWalletTransactions(bool fFirstLoad = false); void ResendWalletTransactions(); CAmount GetBalance() const; CAmount GetZerocoinBalance(bool fMatureOnly) const; From 2fe6da329eb03d9c289df56784ef43ed67f8ae18 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 17 Mar 2016 12:48:05 -0400 Subject: [PATCH 094/132] Fix calculation of balances and available coins. No longer consider coins which aren't in our mempool. Add test for regression in abandonconflict.py --- src/wallet/wallet.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4266e4bfbce02..c3e265b3164ee 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1976,7 +1976,7 @@ CAmount CWallet::GetUnconfirmedBalance() const LOCK2(cs_main, cs_wallet); for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) + if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableCredit(); } } @@ -2018,7 +2018,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const LOCK2(cs_main, cs_wallet); for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) + if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableWatchOnlyCredit(); } } @@ -2084,6 +2084,11 @@ void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed, if (nDepth == 0 && !pcoin->InMempool()) continue; + // We should not consider coins which aren't at least in our mempool + // It's possible for these to be conflicted via ancestors which we may never be able to detect + if (nDepth == 0 && !pcoin->InMempool()) + continue; + for (unsigned int i = 0; i < pcoin->vout.size(); i++) { bool found = false; if (nCoinType == ONLY_DENOMINATED) { From 9d8415fdd82420fecf7868b51909714f1b741aac Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Thu, 12 Jul 2018 17:19:00 -0400 Subject: [PATCH 095/132] Fix that CWallet::AbandonTransaction would only traverse one level Prior to this change, it would mark only the first layer of child transactions abandoned, due to always following the input hashTx rather than the current now tx. --- src/wallet/wallet.cpp | 2 +- test/functional/wallet_abandonconflict.py | 168 ++++++++++++++++++++++ 2 files changed, 169 insertions(+), 1 deletion(-) create mode 100755 test/functional/wallet_abandonconflict.py diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c3e265b3164ee..4db03c697edfe 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1095,7 +1095,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) wtx.WriteToDisk(&walletdb); NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED); // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too - TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(hashTx, 0)); + TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0)); while (iter != mapTxSpends.end() && iter->first.hash == now) { if (!done.count(iter->second)) { todo.insert(iter->second); diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py new file mode 100755 index 0000000000000..00c4a9d44f8d9 --- /dev/null +++ b/test/functional/wallet_abandonconflict.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import urllib.parse + +class AbandonConflictTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False + + def setup_network(self): + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug","-logtimemicros"])) + connect_nodes(self.nodes[0], 1) + + def run_test(self): + self.nodes[1].generate(100) + sync_blocks(self.nodes) + balance = self.nodes[0].getbalance() + txA = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10")) + txB = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10")) + txC = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10")) + sync_mempools(self.nodes) + self.nodes[1].generate(1) + + sync_blocks(self.nodes) + newbalance = self.nodes[0].getbalance() + assert(balance - newbalance < Decimal("0.001")) #no more than fees lost + balance = newbalance + + url = urllib.parse.urlparse(self.nodes[1].url) + self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) + + # Identify the 10btc outputs + nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10")) + nB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txB, 1)["vout"]) if vout["value"] == Decimal("10")) + nC = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txC, 1)["vout"]) if vout["value"] == Decimal("10")) + + inputs =[] + # spend 10btc outputs from txA and txB + inputs.append({"txid":txA, "vout":nA}) + inputs.append({"txid":txB, "vout":nB}) + outputs = {} + + outputs[self.nodes[0].getnewaddress()] = Decimal("14.99998") + outputs[self.nodes[1].getnewaddress()] = Decimal("5") + signed = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs)) + txAB1 = self.nodes[0].sendrawtransaction(signed["hex"]) + + # Identify the 14.99998btc output + nAB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txAB1, 1)["vout"]) if vout["value"] == Decimal("14.99998")) + + #Create a child tx spending AB1 and C + inputs = [] + inputs.append({"txid":txAB1, "vout":nAB}) + inputs.append({"txid":txC, "vout":nC}) + outputs = {} + outputs[self.nodes[0].getnewaddress()] = Decimal("24.9996") + signed2 = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs)) + txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"]) + + # Create a child tx spending ABC2 + signed3_change = Decimal("24.999") + inputs = [ {"txid":txABC2, "vout":0} ] + outputs = { self.nodes[0].getnewaddress(): signed3_change } + signed3 = self.nodes[0].signrawtransactionwithwallet(self.nodes[0].createrawtransaction(inputs, outputs)) + # note tx is never directly referenced, only abandoned as a child of the above + self.nodes[0].sendrawtransaction(signed3["hex"]) + + # In mempool txs from self should increase balance from change + newbalance = self.nodes[0].getbalance() + assert_equal(newbalance, balance - Decimal("30") + signed3_change) + balance = newbalance + + # Restart the node with a higher min relay fee so the parent tx is no longer in mempool + # TODO: redo with eviction + # Note had to make sure tx did not have AllowFree priority + stop_node(self.nodes[0],0) + self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"]) + + # Verify txs no longer in mempool + assert_equal(len(self.nodes[0].getrawmempool()), 0) + + # Not in mempool txs from self should only reduce balance + # inputs are still spent, but change not received + newbalance = self.nodes[0].getbalance() + assert_equal(newbalance, balance - signed3_change) + # Unconfirmed received funds that are not in mempool, also shouldn't show + # up in unconfirmed balance + unconfbalance = self.nodes[0].getunconfirmedbalance() + self.nodes[0].getbalance() + assert_equal(unconfbalance, newbalance) + # Also shouldn't show up in listunspent + assert(not txABC2 in [utxo["txid"] for utxo in self.nodes[0].listunspent(0)]) + balance = newbalance + + # Abandon original transaction and verify inputs are available again + # including that the child tx was also abandoned + self.nodes[0].abandontransaction(txAB1) + newbalance = self.nodes[0].getbalance() + assert_equal(newbalance, balance + Decimal("30")) + balance = newbalance + + # Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned + stop_node(self.nodes[0],0) + self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"]) + assert_equal(len(self.nodes[0].getrawmempool()), 0) + assert_equal(self.nodes[0].getbalance(), balance) + + # But if its received again then it is unabandoned + # And since now in mempool, the change is available + # But its child tx remains abandoned + self.nodes[0].sendrawtransaction(signed["hex"]) + newbalance = self.nodes[0].getbalance() + assert_equal(newbalance, balance - Decimal("20") + Decimal("14.99998")) + balance = newbalance + + # Send child tx again so its unabandoned + self.nodes[0].sendrawtransaction(signed2["hex"]) + newbalance = self.nodes[0].getbalance() + assert_equal(newbalance, balance - Decimal("10") - Decimal("14.99998") + Decimal("24.9996")) + balance = newbalance + + # Remove using high relay fee again + stop_node(self.nodes[0],0) + self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"]) + assert_equal(len(self.nodes[0].getrawmempool()), 0) + newbalance = self.nodes[0].getbalance() + assert_equal(newbalance, balance - Decimal("24.9996")) + balance = newbalance + + # Create a double spend of AB1 by spending again from only A's 10 output + # Mine double spend from node 1 + inputs =[] + inputs.append({"txid":txA, "vout":nA}) + outputs = {} + outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999") + tx = self.nodes[0].createrawtransaction(inputs, outputs) + signed = self.nodes[0].signrawtransaction(tx) + self.nodes[1].sendrawtransaction(signed["hex"]) + self.nodes[1].generate(1) + + connect_nodes(self.nodes[0], 1) + sync_blocks(self.nodes) + + # Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted + newbalance = self.nodes[0].getbalance() + assert_equal(newbalance, balance + Decimal("20")) + balance = newbalance + + # There is currently a minor bug around this and so this test doesn't work. See Issue #7315 + # Invalidate the block with the double spend and B's 10 BTC output should no longer be available + # Don't think C's should either + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + newbalance = self.nodes[0].getbalance() + #assert_equal(newbalance, balance - Decimal("10")) + print("If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer") + print("conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315") + print(str(balance) + " -> " + str(newbalance) + " ?") + +if __name__ == '__main__': + AbandonConflictTest().main() From d56c8444a996a828f0a56743b8c38484d6325a25 Mon Sep 17 00:00:00 2001 From: warrows Date: Sun, 28 Jul 2019 22:49:55 +0200 Subject: [PATCH 096/132] [Tests] Enable abandonconflict functional test --- test/functional/wallet_abandonconflict.py | 63 +++++++++++------------ 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py index 00c4a9d44f8d9..d77eb46c4d714 100755 --- a/test/functional/wallet_abandonconflict.py +++ b/test/functional/wallet_abandonconflict.py @@ -9,24 +9,20 @@ import urllib.parse class AbandonConflictTest(BitcoinTestFramework): - def __init__(self): - super().__init__() + def set_test_params(self): self.num_nodes = 2 - self.setup_clean_chain = False - - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-debug","-logtimemicros"])) - connect_nodes(self.nodes[0], 1) + self.setup_clean_chain = True + self.extra_args = [["-minrelaytxfee=0.00001"],[]] def run_test(self): - self.nodes[1].generate(100) + self.nodes[0].generate(5) + sync_blocks(self.nodes) + self.nodes[1].generate(110) sync_blocks(self.nodes) balance = self.nodes[0].getbalance() - txA = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10")) - txB = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10")) - txC = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10")) + txA = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 10) + txB = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 10) + txC = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 10) sync_mempools(self.nodes) self.nodes[1].generate(1) @@ -39,9 +35,9 @@ def run_test(self): self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) # Identify the 10btc outputs - nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10")) - nB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txB, 1)["vout"]) if vout["value"] == Decimal("10")) - nC = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txC, 1)["vout"]) if vout["value"] == Decimal("10")) + nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == 10) + nB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txB, 1)["vout"]) if vout["value"] == 10) + nC = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txC, 1)["vout"]) if vout["value"] == 10) inputs =[] # spend 10btc outputs from txA and txB @@ -49,8 +45,8 @@ def run_test(self): inputs.append({"txid":txB, "vout":nB}) outputs = {} - outputs[self.nodes[0].getnewaddress()] = Decimal("14.99998") - outputs[self.nodes[1].getnewaddress()] = Decimal("5") + outputs[self.nodes[0].getnewaddress()] = 14.99998 + outputs[self.nodes[1].getnewaddress()] = 5 signed = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs)) txAB1 = self.nodes[0].sendrawtransaction(signed["hex"]) @@ -62,28 +58,29 @@ def run_test(self): inputs.append({"txid":txAB1, "vout":nAB}) inputs.append({"txid":txC, "vout":nC}) outputs = {} - outputs[self.nodes[0].getnewaddress()] = Decimal("24.9996") + outputs[self.nodes[0].getnewaddress()] = 24.9996 signed2 = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs)) txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"]) # Create a child tx spending ABC2 - signed3_change = Decimal("24.999") - inputs = [ {"txid":txABC2, "vout":0} ] - outputs = { self.nodes[0].getnewaddress(): signed3_change } - signed3 = self.nodes[0].signrawtransactionwithwallet(self.nodes[0].createrawtransaction(inputs, outputs)) + inputs = [] + inputs.append({"txid":txABC2, "vout":0}) + outputs = {} + outputs[self.nodes[0].getnewaddress()] = 24.999 + signed3 = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs)) # note tx is never directly referenced, only abandoned as a child of the above self.nodes[0].sendrawtransaction(signed3["hex"]) # In mempool txs from self should increase balance from change newbalance = self.nodes[0].getbalance() - assert_equal(newbalance, balance - Decimal("30") + signed3_change) + assert_equal(newbalance, Decimal(round(balance - Decimal("30") + Decimal(24.999), 8))) balance = newbalance # Restart the node with a higher min relay fee so the parent tx is no longer in mempool # TODO: redo with eviction # Note had to make sure tx did not have AllowFree priority - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"]) + self.stop_node(0) + self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) # Verify txs no longer in mempool assert_equal(len(self.nodes[0].getrawmempool()), 0) @@ -91,7 +88,7 @@ def run_test(self): # Not in mempool txs from self should only reduce balance # inputs are still spent, but change not received newbalance = self.nodes[0].getbalance() - assert_equal(newbalance, balance - signed3_change) + assert_equal(newbalance, balance - Decimal("24.999")) # Unconfirmed received funds that are not in mempool, also shouldn't show # up in unconfirmed balance unconfbalance = self.nodes[0].getunconfirmedbalance() + self.nodes[0].getbalance() @@ -108,8 +105,8 @@ def run_test(self): balance = newbalance # Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"]) + self.stop_node(0) + self.start_node(0, extra_args=["-minrelaytxfee=0.00001"]) assert_equal(len(self.nodes[0].getrawmempool()), 0) assert_equal(self.nodes[0].getbalance(), balance) @@ -128,8 +125,8 @@ def run_test(self): balance = newbalance # Remove using high relay fee again - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"]) + self.stop_node(0) + self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) assert_equal(len(self.nodes[0].getrawmempool()), 0) newbalance = self.nodes[0].getbalance() assert_equal(newbalance, balance - Decimal("24.9996")) @@ -140,7 +137,7 @@ def run_test(self): inputs =[] inputs.append({"txid":txA, "vout":nA}) outputs = {} - outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999") + outputs[self.nodes[1].getnewaddress()] = 9.9999 tx = self.nodes[0].createrawtransaction(inputs, outputs) signed = self.nodes[0].signrawtransaction(tx) self.nodes[1].sendrawtransaction(signed["hex"]) @@ -151,7 +148,7 @@ def run_test(self): # Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted newbalance = self.nodes[0].getbalance() - assert_equal(newbalance, balance + Decimal("20")) + #assert_equal(newbalance, balance + Decimal("20")) balance = newbalance # There is currently a minor bug around this and so this test doesn't work. See Issue #7315 From 5fc8a59ae120072f69ed4965f59c94d2bab1e16a Mon Sep 17 00:00:00 2001 From: warrows Date: Mon, 29 Jul 2019 14:48:19 +0200 Subject: [PATCH 097/132] [Wallet] Fix an error in tx depth computation --- src/wallet/wallet.cpp | 32 +++++++++++++++----------------- src/wallet/wallet.h | 3 +-- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4db03c697edfe..485f28ed02e63 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4062,30 +4062,28 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block) return chainActive.Height() - pindex->nHeight + 1; } -int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const +int CMerkleTx::GetDepthInMainChain(const CBlockIndex*& pindexRet, bool enableIX) const { if (hashUnset()) return 0; AssertLockHeld(cs_main); + int nResult; // Find the block it claims to be in BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi == mapBlockIndex.end()) - return 0; - CBlockIndex* pindex = (*mi).second; - if (!pindex || !chainActive.Contains(pindex)) - return 0; - - pindexRet = pindex; - return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1); -} - -int CMerkleTx::GetDepthInMainChain(const CBlockIndex*& pindexRet, bool enableIX) const -{ - AssertLockHeld(cs_main); - int nResult = GetDepthInMainChainINTERNAL(pindexRet); - if (nResult == 0 && !mempool.exists(GetHash())) - return -1; // Not in chain, not in mempool + if (mi == mapBlockIndex.end()) { + nResult = 0; + } + else { + CBlockIndex* pindex = (*mi).second; + if (!pindex || !chainActive.Contains(pindex)) { + nResult = 0; + } + else { + pindexRet = pindex; + nResult = ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1); + } + } if (enableIX) { if (nResult < 6) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d567593901e38..3d0bd8b91a42e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -656,7 +656,6 @@ struct COutputEntry { class CMerkleTx : public CTransaction { private: - int GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const; /** Constant used in hashBlock to indicate tx has been abandoned */ static const uint256 ABANDON_HASH; @@ -716,7 +715,7 @@ class CMerkleTx : public CTransaction bool IsInMainChain() const { const CBlockIndex* pindexRet; - return GetDepthInMainChainINTERNAL(pindexRet) > 0; + return GetDepthInMainChain(pindexRet, false) > 0; } int GetBlocksToMaturity() const; bool AcceptToMemoryPool(bool fLimitFree = true, bool fRejectInsaneFee = true, bool ignoreFees = false); From 18f8c7adb0434b3bca404f5822c6cfb359bdede2 Mon Sep 17 00:00:00 2001 From: warrows Date: Mon, 23 Sep 2019 20:34:44 +0200 Subject: [PATCH 098/132] [Wallet] Ignore coinbase and zc tx "conflicts" Coinbase and zerocoin transaction can't really be checked for conflicts. Coinbase has no value anyway. Zerocoin transactions are checked for zero knowledge proof, the input hash has no meaning. --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 485f28ed02e63..da6f74b465821 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1028,7 +1028,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { AssertLockHeld(cs_wallet); - if (pblock) { + if (pblock && !tx.HasZerocoinSpendInputs() && !tx.IsCoinBase()) { for (const CTxIn& txin : tx.vin) { std::pair range = mapTxSpends.equal_range(txin.prevout); while (range.first != range.second) { From 1f3df059bd00ca5a176f794c207479317afa6c85 Mon Sep 17 00:00:00 2001 From: warrows Date: Fri, 27 Sep 2019 16:04:54 +0200 Subject: [PATCH 099/132] [Build] Add new merkle files to CMake lists --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75a7f22634aac..bf7ed6c2dbc1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,6 +446,7 @@ set(COMMON_SOURCES ./src/chainparams.cpp ./src/coins.cpp ./src/compressor.cpp + ./src/consensus/merkle.cpp ./src/primitives/block.cpp ./src/zpiv/deterministicmint.cpp ./src/primitives/transaction.cpp From 1b610e60d99f272e01f6452f31bd009685193d7e Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Sat, 28 Mar 2020 15:06:43 -0600 Subject: [PATCH 100/132] Fixes and clean up Added code to upgrade Masternode Message format Changes seen in Dash PR #836 --- src/masternode.cpp | 31 ++++++++++++++++++++++++++++--- src/spork.cpp | 24 ++++++++---------------- src/spork.h | 2 +- src/version.h | 2 +- src/wallet/wallet.cpp | 25 +++++++++++++++++-------- src/wallet/wallet.h | 23 +++++++++++++++++++++++ 6 files changed, 78 insertions(+), 29 deletions(-) diff --git a/src/masternode.cpp b/src/masternode.cpp index c3880e7a1faef..f8ae7a7b5996b 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -521,8 +521,17 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos) return false; } + std::string strMessage; + if(protocolVersion < 70008) { + std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); + std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); + strMessage = addr.ToString() + std::to_string(sigTime) + vchPubKey + vchPubKey2 + std::to_string(protocolVersion); + } else { + strMessage = addr.ToString() + std::to_string(sigTime) + pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() + std::to_string(protocolVersion); + } + std::string errorMessage = ""; - if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetStrMessage(), errorMessage)) + if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, strMessage, errorMessage)) { // don't ban for old masternodes, their sigs could be broken because of the bug nDos = protocolVersion < MIN_PEER_MNANNOUNCE ? 0 : 100; @@ -663,7 +672,14 @@ bool CMasternodeBroadcast::Sign(CKey& keyCollateralAddress) std::string errorMessage; sigTime = GetAdjustedTime(); - std::string strMessage = GetStrMessage(); + std::string strMessage; + if(protocolVersion < 70008) { + std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); + std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); + strMessage = addr.ToString() + std::to_string(sigTime) + vchPubKey + vchPubKey2 + std::to_string(protocolVersion); + } else { + strMessage = addr.ToString() + std::to_string(sigTime) + pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() + std::to_string(protocolVersion); + } if (!obfuScationSigner.SignMessage(strMessage, errorMessage, sig, keyCollateralAddress)) return error("CMasternodeBroadcast::Sign() - Error: %s", errorMessage); @@ -679,7 +695,16 @@ bool CMasternodeBroadcast::VerifySignature() { std::string errorMessage; - if(!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetStrMessage(), errorMessage)) + std::string strMessage; + if(protocolVersion < 70008) { + std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); + std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); + strMessage = addr.ToString() + std::to_string(sigTime) + vchPubKey + vchPubKey2 + std::to_string(protocolVersion); + } else { + strMessage = addr.ToString() + std::to_string(sigTime) + pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() + std::to_string(protocolVersion); + } + + if(!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, strMessage, errorMessage)) return error("CMasternodeBroadcast::VerifySignature() - Error: %s", errorMessage); return true; diff --git a/src/spork.cpp b/src/spork.cpp index db1f0f4bd2af5..1795f82598bd5 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -115,8 +115,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr LogPrintf("spork - new %s ID %d Time %d bestHeight %d\n", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Tip()->nHeight); - bool fRequireNew = spork.nTimeSigned >= Params().NewSporkStart(); - if (!spork.CheckSignature(fRequireNew)) { + if (!spork.CheckSignature()) { LOCK(cs_main); LogPrintf("%s : Invalid Signature\n", __func__); Misbehaving(pfrom->GetId(), 100); @@ -212,8 +211,7 @@ bool CSporkManager::SetPrivKey(std::string strPrivKey) spork.Sign(strPrivKey); - const bool fRequireNew = GetTime() >= Params().NewSporkStart(); - if (spork.CheckSignature(fRequireNew)) { + if (spork.CheckSignature()) { LOCK(cs); // Test signing successful, proceed LogPrintf("%s : Successfully initialized as spork signer\n", __func__); @@ -253,24 +251,18 @@ bool CSporkMessage::Sign(std::string strSignKey) return true; } -bool CSporkMessage::CheckSignature(bool fRequireNew) +bool CSporkMessage::CheckSignature() { //note: need to investigate why this is failing std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned); - CPubKey pubkeynew(ParseHex(Params().SporkPubKey())); - std::string errorMessage = ""; - - bool fValidWithNewKey = obfuScationSigner.VerifyMessage(pubkeynew, vchSig, strMessage, errorMessage); + CPubKey pubkey(ParseHex(Params().SporkKey())); + std::string strError = ""; - if (fRequireNew && !fValidWithNewKey) + if(!obfuScationSigner.VerifyMessage(pubkey, vchSig, strMessage, strError)) { + LogPrintf("CSporkMessage::CheckSignature -- VerifyMessage() failed, error: %s\n", strError); return false; - - // See if window is open that allows for old spork key to sign messages - if (!fValidWithNewKey && GetAdjustedTime() < Params().RejectOldSporkKey()) { - CPubKey pubkeyold(ParseHex(Params().SporkPubKeyOld())); - return obfuScationSigner.VerifyMessage(pubkeyold, vchSig, strMessage, errorMessage); } - return fValidWithNewKey; + return true; } void CSporkMessage::Relay() diff --git a/src/spork.h b/src/spork.h index 0f6370f3b1fce..1c87e5d4f9c5a 100644 --- a/src/spork.h +++ b/src/spork.h @@ -45,7 +45,7 @@ class CSporkMessage uint256 GetHash() { return HashQuark(BEGIN(nSporkID), END(nTimeSigned)); } bool Sign(std::string strSignKey); - bool CheckSignature(bool fRequireNew = false); + bool CheckSignature(); void Relay(); ADD_SERIALIZE_METHODS; diff --git a/src/version.h b/src/version.h index b443a9221ea72..0fa6d1380c8eb 100644 --- a/src/version.h +++ b/src/version.h @@ -12,7 +12,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 70007; +static const int PROTOCOL_VERSION = 70008; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index da6f74b465821..65c7494dbce24 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1028,7 +1028,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { AssertLockHeld(cs_wallet); - if (pblock && !tx.HasZerocoinSpendInputs() && !tx.IsCoinBase()) { + if (pblock && !tx.IsCoinBase()) { for (const CTxIn& txin : tx.vin) { std::pair range = mapTxSpends.equal_range(txin.prevout); while (range.first != range.second) { @@ -1699,7 +1699,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b //If this is a zapwallettx, need to readd zphr if (fCheckZPHR && pindex->nHeight >= Params().Zerocoin_StartHeight()) { std::list listMints; - BlockToZerocoinMintList(block, listMints, true); + BlockToZerocoinMintList(block, listMints); CWalletDB walletdb(strWalletFile); for (auto& m : listMints) { if (IsMyMint(m.GetValue())) { @@ -5159,13 +5159,12 @@ CWallet::CWallet() CWallet::CWallet(std::string strWalletFileIn) { -SetNull(); - -strWalletFile = strWalletFileIn; -fFileBacked = true; + SetNull(); + strWalletFile = strWalletFileIn; + fFileBacked = true; } -~CWallet::CWallet() +CWallet::~CWallet() { delete pwalletdbEncryption; } @@ -5215,7 +5214,10 @@ void CWallet::setZWallet(CzPHRWallet* zwallet) zphrTracker = std::unique_ptr(new CzPHRTracker(strWalletFile)); } -CWallet::CzPHRWallet* getZWallet() { return zwalletMain; } +CzPHRWallet* CWallet::getZWallet() +{ + return zwalletMain; +} bool CWallet::isZeromintEnabled() @@ -5258,6 +5260,13 @@ isminetype CWallet::IsMine(const CTxOut& txout) const return ::IsMine(*this, txout.scriptPubKey); } +CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const +{ + if (!MoneyRange(txout.nValue)) + throw std::runtime_error("CWallet::GetCredit() : value out of range"); + return ((IsMine(txout) & filter) ? txout.nValue : 0); +} + CAmount CWallet::GetChange(const CTxOut& txout) const { if (!MoneyRange(txout.nValue)) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3d0bd8b91a42e..7dbca76eb4d54 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -321,6 +321,29 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool fCombineDust; CAmount nAutoCombineThreshold; + CWallet(); + + CWallet(std::string strWalletFileIn); + + ~CWallet(); + + void SetNull(); + + int getZeromintPercentage(); + + void setZWallet(CzPHRWallet* zwallet); + + CzPHRWallet* getZWallet(); + + + bool isZeromintEnabled(); + + void setZPhrAutoBackups(bool fEnabled); + + bool isMultiSendEnabled(); + + void setMultiSendDisabled(); + std::map mapWallet; std::list laccentries; From 01d28e1f2d978ef9efc520e5d7f6206155ebd893 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 9 Aug 2019 20:18:02 -0700 Subject: [PATCH 101/132] [Tests] Add RPC budget regression tests Adds new regression testing for the following RPC budget commands: - `preparebudget` - `submitbudget` - `getbudgetinfo` --- test/functional/rpc_budget.py | 97 +++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100755 test/functional/rpc_budget.py diff --git a/test/functional/rpc_budget.py b/test/functional/rpc_budget.py new file mode 100755 index 0000000000000..41041a5d9b0c9 --- /dev/null +++ b/test/functional/rpc_budget.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The PIVX developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test RPC commands for budget proposal creation, submission, and verification.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + + +class BudgetProposalTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + + def run_test(self): + budgetcycleblocks = 144 + nextsuperblock = self.nodes[0].getnextsuperblock() + address = self.nodes[0].getnewaddress() + scheme = 'http://' + url = 'test.com/url-with-length-of-57-characters-will-pass-00001' + longurl = 'test.com/url-with-length-of-58-characters-will-not-pass-01' + name = 'proposalwith20chars0' + longname = 'proposalwith21chars01' + numcycles = 2 + cycleamount = 100 + + self.log.info("Test with long name") + assert_raises_rpc_error(-8, "Invalid proposal name, limit of 20 characters.", self.nodes[0].preparebudget, + longname, scheme + url, numcycles, nextsuperblock, address, cycleamount) + + self.log.info("Test with long URL") + assert_raises_rpc_error(-8, "Invalid URL: 65 exceeds limit of 64 characters.", self.nodes[0].preparebudget, + name, scheme + longurl, numcycles, nextsuperblock, address, cycleamount) + + self.log.info("Test with invalid (0) cycles") + assert_raises_rpc_error(-8, "Invalid payment count, must be more than zero.", self.nodes[0].preparebudget, + name, scheme + url, 0, nextsuperblock, address, cycleamount) + + self.log.info("Test with invalid block start") + assert_raises_rpc_error(-8, "Invalid block start", self.nodes[0].preparebudget, + name, scheme + url, numcycles, nextsuperblock - 12, address, cycleamount) + assert_raises_rpc_error(-8, "Invalid block start", self.nodes[0].preparebudget, + name, scheme + url, numcycles, nextsuperblock - budgetcycleblocks, address, cycleamount) + + self.log.info("Test with invalid PIVX address") + assert_raises_rpc_error(-5, "Invalid PIVX address", self.nodes[0].preparebudget, + name, scheme + url, numcycles, nextsuperblock, "DBREvBPNQguwuC4YMoCG5FoH1sA2YntvZm", cycleamount) + + self.log.info("Test with too low amount") + assert_raises_rpc_error(-8, "Invalid amount - Payment of 9.00 is less than minimum 10 PIV allowed", self.nodes[0].preparebudget, + name, scheme + url, numcycles, nextsuperblock, address, 9) + + self.log.info("Test with too high amount") + assert_raises_rpc_error(-8, "Invalid amount - Payment of 648001.00 more than max of 648000.00", self.nodes[0].preparebudget, + name, scheme + url, numcycles, nextsuperblock, address, 648001) + + + self.log.info("Test without URL scheme") + scheme = '' + assert_raises_rpc_error(-8, "Invalid URL, check scheme (e.g. https://)", self.nodes[0].preparebudget, name, scheme + url, 1, nextsuperblock, address, 100) + + self.log.info('Test with invalid URL scheme: ftp://') + scheme = 'ftp://' + assert_raises_rpc_error(-8, "Invalid URL, check scheme (e.g. https://)", self.nodes[0].preparebudget, name, scheme + url, 1, nextsuperblock, address, 100) + + self.log.info("Test with invalid double character scheme: hhttps://") + scheme = 'hhttps://' + url = 'test.com' + assert_raises_rpc_error(-8, "Invalid URL, check scheme (e.g. https://)", self.nodes[0].preparebudget, name, scheme + url, 1, nextsuperblock, address, 100) + + self.log.info("Test with valid scheme: http://") + name = 'testvalid1' + scheme = 'http://' + feehashret = self.nodes[0].preparebudget(name, scheme + url, numcycles, nextsuperblock, address, cycleamount) + txinfo = self.nodes[0].gettransaction(feehashret) + assert_equal(txinfo['amount'], -50.00) + + self.log.info("Generate 7 blocks to confirm fee transaction") + self.nodes[0].generate(7) + + self.log.info("Submit the budget proposal") + submitret = self.nodes[0].submitbudget(name, scheme + url, numcycles, nextsuperblock, address, cycleamount, feehashret) + + self.log.info("Ensure that the budget proposal details are correct") + budgetinfo = self.nodes[0].getbudgetinfo(name)[0] + assert_equal(budgetinfo["Name"], name) + assert_equal(budgetinfo["URL"], scheme + url) + assert_equal(budgetinfo["Hash"], submitret) + assert_equal(budgetinfo["FeeHash"], feehashret) + assert_equal(budgetinfo["BlockStart"], nextsuperblock) + assert_equal(budgetinfo["PaymentAddress"], address) + assert_equal(budgetinfo["MonthlyPayment"], cycleamount) + assert_equal(budgetinfo["TotalPayment"], cycleamount * numcycles) + + +if __name__ == '__main__': + BudgetProposalTest().main() From 413caac10552b457fd066d98dc5202cbd6ffa5a4 Mon Sep 17 00:00:00 2001 From: furszy Date: Sun, 29 Sep 2019 21:34:12 -0300 Subject: [PATCH 102/132] [Wallet][Startup][DB][Backport] #10952 BTC back port. Named "Remove vchDefaultKey and have better first run detection". [Wallet][Startup][DB][Backport] Don't create any default address --- src/init.cpp | 5 ++--- src/wallet/crypter.h | 4 ++-- src/wallet/wallet.cpp | 16 ++++------------ src/wallet/wallet.h | 4 ---- src/wallet/walletdb.cpp | 19 +++++++++---------- src/wallet/walletdb.h | 2 -- 6 files changed, 17 insertions(+), 33 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 08be7a91ac195..a2b40fc88a9a7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1717,14 +1717,13 @@ bool AppInit2(const std::vector& words) // ensure this wallet.dat can only be opened by clients supporting HD pwalletMain->SetMinVersion(FEATURE_HD); } - CPubKey newDefaultKey; if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) { pwalletMain->SetDefaultKey(newDefaultKey); if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive")) return InitError(_("Cannot write default address") += "\n"); } - + pwalletMain->SetBestChain(chainActive.GetLocator()); } else if (mapArgs.count("-usehd")) { @@ -1740,7 +1739,7 @@ bool AppInit2(const std::vector& words) InitWarning(_("Make sure to encrypt your wallet and delete all non-encrypted backups after you verified that wallet works!")); } - LogPrintf("%s", strErrors.str()); + LogPrintf("Init errors: %s\n", strErrors.str()); LogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nWalletStartTime); zwalletMain = new CzPHRWallet(pwalletMain->strWalletFile); pwalletMain->setZWallet(zwalletMain); diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 4171750a779e4..d62a39740b48e 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -121,9 +121,7 @@ bool DecryptAES256(const SecureString& sKey, const std::string& sCiphertext, con class CCryptoKeyStore : public CBasicKeyStore { private: - CryptedKeyMap mapCryptedKeys; CHDChain cryptedHDChain; - CKeyingMaterial vMasterKey; //! if fUseCrypto is true, mapKeys must be empty @@ -144,6 +142,8 @@ class CCryptoKeyStore : public CBasicKeyStore bool SetCryptedHDChain(const CHDChain& chain); bool Unlock(const CKeyingMaterial& vMasterKeyIn); + CryptedKeyMap mapCryptedKeys; + public: CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 65c7494dbce24..e4e0ddc6bbf57 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2976,7 +2976,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { if (!fFileBacked) return DB_LOAD_OK; - fFirstRunRet = false; + DBErrors nLoadWalletRet = CWalletDB(strWalletFile, "cr+").LoadWallet(this); if (nLoadWalletRet == DB_NEED_REWRITE) { if (CDB::Rewrite(strWalletFile, "\x04pool")) { @@ -2988,9 +2988,11 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) } } + // This wallet is in its first run if all of these are empty + fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapMasterKeys.empty() && setWatchOnly.empty() && mapScripts.empty(); + if (nLoadWalletRet != DB_LOAD_OK) return nLoadWalletRet; - fFirstRunRet = !vchDefaultKey.IsValid(); uiInterface.LoadWallet(this); @@ -3062,16 +3064,6 @@ bool CWallet::DelAddressBook(const CTxDestination& address) return CWalletDB(strWalletFile).EraseName(EncodeDestination(address)); } -bool CWallet::SetDefaultKey(const CPubKey& vchPubKey) -{ - if (fFileBacked) { - if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey)) - return false; - } - vchDefaultKey = vchPubKey; - return true; -} - /** * Mark old keypool keys as used, * and generate all new keys diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7dbca76eb4d54..a0275f7a6dbd0 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -356,8 +356,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::map mapAddressBook; - CPubKey vchDefaultKey; - std::set setLockedCoins; int64_t nTimeFirstKey; @@ -565,8 +563,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface unsigned int GetKeyPoolSize(); - bool SetDefaultKey(const CPubKey& vchPubKey); - //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index b5192e53b69ab..361a004f601c6 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -234,12 +234,6 @@ bool CWalletDB::WriteAutoCombineSettings(bool fEnable, CAmount nCombineThreshold return Write(std::string("autocombinesettings"), pSettings, true); } -bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey) -{ - nWalletDBUpdated++; - return Write(std::string("defaultkey"), vchPubKey); -} - bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) { return Read(std::make_pair(std::string("pool"), nPool), keypool); @@ -593,7 +587,14 @@ bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CW (keyMeta.nCreateTime < pwallet->nTimeFirstKey)) pwallet->nTimeFirstKey = keyMeta.nCreateTime; } else if (strType == "defaultkey") { - ssValue >> pwallet->vchDefaultKey; + // We don't want or need the default key, but if there is one set, + // we want to make sure that it is valid so that we can detect corruption + CPubKey vchPubKey; + ssValue >> vchPubKey; + if (!vchPubKey.IsValid()) { + strErr = "Error reading wallet database: Default Key corrupt"; + return false; + } } else if (strType == "pool") { int64_t nIndex; ssKey >> nIndex; @@ -707,7 +708,6 @@ static bool IsKeyType(std::string strType) DBErrors CWalletDB::LoadWallet(CWallet* pwallet) { - pwallet->vchDefaultKey = CPubKey(); CWalletScanState wss; bool fNoncriticalErrors = false; DBErrors result = DB_LOAD_OK; @@ -745,7 +745,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) { // losing keys is considered a catastrophic error, anything else // we assume the user can live with: - if (IsKeyType(strType)) + if (IsKeyType(strType) || strType == "defaultkey") result = DB_CORRUPT; else { // Leave other errors alone, if we try to fix them we might make things worse. @@ -806,7 +806,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, std::vector& vTxHash, std::vector& vWtx) { - pwallet->vchDefaultKey = CPubKey(); bool fNoncriticalErrors = false; DBErrors result = DB_LOAD_OK; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 3dabff4d910b6..151d24a1173ca 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -170,8 +170,6 @@ class CWalletDB : public CDB bool EraseMSDisabledAddresses(std::vector vDisabledAddresses); bool WriteAutoCombineSettings(bool fEnable, CAmount nCombineThreshold); - bool WriteDefaultKey(const CPubKey& vchPubKey); - bool ReadPool(int64_t nPool, CKeyPool& keypool); bool WritePool(int64_t nPool, const CKeyPool& keypool); bool ErasePool(int64_t nPool); From b2df72beca2ec4428cd596fb969c0a7182d39766 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Sat, 12 Oct 2019 00:49:47 +0200 Subject: [PATCH 103/132] [Wallet] Fix inconsistencies with GetDepthInMainChain --- src/init.cpp | 2 +- src/qt/transactiondesc.cpp | 30 +++++++++++-------------- src/qt/transactionrecord.cpp | 43 +++++++++++++++++++++++++++++++----- src/qt/walletmodel.cpp | 10 +++++---- src/wallet/rpcwallet.cpp | 24 +++++++++++++------- src/wallet/wallet.cpp | 19 ++++++++++------ src/wallet/wallet.h | 2 ++ 7 files changed, 88 insertions(+), 42 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a2b40fc88a9a7..75e131bf3cabd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1723,7 +1723,7 @@ bool AppInit2(const std::vector& words) if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive")) return InitError(_("Cannot write default address") += "\n"); } - + pwalletMain->SetBestChain(chainActive.GetLocator()); } else if (mapArgs.count("-usehd")) { diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index ee018f1dd8a9d..51d99a28c701d 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -33,14 +33,19 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } else { - int signatures = wtx.GetTransactionLockSignatures(); + const int signatures = wtx.GetTransactionLockSignatures(); QString strUsingIX = ""; + bool fConflicted; + const int nDepth = wtx.GetDepthAndMempool(fConflicted); + + if (nDepth < 0 || fConflicted) + return tr("conflicted"); + + const bool isOffline = (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0); + if (signatures >= 0) { if (signatures >= SWIFTTX_SIGNATURES_REQUIRED) { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline (verified via SwiftX)").arg(nDepth); else if (nDepth < 6) return tr("%1/confirmed (verified via SwiftX)").arg(nDepth); @@ -48,20 +53,14 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) return tr("%1 confirmations (verified via SwiftX)").arg(nDepth); } else { if (!wtx.IsTransactionLockTimedOut()) { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline (SwiftX verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(SWIFTTX_SIGNATURES_TOTAL); else if (nDepth < 6) return tr("%1/confirmed (SwiftX verification in progress - %2 of %3 signatures )").arg(nDepth).arg(signatures).arg(SWIFTTX_SIGNATURES_TOTAL); else return tr("%1 confirmations (SwiftX verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(SWIFTTX_SIGNATURES_TOTAL); } else { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline (SwiftX verification failed)").arg(nDepth); else if (nDepth < 6) return tr("%1/confirmed (SwiftX verification failed)").arg(nDepth); @@ -70,10 +69,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) } } } else { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline").arg(nDepth); else if (nDepth < 6) return tr("%1/unconfirmed").arg(nDepth); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 46ac18e153c19..f21e6b9dd3229 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -309,8 +309,15 @@ void TransactionRecord::updateStatus(const CWalletTx& wtx) (wtx.IsCoinBase() ? 1 : 0), wtx.nTimeReceived, idx); - status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0); - status.depth = wtx.GetDepthInMainChain(); + //status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0); + bool fConflicted; + status.depth = wtx.GetDepthAndMempool(fConflicted); + const bool isOffline = (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0); + + //Determine the depth of the block + int nBlocksToMaturity = wtx.GetBlocksToMaturity(); + + status.countsForBalance = wtx.IsTrusted() && !(nBlocksToMaturity > 0); status.cur_num_blocks = chainActive.Height(); status.cur_num_ix_locks = nCompleteTXLocks; @@ -332,7 +339,7 @@ void TransactionRecord::updateStatus(const CWalletTx& wtx) status.matures_in = wtx.GetBlocksToMaturity(); // Check if the block was requested by anyone - if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) status.status = TransactionStatus::MaturesWarning; } else { status.status = TransactionStatus::NotAccepted; @@ -341,9 +348,9 @@ void TransactionRecord::updateStatus(const CWalletTx& wtx) status.status = TransactionStatus::Confirmed; } } else { - if (status.depth < 0) { + if (status.depth < 0 || fConflicted) { status.status = TransactionStatus::Conflicted; - } else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) { + } else if (isOffline) { status.status = TransactionStatus::Offline; } else if (status.depth == 0) { status.status = TransactionStatus::Unconfirmed; @@ -370,3 +377,29 @@ int TransactionRecord::getOutputIndex() const { return idx; } + + +std::string TransactionRecord::statusToString(){ + switch (status.status){ + case TransactionStatus::MaturesWarning: + return "Abandoned (not mature because no nodes have confirmed)"; + case TransactionStatus::Confirmed: + return "Confirmed"; + case TransactionStatus::OpenUntilDate: + return "OpenUntilDate"; + case TransactionStatus::OpenUntilBlock: + return "OpenUntilBlock"; + case TransactionStatus::Unconfirmed: + return "Unconfirmed"; + case TransactionStatus::Confirming: + return "Confirming"; + case TransactionStatus::Conflicted: + return "Conflicted"; + case TransactionStatus::Immature: + return "Immature"; + case TransactionStatus::NotAccepted: + return "Not Accepted"; + default: + return "No status"; + } +} diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 31ceb827b2c37..e35c7ed9f8f2b 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -673,8 +673,9 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect LOCK2(cs_main, wallet->cs_wallet); for (const COutPoint& outpoint : vOutpoints) { if (!wallet->mapWallet.count(outpoint.hash)) continue; - int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); - if (nDepth < 0) continue; + bool fConflicted; + const int nDepth = wallet->mapWallet[outpoint.hash].GetDepthAndMempool(fConflicted); + if (nDepth < 0 || fConflicted) continue; COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); vOutputs.push_back(out); } @@ -699,8 +700,9 @@ void WalletModel::listCoins(std::map >& mapCoins) // add locked coins for (const COutPoint& outpoint : vLockedCoins) { if (!wallet->mapWallet.count(outpoint.hash)) continue; - int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); - if (nDepth < 0) continue; + bool fConflicted; + int nDepth = wallet->mapWallet[outpoint.hash].GetDepthAndMempool(fConflicted); + if (nDepth < 0 || fConflicted) continue; COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); if (outpoint.n < out.tx->vout.size() && wallet->IsMine(out.tx->vout[outpoint.n]) == ISMINE_SPENDABLE) vCoins.push_back(out); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c8ada9fd5c9cd..e7b6e74906adc 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -646,13 +646,16 @@ CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, in // Tally wallet transactions for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) + bool fConflicted; + int depth = wtx.GetDepthAndMempool(fConflicted); + + if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || depth < 0 || fConflicted) continue; CAmount nReceived, nSent, nFee; wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); - if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) + if (nReceived != 0 && depth >= nMinDepth) nBalance += nReceived; nBalance -= nSent + nFee; } @@ -713,7 +716,10 @@ UniValue getbalance(const UniValue& params, bool fHelp) CAmount nBalance = 0; for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) + bool fConflicted; + int depth = wtx.GetDepthAndMempool(fConflicted); + + if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || depth < 0 || fConflicted) continue; CAmount allFee; @@ -721,7 +727,7 @@ UniValue getbalance(const UniValue& params, bool fHelp) std::list listReceived; std::list listSent; wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); - if (wtx.GetDepthInMainChain() >= nMinDepth) { + if (depth >= nMinDepth) { for (const COutputEntry& r : listReceived) nBalance += r.amount; } @@ -1352,7 +1358,8 @@ void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int n } // Received - if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) { + int depth = wtx.GetDepthInMainChain(); + if (listReceived.size() > 0 && depth >= nMinDepth) { for (const COutputEntry& r : listReceived) { std::string account; if (pwalletMain->mapAddressBook.count(r.destination)) @@ -1364,7 +1371,7 @@ void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int n entry.push_back(Pair("account", account)); MaybePushAddress(entry, r.destination); if (wtx.IsCoinBase()) { - if (wtx.GetDepthInMainChain() < 1) + if (depth < 1) entry.push_back(Pair("category", "orphan")); else if (wtx.GetBlocksToMaturity() > 0) entry.push_back(Pair("category", "immature")); @@ -1562,8 +1569,9 @@ UniValue listaccounts(const UniValue& params, bool fHelp) std::string strSentAccount; std::list listReceived; std::list listSent; - int nDepth = wtx.GetDepthInMainChain(); - if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0) + bool fConflicted; + int nDepth = wtx.GetDepthAndMempool(fConflicted); + if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0 || fConflicted) continue; wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly); mapAccountBalances[strSentAccount] -= nFee; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e4e0ddc6bbf57..10ef72f3a967e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1801,7 +1801,7 @@ bool CWalletTx::InMempool() const void CWalletTx::RelayWalletTransaction(std::string strCommand) { LOCK(cs_main); - if (!IsCoinBase()) { + if (!IsCoinBase() && !IsCoinStake()) { if (GetDepthInMainChain() == 0 && !isAbandoned()) { uint256 hash = GetHash(); LogPrintf("Relaying wtx %s\n", hash.ToString()); @@ -2084,11 +2084,6 @@ void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed, if (nDepth == 0 && !pcoin->InMempool()) continue; - // We should not consider coins which aren't at least in our mempool - // It's possible for these to be conflicted via ancestors which we may never be able to detect - if (nDepth == 0 && !pcoin->InMempool()) - continue; - for (unsigned int i = 0; i < pcoin->vout.size(); i++) { bool found = false; if (nCoinType == ONLY_DENOMINATED) { @@ -3284,7 +3279,10 @@ std::map CWallet::GetAddressBalances() if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) continue; - int nDepth = pcoin->GetDepthInMainChain(); + bool fConflicted; + int nDepth = pcoin->GetDepthAndMempool(fConflicted); + if (fConflicted) + continue; if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1)) continue; @@ -5422,6 +5420,13 @@ bool CWalletTx::IsTrusted() const return true; } +int CWalletTx::GetDepthAndMempool(bool& fConflicted, bool enableIX) const +{ + int ret = GetDepthInMainChain(enableIX); + fConflicted = (ret == 0 && !InMempool()); // not in chain nor in mempool + return ret; +} + void CWalletTx::MarkDirty() { fCreditCached = false; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a0275f7a6dbd0..4cf795cca36d9 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -845,6 +845,8 @@ class CWalletTx : public CMerkleTx void MarkDirty(); void BindWallet(CWallet* pwalletIn); + int GetDepthAndMempool(bool& fConflicted, bool enableIX = true) const; + //! filter decides which addresses will count towards the debit CAmount GetDebit(const isminefilter& filter) const; CAmount GetCredit(const isminefilter& filter) const; From 4921c7d79ead862a0f3298cf630f31edda169a92 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Tue, 15 Oct 2019 15:43:08 -0700 Subject: [PATCH 104/132] [TravisCI] Run CMake Tests earlier Move the two CMake build tests further up in the test order so we don't have to manually restart them due to caching/timeouts. --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9f02bef30f6ae..5bfe44a2f238a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,13 +37,14 @@ cache: - $HOME/.ccache stages: - lint - - test - cmake + - test + env: global: - MAKEJOBS=-j3 - RUN_UNIT_TESTS=true - - RUN_FUNCTIONAL_TESTS=false # Not Yet Implemented + - RUN_FUNCTIONAL_TESTS=false - RUN_BENCH=false # Set to true for any one job that has debug enabled, to quickly check bench is not crashing or hitting assertions - DOCKER_NAME_TAG=ubuntu:18.04 - BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID From 1e987291dca91601a886afa4aef3c6c0e2cc01ed Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Tue, 15 Oct 2019 15:50:47 -0700 Subject: [PATCH 105/132] Ensure we're building the GUI for all CI tests --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5bfe44a2f238a..44b9737f85a31 100644 --- a/.travis.yml +++ b/.travis.yml @@ -102,7 +102,7 @@ jobs: GOAL="install" # -Wno-psabi is to disable ABI warnings: "note: parameter passing for argument of type ... changed in GCC 7.1" # This could be removed once the ABI change warning does not show up by default - BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi" + BITCOIN_CONFIG="--with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi" - stage: test name: 'ARM 64-bit [GOAL:install] [no unit or functional tests]' @@ -112,7 +112,7 @@ jobs: RUN_UNIT_TESTS=false RUN_FUNCTIONAL_TESTS=false GOAL="install" - BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" + BITCOIN_CONFIG="--with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports" - stage: test name: 'Win32 [GOAL: deploy] [no functional tests]' @@ -122,7 +122,7 @@ jobs: PACKAGES="python3 nsis g++-mingw-w64-i686 wine-binfmt wine32" RUN_FUNCTIONAL_TESTS=false GOAL="deploy" - BITCOIN_CONFIG="--enable-reduce-exports" + BITCOIN_CONFIG="--with-gui=qt5 --enable-reduce-exports" - stage: test name: 'Win64 [GOAL: deploy] [no functional tests]' @@ -131,10 +131,10 @@ jobs: PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64" RUN_FUNCTIONAL_TESTS=false GOAL="deploy" - BITCOIN_CONFIG="--enable-reduce-exports" + BITCOIN_CONFIG="--with-gui=qt5 --enable-reduce-exports" - stage: test - name: '32-bit + dash [GOAL: install] [no gui]' + name: '32-bit + dash [GOAL: install]' env: >- HOST=i686-pc-linux-gnu PACKAGES="g++-multilib python3-zmq" From de63967bb04a7edd8a3c5d7798ecd55e22a83968 Mon Sep 17 00:00:00 2001 From: Warrows Date: Fri, 18 Oct 2019 15:02:05 +0200 Subject: [PATCH 106/132] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 44b9737f85a31..6d611f940e0cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,7 +67,7 @@ script: - export CONTINUE=1 - if [ $SECONDS -gt 1200 ]; then export CONTINUE=0; fi # Likely the depends build took very long - if [ $CONTINUE = "1" ]; then set -o errexit; source .travis/test_06_script_a.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi - - if [ -z ${BUILD_TIMEOUT+x} ] && [ $SECONDS -gt $BUILD_TIMEOUT ]; then export CONTINUE=0; fi + - if [ -n ${BUILD_TIMEOUT+x} ] && [ $SECONDS -gt $BUILD_TIMEOUT ]; then export CONTINUE=0; fi - if [ $SECONDS -gt 2000 ]; then export CONTINUE=0; fi # Likely the build took very long; The tests take about 1000s, so we should abort if we have less than 50*60-1000=2000s left - if [ $CONTINUE = "1" ]; then set -o errexit; source .travis/test_06_script_b.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi after_script: From 28d36d5f5bce1b630b4694dd4fa92cad5029d6ac Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 10 Jul 2019 12:14:35 +0200 Subject: [PATCH 107/132] [Core][Tests] REGTEST: fix nStakeModifier=0 --- src/kernel.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/kernel.cpp b/src/kernel.cpp index b8e894ae36686..a0b86c73af1e2 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -150,6 +150,11 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod { nStakeModifier = 0; fGeneratedStakeModifier = false; + + // modifier 0 on RegTest + if (Params().NetworkID() == CBaseChainParams::REGTEST) { + return true; + } if (!pindexPrev) { fGeneratedStakeModifier = true; return true; // genesis block's modifier is 0 @@ -244,6 +249,10 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifier, int& nStakeModifierHeight, int64_t& nStakeModifierTime, bool fPrintProofOfStake) { nStakeModifier = 0; + // modifier 0 on RegTest + if (Params().NetworkID() == CBaseChainParams::REGTEST) { + return true; + } if (!mapBlockIndex.count(hashBlockFrom)) return error("GetKernelStakeModifier() : block not indexed"); const CBlockIndex* pindexFrom = mapBlockIndex[hashBlockFrom]; From cf7e25370e5ce7347281094870f36cd60aa24966 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 16 Oct 2019 18:25:22 +0200 Subject: [PATCH 108/132] [Tests] Add wallet_reorg-stake functional test to check balances in a reorganization of PoS blocks, and verify that the input of an orphan block's coinstake is spendable after. --- test/functional/wallet_reorg-stake.py | 125 ++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100755 test/functional/wallet_reorg-stake.py diff --git a/test/functional/wallet_reorg-stake.py b/test/functional/wallet_reorg-stake.py new file mode 100755 index 0000000000000..9b98219b4d3f7 --- /dev/null +++ b/test/functional/wallet_reorg-stake.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The PIVX Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import sync_blocks, sync_mempools, connect_nodes_bi, \ + p2p_port, assert_equal, assert_raises_rpc_error +import urllib.parse + +class ReorgStakeTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 2 + self.setup_clean_chain = True + self.extra_args = [["-minrelaytxfee=0.00001"],[]] + + + def generateBatchBlocks(self, nodeid, limit, batch_size = 5): + i = 0 + while i < limit: + i += batch_size + if i <= limit: + self.nodes[nodeid].generate(batch_size) + else: + self.nodes[nodeid].generate(batch_size-i+limit) + + def findUtxoInList(self, txid, vout, utxo_list): + for x in utxo_list: + if x["txid"] == txid and x["vout"] == vout: + return True, x + return False, None + + + def run_test(self): + # NLAST_POW_BLOCK = 250 - so mine 125 blocks each node (25 consecutive blocks for 5 times) + NMATURITY = 100 + self.log.info("Mining 250 blocks (125 with node 0 and 125 with node 1)...") + for i in range(5): + self.generateBatchBlocks(0, 25) + sync_blocks(self.nodes) + self.generateBatchBlocks(1, 25) + sync_blocks(self.nodes) + sync_mempools(self.nodes) + + # Check balances + balance0 = self.nodes[0].getbalance() + balance1 = self.nodes[1].getbalance() + # Last two 25-blocks bursts (for each node) are not mature: NMATURITY = 2 * (2 * 25) + assert_equal(balance0, 250.0 * (125 - 50)) + assert_equal(balance1, 250.0 * (125 - 50)) + self.log.info("Balances check out (%d, %d)" % (balance0, balance1)) + initial_balance = balance0 + initial_unspent = self.nodes[0].listunspent() + + # PoS start reached (block 250) - disconnect nodes + self.nodes[0].disconnectnode(urllib.parse.urlparse(self.nodes[1].url).hostname + ":" + str(p2p_port(1))) + self.nodes[1].disconnectnode(urllib.parse.urlparse(self.nodes[0].url).hostname + ":" + str(p2p_port(0))) + self.log.info("Nodes disconnected") + + # Stake one block with node-0 and save the stake input + self.log.info("Staking 1 block with node 0...") + self.nodes[0].generate(1) + last_block = self.nodes[0].getblock(self.nodes[0].getbestblockhash()) + assert(len(last_block["tx"]) > 1) # a PoS block has at least two txes + coinstake_txid = last_block["tx"][1] + coinstake_tx = self.nodes[0].getrawtransaction(coinstake_txid, True) + assert(coinstake_tx["vout"][0]["scriptPubKey"]["hex"] == "") # first output of coinstake is empty + stakeinput = coinstake_tx["vin"][0] + + # The stake input was unspent 1 block ago, now it's not + res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], initial_unspent) + assert (res and utxo["spendable"]) + res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], self.nodes[0].listunspent()) + assert (not res or not utxo["spendable"]) + self.log.info("Coinstake input %s...%s-%d is no longer spendable." % ( + stakeinput["txid"][:9], stakeinput["txid"][-4:], stakeinput["vout"])) + + # Stake 10 more blocks with node-0 and check balances + self.log.info("Staking 10 more blocks with node 0...") + self.generateBatchBlocks(0, 10) + balance0 = initial_balance + 500 * 11 # mined blocks matured + staked blocks (250*11 + 250*11) + assert_equal(self.nodes[0].getbalance(), balance0) + self.log.info("Balance for node 0 checks out: %d" % balance0) + + # verify that the stakeinput can't be spent + rawtx_unsigned = self.nodes[0].createrawtransaction( + [{"txid": str(stakeinput["txid"]), "vout": int(stakeinput["vout"])}], + {"xxncEuJK27ygNh7imNfaX8JV6ZQUnoBqzN": 249.99}) + rawtx = self.nodes[0].signrawtransaction(rawtx_unsigned) + assert(rawtx["complete"]) + assert_raises_rpc_error(-25, "Missing inputs",self.nodes[0].sendrawtransaction, rawtx["hex"]) + + # Stake 12 blocks with node-1 + self.log.info("Staking 12 blocks with node 1...") + self.generateBatchBlocks(1, 12) + balance1 += 250 * 12 # staked blocks only (250*12) + assert_equal(self.nodes[1].getbalance(), balance1) + self.log.info("Balance for node 1 checks out: %d" % balance1) + new_best_hash = self.nodes[1].getbestblockhash() + + # re-connect and sync nodes and check that node-0 gets on the other chain + self.log.info("Connecting and syncing nodes...") + connect_nodes_bi(self.nodes, 0, 1) + sync_blocks(self.nodes) + assert_equal(self.nodes[0].getbestblockhash(), new_best_hash) + + # check balance of node-0 + balance0 = initial_balance + 250 * 12 # mined blocks matured (250*12) + assert_equal(self.nodes[0].getbalance(), balance0) # <--- !!! THIS FAILS + self.log.info("Balance for node 0 checks out: %d" % balance0) + + # check that NOW the original stakeinput is present and spendable + res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], self.nodes[0].listunspent()) + assert (res and utxo["spendable"]) # <--- !!! THIS FAILS + self.log.info("Coinstake input %s...%s-%d is spendable again." % ( + stakeinput["txid"][:9], stakeinput["txid"][-4:], stakeinput["vout"])) + self.nodes[0].sendrawtransaction(rawtx["hex"]) + self.nodes[1].generate(1) + sync_blocks(self.nodes) + res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], self.nodes[0].listunspent()) + assert (not res or not utxo["spendable"]) + + +if __name__ == '__main__': + ReorgStakeTest().main() \ No newline at end of file From 464b1015666aa1e1636827cb7601c2c4c644c257 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 16 Oct 2019 21:30:11 +0200 Subject: [PATCH 109/132] [Wallet] Fix bug with coinstake inputs wrongly marked as spent --- src/wallet/wallet.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 10ef72f3a967e..6b984d642ab09 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -596,8 +596,11 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const const uint256& wtxid = it->second; std::map::const_iterator mit = mapWallet.find(wtxid); if (mit != mapWallet.end()) { - int depth = mit->second.GetDepthInMainChain(); - if (depth > 0 || (depth == 0 && !mit->second.isAbandoned())) + bool fConflicted; + const int nDepth = mit->second.GetDepthAndMempool(fConflicted); + // not in mempool txes can spend coins only if not coinstakes + const bool fConflictedCoinstake = fConflicted && mit->second.IsCoinStake(); + if (nDepth > 0 || (nDepth == 0 && !mit->second.isAbandoned() && !fConflictedCoinstake) ) return true; // Spent } } From 1cbe3faaa9493a2a98d818e3cb08f67eac20e1c0 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Thu, 17 Oct 2019 00:08:45 +0200 Subject: [PATCH 110/132] [Tests] Add wallet_reorg-stake functional test to test_runner.py --- test/functional/wallet_reorg-stake.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/wallet_reorg-stake.py b/test/functional/wallet_reorg-stake.py index 9b98219b4d3f7..7dbdf028b0b2a 100755 --- a/test/functional/wallet_reorg-stake.py +++ b/test/functional/wallet_reorg-stake.py @@ -106,12 +106,12 @@ def run_test(self): # check balance of node-0 balance0 = initial_balance + 250 * 12 # mined blocks matured (250*12) - assert_equal(self.nodes[0].getbalance(), balance0) # <--- !!! THIS FAILS + assert_equal(self.nodes[0].getbalance(), balance0) # <--- !!! THIS FAILS before PR #1043 self.log.info("Balance for node 0 checks out: %d" % balance0) # check that NOW the original stakeinput is present and spendable res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], self.nodes[0].listunspent()) - assert (res and utxo["spendable"]) # <--- !!! THIS FAILS + assert (res and utxo["spendable"]) # <--- !!! THIS FAILS before PR #1043 self.log.info("Coinstake input %s...%s-%d is spendable again." % ( stakeinput["txid"][:9], stakeinput["txid"][-4:], stakeinput["vout"])) self.nodes[0].sendrawtransaction(rawtx["hex"]) From 9396f69a2473532f296504aa9272488591a597be Mon Sep 17 00:00:00 2001 From: random-zebra Date: Mon, 21 Oct 2019 02:04:23 +0200 Subject: [PATCH 111/132] [Core] Prevent coinstakes from overpaying masternodes --- src/masternode-payments.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index 5eb2a41e0876f..41db34c354e86 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -554,10 +554,11 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew) bool found = false; for (CTxOut out : txNew.vout) { if (payee.scriptPubKey == out.scriptPubKey) { - if(out.nValue >= requiredMasternodePayment) + if(out.nValue == requiredMasternodePayment) found = true; else - LogPrint("masternode","Masternode payment is out of drift range. Paid=%s Min=%s\n", FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str()); + LogPrintf("%s : Masternode payment value (%s) different from required value (%s).\n", + __func__, FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str()); } } From 8a2cdec0b1c44d766500e5f171c10d88d0f2ef06 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Mon, 21 Oct 2019 15:56:23 -0700 Subject: [PATCH 112/132] [CMake] Fix macOS Boost detection --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf7ed6c2dbc1c..6d167026fdcd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,8 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(ENV{CPPFLAGS} "-I${OPENSSL_ROOT_DIR}/include") set(ENV{LDFLAGS} "-L${OPENSSL_ROOT_DIR}/lib") set(BerkeleyDB_ROOT_DIR "/usr/local/Cellar/berkeley-db@4/${BDB_VER}/") + set(Boost_USE_MULTITHREADED ON) + set(Boost_NO_BOOST_CMAKE ON) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(ENV{target} "Linux") file(READ "/proc/version" _SYS_VERSION) From 12360ca3cd756e811784b6b5da5578cc47790251 Mon Sep 17 00:00:00 2001 From: furszy Date: Sat, 26 Oct 2019 12:11:40 -0300 Subject: [PATCH 113/132] [Wallet] Transaction IsEquivalentTo method backported + Duplicated mempool check code cleanup in IsTrusted method. Comes from bitcoin b2b361926215eadd6bf43ed1d7110b925fc7cae5 --- src/wallet/wallet.cpp | 39 ++++++++++++++++++++++++++------------- src/wallet/wallet.h | 3 +++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6b984d642ab09..5036220505427 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -557,20 +557,27 @@ void CWallet::SyncMetaData(std::pair ran // So: find smallest nOrderPos: int nMinOrderPos = std::numeric_limits::max(); - const CWalletTx* copyFrom = NULL; + const CWalletTx* copyFrom = nullptr; for (TxSpends::iterator it = range.first; it != range.second; ++it) { - const uint256& hash = it->second; - int n = mapWallet[hash].nOrderPos; + const CWalletTx* wtx = &mapWallet.at(it->second); + int n = wtx->nOrderPos; if (n < nMinOrderPos) { nMinOrderPos = n; - copyFrom = &mapWallet[hash]; + copyFrom = wtx; } } + + if (!copyFrom) { + return; + } + // Now copy data from copyFrom to rest: for (TxSpends::iterator it = range.first; it != range.second; ++it) { const uint256& hash = it->second; CWalletTx* copyTo = &mapWallet[hash]; if (copyFrom == copyTo) continue; + assert(copyFrom && "Oldest wallet transaction in range assumed to have been found."); + if (!copyFrom->IsEquivalentTo(*copyTo)) continue; copyTo->mapValue = copyFrom->mapValue; copyTo->vOrderForm = copyFrom->vOrderForm; // fTimeReceivedIsTxTime not copied on purpose @@ -5394,7 +5401,12 @@ bool CWalletTx::IsTrusted() const // Quick answer in most cases if (!IsFinalTx(*this)) return false; - int nDepth = GetDepthInMainChain(); + + bool fConflicted; + int nDepth = GetDepthAndMempool(fConflicted); + + if (fConflicted) // Don't trust unconfirmed transactions from us unless they are in the mempool. + return false; if (nDepth >= 1) return true; if (nDepth < 0) @@ -5402,14 +5414,6 @@ bool CWalletTx::IsTrusted() const if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit return false; - // Don't trust unconfirmed transactions from us unless they are in the mempool. - { - LOCK(mempool.cs); - if (!mempool.exists(GetHash())) { - return false; - } - } - // Trusted if all inputs are from us and are in the mempool: for (const CTxIn& txin : vin) { // Transactions not sent by us: not trusted @@ -5430,6 +5434,15 @@ int CWalletTx::GetDepthAndMempool(bool& fConflicted, bool enableIX) const return ret; } +bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const +{ + CMutableTransaction tx1 {*this}; + CMutableTransaction tx2 {_tx}; + for (auto& txin : tx1.vin) txin.scriptSig = CScript(); + for (auto& txin : tx2.vin) txin.scriptSig = CScript(); + return CTransaction(tx1) == CTransaction(tx2); +} + void CWalletTx::MarkDirty() { fCreditCached = false; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 4cf795cca36d9..ec03b12455d55 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -874,6 +874,9 @@ class CWalletTx : public CMerkleTx bool InMempool() const; + // True if only scriptSigs are different + bool IsEquivalentTo(const CWalletTx& tx) const; + bool IsTrusted() const; bool WriteToDisk(CWalletDB *pwalletdb); From 5d5e9e0ccff571ac246cf7bf7ee3b04c5394348c Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 30 Oct 2019 21:41:30 -0300 Subject: [PATCH 114/132] [UI] TransactionFilter, do not invalidate the filter if range is already set. --- src/qt/transactionfilterproxy.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 1ff098453b95b..767f35b576386 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -63,6 +63,8 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex& void TransactionFilterProxy::setDateRange(const QDateTime& from, const QDateTime& to) { + if (from == this->dateFrom && to == this->dateTo) + return; // No need to set the range. this->dateFrom = from; this->dateTo = to; invalidateFilter(); From ae5743f7899bb7c42c1995bddfd4d843d17613d3 Mon Sep 17 00:00:00 2001 From: furszy Date: Thu, 14 Nov 2019 18:41:25 -0300 Subject: [PATCH 115/132] [Spork] Guard chainActive.Tip() and chainActive.Height() methods call. --- src/spork.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/spork.cpp b/src/spork.cpp index 1795f82598bd5..5da7b9ae46dec 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -75,7 +75,15 @@ void CSporkManager::LoadSporksFromDB() void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { - if (fLiteMode || chainActive.Tip() == nullptr) return; // disable all obfuscation/masternode related functionality + if (fLiteMode) return; // disable all obfuscation/masternode related functionality + + int nChainHeight = 0; + { + LOCK(cs_main); + if (chainActive.Tip() == nullptr) + return; + nChainHeight = chainActive.Height(); + } if (strCommand == "spork") { @@ -101,20 +109,19 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr // spork is active if (mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned) { // spork in memory has been signed more recently - if (fDebug) LogPrintf("%s : seen %s block %d \n", __func__, hash.ToString(), chainActive.Tip()->nHeight); + if (fDebug) LogPrintf("%s : seen %s block %d \n", __func__, hash.ToString(), nChainHeight); return; } else { // update active spork - if (fDebug) LogPrintf("%s : got updated spork %s block %d \n", __func__, hash.ToString(), chainActive.Tip()->nHeight); + if (fDebug) LogPrintf("%s : got updated spork %s block %d \n", __func__, hash.ToString(), nChainHeight); } } else { // spork is not active - if (fDebug) LogPrintf("%s : got new spork %s block %d \n", __func__, hash.ToString(), chainActive.Tip()->nHeight); + if (fDebug) LogPrintf("%s : got new spork %s block %d \n", __func__, hash.ToString(), nChainHeight); } } - LogPrintf("spork - new %s ID %d Time %d bestHeight %d\n", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Tip()->nHeight); - + LogPrintf("%s : new %s ID %d Time %d bestHeight %d\n", __func__, hash.ToString(), spork.nSporkID, spork.nValue, nChainHeight); if (!spork.CheckSignature()) { LOCK(cs_main); LogPrintf("%s : Invalid Signature\n", __func__); From d613a1252d4f1fe97dac713040463e870605954c Mon Sep 17 00:00:00 2001 From: random-zebra Date: Mon, 28 Oct 2019 15:04:58 +0100 Subject: [PATCH 116/132] [Wallet][RPC] Lock/UnlockCoin const argument + checks in lockunspent - qualify as constants the arguments of CWallet's functions: IsLockedCoin, LockCoin and UnlockCoin. - Diagnose unsuitable outputs in lockunspent (backports bitcoin/bitcoin #11087) --- src/wallet/rpcwallet.cpp | 59 ++++++++++++++++++++++++++++++++-------- src/wallet/wallet.cpp | 8 +++--- src/wallet/wallet.h | 6 ++-- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e7b6e74906adc..207e8a543f4a2 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2085,29 +2085,64 @@ UniValue lockunspent(const UniValue& params, bool fHelp) return true; } - UniValue outputs = params[1].get_array(); - for (unsigned int idx = 0; idx < outputs.size(); idx++) { - const UniValue& output = outputs[idx]; + UniValue output_params = params[1].get_array(); + + // Create and validate the COutPoints first. + std::vector outputs; + outputs.reserve(output_params.size()); + + for (unsigned int idx = 0; idx < output_params.size(); idx++) { + const UniValue& output = output_params[idx]; if (!output.isObject()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object"); const UniValue& o = output.get_obj(); RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)); - std::string txid = find_value(o, "txid").get_str(); - if (!IsHex(txid)) + const std::string& txid = find_value(o, "txid").get_str(); + if (!IsHex(txid)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid"); + } - int nOutput = find_value(o, "vout").get_int(); - if (nOutput < 0) + const int nOutput = find_value(o, "vout").get_int(); + if (nOutput < 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); + } - COutPoint outpt(uint256(txid), nOutput); + const COutPoint outpt(uint256(txid), nOutput); - if (fUnlock) - pwalletMain->UnlockCoin(outpt); - else - pwalletMain->LockCoin(outpt); + const auto it = pwalletMain->mapWallet.find(outpt.hash); + if (it == pwalletMain->mapWallet.end()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, unknown transaction"); + } + + const CWalletTx& wtx = it->second; + + if (outpt.n >= wtx.vout.size()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds"); + } + + if (pwalletMain->IsSpent(outpt.hash, outpt.n)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output"); + } + + const bool is_locked = pwalletMain->IsLockedCoin(outpt.hash, outpt.n); + + if (fUnlock && !is_locked) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected locked output"); + } + + if (!fUnlock && is_locked) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output already locked"); + } + + outputs.push_back(outpt); + } + + // Atomically set (un)locked status for the outputs. + for (const COutPoint& outpt : outputs) { + if (fUnlock) pwalletMain->UnlockCoin(outpt); + else pwalletMain->LockCoin(outpt); } return true; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5036220505427..f2fe4fea12d85 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3486,13 +3486,13 @@ bool CWallet::UpdatedTransaction(const uint256& hashTx) return false; } -void CWallet::LockCoin(COutPoint& output) +void CWallet::LockCoin(const COutPoint& output) { AssertLockHeld(cs_wallet); // setLockedCoins setLockedCoins.insert(output); } -void CWallet::UnlockCoin(COutPoint& output) +void CWallet::UnlockCoin(const COutPoint& output) { AssertLockHeld(cs_wallet); // setLockedCoins setLockedCoins.erase(output); @@ -3504,10 +3504,10 @@ void CWallet::UnlockAllCoins() setLockedCoins.clear(); } -bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const +bool CWallet::IsLockedCoin(const uint256& hash, unsigned int n) const { AssertLockHeld(cs_wallet); // setLockedCoins - COutPoint outpt(hash, n); + const COutPoint outpt(hash, n); return (setLockedCoins.count(outpt) > 0); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ec03b12455d55..8866bb2309027 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -378,9 +378,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool IsSpent(const uint256& hash, unsigned int n) const; - bool IsLockedCoin(uint256 hash, unsigned int n) const; - void LockCoin(COutPoint& output); - void UnlockCoin(COutPoint& output); + bool IsLockedCoin(const uint256& hash, unsigned int n) const; + void LockCoin(const COutPoint& output); + void UnlockCoin(const COutPoint& output); void UnlockAllCoins(); void ListLockedCoins(std::vector& vOutpts); From 334d851843d912cea7e86c7d376eb38d93442a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 25 May 2018 14:27:58 +0100 Subject: [PATCH 117/132] wallet: Unlock spent outputs --- src/wallet/wallet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f2fe4fea12d85..339b28d5e6ee0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -617,6 +617,8 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid) { mapTxSpends.insert(std::make_pair(outpoint, wtxid)); + setLockedCoins.erase(outpoint); + std::pair range; range = mapTxSpends.equal_range(outpoint); SyncMetaData(range); From e5002d54cac777468e0469f93bcaee4f44d0b6cf Mon Sep 17 00:00:00 2001 From: furszy Date: Sat, 9 Nov 2019 12:19:20 -0300 Subject: [PATCH 118/132] [Masterndoes] Masternodes sync, try locking cs_main when it looks for the tip, preventing possible multi-threading shared resource problem. Remove duplicated tip check. --- src/masternode-sync.cpp | 21 +++++++++++---------- src/obfuscation.cpp | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index 242e95feedcee..df295136f26f5 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -45,14 +45,18 @@ bool CMasternodeSync::IsBlockchainSynced() if (fImporting || fReindex) return false; - TRY_LOCK(cs_main, lockMain); - if (!lockMain) return false; + int64_t blockTime = 0; + { + TRY_LOCK(cs_main, lockMain); + if (!lockMain) return false; - CBlockIndex* pindex = chainActive.Tip(); - if (pindex == NULL) return false; + CBlockIndex *pindex = chainActive.Tip(); + if (pindex == NULL) return false; + blockTime = pindex->nTime; + } - if (pindex->nTime + 60 * 60 < GetTime()) + if (blockTime + 60 * 60 < lastProcess) return false; fBlockchainSynced = true; @@ -310,7 +314,7 @@ void CMasternodeSync::Process() if (lastMasternodeList == 0 && (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3 || GetTime() - nAssetSyncStarted > MASTERNODE_SYNC_TIMEOUT * 5)) { if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { - LogPrintf("CMasternodeSync::Process - ERROR - Sync has failed, will retry later\n"); + LogPrintf("CMasternodeSync::Process - ERROR - Sync has failed on %s, will retry later\n", "MASTERNODE_SYNC_LIST"); RequestedMasternodeAssets = MASTERNODE_SYNC_FAILED; RequestedMasternodeAttempt = 0; lastFailure = GetTime(); @@ -341,7 +345,7 @@ void CMasternodeSync::Process() if (lastMasternodeWinner == 0 && (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3 || GetTime() - nAssetSyncStarted > MASTERNODE_SYNC_TIMEOUT * 5)) { if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { - LogPrintf("CMasternodeSync::Process - ERROR - Sync has failed, will retry later\n"); + LogPrintf("CMasternodeSync::Process - ERROR - Sync has failed on %s, will retry later\n", "MASTERNODE_SYNC_MNW"); RequestedMasternodeAssets = MASTERNODE_SYNC_FAILED; RequestedMasternodeAttempt = 0; lastFailure = GetTime(); @@ -354,9 +358,6 @@ void CMasternodeSync::Process() if (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3) return; - CBlockIndex* pindexPrev = chainActive.Tip(); - if (pindexPrev == NULL) return; - int nMnCount = mnodeman.CountEnabled(); pnode->PushMessage(NetMsgType::MNGET, nMnCount); //sync payees RequestedMasternodeAttempt++; diff --git a/src/obfuscation.cpp b/src/obfuscation.cpp index d2d5b0f886f93..6f944df5e9ada 100644 --- a/src/obfuscation.cpp +++ b/src/obfuscation.cpp @@ -666,7 +666,7 @@ void ThreadCheckObfuScationPool() // Make this thread recognisable as the wallet flushing thread RenameThread("phore-obfuscation"); - + LogPrintf("Masternodes thread started\n"); unsigned int c = 0; while (true) { From 22949e2178fb2c1e6027dc92027d0db62b49d7f9 Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 12 Nov 2019 12:27:50 -0300 Subject: [PATCH 119/132] [Masternodes] Reset mn sync process if it's sleep. --- src/masternode-sync.cpp | 13 ++++++------- src/masternode-sync.h | 3 +++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index df295136f26f5..bbf66909160d9 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -31,15 +31,14 @@ bool CMasternodeSync::IsSynced() bool CMasternodeSync::IsBlockchainSynced() { - static bool fBlockchainSynced = false; - static int64_t lastProcess = GetTime(); + int64_t now = GetTime(); // if the last call to this function was more than 60 minutes ago (client was in sleep mode) reset the sync process - if (GetTime() - lastProcess > 60 * 60) { + if (now > lastProcess + 60 * 60) { Reset(); fBlockchainSynced = false; } - lastProcess = GetTime(); + lastProcess = now; if (fBlockchainSynced) return true; @@ -49,10 +48,8 @@ bool CMasternodeSync::IsBlockchainSynced() { TRY_LOCK(cs_main, lockMain); if (!lockMain) return false; - CBlockIndex *pindex = chainActive.Tip(); - if (pindex == NULL) return false; - + if (pindex == nullptr) return false; blockTime = pindex->nTime; } @@ -66,6 +63,8 @@ bool CMasternodeSync::IsBlockchainSynced() void CMasternodeSync::Reset() { + fBlockchainSynced = false; + lastProcess = 0; lastMasternodeList = 0; lastMasternodeWinner = 0; lastBudgetItem = 0; diff --git a/src/masternode-sync.h b/src/masternode-sync.h index f81f207fe4897..ea7f2e7c1719d 100644 --- a/src/masternode-sync.h +++ b/src/masternode-sync.h @@ -39,6 +39,9 @@ class CMasternodeSync int64_t lastFailure; int nCountFailures; + std::atomic lastProcess; + std::atomic fBlockchainSynced; + // sum of all counts int sumMasternodeList; int sumMasternodeWinner; From 00ff68d974c18b86edf5f2becaa9fa01c188d373 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sun, 28 Oct 2018 21:35:52 +0800 Subject: [PATCH 120/132] gui: explicitly disable "Dark Mode" appearance on macOS --- share/qt/Info.plist.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index 95d1361810a0f..e7d68932f1dfb 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -3,7 +3,7 @@ LSMinimumSystemVersion - 10.8.0 + 10.10.0 LSArchitecturePriority @@ -100,6 +100,9 @@ LSAppNapIsDisabled True + NSRequiresAquaSystemAppearance + True + LSApplicationCategoryType public.app-category.finance From 487f2641616b9d5a702fb066abcbf1fa7b6a4127 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Tue, 30 Oct 2018 12:06:01 -0400 Subject: [PATCH 121/132] build: if VERSION_BUILD is non-zero, include it in the package version When the build number (CLIENT_VERSION_BUILD) is non-zero, we want to include that in the package version number so the resulting binaries are named with the correct version. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cb2eb6d6168c4..e5649bbaa3398 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ define(_CLIENT_VERSION_REVISION, 3) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2019) -AC_INIT([Phore Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[www.phore.io],[phore]) +AC_INIT([Phore Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_REVISION, m4_if(_CLIENT_VERSION_BUILD, [0], [], _CLIENT_VERSION_BUILD)),[https://github.com/https://github.com/phoreproject/Phore/issues],[phore],[https://phore.io/]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/phore-config.h]) AC_CONFIG_AUX_DIR([build-aux]) From c98f3e41c39977181c5de1f769f3187278285e07 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Tue, 30 Oct 2018 14:54:18 -0400 Subject: [PATCH 122/132] build: include rc number in version number --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e5649bbaa3398..b9661a2ad1e32 100644 --- a/configure.ac +++ b/configure.ac @@ -4,9 +4,10 @@ define(_CLIENT_VERSION_MAJOR, 1) define(_CLIENT_VERSION_MINOR, 6) define(_CLIENT_VERSION_REVISION, 3) define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_RC, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2019) -AC_INIT([Phore Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_REVISION, m4_if(_CLIENT_VERSION_BUILD, [0], [], _CLIENT_VERSION_BUILD)),[https://github.com/https://github.com/phoreproject/Phore/issues],[phore],[https://phore.io/]) +AC_INIT([Phore Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_REVISION, m4_if(_CLIENT_VERSION_BUILD, [0], [], _CLIENT_VERSION_BUILD))m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/phoreproject/Phore/issues],[phore],[https://phore.io/]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/phore-config.h]) AC_CONFIG_AUX_DIR([build-aux]) From 792e542614e7b95adc69d1926c7d6de4d09a238e Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Thu, 1 Nov 2018 11:32:18 -0400 Subject: [PATCH 123/132] Update release-process.md to include RC version bumping --- doc/release-process.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 4543b39a5803d..aea7e6fd24d80 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -1,13 +1,12 @@ Release Process ==================== -Before every release candidate: +### Before every release candidate * Update translations (ping Fuzzbawls on Slack) see [translation_process.md](https://github.com/phoreproject/Phore/blob/master/doc/translation_process.md#synchronising-translations). -Before every minor and major release: - -* Update version in `configure.ac` (don't forget to set `CLIENT_VERSION_IS_RELEASE` to `true`) +* Update release candidate version in `configure.ac` (`CLIENT_VERSION_RC`) +* Update version in `configure.ac` (don't forget to set `CLIENT_VERSION_IS_RELEASE` to `true`) (don't forget to set `CLIENT_VERSION_RC` to `0`) * Write release notes (see below) Before every major release: From 3227c93e5359a274d45cb7e98d72c100aec6a0e4 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 10 Nov 2018 13:50:19 +0800 Subject: [PATCH 124/132] build: Add CLIENT_VERSION_BUILD to CFBundleGetInfoString --- share/qt/Info.plist.in | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index e7d68932f1dfb..2beda514e8549 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -17,8 +17,7 @@ APPL CFBundleGetInfoString - @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@, Copyright © 2009-@COPYRIGHT_YEAR@ The Bitcoin Core developers, 2014-@COPYRIGHT_YEAR@ The Dash Core developers, 2015-@COPYRIGHT_YEAR@ The PIVX Core developers, 2017-@COPYRIGHT_YEAR@ The Phore Developers - + @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ The Bitcoin Core developers, 2014-@COPYRIGHT_YEAR@ The Dash Core developers, 2015-@COPYRIGHT_YEAR@ The PIVX Core developers, 2017-@COPYRIGHT_YEAR@ The Phore Developers CFBundleShortVersionString @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@ @@ -30,7 +29,6 @@ CFBundleExecutable Phore-Qt - CFBundleName Phore-Qt From 738635f8e088344639390c9c8dfc3ed47f93c94b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 6 Mar 2019 12:32:33 -0500 Subject: [PATCH 125/132] build: use full version string in setup.exe --- share/setup.nsi.in | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/share/setup.nsi.in b/share/setup.nsi.in index e7c627ddbb234..53c7d8d2ed6cd 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -5,7 +5,6 @@ SetCompressor /SOLID lzma # General Symbol Definitions !define REGKEY "SOFTWARE\$(^Name)" -!define VERSION @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@ !define COMPANY "@PACKAGE_NAME@ project" !define URL https://www.phore.org @@ -49,7 +48,7 @@ Var StartMenuGroup !insertmacro MUI_LANGUAGE English # Installer attributes -OutFile @abs_top_srcdir@/@PACKAGE_TARNAME@-${VERSION}-win@WINDOWS_BITS@-setup.exe +OutFile @abs_top_srcdir@/@PACKAGE_TARNAME@-@PACKAGE_VERSION@-win@WINDOWS_BITS@-setup.exe !if "@WINDOWS_BITS@" == "64" InstallDir $PROGRAMFILES64\Phore !else @@ -59,12 +58,12 @@ CRCCheck on XPStyle on BrandingText " " ShowInstDetails show -VIProductVersion ${VERSION}.@CLIENT_VERSION_BUILD@ +VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@ VIAddVersionKey ProductName "@PACKAGE_NAME@" -VIAddVersionKey ProductVersion "${VERSION}" +VIAddVersionKey ProductVersion "@PACKAGE_VERSION@" VIAddVersionKey CompanyName "${COMPANY}" VIAddVersionKey CompanyWebsite "${URL}" -VIAddVersionKey FileVersion "${VERSION}" +VIAddVersionKey FileVersion "@PACKAGE_VERSION@" VIAddVersionKey FileDescription "" VIAddVersionKey LegalCopyright "" InstallDirRegKey HKCU "${REGKEY}" Path @@ -97,7 +96,7 @@ Section -post SEC0001 CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe !insertmacro MUI_STARTMENU_WRITE_END WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "@PACKAGE_VERSION@" WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}" WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}" WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe From 713eb6db7e7e19a9cd9f6ba97bccec2f4d180371 Mon Sep 17 00:00:00 2001 From: Kolby Moroz <31669092+mrmetech@users.noreply.github.com> Date: Sun, 5 Apr 2020 11:23:58 -0700 Subject: [PATCH 126/132] Some fixes --- src/init.cpp | 9 +++++---- src/qt/transactionrecord.h | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 75e131bf3cabd..669b920f5c359 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1718,10 +1718,11 @@ bool AppInit2(const std::vector& words) pwalletMain->SetMinVersion(FEATURE_HD); } CPubKey newDefaultKey; - if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) { - pwalletMain->SetDefaultKey(newDefaultKey); - if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive")) - return InitError(_("Cannot write default address") += "\n"); + // Top up the keypool + if (!pwalletMain->TopUpKeyPool()) { + // Error generating keys + InitError(_("Unable to generate initial key") += "\n"); + return error("%s %s", __func__ , "Unable to generate initial key"); } pwalletMain->SetBestChain(chainActive.GetLocator()); diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index a26a2a3b01bb9..ff9c67e39dee3 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -145,6 +145,10 @@ class TransactionRecord */ void updateStatus(const CWalletTx& wtx); + /** Return transaction status + */ + std::string statusToString(); + /** Return whether a status update is needed. */ bool statusUpdateNeeded(); From 545338db9ac9b7491400b25875eced4d216c3838 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Tue, 19 May 2020 18:47:57 -0600 Subject: [PATCH 127/132] Update init.cpp --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 669b920f5c359..88acff5a015ae 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1457,7 +1457,7 @@ bool AppInit2(const std::vector& words) if (fReindex) pblocktree->WriteReindexing(true); - + // End loop if shutdown was requested if (ShutdownRequested()) break; From fb5c45d13128d8538b6692c192440a997aebeed6 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Tue, 19 May 2020 18:48:43 -0600 Subject: [PATCH 128/132] Update benchmark_zerocoin.cpp --- src/test/benchmark_zerocoin.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/test/benchmark_zerocoin.cpp b/src/test/benchmark_zerocoin.cpp index c5c9f15127f4c..901d5ae52085b 100644 --- a/src/test/benchmark_zerocoin.cpp +++ b/src/test/benchmark_zerocoin.cpp @@ -184,12 +184,12 @@ Testb_GenerateGroupParams() for (count = 0; count < 1; count++) { - try { - group = deriveIntegerGroupParams(calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (const std::runtime_error& e) { - cout << "Caught exception " << e.what() << endl; - return false; - } + try { + group = deriveIntegerGroupParams(calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); + } catch (const std::runtime_error& e) { + cout << "Caught exception " << e.what() << endl; + return false; + } // Now perform some simple tests on the resulting parameters if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { @@ -219,11 +219,11 @@ Testb_ParamGen() ZerocoinParams testParams(gGetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); timer.stop(); - cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - } catch (const std::runtime_error& e) { - cout << e.what() << endl; - result = false; - } + cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; + } catch (const std::runtime_error& e) { + cout << e.what() << endl; + result = false; + } return result; } From 75e50c3ce1d98d34380583faa40cbb5dd0a1a03a Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Tue, 19 May 2020 19:56:08 -0600 Subject: [PATCH 129/132] Update masternode-budget.cpp --- src/rpc/masternode-budget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/masternode-budget.cpp b/src/rpc/masternode-budget.cpp index 016385ed84dce..c99fcb6772863 100644 --- a/src/rpc/masternode-budget.cpp +++ b/src/rpc/masternode-budget.cpp @@ -126,7 +126,7 @@ UniValue preparebudget(const UniValue& params, bool fHelp) CTxDestination address; CAmount nAmount; - checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, nAmount); + checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, address, nAmount); // Parse Phore address CScript scriptPubKey = GetScriptForDestination(address); @@ -187,7 +187,7 @@ UniValue submitbudget(const UniValue& params, bool fHelp) CTxDestination address; CAmount nAmount; - checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, nAmount); + checkBudgetInputs(params, strProposalName, strURL, nPaymentCount, nBlockStart, address, nAmount); // Parse Phore address CScript scriptPubKey = GetScriptForDestination(address); From bb34701b4d67010076c416814261d73c39eb4a67 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Tue, 19 May 2020 20:37:55 -0600 Subject: [PATCH 130/132] Update optionsmodel.cpp --- src/qt/optionsmodel.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 1ceccbc4d1e96..7c61a0b374ceb 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -93,6 +93,11 @@ void OptionsModel::Init() settings.setValue("nPreferredDenom", 0); nPreferredDenom = settings.value("nPreferredDenom", "0").toLongLong(); + if (!settings.contains("nAnonymizePhoreAmount")) + settings.setValue("nAnonymizePhoreAmount", 1000); + + nAnonymizePhoreAmount = settings.value("nAnonymizePhoreAmount").toLongLong(); + if (!settings.contains("fShowMasternodesTab")) settings.setValue("fShowMasternodesTab", masternodeConfig.getCount()); @@ -259,6 +264,8 @@ QVariant OptionsModel::data(const QModelIndex& index, int role) const return QVariant(nZeromintPercentage); case ZeromintPrefDenom: return QVariant(nPreferredDenom); + case AnonymizePhoreAmount: + return QVariant(nAnonymizePhoreAmount); case Listen: return settings.value("fListen"); default: From aed099e5c9df11d88044a51290b092ddfe7ae625 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Date: Tue, 19 May 2020 21:19:14 -0600 Subject: [PATCH 131/132] f --- src/qt/optionsmodel.cpp | 15 --------------- src/qt/optionsmodel.h | 2 -- 2 files changed, 17 deletions(-) diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 7c61a0b374ceb..81392e687622b 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -93,11 +93,6 @@ void OptionsModel::Init() settings.setValue("nPreferredDenom", 0); nPreferredDenom = settings.value("nPreferredDenom", "0").toLongLong(); - if (!settings.contains("nAnonymizePhoreAmount")) - settings.setValue("nAnonymizePhoreAmount", 1000); - - nAnonymizePhoreAmount = settings.value("nAnonymizePhoreAmount").toLongLong(); - if (!settings.contains("fShowMasternodesTab")) settings.setValue("fShowMasternodesTab", masternodeConfig.getCount()); @@ -170,9 +165,6 @@ void OptionsModel::Init() SoftSetArg("-zeromintpercentage", settings.value("nZeromintPercentage").toString().toStdString()); if (settings.contains("nPreferredDenom")) SoftSetArg("-preferredDenom", settings.value("nPreferredDenom").toString().toStdString()); - if (settings.contains("nAnonymizePhoreAmount")) - SoftSetArg("-anonymizephoreamount", settings.value("nAnonymizePhoreAmount").toString().toStdString()); - language = settings.value("language").toString(); } @@ -264,8 +256,6 @@ QVariant OptionsModel::data(const QModelIndex& index, int role) const return QVariant(nZeromintPercentage); case ZeromintPrefDenom: return QVariant(nPreferredDenom); - case AnonymizePhoreAmount: - return QVariant(nAnonymizePhoreAmount); case Listen: return settings.value("fListen"); default: @@ -398,11 +388,6 @@ bool OptionsModel::setData(const QModelIndex& index, const QVariant& value, int settings.setValue("fHideOrphans", fHideOrphans); emit hideOrphansChanged(fHideOrphans); break; - case AnonymizePhoreAmount: - nAnonymizePhoreAmount = value.toInt(); - settings.setValue("nAnonymizePhoreAmount", nAnonymizePhoreAmount); - emit anonymizePhoreAmountChanged(nAnonymizePhoreAmount); - break; case CoinControlFeatures: fCoinControlFeatures = value.toBool(); settings.setValue("fCoinControlFeatures", fCoinControlFeatures); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 55a9fb989020e..5892f07189216 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -48,7 +48,6 @@ class OptionsModel : public QAbstractListModel ZeromintPrefDenom, // int HideZeroBalances, // bool HideOrphans, // bool - AnonymizePhoreAmount, //int ShowMasternodesTab, // bool Listen, // bool StakeSplitThreshold, // int @@ -101,7 +100,6 @@ class OptionsModel : public QAbstractListModel void zeromintEnableChanged(bool); void zeromintPercentageChanged(int); void preferredDenomChanged(int); - void anonymizePhoreAmountChanged(int); void coinControlFeaturesChanged(bool); void hideZeroBalancesChanged(bool); void hideOrphansChanged(bool); From 799f1917d0cf79147c82d49d5b55162c407b365f Mon Sep 17 00:00:00 2001 From: wqking Date: Thu, 11 Nov 2021 09:26:34 +0800 Subject: [PATCH 132/132] Fixed compile errors --- src/kernel.cpp | 2 +- src/masternode.cpp | 24 +++++++++++++++++------- src/qt/walletview.cpp | 8 -------- src/sporkid.h | 1 + 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/kernel.cpp b/src/kernel.cpp index 2f83a6300c405..d2c8995f89bce 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -484,7 +484,7 @@ bool CheckProofOfStake(const CBlock block, uint256& hashProofOfStake, std::uniqu if (!pindexfrom) return error("%s: Failed to find the block index for stake origin", __func__); - if(GetSporkValue(SPORK_20_KERNEL_EXTRA_STAKING_CHECK) >= pindexfrom->nHeight) { + if(sporkManager.GetSporkValue(SPORK_20_KERNEL_EXTRA_STAKING_CHECK) >= pindexfrom->nHeight) { const CTxIn& txin = tx.vin[0]; uint256 hashBlock; CTransaction txPrev; diff --git a/src/masternode.cpp b/src/masternode.cpp index 6ad81cdf4b9af..abf0a3d41b251 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -699,14 +699,24 @@ bool CMasternodeBroadcast::VerifySignature() return true; } -std::string CMasternodeBroadcast::GetStrMessage() +std::string CMasternodeBroadcast::GetOldStrMessage() { - return (addr.ToString() + - std::to_string(sigTime) + - pubKeyCollateralAddress.GetID().ToString() + - pubKeyMasternode.GetID().ToString() + - std::to_string(protocolVersion) - ); + std::string strMessage; + + std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); + std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); + strMessage = addr.ToString() + std::to_string(sigTime) + vchPubKey + vchPubKey2 + std::to_string(protocolVersion); + + return strMessage; +} + +std::string CMasternodeBroadcast::GetNewStrMessage() +{ + std::string strMessage; + + strMessage = addr.ToString() + std::to_string(sigTime) + pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() + std::to_string(protocolVersion); + + return strMessage; } CMasternodePing::CMasternodePing() diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index fa13d4560bf7a..b45caa70f58ad 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -136,14 +136,6 @@ WalletView::WalletView(QWidget* parent) : QStackedWidget(parent), addWidget(masternodeListPage); } - QVBoxLayout* vbox_2 = new QVBoxLayout(); - proposalList = new ProposalList(this); - vbox_2->addWidget(proposalList); - vbox_2->setStretch(1, 1); - proposalListPage = new QWidget(this); - proposalListPage->setLayout(vbox_2); - addWidget(proposalListPage); - // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex))); diff --git a/src/sporkid.h b/src/sporkid.h index 2e0377d08f96c..34e8aa500a2e6 100644 --- a/src/sporkid.h +++ b/src/sporkid.h @@ -24,6 +24,7 @@ enum SporkId : int32_t { SPORK_17_SEGWIT_ACTIVATION = 10016, //SPORK_18_NEW_PROTOCOL_ENFORCEMENT_3 = 10017, SPORK_19_SEGWIT_ON_COINBASE = 10018, + SPORK_20_KERNEL_EXTRA_STAKING_CHECK = 10019, SPORK_INVALID = -1 };