diff options
32 files changed, 168 insertions, 195 deletions
diff --git a/build-aux/m4/ax_boost_chrono.m4 b/build-aux/m4/ax_boost_chrono.m4 index 318ecea17f..e9b0f2061c 100644 --- a/build-aux/m4/ax_boost_chrono.m4 +++ b/build-aux/m4/ax_boost_chrono.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html # =========================================================================== # # SYNOPSIS @@ -8,7 +8,7 @@ # # DESCRIPTION # -# Test for System library from the Boost C++ libraries. The macro requires +# Test for Chrono library from the Boost C++ libraries. The macro requires # a preceding call to AX_BOOST_BASE. Further documentation is available at # <http://randspringer.de/boost/index.html>. # @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 1 +#serial 4 AC_DEFUN([AX_BOOST_CHRONO], [ @@ -68,7 +68,7 @@ AC_DEFUN([AX_BOOST_CHRONO], CXXFLAGS_SAVE=$CXXFLAGS AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/chrono.hpp>]], - [[boost::chrono::system_clock::time_point time;]])], + [[boost::chrono::system_clock::time_point* time = new boost::chrono::system_clock::time_point; delete time;]])], ax_cv_boost_chrono=yes, ax_cv_boost_chrono=no) CXXFLAGS=$CXXFLAGS_SAVE AC_LANG_POP([C++]) diff --git a/build-aux/m4/ax_boost_unit_test_framework.m4 b/build-aux/m4/ax_boost_unit_test_framework.m4 index 4efd1e2f18..0cdbe752cf 100644 --- a/build-aux/m4/ax_boost_unit_test_framework.m4 +++ b/build-aux/m4/ax_boost_unit_test_framework.m4 @@ -1,6 +1,6 @@ -# ================================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html -# ================================================================================ +# ================================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html +# ================================================================================= # # SYNOPSIS # @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 19 +#serial 21 AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], [ @@ -66,7 +66,7 @@ AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], [AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/test/unit_test.hpp>]], [[using boost::unit_test::test_suite; - test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); return 0;]])], + test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); if (test == NULL) { return 1; } else { return 0; }]])], ax_cv_boost_unit_test_framework=yes, ax_cv_boost_unit_test_framework=no) AC_LANG_POP([C++]) ]) diff --git a/configure.ac b/configure.ac index 18f707f0ba..4f57750a1a 100644 --- a/configure.ac +++ b/configure.ac @@ -643,22 +643,6 @@ AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64],,, AC_CHECK_DECLS([__builtin_clz, __builtin_clzl, __builtin_clzll]) -dnl Check for MSG_NOSIGNAL -AC_MSG_CHECKING(for MSG_NOSIGNAL) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], - [[ int f = MSG_NOSIGNAL; ]])], - [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MSG_NOSIGNAL, 1,[Define this symbol if you have MSG_NOSIGNAL]) ], - [ AC_MSG_RESULT(no)] -) - -dnl Check for MSG_DONTWAIT -AC_MSG_CHECKING(for MSG_DONTWAIT) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], - [[ int f = MSG_DONTWAIT; ]])], - [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MSG_DONTWAIT, 1,[Define this symbol if you have MSG_DONTWAIT]) ], - [ AC_MSG_RESULT(no)] -) - dnl Check for malloc_info (for memory statistics information in getmemoryinfo) AC_MSG_CHECKING(for getmemoryinfo) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <malloc.h>]], @@ -771,7 +755,7 @@ dnl Check for libminiupnpc (optional) if test x$use_upnp != xno; then AC_CHECK_HEADERS( [miniupnpc/miniwget.h miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h], - [AC_CHECK_LIB([miniupnpc], [main],[MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])], + [AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])], [have_miniupnpc=no] ) fi diff --git a/doc/developer-notes.md b/doc/developer-notes.md index a5468c3be3..8f06ee4eca 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -710,3 +710,14 @@ A few guidelines for introducing and reviewing new RPC interfaces: client may be aware of prior to entering a wallet RPC call, we must block until the wallet is caught up to the chainstate as of the RPC call's entry. This also makes the API much easier for RPC clients to reason about. + +- Be aware of RPC method aliases and generally avoid registering the same + callback function pointer for different RPCs. + + - *Rationale*: RPC methods registered with the same function pointer will be + considered aliases and only the first method name will show up in the + `help` rpc command list. + + - *Exception*: Using RPC method aliases may be appropriate in cases where a + new RPC is replacing a deprecated RPC, to avoid both RPCs confusingly + showing up in the command list. diff --git a/src/net.cpp b/src/net.cpp index 53a0a9b180..4849e067aa 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -42,12 +42,13 @@ // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization. #define FEELER_SLEEP_WINDOW 1 -#if !defined(HAVE_MSG_NOSIGNAL) +// MSG_NOSIGNAL is not available on some platforms, if it doesn't exist define it as 0 +#if !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif // MSG_DONTWAIT is not available on some platforms, if it doesn't exist define it as 0 -#if !defined(HAVE_MSG_DONTWAIT) +#if !defined(MSG_DONTWAIT) #define MSG_DONTWAIT 0 #endif diff --git a/src/netbase.cpp b/src/netbase.cpp index 3ea3141d5e..92ac1c4c85 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -21,7 +21,7 @@ #include <boost/algorithm/string/case_conv.hpp> // for to_lower() #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith() -#if !defined(HAVE_MSG_NOSIGNAL) +#if !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 4f9a79d654..801334483a 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -441,6 +441,8 @@ int AddressTableModel::lookupAddress(const QString &address) const } } +OutputType AddressTableModel::GetDefaultAddressType() const { return wallet->m_default_address_type; }; + void AddressTableModel::emitDataChanged(int idx) { Q_EMIT dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex())); diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index 11439e25d5..ed7a4e6f43 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -8,7 +8,7 @@ #include <QAbstractTableModel> #include <QStringList> -enum OutputType : int; +enum class OutputType; class AddressTablePriv; class WalletModel; @@ -76,6 +76,8 @@ public: EditStatus getEditStatus() const { return editStatus; } + OutputType GetDefaultAddressType() const; + private: WalletModel *walletModel; CWallet *wallet; diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index a945fc6aa0..ba2f7d0d1d 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -11,7 +11,6 @@ #include <QDataWidgetMapper> #include <QMessageBox> -extern OutputType g_address_type; EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) : QDialog(parent), @@ -80,7 +79,7 @@ bool EditAddressDialog::saveCurrentRow() mode == NewSendingAddress ? AddressTableModel::Send : AddressTableModel::Receive, ui->labelEdit->text(), ui->addressEdit->text(), - g_address_type); + model->GetDefaultAddressType()); break; case EditReceivingAddress: case EditSendingAddress: diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 4b6fdc8d57..92d7d72935 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -643,7 +643,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, const SendCoinsRecipient& r // use for change. Despite an actual payment and not change, this is a close match: // it's the output type we use subject to privacy issues, but not restricted by what // other software supports. - const OutputType change_type = g_change_type != OUTPUT_TYPE_NONE ? g_change_type : g_address_type; + const OutputType change_type = wallet->m_default_change_type != OutputType::NONE ? wallet->m_default_change_type : wallet->m_default_address_type; wallet->LearnRelatedScripts(newKey, change_type); CTxDestination dest = GetDestinationForKey(newKey, change_type); wallet->SetAddressBook(dest, strAccount, "refund"); diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 7fd5285467..132fb54d66 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -95,13 +95,13 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this); // configure bech32 checkbox, disable if launched with legacy as default: - if (model->getDefaultAddressType() == OUTPUT_TYPE_BECH32) { + if (model->getDefaultAddressType() == OutputType::BECH32) { ui->useBech32->setCheckState(Qt::Checked); } else { ui->useBech32->setCheckState(Qt::Unchecked); } - ui->useBech32->setVisible(model->getDefaultAddressType() != OUTPUT_TYPE_LEGACY); + ui->useBech32->setVisible(model->getDefaultAddressType() != OutputType::LEGACY); } } @@ -145,8 +145,8 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() QString label = ui->reqLabel->text(); /* Generate new receiving address */ OutputType address_type = model->getDefaultAddressType(); - if (address_type != OUTPUT_TYPE_LEGACY) { - address_type = ui->useBech32->isChecked() ? OUTPUT_TYPE_BECH32 : OUTPUT_TYPE_P2SH_SEGWIT; + if (address_type != OutputType::LEGACY) { + address_type = ui->useBech32->isChecked() ? OutputType::BECH32 : OutputType::P2SH_SEGWIT; } address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type); SendCoinsRecipient info(address, label, diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 976aadc0af..c9898e52ca 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -150,9 +150,6 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st // src/qt/test/test_bitcoin-qt -platform cocoa # macOS void TestGUI() { - g_address_type = OUTPUT_TYPE_P2SH_SEGWIT; - g_change_type = OUTPUT_TYPE_P2SH_SEGWIT; - // Set up wallet and chain with 105 blocks (5 mature blocks for spending). TestChain100Setup test; for (int i = 0; i < 5; ++i) { @@ -163,7 +160,7 @@ void TestGUI() wallet.LoadWallet(firstRun); { LOCK(wallet.cs_wallet); - wallet.SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), g_address_type), "", "receive"); + wallet.SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet.m_default_address_type), "", "receive"); wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); } { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 39ef20c835..5e7aefb187 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -736,7 +736,7 @@ bool WalletModel::hdEnabled() const OutputType WalletModel::getDefaultAddressType() const { - return g_address_type; + return wallet->m_default_address_type; } int WalletModel::getDefaultConfirmTarget() const diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 811996b98f..64813e0f5a 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -20,7 +20,7 @@ #include <QObject> -enum OutputType : int; +enum class OutputType; class AddressTableModel; class OptionsModel; diff --git a/src/rpc/server.h b/src/rpc/server.h index 8b32924fbc..d25268a8ab 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -165,8 +165,17 @@ public: /** * Appends a CRPCCommand to the dispatch table. + * * Returns false if RPC server is already running (dump concurrency protection). + * * Commands cannot be overwritten (returns false). + * + * Commands with different method names but the same callback function will + * be considered aliases, and only the first registered method name will + * show up in the help text command listing. Aliased commands do not have + * to have the same behavior. Server and client code can distinguish + * between calls based on method name, and aliased commands can also + * register different names, types, and numbers of parameters. */ bool appendCommand(const std::string& name, const CRPCCommand* pcmd); }; diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 593962e710..e72b1c4840 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -4,7 +4,6 @@ #include <key_io.h> #include <keystore.h> -#include <pubkey.h> #include <rpc/protocol.h> #include <rpc/util.h> #include <tinyformat.h> diff --git a/src/rpc/util.h b/src/rpc/util.h index 5380d45a83..c6a79d5cf9 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -8,7 +8,6 @@ #include <pubkey.h> #include <script/standard.h> #include <univalue.h> -#include <utilstrencodings.h> #include <boost/variant/static_visitor.hpp> diff --git a/src/util.cpp b/src/util.cpp index 62cdce3012..94f829ad32 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -4,7 +4,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <util.h> -#include <fs.h> #include <chainparamsbase.h> #include <random.h> diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 458e770e03..52d6a291c9 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -18,8 +18,8 @@ class CCoinControl public: //! Custom change destination, if not set an address is generated CTxDestination destChange; - //! Custom change type, ignored if destChange is set, defaults to g_change_type - OutputType change_type; + //! Override the default change type if set, ignored if destChange is set + boost::optional<OutputType> m_change_type; //! If false, allows unselected inputs, but requires all selected inputs be used bool fAllowOtherInputs; //! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria @@ -43,7 +43,7 @@ public: void SetNull() { destChange = CNoDestination(); - change_type = g_change_type; + m_change_type.reset(); fAllowOtherInputs = false; fAllowWatchOnly = false; setSelected.clear(); diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index e028cf4210..61481e01b6 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -17,7 +17,7 @@ std::string GetWalletHelpString(bool showDebug) { std::string strUsage = HelpMessageGroup(_("Wallet options:")); - strUsage += HelpMessageOpt("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(OUTPUT_TYPE_DEFAULT))); + strUsage += HelpMessageOpt("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE))); strUsage += HelpMessageOpt("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)"); strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-discardfee=<amt>", strprintf(_("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). " @@ -181,18 +181,6 @@ bool WalletParameterInteraction() bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); fWalletRbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF); - g_address_type = ParseOutputType(gArgs.GetArg("-addresstype", "")); - if (g_address_type == OUTPUT_TYPE_NONE) { - return InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", ""))); - } - - // If changetype is set in config file or parameter, check that it's valid. - // Default to OUTPUT_TYPE_NONE if not set. - g_change_type = ParseOutputType(gArgs.GetArg("-changetype", ""), OUTPUT_TYPE_NONE); - if (g_change_type == OUTPUT_TYPE_NONE && !gArgs.GetArg("-changetype", "").empty()) { - return InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", ""))); - } - return true; } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 01125dd618..1721bc6df6 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -83,7 +83,7 @@ bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyid, std: } } if (!fLabelFound) { - strAddr = EncodeDestination(GetDestinationForKey(key.GetPubKey(), g_address_type)); + strAddr = EncodeDestination(GetDestinationForKey(key.GetPubKey(), pwallet->m_default_address_type)); } return fLabelFound; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7ad9efff70..9aae1a5e55 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -162,10 +162,10 @@ UniValue getnewaddress(const JSONRPCRequest& request) if (!request.params[0].isNull()) strAccount = AccountFromValue(request.params[0]); - OutputType output_type = g_address_type; + OutputType output_type = pwallet->m_default_address_type; if (!request.params[1].isNull()) { - output_type = ParseOutputType(request.params[1].get_str(), g_address_type); - if (output_type == OUTPUT_TYPE_NONE) { + output_type = ParseOutputType(request.params[1].get_str(), pwallet->m_default_address_type); + if (output_type == OutputType::NONE) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str())); } } @@ -259,10 +259,10 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) pwallet->TopUpKeyPool(); } - OutputType output_type = g_change_type != OUTPUT_TYPE_NONE ? g_change_type : g_address_type; + OutputType output_type = pwallet->m_default_change_type != OutputType::NONE ? pwallet->m_default_change_type : pwallet->m_default_address_type; if (!request.params[0].isNull()) { output_type = ParseOutputType(request.params[0].get_str(), output_type); - if (output_type == OUTPUT_TYPE_NONE) { + if (output_type == OutputType::NONE) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str())); } } @@ -1221,10 +1221,10 @@ UniValue addmultisigaddress(const JSONRPCRequest& request) } } - OutputType output_type = g_address_type; + OutputType output_type = pwallet->m_default_address_type; if (!request.params[3].isNull()) { output_type = ParseOutputType(request.params[3].get_str(), output_type); - if (output_type == OUTPUT_TYPE_NONE) { + if (output_type == OutputType::NONE) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str())); } } @@ -3183,8 +3183,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) if (options.exists("changeAddress")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options"); } - coinControl.change_type = ParseOutputType(options["change_type"].get_str(), coinControl.change_type); - if (coinControl.change_type == OUTPUT_TYPE_NONE) { + coinControl.m_change_type = ParseOutputType(options["change_type"].get_str(), pwallet->m_default_change_type); + if (coinControl.m_change_type == OutputType::NONE) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str())); } } diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 77ccd0b8d8..5c550742c8 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -12,8 +12,6 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): TestingSetup(chainName), m_wallet("mock", CWalletDBWrapper::CreateMock()) { bool fFirstRun; - g_address_type = OUTPUT_TYPE_DEFAULT; - g_change_type = OUTPUT_TYPE_DEFAULT; m_wallet.LoadWallet(fFirstRun); RegisterValidationInterface(&m_wallet); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index d6b0daf4fe..808f8b8838 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -114,9 +114,6 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // than or equal to key birthday. BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { - g_address_type = OUTPUT_TYPE_DEFAULT; - g_change_type = OUTPUT_TYPE_DEFAULT; - // Create two blocks with same timestamp to verify that importwallet rescan // will pick up both blocks, not just the first. const int64_t BLOCK_TIME = chainActive.Tip()->GetBlockTimeMax() + 5; @@ -272,8 +269,6 @@ public: ListCoinsTestingSetup() { CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); - g_address_type = OUTPUT_TYPE_DEFAULT; - g_change_type = OUTPUT_TYPE_DEFAULT; wallet = MakeUnique<CWallet>("mock", CWalletDBWrapper::CreateMock()); bool firstRun; wallet->LoadWallet(firstRun); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bd5094085e..3f1a2c1990 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -42,8 +42,6 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; bool fWalletRbf = DEFAULT_WALLET_RBF; -OutputType g_address_type = OUTPUT_TYPE_NONE; -OutputType g_change_type = OUTPUT_TYPE_NONE; bool g_wallet_allow_fallback_fee = true; //<! will be defined via chainparams const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; @@ -823,7 +821,7 @@ bool CWallet::GetAccountDestination(CTxDestination &dest, std::string strAccount bForceNew = true; else { // Check if the current key has been used (TODO: check other addresses with the same key) - CScript scriptPubKey = GetScriptForDestination(GetDestinationForKey(account.vchPubKey, g_address_type)); + CScript scriptPubKey = GetScriptForDestination(GetDestinationForKey(account.vchPubKey, m_default_address_type)); for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end() && account.vchPubKey.IsValid(); ++it) @@ -840,12 +838,12 @@ bool CWallet::GetAccountDestination(CTxDestination &dest, std::string strAccount if (!GetKeyFromPool(account.vchPubKey, false)) return false; - LearnRelatedScripts(account.vchPubKey, g_address_type); - dest = GetDestinationForKey(account.vchPubKey, g_address_type); + LearnRelatedScripts(account.vchPubKey, m_default_address_type); + dest = GetDestinationForKey(account.vchPubKey, m_default_address_type); SetAddressBook(dest, strAccount, "receive"); walletdb.WriteAccount(strAccount, account); } else { - dest = GetDestinationForKey(account.vchPubKey, g_address_type); + dest = GetDestinationForKey(account.vchPubKey, m_default_address_type); } return true; @@ -2649,14 +2647,14 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend) { // If -changetype is specified, always use that change type. - if (change_type != OUTPUT_TYPE_NONE) { + if (change_type != OutputType::NONE) { return change_type; } - // if g_address_type is legacy, use legacy address as change (even + // if m_default_address_type is legacy, use legacy address as change (even // if some of the outputs are P2WPKH or P2WSH). - if (g_address_type == OUTPUT_TYPE_LEGACY) { - return OUTPUT_TYPE_LEGACY; + if (m_default_address_type == OutputType::LEGACY) { + return OutputType::LEGACY; } // if any destination is P2WPKH or P2WSH, use P2WPKH for the change @@ -2666,12 +2664,12 @@ OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vec int witnessversion = 0; std::vector<unsigned char> witnessprogram; if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { - return OUTPUT_TYPE_BECH32; + return OutputType::BECH32; } } - // else use g_address_type for change - return g_address_type; + // else use m_default_address_type for change + return m_default_address_type; } bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, @@ -2768,7 +2766,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac return false; } - const OutputType change_type = TransactionChangeType(coin_control.change_type, vecSend); + const OutputType change_type = TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend); LearnRelatedScripts(vchPubKey, change_type); scriptChange = GetScriptForDestination(GetDestinationForKey(vchPubKey, change_type)); @@ -4002,8 +4000,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& } walletInstance->SetBestChain(chainActive.GetLocator()); - } - else if (gArgs.IsArgSet("-usehd")) { + } else if (gArgs.IsArgSet("-usehd")) { bool useHD = gArgs.GetBoolArg("-usehd", true); if (walletInstance->IsHDEnabled() && !useHD) { InitError(strprintf(_("Error loading %s: You can't disable HD on an already existing HD wallet"), walletFile)); @@ -4015,6 +4012,20 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& } } + walletInstance->m_default_address_type = ParseOutputType(gArgs.GetArg("-addresstype", ""), DEFAULT_ADDRESS_TYPE); + if (walletInstance->m_default_address_type == OutputType::NONE) { + InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", ""))); + return nullptr; + } + + // If changetype is set in config file or parameter, check that it's valid. + // Default to OutputType::NONE if not set. + walletInstance->m_default_change_type = ParseOutputType(gArgs.GetArg("-changetype", ""), OutputType::NONE); + if (walletInstance->m_default_change_type == OutputType::NONE && !gArgs.GetArg("-changetype", "").empty()) { + InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", ""))); + return nullptr; + } + LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); // Try to top up keypool. No-op if the wallet is locked. @@ -4203,29 +4214,29 @@ OutputType ParseOutputType(const std::string& type, OutputType default_type) if (type.empty()) { return default_type; } else if (type == OUTPUT_TYPE_STRING_LEGACY) { - return OUTPUT_TYPE_LEGACY; + return OutputType::LEGACY; } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) { - return OUTPUT_TYPE_P2SH_SEGWIT; + return OutputType::P2SH_SEGWIT; } else if (type == OUTPUT_TYPE_STRING_BECH32) { - return OUTPUT_TYPE_BECH32; + return OutputType::BECH32; } else { - return OUTPUT_TYPE_NONE; + return OutputType::NONE; } } const std::string& FormatOutputType(OutputType type) { switch (type) { - case OUTPUT_TYPE_LEGACY: return OUTPUT_TYPE_STRING_LEGACY; - case OUTPUT_TYPE_P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT; - case OUTPUT_TYPE_BECH32: return OUTPUT_TYPE_STRING_BECH32; + case OutputType::LEGACY: return OUTPUT_TYPE_STRING_LEGACY; + case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT; + case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32; default: assert(false); } } void CWallet::LearnRelatedScripts(const CPubKey& key, OutputType type) { - if (key.IsCompressed() && (type == OUTPUT_TYPE_P2SH_SEGWIT || type == OUTPUT_TYPE_BECH32)) { + if (key.IsCompressed() && (type == OutputType::P2SH_SEGWIT || type == OutputType::BECH32)) { CTxDestination witdest = WitnessV0KeyHash(key.GetID()); CScript witprog = GetScriptForDestination(witdest); // Make sure the resulting program is solvable. @@ -4236,20 +4247,20 @@ void CWallet::LearnRelatedScripts(const CPubKey& key, OutputType type) void CWallet::LearnAllRelatedScripts(const CPubKey& key) { - // OUTPUT_TYPE_P2SH_SEGWIT always adds all necessary scripts for all types. - LearnRelatedScripts(key, OUTPUT_TYPE_P2SH_SEGWIT); + // OutputType::P2SH_SEGWIT always adds all necessary scripts for all types. + LearnRelatedScripts(key, OutputType::P2SH_SEGWIT); } CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type) { switch (type) { - case OUTPUT_TYPE_LEGACY: return key.GetID(); - case OUTPUT_TYPE_P2SH_SEGWIT: - case OUTPUT_TYPE_BECH32: { + case OutputType::LEGACY: return key.GetID(); + case OutputType::P2SH_SEGWIT: + case OutputType::BECH32: { if (!key.IsCompressed()) return key.GetID(); CTxDestination witdest = WitnessV0KeyHash(key.GetID()); CScript witprog = GetScriptForDestination(witdest); - if (type == OUTPUT_TYPE_P2SH_SEGWIT) { + if (type == OutputType::P2SH_SEGWIT) { return CScriptID(witprog); } else { return witdest; @@ -4275,10 +4286,10 @@ CTxDestination CWallet::AddAndGetDestinationForScript(const CScript& script, Out { // Note that scripts over 520 bytes are not yet supported. switch (type) { - case OUTPUT_TYPE_LEGACY: + case OutputType::LEGACY: return CScriptID(script); - case OUTPUT_TYPE_P2SH_SEGWIT: - case OUTPUT_TYPE_BECH32: { + case OutputType::P2SH_SEGWIT: + case OutputType::BECH32: { WitnessV0ScriptHash hash; CSHA256().Write(script.data(), script.size()).Finalize(hash.begin()); CTxDestination witdest = hash; @@ -4287,7 +4298,7 @@ CTxDestination CWallet::AddAndGetDestinationForScript(const CScript& script, Out if (!IsSolvable(*this, witprog)) return CScriptID(script); // Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours. AddCScript(witprog); - if (type == OUTPUT_TYPE_BECH32) { + if (type == OutputType::BECH32) { return witdest; } else { return CScriptID(witprog); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index dc0e8d07d7..5ac8457eb4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -43,6 +43,7 @@ extern bool bSpendZeroConfChange; extern bool fWalletRbf; extern bool g_wallet_allow_fallback_fee; +//! Default for -keypool static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000; //! -paytxfee default static const CAmount DEFAULT_TRANSACTION_FEE = 0; @@ -96,18 +97,15 @@ enum WalletFeature FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version }; -enum OutputType : int -{ - OUTPUT_TYPE_NONE, - OUTPUT_TYPE_LEGACY, - OUTPUT_TYPE_P2SH_SEGWIT, - OUTPUT_TYPE_BECH32, - - OUTPUT_TYPE_DEFAULT = OUTPUT_TYPE_P2SH_SEGWIT +enum class OutputType { + NONE, + LEGACY, + P2SH_SEGWIT, + BECH32, }; -extern OutputType g_address_type; -extern OutputType g_change_type; +//! Default for -addresstype +constexpr OutputType DEFAULT_ADDRESS_TYPE{OutputType::P2SH_SEGWIT}; /** A key pool entry */ @@ -989,6 +987,8 @@ public: static CFeeRate minTxFee; static CFeeRate fallbackFee; static CFeeRate m_discard_rate; + OutputType m_default_address_type{DEFAULT_ADDRESS_TYPE}; + OutputType m_default_change_type{OutputType::NONE}; // Default to OutputType::NONE if not set by -changetype bool NewKeyPool(); size_t KeypoolCountExternalKeys(); @@ -1232,7 +1232,7 @@ public: } }; -OutputType ParseOutputType(const std::string& str, OutputType default_type = OUTPUT_TYPE_DEFAULT); +OutputType ParseOutputType(const std::string& str, OutputType default_type); const std::string& FormatOutputType(OutputType type); /** diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index 49ad7f838c..8dfa1be2fa 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -11,7 +11,6 @@ This test takes 30 mins or more (up to 2 hours) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import time import os MIN_BLOCKS_TO_KEEP = 288 @@ -23,7 +22,7 @@ TIMESTAMP_WINDOW = 2 * 60 * 60 def calc_usage(blockdir): - return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f)) / (1024. * 1024.) + return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(os.path.join(blockdir, f))) / (1024. * 1024.) class PruneTest(BitcoinTestFramework): def set_test_params(self): @@ -70,7 +69,7 @@ class PruneTest(BitcoinTestFramework): sync_blocks(self.nodes[0:5]) def test_height_min(self): - if not os.path.isfile(self.prunedir+"blk00000.dat"): + if not os.path.isfile(os.path.join(self.prunedir, "blk00000.dat")): raise AssertionError("blk00000.dat is missing, pruning too early") self.log.info("Success") self.log.info("Though we're already using more than 550MiB, current usage: %d" % calc_usage(self.prunedir)) @@ -79,11 +78,8 @@ class PruneTest(BitcoinTestFramework): for i in range(25): mine_large_block(self.nodes[0], self.utxo_cache_0) - waitstart = time.time() - while os.path.isfile(self.prunedir+"blk00000.dat"): - time.sleep(0.1) - if time.time() - waitstart > 30: - raise AssertionError("blk00000.dat not pruned when it should be") + # Wait for blk00000.dat to be pruned + wait_until(lambda: not os.path.isfile(os.path.join(self.prunedir, "blk00000.dat")), timeout=30) self.log.info("Success") usage = calc_usage(self.prunedir) @@ -218,11 +214,8 @@ class PruneTest(BitcoinTestFramework): goalbestheight = first_reorg_height + 1 self.log.info("Verify node 2 reorged back to the main chain, some blocks of which it had to redownload") - waitstart = time.time() - while self.nodes[2].getblockcount() < goalbestheight: - time.sleep(0.1) - if time.time() - waitstart > 900: - raise AssertionError("Node 2 didn't reorg to proper height") + # Wait for Node 2 to reorg to proper height + wait_until(lambda: self.nodes[2].getblockcount() >= goalbestheight, timeout=900) assert(self.nodes[2].getbestblockhash() == goalbesthash) # Verify we can now have the data for a block previously pruned assert(self.nodes[2].getblock(self.forkhash)["height"] == self.forkheight) @@ -262,7 +255,7 @@ class PruneTest(BitcoinTestFramework): assert_equal(ret, expected_ret) def has_block(index): - return os.path.isfile(self.options.tmpdir + "/node{}/regtest/blocks/blk{:05}.dat".format(node_number, index)) + return os.path.isfile(os.path.join(self.nodes[node_number].datadir, "regtest", "blocks", "blk{:05}.dat".format(index))) # should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000) assert_raises_rpc_error(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500)) diff --git a/test/functional/feature_reindex.py b/test/functional/feature_reindex.py index ac67e6e9ba..d1d3f1d7f1 100755 --- a/test/functional/feature_reindex.py +++ b/test/functional/feature_reindex.py @@ -10,8 +10,7 @@ """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal -import time +from test_framework.util import wait_until class ReindexTest(BitcoinTestFramework): @@ -25,9 +24,7 @@ class ReindexTest(BitcoinTestFramework): self.stop_nodes() extra_args = [["-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]] self.start_nodes(extra_args) - while self.nodes[0].getblockcount() < blockcount: - time.sleep(0.1) - assert_equal(self.nodes[0].getblockcount(), blockcount) + wait_until(lambda: self.nodes[0].getblockcount() == blockcount) self.log.info("Success") def run_test(self): diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py index 5f34b35bfb..d8348432aa 100755 --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -7,8 +7,6 @@ Tests correspond to code in rpc/net.cpp. """ -import time - from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -62,12 +60,8 @@ class NetTest(BitcoinTestFramework): self.nodes[0].setnetworkactive(False) assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False) - timeout = 3 - while self.nodes[0].getnetworkinfo()['connections'] != 0: - # Wait a bit for all sockets to close - assert timeout > 0, 'not all connections closed in time' - timeout -= 0.1 - time.sleep(0.1) + # Wait a bit for all sockets to close + wait_until(lambda: self.nodes[0].getnetworkinfo()['connections'] == 0, timeout=3) self.nodes[0].setnetworkactive(True) connect_nodes_bi(self.nodes, 0, 1) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 7be695550b..68ac97d755 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -340,20 +340,15 @@ def disconnect_nodes(from_connection, node_num): for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]: from_connection.disconnectnode(nodeid=peer_id) - for _ in range(50): - if [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == []: - break - time.sleep(0.1) - else: - raise AssertionError("timed out waiting for disconnect") + # wait to disconnect + wait_until(lambda: [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == [], timeout=5) def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:" + str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") # poll until version handshake complete to avoid race conditions # with transaction relaying - while any(peer['version'] == 0 for peer in from_connection.getpeerinfo()): - time.sleep(0.1) + wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo())) def connect_nodes_bi(nodes, a, b): connect_nodes(nodes[a], b) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 082191098e..09f7f50de0 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -52,6 +52,9 @@ if os.name == 'posix': TEST_EXIT_PASSED = 0 TEST_EXIT_SKIPPED = 77 +# 20 minutes represented in seconds +TRAVIS_TIMEOUT_DURATION = 20 * 60 + BASE_SCRIPTS= [ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -233,29 +236,27 @@ def main(): sys.exit(0) # Build list of tests + test_list = [] if tests: # Individual tests have been specified. Run specified tests that exist # in the ALL_SCRIPTS list. Accept the name with or without .py extension. - tests = [re.sub("\.py$", "", t) + ".py" for t in tests] - test_list = [] - for t in tests: - if t in ALL_SCRIPTS: - test_list.append(t) + tests = [re.sub("\.py$", "", test) + ".py" for test in tests] + for test in tests: + if test in ALL_SCRIPTS: + test_list.append(test) else: - print("{}WARNING!{} Test '{}' not found in full test list.".format(BOLD[1], BOLD[0], t)) + print("{}WARNING!{} Test '{}' not found in full test list.".format(BOLD[1], BOLD[0], test)) + elif args.extended: + # Include extended tests + test_list += ALL_SCRIPTS else: - # No individual tests have been specified. - # Run all base tests, and optionally run extended tests. - test_list = BASE_SCRIPTS - if args.extended: - # place the EXTENDED_SCRIPTS first since the three longest ones - # are there and the list is shorter - test_list = EXTENDED_SCRIPTS + test_list + # Run base tests only + test_list += BASE_SCRIPTS # Remove the test cases that the user has explicitly asked to exclude. if args.exclude: - tests_excl = [re.sub("\.py$", "", t) + ".py" for t in args.exclude.split(',')] - for exclude_test in tests_excl: + exclude_tests = [re.sub("\.py$", "", test) + ".py" for test in args.exclude.split(',')] + for exclude_test in exclude_tests: if exclude_test in test_list: test_list.remove(exclude_test) else: @@ -320,7 +321,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove #Run Tests job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags) - time0 = time.time() + start_time = time.time() test_results = [] max_len_name = len(max(test_list, key=len)) @@ -346,7 +347,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove combined_logs, _ = subprocess.Popen([sys.executable, os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate() print("\n".join(deque(combined_logs.splitlines(), combined_logs_len))) - print_results(test_results, max_len_name, (int(time.time() - time0))) + print_results(test_results, max_len_name, (int(time.time() - start_time))) if coverage: coverage.report_rpc_coverage() @@ -403,15 +404,15 @@ class TestHandler: while self.num_running < self.num_jobs and self.test_list: # Add tests self.num_running += 1 - t = self.test_list.pop(0) + test = self.test_list.pop(0) portseed = len(self.test_list) + self.portseed_offset portseed_arg = ["--portseed={}".format(portseed)] log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) - test_argv = t.split() + test_argv = test.split() testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed) tmpdir_arg = ["--tmpdir={}".format(testdir)] - self.jobs.append((t, + self.jobs.append((test, time.time(), subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg, universal_newlines=True, @@ -425,15 +426,14 @@ class TestHandler: while True: # Return first proc that finishes time.sleep(.5) - for j in self.jobs: - (name, time0, proc, testdir, log_out, log_err) = j - if os.getenv('TRAVIS') == 'true' and int(time.time() - time0) > 20 * 60: - # In travis, timeout individual tests after 20 minutes (to stop tests hanging and not - # providing useful output. + for job in self.jobs: + (name, start_time, proc, testdir, log_out, log_err) = job + if os.getenv('TRAVIS') == 'true' and int(time.time() - start_time) > TRAVIS_TIMEOUT_DURATION: + # In travis, timeout individual tests (to stop tests hanging and not providing useful output). proc.send_signal(signal.SIGINT) if proc.poll() is not None: log_out.seek(0), log_err.seek(0) - [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] + [stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)] log_out.close(), log_err.close() if proc.returncode == TEST_EXIT_PASSED and stderr == "": status = "Passed" @@ -442,9 +442,9 @@ class TestHandler: else: status = "Failed" self.num_running -= 1 - self.jobs.remove(j) + self.jobs.remove(job) - return TestResult(name, status, int(time.time() - time0)), testdir, stdout, stderr + return TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr print('.', end='', flush=True) class TestResult(): @@ -490,7 +490,7 @@ def check_script_list(src_dir): Check that there are no scripts in the functional tests directory which are not being run by pull-tester.py.""" script_dir = src_dir + '/test/functional/' - python_files = set([t for t in os.listdir(script_dir) if t[-3:] == ".py"]) + python_files = set([test_file for test_file in os.listdir(script_dir) if test_file.endswith(".py")]) missed_tests = list(python_files - set(map(lambda x: x.split()[0], ALL_SCRIPTS + NON_SCRIPTS))) if len(missed_tests) != 0: print("%sWARNING!%s The following scripts are not being run: %s. Check the test lists in test_runner.py." % (BOLD[1], BOLD[0], str(missed_tests))) @@ -526,7 +526,7 @@ class RPCCoverage(): if uncovered: print("Uncovered RPC commands:") - print("".join((" - %s\n" % i) for i in sorted(uncovered))) + print("".join((" - %s\n" % command) for command in sorted(uncovered))) else: print("All RPC commands covered.") @@ -550,8 +550,8 @@ class RPCCoverage(): if not os.path.isfile(coverage_ref_filename): raise RuntimeError("No coverage reference found") - with open(coverage_ref_filename, 'r') as f: - all_cmds.update([i.strip() for i in f.readlines()]) + with open(coverage_ref_filename, 'r') as coverage_ref_file: + all_cmds.update([line.strip() for line in coverage_ref_file.readlines()]) for root, dirs, files in os.walk(self.dir): for filename in files: @@ -559,8 +559,8 @@ class RPCCoverage(): coverage_filenames.add(os.path.join(root, filename)) for filename in coverage_filenames: - with open(filename, 'r') as f: - covered_cmds.update([i.strip() for i in f.readlines()]) + with open(filename, 'r') as coverage_file: + covered_cmds.update([line.strip() for line in coverage_file.readlines()]) return all_cmds - covered_cmds diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index f686cb6ea5..dcd6c54d97 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -379,9 +379,9 @@ class WalletTest(BitcoinTestFramework): self.start_node(0, [m, "-limitancestorcount="+str(chainlimit)]) self.start_node(1, [m, "-limitancestorcount="+str(chainlimit)]) self.start_node(2, [m, "-limitancestorcount="+str(chainlimit)]) - while m == '-reindex' and [block_count] * 3 != [self.nodes[i].getblockcount() for i in range(3)]: + if m == '-reindex': # reindex will leave rpc warm up "early"; Wait for it to finish - time.sleep(0.1) + wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)]) assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)]) # Exercise listsinceblock with the last two blocks |