From 50e746ac2e644b28a75ebb5c8afe248791b26ddb Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 Jun 2018 09:25:05 +0200 Subject: [PATCH 01/18] Merge #13439: rpc: Avoid "duplicate" return value for invalid submitblock f74894480 Only set fNewBlock to true in AcceptBlock when we write to disk (Matt Corallo) fa6e49731 rpc: Avoid "duplicate" return value for invalid submitblock (MarcoFalke) Pull request description: This is #13395 with one more commit tacked on. MarcoFalke got tired of dealing with the stupidity of fixing a return code with too many rounds of review (not that I blame him). Honestly we should probably have no return whatsoever, but for now, this fixes it (as well as nLastBlockTime for eviction purposes). Original description: When `submitblock` of an invalid block, the return value should not be `"duplicate"`. This is only seen when the header was previously found (denoted by the incorrectly named boolean `fBlockPresent`). Fix this bug by removing `fBlockPresent`. Tree-SHA512: 0ce3092655d5d904b4c8c5ff7479f73ce387144a738f20472b8af132564005c6db5594ae366e589508f6258506ee7a28b1c7995a83a8328b334f99316006bf2d --- src/rpc/mining.cpp | 13 ++++++------- src/validation.cpp | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 9d9ec58564..212b8f5746 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -757,7 +757,6 @@ UniValue submitblock(const JSONRPCRequest& request) } uint256 hash = block.GetHash(); - bool fBlockPresent = false; { LOCK(cs_main); const CBlockIndex* pindex = LookupBlockIndex(hash); @@ -768,18 +767,18 @@ UniValue submitblock(const JSONRPCRequest& request) if (pindex->nStatus & BLOCK_FAILED_MASK) { return "duplicate-invalid"; } - // Otherwise, we might only have the header - process the block before returning - fBlockPresent = true; } } + bool new_block; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(Params(), blockptr, true, nullptr); + bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block); UnregisterValidationInterface(&sc); - if (fBlockPresent) { - if (fAccepted && !sc.found) { - return "duplicate-inconclusive"; + if (!new_block) { + if (!accepted) { + // TODO Maybe pass down fNewBlock to AcceptBlockHeader, so it is properly set to true in this case? + return "invalid"; } return "duplicate"; } diff --git a/src/validation.cpp b/src/validation.cpp index e8ee60c177..e4683cd372 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3876,7 +3876,6 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, CVali // request; don't process these. if (pindex->nChainWork < nMinimumChainWork) return true; } - if (fNewBlock) *fNewBlock = true; if (!CheckBlock(block, state, chainparams.GetConsensus()) || !ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev)) { @@ -3893,6 +3892,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, CVali GetMainSignals().NewPoWValidBlock(pindex, pblock); // Write block to history file + if (fNewBlock) *fNewBlock = true; try { CDiskBlockPos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp); if (blockPos.IsNull()) { From be4345ce12b7f16fdb00d0dbd72aa190141112b2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 24 Jun 2018 16:41:58 +0200 Subject: [PATCH 02/18] Merge #13510: Scripts and tools: Obsolete #!/bin/bash shebang 000000035b20402dea3e8168165cd4eefdc97539 Obsolete #!/bin/bash shebang (DesWurstes) Pull request description: > `#!/bin/bash` assumes it is always installed to `/bin/` which can cause issues > `#!/usr/bin/env bash` searches the user's `PATH` to find the `bash` binary Details: https://github.com/dylanaraps/pure-bash-bible#obsolete-syntax I'm open to comments: Should I also fix `#!/bin/sh`? Tree-SHA512: b47bb4828116aa119f1899c68fee081270d51a898535490b9c616bf0f3660ad953f29c361eafc759bc64cdd54ee6eeecb2d79e9fdb5291a996a515c719805476 --- contrib/devtools/gen-manpages.sh | 2 +- contrib/gitian-descriptors/gitian-osx-signer.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 4 ++-- contrib/init/dashd.init | 2 +- contrib/macdeploy/extract-osx-sdk.sh | 2 +- contrib/verify-commits/pre-push-hook.sh | 2 +- contrib/verifybinaries/verify.sh | 2 +- test/lint/lint-all.sh | 2 +- test/lint/lint-filenames.sh | 2 +- test/lint/lint-include-guards.sh | 2 +- test/lint/lint-includes.sh | 2 +- test/lint/lint-locale-dependence.sh | 2 +- test/lint/lint-logs.sh | 2 +- test/lint/lint-python-shebang.sh | 2 +- test/lint/lint-python-utf8-encoding.sh | 2 +- test/lint/lint-shell-locale.sh | 2 +- test/lint/lint-shell.sh | 2 +- test/lint/lint-tests.sh | 2 +- test/lint/lint-whitespace.sh | 2 +- 19 files changed, 20 insertions(+), 20 deletions(-) diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh index 9cc2af74ea..52697f585f 100755 --- a/contrib/devtools/gen-manpages.sh +++ b/contrib/devtools/gen-manpages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash export LC_ALL=C TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)} diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml index 214c5425ff..43467434ec 100644 --- a/contrib/gitian-descriptors/gitian-osx-signer.yml +++ b/contrib/gitian-descriptors/gitian-osx-signer.yml @@ -19,7 +19,7 @@ script: | # Create global faketime wrappers for prog in ${FAKETIME_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog} diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 5d398af0c0..de9e403432 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -73,7 +73,7 @@ script: | function create_global_faketime_wrappers { for prog in ${FAKETIME_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} @@ -86,7 +86,7 @@ script: | function create_per-host_faketime_wrappers { for i in $HOSTS; do for prog in ${FAKETIME_HOST_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} diff --git a/contrib/init/dashd.init b/contrib/init/dashd.init index 3bfc473f9c..0013ccfd10 100644 --- a/contrib/init/dashd.init +++ b/contrib/init/dashd.init @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # dashd The Dash Core server. # diff --git a/contrib/macdeploy/extract-osx-sdk.sh b/contrib/macdeploy/extract-osx-sdk.sh index 94122b56fc..4c175156f4 100755 --- a/contrib/macdeploy/extract-osx-sdk.sh +++ b/contrib/macdeploy/extract-osx-sdk.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright (c) 2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh index 45b54150f5..0971989439 100755 --- a/contrib/verify-commits/pre-push-hook.sh +++ b/contrib/verify-commits/pre-push-hook.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright (c) 2014-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. diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index 42d9ffb752..fc7492ad3b 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright (c) 2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/test/lint/lint-all.sh b/test/lint/lint-all.sh index c9d4ec7199..7c4f96cb3b 100755 --- a/test/lint/lint-all.sh +++ b/test/lint/lint-all.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-filenames.sh b/test/lint/lint-filenames.sh index 9020567e6f..5391e43d91 100755 --- a/test/lint/lint-filenames.sh +++ b/test/lint/lint-filenames.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-include-guards.sh b/test/lint/lint-include-guards.sh index 4e5dac7b2f..9d6822f818 100755 --- a/test/lint/lint-include-guards.sh +++ b/test/lint/lint-include-guards.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh index fef79f199e..1ce2c00530 100755 --- a/test/lint/lint-includes.sh +++ b/test/lint/lint-includes.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh index a628382cf7..36ff6133fc 100755 --- a/test/lint/lint-locale-dependence.sh +++ b/test/lint/lint-locale-dependence.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash export LC_ALL=C diff --git a/test/lint/lint-logs.sh b/test/lint/lint-logs.sh index e3cf49e1ed..38ba157595 100755 --- a/test/lint/lint-logs.sh +++ b/test/lint/lint-logs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-python-shebang.sh b/test/lint/lint-python-shebang.sh index 031487a91a..4ff87f0bf7 100755 --- a/test/lint/lint-python-shebang.sh +++ b/test/lint/lint-python-shebang.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Shebang must use python3 (not python or python2) export LC_ALL=C diff --git a/test/lint/lint-python-utf8-encoding.sh b/test/lint/lint-python-utf8-encoding.sh index d0ff38ea0a..14183a5ccf 100755 --- a/test/lint/lint-python-utf8-encoding.sh +++ b/test/lint/lint-python-utf8-encoding.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-shell-locale.sh b/test/lint/lint-shell-locale.sh index 729942b005..edcd254559 100755 --- a/test/lint/lint-shell-locale.sh +++ b/test/lint/lint-shell-locale.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh index e5dcc7afdb..9af3c10ed6 100755 --- a/test/lint/lint-shell.sh +++ b/test/lint/lint-shell.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-tests.sh b/test/lint/lint-tests.sh index 9d83547df4..35d11023eb 100755 --- a/test/lint/lint-tests.sh +++ b/test/lint/lint-tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/test/lint/lint-whitespace.sh b/test/lint/lint-whitespace.sh index 98591719c6..2b6c1cd19c 100755 --- a/test/lint/lint-whitespace.sh +++ b/test/lint/lint-whitespace.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright (c) 2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying From 0da4f596bb388f10a10db3f62a81b40756abbeba Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 9 Jul 2018 20:23:46 +0200 Subject: [PATCH 03/18] Merge #13452: rpc: have verifytxoutproof check the number of txns in proof structure d280617bf569f84457eaea546541dc74c67cd1e4 [qa] Add a test for merkle proof malleation (Suhas Daftuar) ed82f1700006830b6fe34572b66245c1487ccd29 have verifytxoutproof check the number of txns in proof structure (Gregory Sanders) Pull request description: Recent publication of a weakness in Bitcoin's merkle tree construction demonstrates many SPV applications vulnerable to an expensive to pull off yet still plausible attack: https://bitslog.wordpress.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/ This change would at least allow `verifytxoutproof` to properly validate that the proof matches a known block, with known number of transactions any time after the full block is processed. This should neuter the attack entirely. The negative is that a header-only processed block/future syncing mode would cause this to fail until the node has imported the data required. related: #13451 `importprunedfunds` needs this check as well. Can expand it to cover this if people like the idea. Tree-SHA512: 0682ec2b622a38b29f3f635323e0a8b6fc071e8a6fd134c954579926ee7b516e642966bafa667016744ce49c16e19b24dbc8801f982a36ad0a6a4aff6d93f82b --- src/merkleblock.h | 6 +++ src/rpc/rawtransaction.cpp | 13 ++++-- test/functional/rpc_txoutproof.py | 23 +++++++++++ test/functional/test_framework/messages.py | 46 ++++++++++++++++++++++ 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/merkleblock.h b/src/merkleblock.h index f76e7e3c1e..3207022fb2 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -115,6 +115,12 @@ public: * returns the merkle root, or 0 in case of failure */ uint256 ExtractMatches(std::vector &vMatch, std::vector &vnIndex); + + /** Get number of transactions the merkle proof is indicating for cross-reference with + * local blockchain knowledge. + */ + unsigned int GetNumTransactions() const { return nTransactions; }; + }; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b46b6acf39..1c803a1678 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -337,7 +337,7 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) "\nArguments:\n" "1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n" "\nResult:\n" - "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n" + "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n" "\nExamples:\n" + HelpExampleCli("verifytxoutproof", "\"proof\"") @@ -358,12 +358,17 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) LOCK(cs_main); const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash()); - if (!pindex || !chainActive.Contains(pindex)) { + if (!pindex || !chainActive.Contains(pindex) || pindex->nTx == 0) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain"); } - for (const uint256& hash : vMatch) - res.push_back(hash.GetHex()); + // Check if proof is valid, only add results if so + if (pindex->nTx == merkleBlock.txn.GetNumTransactions()) { + for (const uint256& hash : vMatch) { + res.push_back(hash.GetHex()); + } + } + return res; } diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py index 37c9823508..46f7a70f90 100755 --- a/test/functional/rpc_txoutproof.py +++ b/test/functional/rpc_txoutproof.py @@ -6,6 +6,8 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * +from test_framework.mininode import FromHex, ToHex +from test_framework.messages import CMerkleBlock class MerkleBlockTest(BitcoinTestFramework): def set_test_params(self): @@ -80,6 +82,27 @@ class MerkleBlockTest(BitcoinTestFramework): # We can't get a proof if we specify transactions from different blocks assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", self.nodes[2].gettxoutproof, [txid1, txid3]) + # Now we'll try tweaking a proof. + proof = self.nodes[3].gettxoutproof([txid1, txid2]) + assert txid1 in self.nodes[0].verifytxoutproof(proof) + assert txid2 in self.nodes[1].verifytxoutproof(proof) + + tweaked_proof = FromHex(CMerkleBlock(), proof) + + # Make sure that our serialization/deserialization is working + assert txid1 in self.nodes[2].verifytxoutproof(ToHex(tweaked_proof)) + + # Check to see if we can go up the merkle tree and pass this off as a + # single-transaction block + tweaked_proof.txn.nTransactions = 1 + tweaked_proof.txn.vHash = [tweaked_proof.header.hashMerkleRoot] + tweaked_proof.txn.vBits = [True] + [False]*7 + + for n in self.nodes: + assert not n.verifytxoutproof(ToHex(tweaked_proof)) + + # TODO: try more variants, eg transactions at different depths, and + # verify that the proofs are invalid if __name__ == '__main__': MerkleBlockTest().main() diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index fda278edc5..cbec5db951 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -732,6 +732,52 @@ class BlockTransactions(): def __repr__(self): return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions)) +class CPartialMerkleTree(): + def __init__(self): + self.nTransactions = 0 + self.vHash = [] + self.vBits = [] + self.fBad = False + + def deserialize(self, f): + self.nTransactions = struct.unpack(" Date: Thu, 12 Jul 2018 07:46:43 -0400 Subject: [PATCH 04/18] Merge #13145: Use common getPath method to create temp directory in tests. 075429a482 Use common SetDataDir method to create temp directory in tests. (winder) Pull request description: Took a stab at #12574 Created a `getPath` method which can be used with the `TestingSetup` fixture to create a temp directory. Updated tests using temp directories to use this method. I tried setting up a `BOOST_GLOBAL_FIXTURE` to create a truly global path for all tests but was getting linker errors when including `boost/test/unit_test.hpp` in `test_bitcoin.cpp`. Even if I had gotten the linking to work, it looks like `make check` invokes the test binary a bunch of times, so it may not have worked anyway. Tree-SHA512: b51d0f5fada5d652ccc9362596cf98a742aa47f5daf94f189b5f034d8c035c85d095377befdcff7fb4247154d5160e8c500d70f554a2158e2c185a9d24f694f1 --- src/test/dbwrapper_tests.cpp | 14 ++++----- src/test/test_dash.cpp | 51 ++++++++++++++++++-------------- src/test/test_dash.h | 6 +++- src/test/util_tests.cpp | 8 ++--- src/wallet/test/wallet_tests.cpp | 6 ++-- 5 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 753e2fb45a..4c6076178f 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper) { // Perform tests both obfuscated and non-obfuscated. for (bool obfuscate : {false, true}) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir(std::string("dbwrapper").append(obfuscate ? "_true" : "_false")); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; uint256 in = InsecureRand256(); @@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) { // Perform tests both obfuscated and non-obfuscated. for (bool obfuscate : {false, true}) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir(std::string("dbwrapper_batch").append(obfuscate ? "_true" : "_false")); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'i'; @@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) { // Perform tests both obfuscated and non-obfuscated. for (bool obfuscate : {false, true}) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir(std::string("dbwrapper_iterator").append(obfuscate ? "_true" : "_false")); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); // The two keys are intentionally chosen for ordering @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) { // We're going to share this fs::path between two wrappers - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("existing_data_no_obfuscate"); create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. @@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) BOOST_AUTO_TEST_CASE(existing_data_reindex) { // We're going to share this fs::path between two wrappers - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("existing_data_reindex"); create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_AUTO_TEST_CASE(iterator_ordering) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("iterator_ordering"); CDBWrapper dbw(ph, (1 << 20), true, false, false); for (int x=0x00; x<256; ++x) { uint8_t key = x; @@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) { char buf[10]; - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("iterator_string_ordering"); CDBWrapper dbw(ph, (1 << 20), true, false, false); for (int x=0x00; x<10; ++x) { for (int y = 0; y < 10; y++) { diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 6b7ce986ef..8de199b61f 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -53,42 +53,50 @@ extern bool fPrintToConsole; extern void noui_connect(); BasicTestingSetup::BasicTestingSetup(const std::string& chainName) + : m_path_root(fs::temp_directory_path() / "test_bitcoin" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) { - SHA256AutoDetect(); - RandomInit(); - ECC_Start(); - BLSInit(); - SetupEnvironment(); - SetupNetworking(); - InitSignatureCache(); - InitScriptExecutionCache(); - CPrivateSend::InitStandardDenominations(); - fPrintToDebugLog = false; // don't want to write to debug.log file - fCheckBlockIndex = true; - SelectParams(chainName); - evoDb.reset(new CEvoDB(1 << 20, true, true)); - deterministicMNManager.reset(new CDeterministicMNManager(*evoDb)); - noui_connect(); + SHA256AutoDetect(); + RandomInit(); + ECC_Start(); + BLSInit(); + SetupEnvironment(); + SetupNetworking(); + InitSignatureCache(); + InitScriptExecutionCache(); + CPrivateSend::InitStandardDenominations(); + fPrintToDebugLog = false; // don't want to write to debug.log file + fCheckBlockIndex = true; + SelectParams(chainName); + evoDb.reset(new CEvoDB(1 << 20, true, true)); + deterministicMNManager.reset(new CDeterministicMNManager(*evoDb)); + noui_connect(); } BasicTestingSetup::~BasicTestingSetup() { - deterministicMNManager.reset(); - evoDb.reset(); + deterministicMNManager.reset(); + evoDb.reset(); - ECC_Stop(); + fs::remove_all(m_path_root); + ECC_Stop(); +} + +fs::path BasicTestingSetup::SetDataDir(const std::string& name) +{ + fs::path ret = m_path_root / name; + fs::create_directories(ret); + gArgs.ForceSetArg("-datadir", ret.string()); + return ret; } TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) { + SetDataDir("tempdir"); const CChainParams& chainparams = Params(); // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); ClearDatadirCache(); - pathTemp = fs::temp_directory_path() / strprintf("test_dash_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000))); - fs::create_directories(pathTemp); - gArgs.ForceSetArg("-datadir", pathTemp.string()); // We have to run a scheduler thread to prevent ActivateBestChain // from blocking due to queue overrun. @@ -131,7 +139,6 @@ TestingSetup::~TestingSetup() llmq::DestroyLLMQSystem(); pcoinsdbview.reset(); pblocktree.reset(); - fs::remove_all(pathTemp); } TestChainSetup::TestChainSetup(int blockCount) : TestingSetup(CBaseChainParams::REGTEST) diff --git a/src/test/test_dash.h b/src/test/test_dash.h index c3dd84be61..a1ede8d5f7 100644 --- a/src/test/test_dash.h +++ b/src/test/test_dash.h @@ -51,6 +51,11 @@ struct BasicTestingSetup { explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~BasicTestingSetup(); + + fs::path SetDataDir(const std::string& name); + +private: + const fs::path m_path_root; }; /** Testing setup that configures a complete environment. @@ -65,7 +70,6 @@ struct CConnmanTest { class PeerLogicValidation; struct TestingSetup: public BasicTestingSetup { - fs::path pathTemp; boost::thread_group threadGroup; CConnman* connman; CScheduler scheduler; diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 7a0da6d195..32647b877a 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1108,7 +1108,7 @@ static void TestOtherProcess(fs::path dirname, std::string lockname, int fd) BOOST_AUTO_TEST_CASE(test_LockDirectory) { - fs::path dirname = fs::temp_directory_path() / fs::unique_path(); + fs::path dirname = SetDataDir("test_LockDirectory") / fs::unique_path(); const std::string lockname = ".lock"; #ifndef WIN32 // Revert SIGCHLD to default, otherwise boost.test will catch and fail on @@ -1196,12 +1196,12 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory) BOOST_AUTO_TEST_CASE(test_DirIsWritable) { - // Should be able to write to the system tmp dir. - fs::path tmpdirname = fs::temp_directory_path(); + // Should be able to write to the data dir. + fs::path tmpdirname = SetDataDir("test_DirIsWritable"); BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true); // Should not be able to write to a non-existent dir. - tmpdirname = fs::temp_directory_path() / fs::unique_path(); + tmpdirname = tmpdirname / fs::unique_path(); BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false); fs::create_directory(tmpdirname); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 33c2d0b173..bd1e63b0cd 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -469,6 +469,8 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) LOCK(cs_main); + std::string backup_file = (SetDataDir("importwallet_rescan") / "wallet.backup").string(); + // Import key into wallet and call dumpwallet to create backup file. { CWallet wallet("dummy", WalletDatabase::CreateDummy()); @@ -478,7 +480,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); - request.params.push_back((pathTemp / "wallet.backup").string()); + request.params.push_back(backup_file); AddWallet(&wallet); ::dumpwallet(request); RemoveWallet(&wallet); @@ -491,7 +493,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); - request.params.push_back((pathTemp / "wallet.backup").string()); + request.params.push_back(backup_file); AddWallet(&wallet); ::importwallet(request); RemoveWallet(&wallet); From 672beb21794fed0f440d61c085315172773dbe2c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 12 Jul 2018 14:03:51 +0200 Subject: [PATCH 05/18] Merge #13627: Free keystore.h from file scope level type aliases d0b9405f964670d6eaa8529f65fa7993b2a406c8 Refactors `keystore.h` type aliases. (251) Pull request description: This pull request frees `keystore.h` from type alias declarations that have been declared at file scope level. `keystore.h` has various type aliases that have been declared ~3 - 6 years ago at file scope level, which can either be encapsulated or removed. Where type alias declarations are encapsulated at the appropriate scope and access level, C++11's `using` notation is used in favor of the `typedef` notation. Tree-SHA512: 1395cdc63e0c7ff5a1b1721675ad4416f71f507e999bd4ba019f03457cbfc08877848f10a8db7f5ccd2cd5ca3f5a291c986616f7703172fb6d79fba7447ffba8 --- src/keystore.h | 13 +++++-------- src/wallet/crypter.h | 2 ++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/keystore.h b/src/keystore.h index 9d7cd5f0bc..61d0502869 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -39,17 +39,17 @@ public: virtual bool HaveWatchOnly() const =0; }; -typedef std::map KeyMap; -typedef std::map WatchKeyMap; -typedef std::map ScriptMap; -typedef std::set WatchOnlySet; - /** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore { protected: mutable CCriticalSection cs_KeyStore; + using KeyMap = std::map; + using WatchKeyMap = std::map; + using ScriptMap = std::map; + using WatchOnlySet = std::set; + KeyMap mapKeys GUARDED_BY(cs_KeyStore); WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore); ScriptMap mapScripts GUARDED_BY(cs_KeyStore); @@ -77,7 +77,4 @@ public: virtual bool GetHDChain(CHDChain& hdChainRet) const; }; -typedef std::vector > CKeyingMaterial; -typedef std::map > > CryptedKeyMap; - #endif // BITCOIN_KEYSTORE_H diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 21be885de4..6789031091 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -134,6 +134,8 @@ private: bool fOnlyMixingAllowed; protected: + using CryptedKeyMap = std::map>>; + bool SetCrypted(); //! will encrypt previously unencrypted keys From 0a255fec404892f28bc622993e66e62959c31f8e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 13 Jul 2018 05:58:14 -0400 Subject: [PATCH 06/18] Merge #13645: [tests] skip rpc_zmq functional test as necessary a0b604c166 [tests] skip rpc_zmq functional test when python3 zmq lib is not present (James O'Beirne) Pull request description: As noted in https://github.com/bitcoin/bitcoin/pull/13570/files#r201715904, the `rpc_zmq` functional test should be skipped when the `zmq` python3 package is not installed. This is breaking https://bitcoinperf.com benchmarks at the moment. Tree-SHA512: ab519ae717f4b7a282640cf0389651723fdc108990aeb9852e8b9e96d61fa1ded2461717ae31558b37ff8401a5b1ccc41f4e858e402b8c3d98563d962599767a --- test/functional/interface_zmq.py | 21 ++++++------------- test/functional/rpc_zmq.py | 5 ++++- .../test_framework/test_framework.py | 17 +++++++++++++++ 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 7b5b173d37..8ace2645b2 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -3,17 +3,17 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the ZMQ notification interface.""" -import configparser import struct from codecs import encode +from test_framework.test_framework import ( + BitcoinTestFramework, skip_if_no_bitcoind_zmq, skip_if_no_py3_zmq) from test_framework.mininode import dashhash -from test_framework.test_framework import BitcoinTestFramework, SkipTest from test_framework.util import (assert_equal, bytes_to_hex_str, hash256, - ) + ) def dashhash_helper(b): return encode(dashhash(b)[::-1], 'hex_codec').decode('ascii') @@ -42,18 +42,9 @@ class ZMQTest (BitcoinTestFramework): self.num_nodes = 2 def setup_nodes(self): - # Try to import python3-zmq. Skip this test if the import fails. - try: - import zmq - except ImportError: - raise SkipTest("python3-zmq module not available.") - - # Check that dash has been built with ZMQ enabled. - config = configparser.ConfigParser() - config.read_file(open(self.options.configfile)) - - if not config["components"].getboolean("ENABLE_ZMQ"): - raise SkipTest("dashd has not been built with zmq enabled.") + skip_if_no_py3_zmq() + skip_if_no_bitcoind_zmq(self) + import zmq # Initialize ZMQ context and socket. # All messages are received in the same socket which means diff --git a/test/functional/rpc_zmq.py b/test/functional/rpc_zmq.py index eb789face2..6dbc726d5e 100755 --- a/test/functional/rpc_zmq.py +++ b/test/functional/rpc_zmq.py @@ -4,7 +4,8 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test for the ZMQ RPC methods.""" -from test_framework.test_framework import BitcoinTestFramework +from test_framework.test_framework import ( + BitcoinTestFramework, skip_if_no_py3_zmq, skip_if_no_bitcoind_zmq) from test_framework.util import assert_equal @@ -17,6 +18,8 @@ class RPCZMQTest(BitcoinTestFramework): self.setup_clean_chain = True def run_test(self): + skip_if_no_py3_zmq() + skip_if_no_bitcoind_zmq(self) self._test_getzmqnotifications() def _test_getzmqnotifications(self): diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index e5f14744a1..e431b383af 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1078,3 +1078,20 @@ class SkipTest(Exception): """This exception is raised to skip a test""" def __init__(self, message): self.message = message + + +def skip_if_no_py3_zmq(): + """Attempt to import the zmq package and skip the test if the import fails.""" + try: + import zmq # noqa + except ImportError: + raise SkipTest("python3-zmq module not available.") + + +def skip_if_no_bitcoind_zmq(test_instance): + """Skip the running test if dashd has not been compiled with zmq support.""" + config = configparser.ConfigParser() + config.read_file(open(test_instance.options.configfile)) + + if not config["components"].getboolean("ENABLE_ZMQ"): + raise SkipTest("dashd has not been built with zmq enabled.") From 29bb4f2e1535da09fe53c25e721f13b7757887f2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 13 Jul 2018 19:27:59 -0700 Subject: [PATCH 07/18] Merge #13630: Drop unused pindexRet arg to CMerkleTx::GetDepthInMainChain d6f39b6c64 Drop unused pindexRet arg to CMerkleTx::GetDepthInMainChain (Ben Woosley) Pull request description: Tree-SHA512: 5f064a47e71113f90f296ab36dae92173ff3fc632ab4e1e85dc71d556cb9239d15939b1e542f4292dab93d336795b7f2e4ae64f6984303c852df8d24f54ccebe --- src/wallet/wallet.cpp | 3 +-- src/wallet/wallet.h | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 69b1a79737..d59003132f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5564,7 +5564,7 @@ void CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock) nIndex = posInBlock; } -int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const +int CMerkleTx::GetDepthInMainChain() const { int nResult; @@ -5578,7 +5578,6 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const if (!pindex || !chainActive.Contains(pindex)) return 0; - pindexRet = pindex; return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 8d0c0d534b..d2b872b30b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -263,9 +263,8 @@ public: * 0 : in memory pool, waiting to be included in a block * >=1 : this many blocks deep in the main chain */ - int GetDepthInMainChain(const CBlockIndex* &pindexRet) const; - int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } - bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; } + int GetDepthInMainChain() const; + bool IsInMainChain() const { return GetDepthInMainChain() > 0; } bool IsLockedByInstantSend() const; bool IsChainLocked() const; int GetBlocksToMaturity() const; From 16591be58064f1023db4ffdd2aadfd63e5025f3f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 17 Jul 2018 08:04:33 -0400 Subject: [PATCH 08/18] Merge #13663: tests: Avoid read/write to default datadir fa43a4138b bench_bitcoin: Avoid read/write to default datadir (MarcoFalke) ea80b81e2e test_bitcoin: Avoid read/write to default datadir (MarcoFalke) Pull request description: tests should never read or write and potentially corrupt the default datadir, so try to avoid it. Tree-SHA512: ee446ff4bf59da2aed38c2e4758581d6103e9d4c35a118497e9ec21d566ba33d913e160c2d7ba2ea6f937f000343ecea3816154bd87ee47f64f5b0cf9e88f6e0 --- src/bench/bench_dash.cpp | 16 ++++++++++++++-- src/test/net_tests.cpp | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/bench/bench_dash.cpp b/src/bench/bench_dash.cpp index ad25cd2eef..4ec6c64a0f 100644 --- a/src/bench/bench_dash.cpp +++ b/src/bench/bench_dash.cpp @@ -29,8 +29,15 @@ void InitBLSTests(); void CleanupBLSTests(); void CleanupBLSDkgTests(); -int -main(int argc, char** argv) +static fs::path SetDataDir() +{ + fs::path ret = fs::temp_directory_path() / "bench_bitcoin" / fs::unique_path(); + fs::create_directories(ret); + gArgs.ForceSetArg("-datadir", ret.string()); + return ret; +} + +int main(int argc, char** argv) { gArgs.ParseParameters(argc, argv); @@ -49,6 +56,9 @@ main(int argc, char** argv) return 0; } + // Set the datadir after parsing the bench options + const fs::path bench_datadir{SetDataDir()}; + SHA256AutoDetect(); RegisterPrettySignalHandlers(); @@ -82,6 +92,8 @@ main(int argc, char** argv) benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only); + fs::remove_all(bench_datadir); + // need to be called before global destructors kick in (PoolAllocator is needed due to many BLSSecretKeys) CleanupBLSDkgTests(); CleanupBLSTests(); diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 9336f833e9..156d0be72a 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -89,6 +89,7 @@ BOOST_AUTO_TEST_CASE(cnode_listen_port) BOOST_AUTO_TEST_CASE(caddrdb_read) { + SetDataDir("caddrdb_read"); CAddrManUncorrupted addrmanUncorrupted; addrmanUncorrupted.MakeDeterministic(); @@ -134,6 +135,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) { + SetDataDir("caddrdb_read_corrupted"); CAddrManCorrupted addrmanCorrupted; addrmanCorrupted.MakeDeterministic(); From 44c7301288415cbfc9121b2f328a22769c0c7b91 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 9 Jul 2018 19:56:59 +0200 Subject: [PATCH 09/18] Merge #13603: bitcoin-tx: Stricter check for valid integers 57889e688dd0987a1e087cd48d216a413127601e bitcoin-tx: Stricter check for valid integers (Daniel Kraft) Pull request description: Just calling `atoi` to convert strings to integers does not check for valid integers very thoroughly; in particular, it just ignores everything starting from the first non-numeral character. Even a string like "foo" is fine and silently returns 0. This meant that `bitcoin-tx` would not fail if such a string was passed in various places where an integer is expected (like the `locktime` or an input/output index); this means that it would, for instance, silently accept a typo and interpret it in an unexpected way. In this change, we use `ParseInt64` for parsing strings to integers, which actually verifies that the full string is valid as number. New tests in the `bitcoin-util-test` cover the new error paths. This fixes #13599. Tree-SHA512: 146a0af275e9f57784e5d0582d3defbac35551b54b6b7232f8a0b20db04aa611125e52aa4512ef2f8ed2cafc2a12fe586f9d10ed66d641cff090288f279b1988 --- src/dash-tx.cpp | 38 +++++++++--------- test/util/data/bitcoin-util-test.json | 55 +++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp index 9268e7a166..9d4d88dd3e 100644 --- a/src/dash-tx.cpp +++ b/src/dash-tx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-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. @@ -190,18 +190,18 @@ static CAmount ExtractAndValidateValue(const std::string& strValue) static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) { - int64_t newVersion = atoi64(cmdVal); - if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION) - throw std::runtime_error("Invalid TX version requested"); + int64_t newVersion; + if (!ParseInt64(cmdVal, &newVersion) || newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION) + throw std::runtime_error("Invalid TX version requested: '" + cmdVal + "'"); tx.nVersion = (int) newVersion; } static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal) { - int64_t newLocktime = atoi64(cmdVal); - if (newLocktime < 0LL || newLocktime > 0xffffffffLL) - throw std::runtime_error("Invalid TX locktime requested"); + int64_t newLocktime; + if (!ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL) + throw std::runtime_error("Invalid TX locktime requested: '" + cmdVal + "'"); tx.nLockTime = (unsigned int) newLocktime; } @@ -225,10 +225,10 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu static const unsigned int maxVout = MaxBlockSize() / minTxOutSz; // extract and validate vout - std::string strVout = vStrInputParts[1]; - int vout = atoi(strVout); - if ((vout < 0) || (vout > (int)maxVout)) - throw std::runtime_error("invalid TX input vout"); + const std::string& strVout = vStrInputParts[1]; + int64_t vout; + if (!ParseInt64(strVout, &vout) || vout < 0 || vout > static_cast(maxVout)) + throw std::runtime_error("invalid TX input vout '" + strVout + "'"); // extract the optional sequence number uint32_t nSequenceIn=std::numeric_limits::max(); @@ -433,10 +433,9 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInIdx) { // parse requested deletion index - int inIdx = atoi(strInIdx); - if (inIdx < 0 || inIdx >= (int)tx.vin.size()) { - std::string strErr = "Invalid TX input index '" + strInIdx + "'"; - throw std::runtime_error(strErr.c_str()); + int64_t inIdx; + if (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast(tx.vin.size())) { + throw std::runtime_error("Invalid TX input index '" + strInIdx + "'"); } // delete input from transaction @@ -446,10 +445,9 @@ static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInId static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOutIdx) { // parse requested deletion index - int outIdx = atoi(strOutIdx); - if (outIdx < 0 || outIdx >= (int)tx.vout.size()) { - std::string strErr = "Invalid TX output index '" + strOutIdx + "'"; - throw std::runtime_error(strErr.c_str()); + int64_t outIdx; + if (!ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >= static_cast(tx.vout.size())) { + throw std::runtime_error("Invalid TX output index '" + strOutIdx + "'"); } // delete output from transaction @@ -547,7 +545,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) uint256 txid = ParseHashStr(prevOut["txid"].get_str(), "txid"); - int nOut = atoi(prevOut["vout"].getValStr()); + const int nOut = prevOut["vout"].get_int(); if (nOut < 0) throw std::runtime_error("vout must be positive"); diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json index d30879c400..0becb4dc70 100644 --- a/test/util/data/bitcoin-util-test.json +++ b/test/util/data/bitcoin-util-test.json @@ -26,6 +26,12 @@ "output_cmp": "blanktxv2.json", "description": "Creates a blank transaction when nothing is piped into dash-tx (output in json)" }, + { "exec": "./dash-tx", + "args": ["-create", "nversion=1foo"], + "return_code": 1, + "error_txt": "error: Invalid TX version requested", + "description": "Tests the check for invalid nversion value" + }, { "exec": "./dash-tx", "args": ["-", "delin=1"], "input": "tx394b54bb.hex", @@ -45,6 +51,13 @@ "error_txt": "error: Invalid TX input index '31'", "description": "Attempts to delete an input with a bad index from a transaction. Expected to fail." }, + { "exec": "./dash-tx", + "args": ["-", "delin=1foo"], + "input": "tx394b54bb.hex", + "return_code": 1, + "error_txt": "error: Invalid TX input index", + "description": "Tests the check for an invalid input index with delin" + }, { "exec": "./dash-tx", "args": ["-", "delout=1"], "input": "tx394b54bb.hex", @@ -64,6 +77,13 @@ "error_txt": "error: Invalid TX output index '2'", "description": "Attempts to delete an output with a bad index from a transaction. Expected to fail." }, + { "exec": "./dash-tx", + "args": ["-", "delout=1foo"], + "input": "tx394b54bb.hex", + "return_code": 1, + "error_txt": "error: Invalid TX output index", + "description": "Tests the check for an invalid output index with delout" + }, { "exec": "./dash-tx", "args": ["-", "locktime=317000"], "input": "tx394b54bb.hex", @@ -76,6 +96,29 @@ "output_cmp": "tt-locktime317000-out.json", "description": "Adds an nlocktime to a transaction (output in json)" }, + { "exec": "./dash-tx", + "args": ["-create", "locktime=317000foo"], + "return_code": 1, + "error_txt": "error: Invalid TX locktime requested", + "description": "Tests the check for invalid locktime value" + }, + { "exec": "./dash-tx", + "args": + ["-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "replaceable=0foo"], + "return_code": 1, + "error_txt": "error: Invalid TX input index", + "description": "Tests the check for an invalid input index with replaceable" + }, + { "exec": "./dash-tx", + "args": + ["-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0x"], + "return_code": 1, + "error_txt": "error: invalid TX input vout", + "description": "Tests the check for an invalid vout value when adding an input" + }, { "exec": "./dash-tx", "args": ["-create", @@ -205,6 +248,18 @@ "output_cmp": "txcreatesignv2.hex", "description": "Creates a new transaction with a single input and a single output, and then signs the transaction" }, + { "exec": "./dash-tx", + "args": + ["-create", + "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", + "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", + "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":\"0foo\",\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", + "sign=ALL", + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "return_code": 1, + "error_txt": "error: prevtxs internal object typecheck fail", + "description": "Tests the check for invalid vout index in prevtxs for sign" + }, { "exec": "./dash-tx", "args": ["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", "nversion=1"], From 8fa51dce7dde31f987f08e50b11a2221016f78e7 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 16 Dec 2020 17:22:56 -0600 Subject: [PATCH 10/18] attempt to fix test failure Signed-off-by: pasta --- test/util/data/bitcoin-util-test.json | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json index 0becb4dc70..ff8174da65 100644 --- a/test/util/data/bitcoin-util-test.json +++ b/test/util/data/bitcoin-util-test.json @@ -102,15 +102,6 @@ "error_txt": "error: Invalid TX locktime requested", "description": "Tests the check for invalid locktime value" }, - { "exec": "./dash-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "replaceable=0foo"], - "return_code": 1, - "error_txt": "error: Invalid TX input index", - "description": "Tests the check for an invalid input index with replaceable" - }, { "exec": "./dash-tx", "args": ["-create", @@ -252,10 +243,10 @@ "args": ["-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", - "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", + "set=privatekeys:[\"cW5MmkEJF4PzKgwyyZU2ecUEecGXnhEyrB6JAmVpQkWVxErFuvnX\"]", "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":\"0foo\",\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "outaddr=0.001:ycgEaAAqfXUyuansGTRRn9fCvLmQ6nWNKS"], "return_code": 1, "error_txt": "error: prevtxs internal object typecheck fail", "description": "Tests the check for invalid vout index in prevtxs for sign" From e6089da99464ab83912309170c39ae02b3a8bf18 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 2 Aug 2018 15:58:39 +0200 Subject: [PATCH 11/18] Merge #13823: qa: quote path in authproxy for external multiwallets fa67505e1ea007bdc081bc7425fb83d5455d8308 qa: Quote wallet name for rpc path (MarcoFalke) Pull request description: When using external multiwallets they are specified by their full path which might contain non-ascii characters (e.g. umlauts or emojis). Fix this by url-quoting the path. Tree-SHA512: 7cc66514579d9f602f88a6817c5ab43a44c6d3711df452dc904173f0bc34e2c0b2c34877497f06b61f6720c532fa183053f54622dc454e316c89cee7eaa72463 --- test/functional/test_framework/test_node.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 4d155044af..2e5af8cb84 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -15,6 +15,7 @@ import re import subprocess import tempfile import time +import urllib.parse from .authproxy import JSONRPCException from .messages import MY_SUBVERSION @@ -167,7 +168,7 @@ class TestNode(): return self.cli("-rpcwallet={}".format(wallet_name)) else: assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected") - wallet_path = "wallet/%s" % wallet_name + wallet_path = "wallet/{}".format(urllib.parse.quote(wallet_name)) return self.rpc / wallet_path def stop_node(self, wait=0): From 4d0edcfbdd7b8b18eba8398e87e322f228101432 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 7 Aug 2018 14:09:13 +0200 Subject: [PATCH 12/18] Merge #13657: wallet: assert to ensure accuracy of CMerkleTx::GetBlocksToMaturity 93de2891fa9cb8314573ba3a6ab764bc9c52444d wallet: assert to ensure accuracy of CMerkleTx::GetBlocksToMaturity (Ben Woosley) Pull request description: According to my understanding, it should not be possible for coinbase transactions to be conflicting, thus it should not be possible for GetDepthInMainChain to return a negative result. If it did, this would also result in innacurate results for GetBlocksToMaturity due to the math therein. asserting ensures accuracy. Tree-SHA512: 8e71c26f09fe457cfb00c362ca27066f7f018ea2af1f395090fdc7fd9f5964b76f4317c23f7a4923776f00087558511da5c1c368095be39fb1bacc614a93c32f --- src/wallet/wallet.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d59003132f..4475f22a63 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5607,7 +5607,9 @@ int CMerkleTx::GetBlocksToMaturity() const { if (!IsCoinBase()) return 0; - return std::max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain()); + int chain_depth = GetDepthInMainChain(); + assert(chain_depth >= 0); // coinbase tx should not be conflicted + return std::max(0, (COINBASE_MATURITY+1) - chain_depth); } From a53aabdb5e0f68e9850e859c1fd45dc17c7f7c83 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 18 Dec 2020 03:47:19 +0100 Subject: [PATCH 13/18] test: Fix test data in bitcoin-util-test.json --- test/util/data/bitcoin-util-test.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json index ff8174da65..b249cf9cef 100644 --- a/test/util/data/bitcoin-util-test.json +++ b/test/util/data/bitcoin-util-test.json @@ -243,10 +243,10 @@ "args": ["-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", - "set=privatekeys:[\"cW5MmkEJF4PzKgwyyZU2ecUEecGXnhEyrB6JAmVpQkWVxErFuvnX\"]", + "set=privatekeys:[\"7qYrzJZWqnyCWMYswFcqaRJypGdVceudXPSxmZKsngN7fyo7aAV\"]", "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":\"0foo\",\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", - "outaddr=0.001:ycgEaAAqfXUyuansGTRRn9fCvLmQ6nWNKS"], + "outaddr=0.001:XijDvbYpPmznwgpWD3DkdYNfGmRP2KoVSk"], "return_code": 1, "error_txt": "error: prevtxs internal object typecheck fail", "description": "Tests the check for invalid vout index in prevtxs for sign" From 724e8aed19293fa9fa23fc55a52d3372bb7692e5 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 18 Dec 2020 04:33:37 +0100 Subject: [PATCH 14/18] More of bitcoin#13645 in interface_zmq_dash.py --- test/functional/interface_zmq_dash.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/functional/interface_zmq_dash.py b/test/functional/interface_zmq_dash.py index 5e61271b3e..f4ad9cdc9f 100755 --- a/test/functional/interface_zmq_dash.py +++ b/test/functional/interface_zmq_dash.py @@ -11,9 +11,13 @@ import json import random import struct import time -import zmq +try: + import zmq +finally: + pass -from test_framework.test_framework import DashTestFramework, SkipTest +from test_framework.test_framework import ( + DashTestFramework, skip_if_no_bitcoind_zmq, skip_if_no_py3_zmq) from test_framework.mininode import P2PInterface, network_thread_start from test_framework.util import assert_equal, assert_raises_rpc_error, bytes_to_hex_str from test_framework.messages import ( @@ -96,8 +100,8 @@ class DashZMQTest (DashTestFramework): config = configparser.ConfigParser() config.read_file(open(self.options.configfile)) - if not config["components"].getboolean("ENABLE_ZMQ"): - raise SkipTest("dashd has not been built with zmq enabled.") + skip_if_no_py3_zmq() + skip_if_no_bitcoind_zmq(self) try: # Setup the ZMQ subscriber socket From 724c6d51c18692bdec730828041a2b72b4738e9b Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 18 Dec 2020 04:37:24 +0100 Subject: [PATCH 15/18] bench: bench_bitcoin -> bench_dash --- src/bench/bench_dash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bench/bench_dash.cpp b/src/bench/bench_dash.cpp index 4ec6c64a0f..0ead08ad41 100644 --- a/src/bench/bench_dash.cpp +++ b/src/bench/bench_dash.cpp @@ -31,7 +31,7 @@ void CleanupBLSDkgTests(); static fs::path SetDataDir() { - fs::path ret = fs::temp_directory_path() / "bench_bitcoin" / fs::unique_path(); + fs::path ret = fs::temp_directory_path() / "bench_dash" / fs::unique_path(); fs::create_directories(ret); gArgs.ForceSetArg("-datadir", ret.string()); return ret; From 5e686c9c017776aa4f403bb888cc9ce71f3d48bb Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 18 Dec 2020 21:15:41 +0300 Subject: [PATCH 16/18] More of 13510 --- contrib/auto_gdb/dash_dbg.sh | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 6 +++--- contrib/gitian-descriptors/gitian-win.yml | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contrib/auto_gdb/dash_dbg.sh b/contrib/auto_gdb/dash_dbg.sh index b1e1b2fd9c..dd9588c906 100755 --- a/contrib/auto_gdb/dash_dbg.sh +++ b/contrib/auto_gdb/dash_dbg.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # use testnet settings, if you need mainnet, use ~/.dashcore/dashd.pid file instead export LC_ALL=C diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 7944460847..3b11890ab1 100755 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -80,7 +80,7 @@ script: | function create_global_faketime_wrappers { for prog in ${FAKETIME_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} echo "# GCCVERSION=${GCCVERSION}" >> ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} @@ -94,7 +94,7 @@ script: | function create_per-host_faketime_wrappers { for i in $HOSTS; do for prog in ${FAKETIME_HOST_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} echo "# GCCVERSION=${GCCVERSION}" >> ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} @@ -126,7 +126,7 @@ script: | for prog in gcc g++; do rm -f ${WRAP_DIR}/${prog} cat << EOF > ${WRAP_DIR}/${prog} - #!/bin/bash + #!/usr/bin/env bash # GCCVERSION=${GCCVERSION} REAL="`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1`" for var in "\$@" diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 000f8509cc..0a94990b7f 100755 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -72,7 +72,7 @@ script: | function create_global_faketime_wrappers { for prog in ${FAKETIME_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} echo "# GCCVERSION=${GCCVERSION}" >> ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} @@ -86,7 +86,7 @@ script: | function create_per-host_faketime_wrappers { for i in $HOSTS; do for prog in ${FAKETIME_HOST_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} echo "# GCCVERSION=${GCCVERSION}" >> ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} @@ -104,7 +104,7 @@ script: | for i in $HOSTS; do mkdir -p ${WRAP_DIR}/${i} for prog in collect2; do - echo '#!/bin/bash' > ${WRAP_DIR}/${i}/${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}/${prog} echo "# GCCVERSION=${GCCVERSION}" >> ${WRAP_DIR}/${i}/${prog} REAL=$(${i}-gcc -print-prog-name=${prog}) echo "export MALLOC_PERTURB_=255" >> ${WRAP_DIR}/${i}/${prog} @@ -113,7 +113,7 @@ script: | touch -d "${REFERENCE_DATETIME}" ${WRAP_DIR}/${i}/${prog} done for prog in gcc g++; do - echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} echo "# GCCVERSION=${GCCVERSION}" >> ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog}-posix | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo '# Add the gcc version to the wrapper so that ccache takes this into account (we use CCACHE_COMPILERCHECK=content)' >> ${WRAP_DIR}/${i}-${prog} From 7d2ca30db1c7834efd047a48fbed78facb504217 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 18 Dec 2020 21:20:03 +0300 Subject: [PATCH 17/18] dashify --- src/test/test_dash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 8de199b61f..5287eb3da2 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -53,7 +53,7 @@ extern bool fPrintToConsole; extern void noui_connect(); BasicTestingSetup::BasicTestingSetup(const std::string& chainName) - : m_path_root(fs::temp_directory_path() / "test_bitcoin" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) + : m_path_root(fs::temp_directory_path() / "test_dash" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) { SHA256AutoDetect(); RandomInit(); From 71c49d743d23557797c2e760b0f6609e7e59f91b Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 18 Dec 2020 21:29:17 +0300 Subject: [PATCH 18/18] Redo "Drop redundant CPartialMerkleTree and CMerkleBlock" correctly But this time keep our versions and add missing parts instead --- test/functional/test_framework/messages.py | 49 +--------------------- 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index cbec5db951..ee7e2774d2 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -732,59 +732,14 @@ class BlockTransactions(): def __repr__(self): return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions)) + class CPartialMerkleTree(): def __init__(self): self.nTransactions = 0 - self.vHash = [] self.vBits = [] + self.vHash = [] self.fBad = False - def deserialize(self, f): - self.nTransactions = struct.unpack("