diff options
30 files changed, 196 insertions, 202 deletions
diff --git a/configure.ac b/configure.ac index 490b638ee1..bf0f3f8f52 100644 --- a/configure.ac +++ b/configure.ac @@ -651,6 +651,8 @@ if test x$use_glibc_compat != xno; then [ fdelt_type="long int"]) AC_MSG_RESULT($fdelt_type) AC_DEFINE_UNQUOTED(FDELT_TYPE, $fdelt_type,[parameter and return value type for __fdelt_chk]) + AX_CHECK_LINK_FLAG([[-Wl,--wrap=__divmoddi4]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=__divmoddi4"]) + AX_CHECK_LINK_FLAG([[-Wl,--wrap=log2f]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=log2f"]) else AC_SEARCH_LIBS([clock_gettime],[rt]) fi @@ -1351,6 +1353,7 @@ AC_SUBST(DEBUG_CPPFLAGS) AC_SUBST(WARN_CXXFLAGS) AC_SUBST(NOWARN_CXXFLAGS) AC_SUBST(DEBUG_CXXFLAGS) +AC_SUBST(COMPAT_LDFLAGS) AC_SUBST(ERROR_CXXFLAGS) AC_SUBST(GPROF_CXXFLAGS) AC_SUBST(GPROF_LDFLAGS) diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 3a67319eaa..6808e77da7 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -46,7 +46,7 @@ MAX_VERSIONS = { # Ignore symbols that are exported as part of every executable IGNORE_EXPORTS = { -'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used' +'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr' } READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt') diff --git a/src/Makefile.am b/src/Makefile.am index 458721293e..5d7eafb3f1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -418,6 +418,7 @@ libbitcoin_util_a_SOURCES = \ if GLIBC_BACK_COMPAT libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp +AM_LDFLAGS += $(COMPAT_LDFLAGS) endif # cli: shared between bitcoin-cli and bitcoin-qt diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 7b32b72bd1..f5293585a0 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -26,6 +26,7 @@ bench_bench_bitcoin_SOURCES = \ bench/mempool_eviction.cpp \ bench/verify_script.cpp \ bench/base58.cpp \ + bench/bech32.cpp \ bench/lockedpool.cpp \ bench/prevector.cpp diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp new file mode 100644 index 0000000000..ff655bded0 --- /dev/null +++ b/src/bench/bech32.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 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. + +#include <bench/bench.h> + +#include <validation.h> +#include <bech32.h> +#include <utilstrencodings.h> + +#include <vector> +#include <string> + + +static void Bech32Encode(benchmark::State& state) +{ + std::vector<uint8_t> v = ParseHex("c97f5a67ec381b760aeaf67573bc164845ff39a3bb26a1cee401ac67243b48db"); + std::vector<unsigned char> tmp = {0}; + tmp.reserve(1 + 32 * 8 / 5); + ConvertBits<8, 5, true>([&](unsigned char c) { tmp.push_back(c); }, v.begin(), v.end()); + while (state.KeepRunning()) { + bech32::Encode("bc", tmp); + } +} + + +static void Bech32Decode(benchmark::State& state) +{ + std::string addr = "bc1qkallence7tjawwvy0dwt4twc62qjgaw8f4vlhyd006d99f09"; + std::vector<unsigned char> vch; + while (state.KeepRunning()) { + bech32::Decode(addr); + } +} + + +BENCHMARK(Bech32Encode, 800 * 1000); +BENCHMARK(Bech32Decode, 800 * 1000); diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index 55da5ef63f..b1cbe9f72a 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -7,6 +7,7 @@ #endif #include <cstddef> +#include <cstdint> #if defined(HAVE_SYS_SELECT_H) #include <sys/select.h> @@ -27,3 +28,47 @@ extern "C" FDELT_TYPE __fdelt_warn(FDELT_TYPE a) return a / __NFDBITS; } extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn"))); + +#if defined(__i386__) || defined(__arm__) + +extern "C" int64_t __udivmoddi4(uint64_t u, uint64_t v, uint64_t* rp); + +extern "C" int64_t __wrap___divmoddi4(int64_t u, int64_t v, int64_t* rp) +{ + int32_t c1 = 0, c2 = 0; + int64_t uu = u, vv = v; + int64_t w; + int64_t r; + + if (uu < 0) { + c1 = ~c1, c2 = ~c2, uu = -uu; + } + if (vv < 0) { + c1 = ~c1, vv = -vv; + } + + w = __udivmoddi4(uu, vv, (uint64_t*)&r); + if (c1) + w = -w; + if (c2) + r = -r; + + *rp = r; + return w; +} +#endif + +extern "C" float log2f_old(float x); +#ifdef __i386__ +__asm(".symver log2f_old,log2f@GLIBC_2.1"); +#elif defined(__amd64__) +__asm(".symver log2f_old,log2f@GLIBC_2.2.5"); +#elif defined(__arm__) +__asm(".symver log2f_old,log2f@GLIBC_2.4"); +#elif defined(__aarch64__) +__asm(".symver log2f_old,log2f@GLIBC_2.17"); +#endif +extern "C" float __wrap_log2f(float x) +{ + return log2f_old(x); +} diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index e98acba0df..aade4b2df3 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -93,7 +93,6 @@ WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx) result.block_height = (block ? block->nHeight : std::numeric_limits<int>::max()), result.blocks_to_maturity = wtx.GetBlocksToMaturity(); result.depth_in_main_chain = wtx.GetDepthInMainChain(); - result.request_count = wtx.GetRequestCount(); result.time_received = wtx.nTimeReceived; result.lock_time = wtx.tx->nLockTime; result.is_final = CheckFinalTx(*wtx.tx); diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index ce42e14eea..96e742eaca 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -346,7 +346,6 @@ struct WalletTxStatus int block_height; int blocks_to_maturity; int depth_in_main_chain; - int request_count; unsigned int time_received; uint32_t lock_time; bool is_final; diff --git a/src/keystore.h b/src/keystore.h index cd5ded9203..f64024c7e7 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -38,21 +38,21 @@ public: virtual bool HaveWatchOnly() const =0; }; -typedef std::map<CKeyID, CKey> KeyMap; -typedef std::map<CKeyID, CPubKey> WatchKeyMap; -typedef std::map<CScriptID, CScript > ScriptMap; -typedef std::set<CScript> WatchOnlySet; - /** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore { protected: mutable CCriticalSection cs_KeyStore; - KeyMap mapKeys; - WatchKeyMap mapWatchKeys; - ScriptMap mapScripts; - WatchOnlySet setWatchOnly; + using KeyMap = std::map<CKeyID, CKey>; + using WatchKeyMap = std::map<CKeyID, CPubKey>; + using ScriptMap = std::map<CScriptID, CScript>; + using WatchOnlySet = std::set<CScript>; + + KeyMap mapKeys GUARDED_BY(cs_KeyStore); + WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore); + ScriptMap mapScripts GUARDED_BY(cs_KeyStore); + WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore); void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); @@ -74,9 +74,6 @@ public: bool HaveWatchOnly() const override; }; -typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial; -typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap; - /** Return the CKeyID of the key involved in a script (if there is a unique one). */ CKeyID GetKeyForDestination(const CKeyStore& store, const CTxDestination& dest); diff --git a/src/net.cpp b/src/net.cpp index b24ceb67d6..d806059ece 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2254,7 +2254,7 @@ bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<C if (binds.empty() && whiteBinds.empty()) { struct in_addr inaddr_any; inaddr_any.s_addr = INADDR_ANY; - fBound |= Bind(CService(in6addr_any, GetListenPort()), BF_NONE); + fBound |= Bind(CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE); fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); } return fBound; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 458e9c2e9f..2f3a604064 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1264,9 +1264,6 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm if (!push) { vNotFound.push_back(inv); } - - // Track requests for our stuff. - GetMainSignals().Inventory(inv.hash); } } // release cs_main @@ -1965,9 +1962,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->AskFor(inv); } } - - // Track requests for our stuff - GetMainSignals().Inventory(inv.hash); } } diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 1d21d8c766..ff47653fb7 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -27,8 +27,6 @@ static const bool DEFAULT_SPLASHSCREEN = true; #define COLOR_BAREADDRESS QColor(140, 140, 140) /* Transaction list -- TX status decoration - open until date */ #define COLOR_TX_STATUS_OPENUNTILDATE QColor(64, 64, 255) -/* Transaction list -- TX status decoration - offline */ -#define COLOR_TX_STATUS_OFFLINE QColor(192, 192, 192) /* Transaction list -- TX status decoration - danger, tx needs attention */ #define COLOR_TX_STATUS_DANGER QColor(200, 100, 100) /* Transaction list -- TX status decoration - default color */ diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 2cb446c459..8297f75799 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -37,8 +37,6 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i int nDepth = status.depth_in_main_chain; if (nDepth < 0) return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth); - else if (adjustedTime - status.time_received > 2 * 60 && status.request_count == 0) - return tr("%1/offline").arg(nDepth); else if (nDepth == 0) return tr("0/unconfirmed, %1").arg((inMempool ? tr("in memory pool") : tr("not in memory pool"))) + (status.is_abandoned ? ", "+tr("abandoned") : ""); else if (nDepth < 6) @@ -68,14 +66,6 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall CAmount nNet = nCredit - nDebit; strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks, adjustedTime); - int nRequests = status.request_count; - if (nRequests != -1) - { - if (nRequests == 0) - strHTML += tr(", has not been successfully broadcast yet"); - else if (nRequests > 0) - strHTML += tr(", broadcast through %n node(s)", "", nRequests); - } strHTML += "<br>"; strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index b6ed66ad96..65f5e87d15 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -195,10 +195,6 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int if (wtx.is_in_main_chain) { status.matures_in = wtx.blocks_to_maturity; - - // Check if the block was requested by anyone - if (adjustedTime - wtx.time_received > 2 * 60 && wtx.request_count == 0) - status.status = TransactionStatus::MaturesWarning; } else { @@ -216,10 +212,6 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int { status.status = TransactionStatus::Conflicted; } - else if (adjustedTime - wtx.time_received > 2 * 60 && wtx.request_count == 0) - { - status.status = TransactionStatus::Offline; - } else if (status.depth == 0) { status.status = TransactionStatus::Unconfirmed; diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 62961434ed..a6424e74fa 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -25,7 +25,7 @@ class TransactionStatus public: TransactionStatus(): countsForBalance(false), sortKey(""), - matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1) + matures_in(0), status(Unconfirmed), depth(0), open_for(0), cur_num_blocks(-1) { } enum Status { @@ -33,14 +33,12 @@ public: /// Normal (sent/received) transactions OpenUntilDate, /**< Transaction not yet final, waiting for date */ OpenUntilBlock, /**< Transaction not yet final, waiting for block */ - Offline, /**< Not sent to any other nodes **/ Unconfirmed, /**< Not yet mined into a block **/ Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/ Conflicted, /**< Conflicts with other transaction or mempool **/ Abandoned, /**< Abandoned from the wallet **/ /// Generated (mined) transactions Immature, /**< Mined but waiting for maturity */ - MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */ NotAccepted /**< Mined but not accepted */ }; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 46169a91d1..63a4afe191 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -286,9 +286,6 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons case TransactionStatus::OpenUntilDate: status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for)); break; - case TransactionStatus::Offline: - status = tr("Offline"); - break; case TransactionStatus::Unconfirmed: status = tr("Unconfirmed"); break; @@ -307,9 +304,6 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons case TransactionStatus::Immature: status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in); break; - case TransactionStatus::MaturesWarning: - status = tr("This block was not received by any other nodes and will probably not be accepted!"); - break; case TransactionStatus::NotAccepted: status = tr("Generated but not accepted"); break; @@ -447,8 +441,6 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) case TransactionStatus::OpenUntilBlock: case TransactionStatus::OpenUntilDate: return COLOR_TX_STATUS_OPENUNTILDATE; - case TransactionStatus::Offline: - return COLOR_TX_STATUS_OFFLINE; case TransactionStatus::Unconfirmed: return QIcon(":/icons/transaction_0"); case TransactionStatus::Abandoned: @@ -471,7 +463,6 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) int part = (wtx->status.depth * 4 / total) + 1; return QIcon(QString(":/icons/transaction_%1").arg(part)); } - case TransactionStatus::MaturesWarning: case TransactionStatus::NotAccepted: return QIcon(":/icons/transaction_0"); default: diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 6df5aec9c9..fac7418cba 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_bitcoin.cpp b/src/test/test_bitcoin.cpp index e9814edc23..6ede65c23a 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -46,35 +46,43 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) } 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(); - SetupEnvironment(); - SetupNetworking(); - InitSignatureCache(); - InitScriptExecutionCache(); - fCheckBlockIndex = true; - SelectParams(chainName); - noui_connect(); + SHA256AutoDetect(); + RandomInit(); + ECC_Start(); + SetupEnvironment(); + SetupNetworking(); + InitSignatureCache(); + InitScriptExecutionCache(); + fCheckBlockIndex = true; + SelectParams(chainName); + noui_connect(); } BasicTestingSetup::~BasicTestingSetup() { - 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_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))); - 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. @@ -114,7 +122,6 @@ TestingSetup::~TestingSetup() pcoinsTip.reset(); pcoinsdbview.reset(); pblocktree.reset(); - fs::remove_all(pathTemp); } TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST) diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index d013613de2..88b2d37e87 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -45,6 +45,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. @@ -59,7 +64,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 611ccc9b77..d535f74e91 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1100,7 +1100,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 @@ -1188,12 +1188,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/validationinterface.cpp b/src/validationinterface.cpp index 55aa5c2cdf..aff4c44cea 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -25,7 +25,6 @@ struct MainSignalsInstance { boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected; boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool; boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed; - boost::signals2::signal<void (const uint256 &)> Inventory; boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast; boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked; boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock; @@ -80,7 +79,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1)); g_signals.m_internals->ChainStateFlushed.connect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1)); - g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.m_internals->NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); @@ -89,7 +87,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); - g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.m_internals->ChainStateFlushed.disconnect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1)); g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); @@ -105,7 +102,6 @@ void UnregisterAllValidationInterfaces() { } g_signals.m_internals->BlockChecked.disconnect_all_slots(); g_signals.m_internals->Broadcast.disconnect_all_slots(); - g_signals.m_internals->Inventory.disconnect_all_slots(); g_signals.m_internals->ChainStateFlushed.disconnect_all_slots(); g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots(); g_signals.m_internals->BlockConnected.disconnect_all_slots(); @@ -171,12 +167,6 @@ void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) { }); } -void CMainSignals::Inventory(const uint256 &hash) { - m_internals->m_schedulerClient.AddToProcessQueue([hash, this] { - m_internals->Inventory(hash); - }); -} - void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) { m_internals->Broadcast(nBestBlockTime, connman); } diff --git a/src/validationinterface.h b/src/validationinterface.h index 0ca82235da..42cc2e9a20 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -117,12 +117,6 @@ protected: * Called on a background thread. */ virtual void ChainStateFlushed(const CBlockLocator &locator) {} - /** - * Notifies listeners about an inventory item being seen on the network. - * - * Called on a background thread. - */ - virtual void Inventory(const uint256 &hash) {} /** Tells listeners to broadcast their data. */ virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} /** @@ -173,7 +167,6 @@ public: void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &); void BlockDisconnected(const std::shared_ptr<const CBlock> &); void ChainStateFlushed(const CBlockLocator &); - void Inventory(const uint256 &); void Broadcast(int64_t nBestBlockTime, CConnman* connman); void BlockChecked(const CBlock&, const CValidationState&); void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&); diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 4c0c8ff5ec..52842cd978 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -116,7 +116,7 @@ class CCryptoKeyStore : public CBasicKeyStore { private: - CKeyingMaterial vMasterKey; + CKeyingMaterial vMasterKey GUARDED_BY(cs_KeyStore); //! if fUseCrypto is true, mapKeys must be empty //! if fUseCrypto is false, vMasterKey must be empty @@ -126,13 +126,15 @@ private: bool fDecryptionThoroughlyChecked; protected: + using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>; + bool SetCrypted(); //! will encrypt previously unencrypted keys bool EncryptKeys(CKeyingMaterial& vMasterKeyIn); bool Unlock(const CKeyingMaterial& vMasterKeyIn); - CryptedKeyMap mapCryptedKeys; + CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore); public: CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false) diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 03754154fc..a946b565f1 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -130,6 +130,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. { std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy()); @@ -139,7 +141,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); @@ -152,7 +154,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); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 506c4ee341..3de0c0ad08 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1227,10 +1227,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) } } -void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock) { +void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock, bool update_tx) { const CTransaction& tx = *ptx; - if (!AddToWalletIfInvolvingMe(ptx, pindex, posInBlock, true)) + if (!AddToWalletIfInvolvingMe(ptx, pindex, posInBlock, update_tx)) return; // Not one of ours // If a transaction changes 'conflicted' state, that changes the balance @@ -1532,45 +1532,6 @@ int64_t CWalletTx::GetTxTime() const return n ? n : nTimeReceived; } -int CWalletTx::GetRequestCount() const -{ - // Returns -1 if it wasn't being tracked - int nRequests = -1; - { - LOCK(pwallet->cs_wallet); - if (IsCoinBase()) - { - // Generated block - if (!hashUnset()) - { - std::map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); - if (mi != pwallet->mapRequestCount.end()) - nRequests = (*mi).second; - } - } - else - { - // Did anyone request this transaction? - std::map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash()); - if (mi != pwallet->mapRequestCount.end()) - { - nRequests = (*mi).second; - - // How about the block it's in? - if (nRequests == 0 && !hashUnset()) - { - std::map<uint256, int>::const_iterator _mi = pwallet->mapRequestCount.find(hashBlock); - if (_mi != pwallet->mapRequestCount.end()) - nRequests = (*_mi).second; - else - nRequests = 1; // If it's in someone else's block it must have got out - } - } - } - } - return nRequests; -} - // Helper for producing a max-sized low-S signature (eg 72 bytes) bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout) const { @@ -1797,7 +1758,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock break; } for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) { - AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate); + SyncTransaction(block.vtx[posInBlock], pindex, posInBlock, fUpdate); } } else { ret = pindex; @@ -3145,9 +3106,6 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve } } - // Track how many getdata requests our transaction gets - mapRequestCount[wtxNew.GetHash()] = 0; - // Get the inserted-CWalletTx from mapWallet so that the // fInMempool flag is cached properly CWalletTx& wtx = mapWallet.at(wtxNew.GetHash()); @@ -3210,8 +3168,11 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) } } - // This wallet is in its first run if all of these are empty - fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty(); + { + LOCK(cs_KeyStore); + // This wallet is in its first run if all of these are empty + fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty(); + } if (nLoadWalletRet != DBErrors::LOAD_OK) return nLoadWalletRet; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 663538dc01..d3c9b692ac 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -485,7 +485,6 @@ public: bool IsTrusted() const; int64_t GetTxTime() const; - int GetRequestCount() const; // RelayWalletTransaction may only be called if fBroadcastTransactions! bool RelayWalletTransaction(CConnman* connman); @@ -708,9 +707,9 @@ private: void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>); - /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected. + /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions. * Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */ - void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0, bool update_tx = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); /* the HD chain data model (external chain counters) */ CHDChain hdChain; @@ -819,7 +818,6 @@ public: int64_t nOrderPosNext = 0; uint64_t nAccountingEntryNumber = 0; - std::map<uint256, int> mapRequestCount; std::map<CTxDestination, CAddressBookData> mapAddressBook; @@ -1063,16 +1061,6 @@ public: const std::string& GetLabelName(const CScript& scriptPubKey) const; - void Inventory(const uint256 &hash) override - { - { - LOCK(cs_wallet); - std::map<uint256, int>::iterator mi = mapRequestCount.find(hash); - if (mi != mapRequestCount.end()) - (*mi).second++; - } - } - void GetScriptForMining(std::shared_ptr<CReserveScript> &script); unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index af2e752b7a..def71c5f0f 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -3,10 +3,10 @@ # 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 test_framework.test_framework import BitcoinTestFramework, SkipTest +from test_framework.test_framework import ( + BitcoinTestFramework, skip_if_no_bitcoind_zmq, skip_if_no_py3_zmq) from test_framework.mininode import CTransaction from test_framework.util import (assert_equal, bytes_to_hex_str, @@ -38,18 +38,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 bitcoin 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("bitcoind 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/p2p_segwit.py b/test/functional/p2p_segwit.py index 727f2d1c6e..801c4b87a0 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -41,6 +41,7 @@ from test_framework.messages import ( from test_framework.mininode import ( P2PInterface, mininode_lock, + wait_until, ) from test_framework.script import ( CScript, @@ -221,7 +222,7 @@ class SegWitTest(BitcoinTestFramework): block.solve() def run_test(self): - # Setup the p2p connections and start up the network thread. + # Setup the p2p connections # self.test_node sets NODE_WITNESS|NODE_NETWORK self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK | NODE_WITNESS) # self.old_node sets only NODE_NETWORK @@ -351,10 +352,7 @@ class SegWitTest(BitcoinTestFramework): # Sending witness data before activation is not allowed (anti-spam # rule). test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False) - # TODO: fix synchronization so we can test reject reason - # Right now, bitcoind delays sending reject messages for blocks - # until the future, making synchronization here difficult. - # assert_equal(self.test_node.last_message["reject"].reason, "unexpected-witness") + wait_until(lambda: 'reject' in self.test_node.last_message and self.test_node.last_message["reject"].reason == b"unexpected-witness") # But it should not be permanently marked bad... # Resend without witness information. @@ -605,9 +603,6 @@ class SegWitTest(BitcoinTestFramework): @subtest def advance_to_segwit_lockin(self): """Mine enough blocks to lock in segwit, but don't activate.""" - # TODO: we could verify that lockin only happens at the right threshold of - # signalling blocks, rather than just at the right period boundary. - height = self.nodes[0].getblockcount() # Advance to end of period, and verify lock-in happens at the end self.nodes[0].generate(VB_PERIOD - 1) @@ -741,9 +736,6 @@ class SegWitTest(BitcoinTestFramework): @subtest def advance_to_segwit_active(self): """Mine enough blocks to activate segwit.""" - # TODO: we could verify that activation only happens at the right threshold - # of signalling blocks, rather than just at the right period boundary. - height = self.nodes[0].getblockcount() self.nodes[0].generate(VB_PERIOD - (height % VB_PERIOD) - 2) assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in') @@ -1402,30 +1394,28 @@ class SegWitTest(BitcoinTestFramework): Future segwit version transactions are non-standard, but valid in blocks. Can run this before and after segwit activation.""" - num_tests = 17 # will test OP_0, OP1, ..., OP_16 - if (len(self.utxo) < num_tests): + NUM_SEGWIT_VERSIONS = 17 # will test OP_0, OP1, ..., OP_16 + if len(self.utxo) < NUM_SEGWIT_VERSIONS: tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - split_value = (self.utxo[0].nValue - 4000) // num_tests - for i in range(num_tests): + split_value = (self.utxo[0].nValue - 4000) // NUM_SEGWIT_VERSIONS + for i in range(NUM_SEGWIT_VERSIONS): tx.vout.append(CTxOut(split_value, CScript([OP_TRUE]))) tx.rehash() block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) self.utxo.pop(0) - for i in range(num_tests): + for i in range(NUM_SEGWIT_VERSIONS): self.utxo.append(UTXO(tx.sha256, i, split_value)) sync_blocks(self.nodes) temp_utxo = [] tx = CTransaction() - count = 0 witness_program = CScript([OP_TRUE]) witness_hash = sha256(witness_program) assert_equal(len(self.nodes[1].getrawmempool()), 0) for version in list(range(OP_1, OP_16 + 1)) + [OP_0]: - count += 1 # First try to spend to a future version segwit script_pubkey. script_pubkey = CScript([CScriptOp(version), witness_hash]) tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")] @@ -1680,19 +1670,19 @@ class SegWitTest(BitcoinTestFramework): # Test combinations of signature hashes. # Split the utxo into a lot of outputs. # Randomly choose up to 10 to spend, sign with different hashtypes, and - # output to a random number of outputs. Repeat num_tests times. + # output to a random number of outputs. Repeat NUM_SIGHASH_TESTS times. # Ensure that we've tested a situation where we use SIGHASH_SINGLE with # an input index > number of outputs. - num_tests = 500 + NUM_SIGHASH_TESTS = 500 temp_utxos = [] tx = CTransaction() tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b"")) - split_value = prev_utxo.nValue // num_tests - for i in range(num_tests): + split_value = prev_utxo.nValue // NUM_SIGHASH_TESTS + for i in range(NUM_SIGHASH_TESTS): tx.vout.append(CTxOut(split_value, script_pubkey)) tx.wit.vtxinwit.append(CTxInWitness()) sign_p2pk_witness_input(witness_program, tx, 0, SIGHASH_ALL, prev_utxo.nValue, key) - for i in range(num_tests): + for i in range(NUM_SIGHASH_TESTS): temp_utxos.append(UTXO(tx.sha256, i, split_value)) block = self.build_next_block() @@ -1701,7 +1691,7 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() used_sighash_single_out_of_bounds = False - for i in range(num_tests): + for i in range(NUM_SIGHASH_TESTS): # Ping regularly to keep the connection alive if (not i % 100): self.test_node.sync_with_ping() 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 abe8d12e59..c2fb2077ac 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -475,3 +475,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 bitcoind 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("bitcoind has not been built with zmq enabled.") |