From d8ab8dc12db14cd206c61fb5d30a6a130160d9b9 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 27 Jul 2018 17:21:45 +0000 Subject: [PATCH 0001/4486] configure: Invert --enable-asm help string since default is now enabled --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 5851413cf4..080082f316 100644 --- a/configure.ac +++ b/configure.ac @@ -183,8 +183,8 @@ AC_ARG_ENABLE([glibc-back-compat], [use_glibc_compat=no]) AC_ARG_ENABLE([asm], - [AS_HELP_STRING([--enable-asm], - [Enable assembly routines (default is yes)])], + [AS_HELP_STRING([--disable-asm], + [disable assembly routines (enabled by default)])], [use_asm=$enableval], [use_asm=yes]) From afe087557747f640af90eaca8de8786dc226e56a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 27 Jul 2018 17:25:09 +0000 Subject: [PATCH 0002/4486] configure: Skip assembly support checks, when assembly is disabled --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index 080082f316..11df27220e 100644 --- a/configure.ac +++ b/configure.ac @@ -314,6 +314,8 @@ if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]]) fi +if test "x$use_asm" = "xyes"; then + # Check for optional instruction set support. Enabling these does _not_ imply that all code will # be compiled with them, rather that specific objects/libs may use them after checking for runtime # compatibility. @@ -391,6 +393,8 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ) CXXFLAGS="$TEMP_CXXFLAGS" +fi + CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], From 4207c1b35c2e2ee1c9217cc7db3290a24c3b4b52 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 27 Jul 2018 17:26:43 +0000 Subject: [PATCH 0003/4486] configure: Initialise assembly enable_* variables --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 11df27220e..13ea660198 100644 --- a/configure.ac +++ b/configure.ac @@ -314,6 +314,11 @@ if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]]) fi +enable_hwcrc32=no +enable_sse41=no +enable_avx2=no +enable_shani=no + if test "x$use_asm" = "xyes"; then # Check for optional instruction set support. Enabling these does _not_ imply that all code will From af5fa82b676a36e60eda080ca0a946bdfffefd49 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 13 Apr 2018 21:20:29 +0200 Subject: [PATCH 0004/4486] Allow quicker shutdowns during LoadBlockIndex() --- src/init.cpp | 1 + src/txdb.cpp | 1 + src/validation.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 18402ef5d7..feb5ff2c5e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1468,6 +1468,7 @@ bool AppInitMain() // Note that it also sets fReindex based on the disk flag! // From here on out fReindex and fReset mean something different! if (!LoadBlockIndex(chainparams)) { + if (ShutdownRequested()) break; strLoadError = _("Error loading block database"); break; } diff --git a/src/txdb.cpp b/src/txdb.cpp index cbea550739..eda959e1a1 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -255,6 +255,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, // Load mapBlockIndex while (pcursor->Valid()) { boost::this_thread::interruption_point(); + if (ShutdownRequested()) return false; std::pair key; if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) { CDiskBlockIndex diskindex; diff --git a/src/validation.cpp b/src/validation.cpp index 702a8d7e05..563cd59382 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3855,6 +3855,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo sort(vSortedByHeight.begin(), vSortedByHeight.end()); for (const std::pair& item : vSortedByHeight) { + if (ShutdownRequested()) return false; CBlockIndex* pindex = item.second; pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); pindex->nTimeMax = (pindex->pprev ? std::max(pindex->pprev->nTimeMax, pindex->nTime) : pindex->nTime); From bb530efa1872ec963417f61da9a95185c7a7a7d6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 23 Aug 2018 17:01:14 -0700 Subject: [PATCH 0005/4486] Disallow extended encoding for non-witness transactions --- src/primitives/transaction.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index fb9db508d2..c1568f9b2a 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -220,6 +220,10 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) { for (size_t i = 0; i < tx.vin.size(); i++) { s >> tx.vin[i].scriptWitness.stack; } + if (!tx.HasWitness()) { + /* It's illegal to encode witnesses when all witness stacks are empty. */ + throw std::ios_base::failure("Superfluous witness record"); + } } if (flags) { /* Unknown flag in the serialization */ From d2eee87928781ab3082d4279aa6f19641a45e801 Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Wed, 19 Sep 2018 02:02:12 -0400 Subject: [PATCH 0006/4486] Lift prevector default vals to the member declaration --- src/prevector.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 6ddb6f321f..24831848b5 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -148,14 +148,14 @@ class prevector { }; private: - size_type _size; + size_type _size = 0; union direct_or_indirect { char direct[sizeof(T) * N]; struct { size_type capacity; char* indirect; }; - } _union; + } _union = {}; T* direct_ptr(difference_type pos) { return reinterpret_cast(_union.direct) + pos; } const T* direct_ptr(difference_type pos) const { return reinterpret_cast(_union.direct) + pos; } @@ -246,34 +246,34 @@ class prevector { fill(item_ptr(0), first, last); } - prevector() : _size(0), _union{{}} {} + prevector() {} - explicit prevector(size_type n) : prevector() { + explicit prevector(size_type n) { resize(n); } - explicit prevector(size_type n, const T& val) : prevector() { + explicit prevector(size_type n, const T& val) { change_capacity(n); _size += n; fill(item_ptr(0), n, val); } template - prevector(InputIterator first, InputIterator last) : prevector() { + prevector(InputIterator first, InputIterator last) { size_type n = last - first; change_capacity(n); _size += n; fill(item_ptr(0), first, last); } - prevector(const prevector& other) : prevector() { + prevector(const prevector& other) { size_type n = other.size(); change_capacity(n); _size += n; fill(item_ptr(0), other.begin(), other.end()); } - prevector(prevector&& other) : prevector() { + prevector(prevector&& other) { swap(other); } From c276df775914e4e42993c76e172ef159e3b830d4 Mon Sep 17 00:00:00 2001 From: mruddy <6440430+mruddy@users.noreply.github.com> Date: Thu, 8 Nov 2018 06:38:21 -0500 Subject: [PATCH 0007/4486] zmq: enable tcp keepalive --- doc/zmq.md | 14 ++++++++++++++ src/zmq/zmqpublishnotifier.cpp | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/doc/zmq.md b/doc/zmq.md index 7ffc5623b6..35bb0fc377 100644 --- a/doc/zmq.md +++ b/doc/zmq.md @@ -98,6 +98,20 @@ ZMQ_SUBSCRIBE option set to one or either of these prefixes (for instance, just `hash`); without doing so will result in no messages arriving. Please see `contrib/zmq/zmq_sub.py` for a working example. +The ZMQ_PUB socket's ZMQ_TCP_KEEPALIVE option is enabled. This means that +the underlying SO_KEEPALIVE option is enabled when using a TCP transport. +The effective TCP keepalive values are managed through the underlying +operating system configuration and must be configured prior to connection establishment. + +For example, when running on GNU/Linux, one might use the following +to lower the keepalive setting to 10 minutes: + +sudo sysctl -w net.ipv4.tcp_keepalive_time=600 + +Setting the keepalive values appropriately for your operating environment may +improve connectivity in situations where long-lived connections are silently +dropped by network middle boxes. + ## Remarks From the perspective of bitcoind, the ZeroMQ socket is write-only; PUB diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 15d4ac1b89..e2177efe56 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -86,6 +86,14 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext) return false; } + const int so_keepalive_option {1}; + rc = zmq_setsockopt(psocket, ZMQ_TCP_KEEPALIVE, &so_keepalive_option, sizeof(so_keepalive_option)); + if (rc != 0) { + zmqError("Failed to set SO_KEEPALIVE"); + zmq_close(psocket); + return false; + } + rc = zmq_bind(psocket, address.c_str()); if (rc != 0) { From 0f459d868d85053f1cc066ea9099793f88cbd655 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Thu, 15 Nov 2018 17:21:28 -0800 Subject: [PATCH 0008/4486] fix an undefined behavior in uint::SetHex Decrementing psz beyond the beginning of the string is UB, even though the out-of-bounds pointer is never dereferenced. --- src/uint256.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/uint256.cpp b/src/uint256.cpp index d9da668036..b164e8678b 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -37,16 +37,15 @@ void base_blob::SetHex(const char* psz) psz += 2; // hex string to uint - const char* pbegin = psz; - while (::HexDigit(*psz) != -1) - psz++; - psz--; + size_t digits = 0; + while (::HexDigit(psz[digits]) != -1) + digits++; unsigned char* p1 = (unsigned char*)data; unsigned char* pend = p1 + WIDTH; - while (psz >= pbegin && p1 < pend) { - *p1 = ::HexDigit(*psz--); - if (psz >= pbegin) { - *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); + while (digits > 0 && p1 < pend) { + *p1 = ::HexDigit(psz[--digits]); + if (digits > 0) { + *p1 |= ((unsigned char)::HexDigit(psz[--digits]) << 4); p1++; } } From 097c4aa379f255639ce0084702693fa72a595d6b Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 27 Nov 2018 17:43:48 +0000 Subject: [PATCH 0009/4486] Bugfix: test/functional/rpc_psbt: Remove check for specific error message that depends on uncertain assumptions When converttopsbt is called with a signed transaction, it either fails with "TX decode failed" if one or more inputs were segwit, or "Inputs must not have scriptSigs and scriptWitnesses" otherwise. Since no effort is made by the test to ensure the inputs are segwit or not, avoid checking the exact message used. The error code is still checked to ensure it is of the correct kind of failure. --- test/functional/rpc_psbt.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 04d9bb65a6..b48339df29 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -144,9 +144,10 @@ def run_test(self): self.nodes[0].decodepsbt(new_psbt) # Make sure that a psbt with signatures cannot be converted + # Error could be either "TX decode failed" (segwit inputs causes parsing to fail) or "Inputs must not have scriptSigs and scriptWitnesses" signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex']) - assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex']) - assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'], False) + assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, signedtx['hex']) + assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, signedtx['hex'], False) # Unless we allow it to convert and strip signatures self.nodes[0].converttopsbt(signedtx['hex'], True) From c87fc71f7e9316bcc0653cd86c50177424b5b1f9 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 27 Nov 2018 17:46:20 +0000 Subject: [PATCH 0010/4486] Bugfix: test/functional/rpc_psbt: Correct test description comment --- test/functional/rpc_psbt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index b48339df29..6f9f52f001 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -143,7 +143,7 @@ def run_test(self): new_psbt = self.nodes[0].converttopsbt(rawtx['hex']) self.nodes[0].decodepsbt(new_psbt) - # Make sure that a psbt with signatures cannot be converted + # Make sure that a non-psbt with signatures cannot be converted # Error could be either "TX decode failed" (segwit inputs causes parsing to fail) or "Inputs must not have scriptSigs and scriptWitnesses" signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex']) assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, signedtx['hex']) From f33efa8ec535faae96b490c34978432799ca221f Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 21 Dec 2018 22:14:09 +0000 Subject: [PATCH 0011/4486] GUI: Restore RPC Console to non-wallet tray icon menu --- src/qt/bitcoingui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index d7056ddd89..58b93c45f7 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -686,9 +686,9 @@ void BitcoinGUI::createTrayIconMenu() trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); trayIconMenu->addSeparator(); - trayIconMenu->addAction(openRPCConsoleAction); } trayIconMenu->addAction(optionsAction); + trayIconMenu->addAction(openRPCConsoleAction); #ifndef Q_OS_MAC // This is built-in on macOS trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); From 11fdfcf7f940fab48625d102e825a59c16ad4fbc Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 4 Jan 2019 09:09:06 +0200 Subject: [PATCH 0012/4486] Show addresses for "SendToSelf" transactions Change addresses are not recognized. --- src/qt/transactionrecord.cpp | 10 +++++++--- src/qt/transactiontablemodel.cpp | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index d88cfe52ed..00455630e4 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -93,10 +93,14 @@ QList TransactionRecord::decomposeTransaction(const interface if (fAllFromMe && fAllToMe) { // Payment to self - CAmount nChange = wtx.change; + std::string address; + for (auto it = wtx.txout_address.begin(); it != wtx.txout_address.end(); ++it) { + if (it != wtx.txout_address.begin()) address += ", "; + address += EncodeDestination(*it); + } - parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", - -(nDebit - nChange), nCredit - nChange)); + CAmount nChange = wtx.change; + parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, address, -(nDebit - nChange), nCredit - nChange)); parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe) diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 01722146c5..2aed965d8d 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -395,6 +395,7 @@ QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, b case TransactionRecord::SendToOther: return QString::fromStdString(wtx->address) + watchAddress; case TransactionRecord::SendToSelf: + return lookupAddress(wtx->address, tooltip) + watchAddress; default: return tr("(n/a)") + watchAddress; } From ccc27bdcd2d91fe2c023ad004019d5b970f21dbf Mon Sep 17 00:00:00 2001 From: Daniel McNally Date: Tue, 2 Oct 2018 08:59:24 -0400 Subject: [PATCH 0013/4486] doc: Clarify -blocksdir usage This commit attempts to clarify and correct the `-blocksdir` argument description and default value. `-blocksdir` does not refer to the full path to the actual `blocks` directory, but rather the root/parent directory which contains the `blocks` directory. Accordingly, the default value is `` and not `/blocks`. It also attempts to clarify that only the `.dat` files containing block data are impacted by `-blocksdir`, not the index files. --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index f9efaf7dc1..5f8fdb4881 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -333,7 +333,7 @@ void SetupServerArgs() gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS); gArgs.AddArg("-alertnotify=", "Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)", false, OptionsCategory::OPTIONS); gArgs.AddArg("-assumevalid=", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()), false, OptionsCategory::OPTIONS); - gArgs.AddArg("-blocksdir=", "Specify blocks directory (default: /blocks)", false, OptionsCategory::OPTIONS); + gArgs.AddArg("-blocksdir=", "Specify directory to hold blocks subdirectory for *.dat files (default: )", false, OptionsCategory::OPTIONS); gArgs.AddArg("-blocknotify=", "Execute command when the best block changes (%s in cmd is replaced by block hash)", false, OptionsCategory::OPTIONS); gArgs.AddArg("-blockreconstructionextratxn=", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), false, OptionsCategory::OPTIONS); gArgs.AddArg("-blocksonly", strprintf("Whether to operate in a blocks only mode (default: %u)", DEFAULT_BLOCKSONLY), true, OptionsCategory::OPTIONS); From 5c04814b2de179fd03ca18c19049f035a2454f81 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 23 Jan 2019 22:30:20 +0200 Subject: [PATCH 0014/4486] Move non-linux source tarball to bitcoin-binaries --- contrib/gitian-build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py index fc7fbb764d..b77f398757 100755 --- a/contrib/gitian-build.py +++ b/contrib/gitian-build.py @@ -68,14 +68,14 @@ def build(): subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-win.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-win.yml']) subprocess.check_call('mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/', shell=True) - subprocess.check_call('mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../bitcoin-binaries/'+args.version, shell=True) + subprocess.check_call('mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe build/out/src/bitcoin-*.tar.gz ../bitcoin-binaries/'+args.version, shell=True) if args.macos: print('\nCompiling ' + args.version + ' MacOS') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml']) subprocess.check_call('mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/', shell=True) - subprocess.check_call('mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../bitcoin-binaries/'+args.version, shell=True) + subprocess.check_call('mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg build/out/src/bitcoin-*.tar.gz ../bitcoin-binaries/'+args.version, shell=True) os.chdir(workdir) From 593ba696fb32da558091ac02ad87c4893db4ce97 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 5 Dec 2018 22:51:49 +0200 Subject: [PATCH 0015/4486] Add warning messages to the debug window --- src/qt/forms/debugwindow.ui | 19 +++++++++++++++++++ src/qt/overviewpage.cpp | 5 ++--- src/qt/rpcconsole.cpp | 17 +++++++++++++++++ src/qt/rpcconsole.h | 3 +++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index dca16d6f78..671d14437b 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -14,6 +14,25 @@ Debug window + + + + false + + + QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; } + + + true + + + 3 + + + Qt::TextSelectableByMouse + + + diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index bec79335e7..c743c4f862 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -204,9 +204,8 @@ void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly) void OverviewPage::setClientModel(ClientModel *model) { this->clientModel = model; - if(model) - { - // Show warning if this is a prerelease version + if (model) { + // Show warning, for example if this is a prerelease version connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts); updateAlerts(model->getStatusBarWarnings()); } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 774a0d78e7..20d1eee016 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -563,6 +563,17 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event) void RPCConsole::setClientModel(ClientModel *model) { clientModel = model; + + bool wallet_enabled{false}; +#ifdef ENABLE_WALLET + wallet_enabled = WalletModel::isWalletEnabled(); +#endif // ENABLE_WALLET + if (model && !wallet_enabled) { + // Show warning, for example if this is a prerelease version + connect(model, &ClientModel::alertsChanged, this, &RPCConsole::updateAlerts); + updateAlerts(model->getStatusBarWarnings()); + } + ui->trafficGraph->setClientModel(model); if (model && clientModel->getPeerTableModel() && clientModel->getBanTableModel()) { // Keep up to date with client @@ -1289,3 +1300,9 @@ QString RPCConsole::tabTitle(TabTypes tab_type) const { return ui->tabWidget->tabText(tab_type); } + +void RPCConsole::updateAlerts(const QString& warnings) +{ + this->ui->label_alerts->setVisible(!warnings.isEmpty()); + this->ui->label_alerts->setText(warnings); +} diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 20dbf5ec95..876310a788 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -169,6 +169,9 @@ public Q_SLOTS: /** Update UI with latest network info from model. */ void updateNetworkState(); + +private Q_SLOTS: + void updateAlerts(const QString& warnings); }; #endif // BITCOIN_QT_RPCCONSOLE_H From ec30a79f1c430cc7fbda37e5d747b0b31b262fa5 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Tue, 29 Jan 2019 13:03:53 +0000 Subject: [PATCH 0016/4486] Fix UB with bench on genesis block --- src/validation.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 6a26bf9baa..70f233f464 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1834,6 +1834,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl uint256 hashPrevBlock = pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash(); assert(hashPrevBlock == view.GetBestBlock()); + nBlocksTotal++; + // Special case for the genesis block, skipping connection of its transactions // (its coinbase is unspendable) if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) { @@ -1842,8 +1844,6 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl return true; } - nBlocksTotal++; - bool fScriptChecks = true; if (!hashAssumeValid.IsNull()) { // We've been configured with the hash of a block which has been externally verified to have a valid history. @@ -2445,6 +2445,7 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp return error("%s: ConnectBlock %s failed, %s", __func__, pindexNew->GetBlockHash().ToString(), FormatStateMessage(state)); } nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2; + assert(nBlocksTotal > 0); LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime3 - nTime2) * MILLI, nTimeConnectTotal * MICRO, nTimeConnectTotal * MILLI / nBlocksTotal); bool flushed = view.Flush(); assert(flushed); From 2290269759ad10cc2e35958c7b0a63f3a7608621 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Wed, 12 Dec 2018 09:45:55 +0100 Subject: [PATCH 0017/4486] scripted-diff: rename DescriptorImpl m_script_arg to m_subdescriptor_arg -BEGIN VERIFY SCRIPT- sed -i -e 's/m_script_arg/m_subdescriptor_arg/g' src/script/descriptor.cpp -END VERIFY SCRIPT- --- src/script/descriptor.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index a702be5b78..5f758ab42d 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -210,7 +210,7 @@ class DescriptorImpl : public Descriptor //! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size of Multisig). const std::vector> m_pubkey_args; //! The sub-descriptor argument (nullptr for everything but SH and WSH). - const std::unique_ptr m_script_arg; + const std::unique_ptr m_subdescriptor_arg; //! The string name of the descriptor function. const std::string m_name; @@ -221,10 +221,10 @@ class DescriptorImpl : public Descriptor /** A helper function to construct the scripts for this descriptor. * * This function is invoked once for every CScript produced by evaluating - * m_script_arg, or just once in case m_script_arg is nullptr. + * m_subdescriptor_arg, or just once in case m_subdescriptor_arg is nullptr. * @param pubkeys The evaluations of the m_pubkey_args field. - * @param script The evaluation of m_script_arg (or nullptr when m_script_arg is nullptr). + * @param script The evaluation of m_subdescriptor_arg (or nullptr when m_subdescriptor_arg is nullptr). * @param out A FlatSigningProvider to put scripts or public keys in that are necessary to the solver. * The script and pubkeys argument to this function are automatically added. * @return A vector with scriptPubKeys for this descriptor. @@ -232,12 +232,12 @@ class DescriptorImpl : public Descriptor virtual std::vector MakeScripts(const std::vector& pubkeys, const CScript* script, FlatSigningProvider& out) const = 0; public: - DescriptorImpl(std::vector> pubkeys, std::unique_ptr script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_script_arg(std::move(script)), m_name(name) {} + DescriptorImpl(std::vector> pubkeys, std::unique_ptr script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_subdescriptor_arg(std::move(script)), m_name(name) {} bool IsSolvable() const override { - if (m_script_arg) { - if (!m_script_arg->IsSolvable()) return false; + if (m_subdescriptor_arg) { + if (!m_subdescriptor_arg->IsSolvable()) return false; } return true; } @@ -247,8 +247,8 @@ class DescriptorImpl : public Descriptor for (const auto& pubkey : m_pubkey_args) { if (pubkey->IsRange()) return true; } - if (m_script_arg) { - if (m_script_arg->IsRange()) return true; + if (m_subdescriptor_arg) { + if (m_subdescriptor_arg->IsRange()) return true; } return false; } @@ -268,10 +268,10 @@ class DescriptorImpl : public Descriptor } ret += std::move(tmp); } - if (m_script_arg) { + if (m_subdescriptor_arg) { if (pos++) ret += ","; std::string tmp; - if (!m_script_arg->ToStringHelper(arg, tmp, priv)) return false; + if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) return false; ret += std::move(tmp); } out = std::move(ret) + ")"; @@ -311,9 +311,9 @@ class DescriptorImpl : public Descriptor } } std::vector subscripts; - if (m_script_arg) { + if (m_subdescriptor_arg) { FlatSigningProvider subprovider; - if (!m_script_arg->ExpandHelper(pos, arg, cache_read, subscripts, subprovider, cache_write)) return false; + if (!m_subdescriptor_arg->ExpandHelper(pos, arg, cache_read, subscripts, subprovider, cache_write)) return false; out = Merge(out, subprovider); } @@ -324,7 +324,7 @@ class DescriptorImpl : public Descriptor out.origins.emplace(entry.first.GetID(), std::move(entry.second)); out.pubkeys.emplace(entry.first.GetID(), entry.first); } - if (m_script_arg) { + if (m_subdescriptor_arg) { for (const auto& subscript : subscripts) { out.scripts.emplace(CScriptID(subscript), subscript); std::vector addscripts = MakeScripts(pubkeys, &subscript, out); From 2e68ffaf205866e4cea71f64e79bbfb89e17280a Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Wed, 12 Dec 2018 10:08:08 +0100 Subject: [PATCH 0018/4486] [doc] descriptor: explain GetPubKey() usage with cached public key Plus a few typo fixes. --- src/script/descriptor.cpp | 6 +++++- src/script/descriptor.h | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 5f758ab42d..96cd93df5a 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -207,9 +207,11 @@ class BIP32PubkeyProvider final : public PubkeyProvider /** Base class for all Descriptor implementations. */ class DescriptorImpl : public Descriptor { - //! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size of Multisig). + //! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size for Multisig). const std::vector> m_pubkey_args; //! The sub-descriptor argument (nullptr for everything but SH and WSH). + //! In doc/descriptors.m this is referred to as SCRIPT expressions sh(SCRIPT) + //! and wsh(SCRIPT), and distinct from KEY expressions and ADDR expressions. const std::unique_ptr m_subdescriptor_arg; //! The string name of the descriptor function. const std::string m_name; @@ -295,6 +297,8 @@ class DescriptorImpl : public Descriptor // Construct temporary data in `entries` and `subscripts`, to avoid producing output in case of failure. for (const auto& p : m_pubkey_args) { entries.emplace_back(); + // If we have a cache, we don't need GetPubKey to compute the public key. + // Pass in nullptr to signify only origin info is desired. if (!p->GetPubKey(pos, arg, cache_read ? nullptr : &entries.back().first, entries.back().second)) return false; if (cache_read) { // Cached expanded public key exists, use it. diff --git a/src/script/descriptor.h b/src/script/descriptor.h index 44f0efca03..2be157b861 100644 --- a/src/script/descriptor.h +++ b/src/script/descriptor.h @@ -46,9 +46,9 @@ struct Descriptor { * * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. * provider: the provider to query for private keys in case of hardened derivation. - * output_script: the expanded scriptPubKeys will be put here. + * output_scripts: the expanded scriptPubKeys will be put here. * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider). - * cache: vector which will be overwritten with cache data necessary to-evaluate the descriptor at this point without access to private keys. + * cache: vector which will be overwritten with cache data necessary to evaluate the descriptor at this point without access to private keys. */ virtual bool Expand(int pos, const SigningProvider& provider, std::vector& output_scripts, FlatSigningProvider& out, std::vector* cache = nullptr) const = 0; @@ -56,7 +56,7 @@ struct Descriptor { * * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. * cache: vector from which cached expansion data will be read. - * output_script: the expanded scriptPubKeys will be put here. + * output_scripts: the expanded scriptPubKeys will be put here. * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider). */ virtual bool ExpandFromCache(int pos, const std::vector& cache, std::vector& output_scripts, FlatSigningProvider& out) const = 0; From 86b47fa741408b061ab0bda784b8678bfd7dfa88 Mon Sep 17 00:00:00 2001 From: Akio Nakamura Date: Thu, 1 Feb 2018 19:34:50 +0900 Subject: [PATCH 0019/4486] speed up Unserialize_impl for prevector The unserializer for prevector uses resize() for reserve the area, but it's prefer to use reserve() because resize() have overhead to call its constructor many times. However, reserve() does not change the value of "_size" (a private member of prevector). This PR introduce resize_uninitialized() to prevector that similar to resize() but does not call constructor, and added elements are explicitly initialized in Unserialize_imple(). The changes are as follows: 1. prevector.h Add a public member function named 'resize_uninitialized'. This function processes like as resize() but does not call constructors. So added elemensts needs explicitly initialized after this returns. 2. serialize.h In the following two function: Unserialize_impl(Stream& is, prevector& v, const unsigned char&) Unserialize_impl(Stream& is, prevector& v, const V&) Calls resize_uninitialized() instead of resize() 3. test/prevector_tests.cpp Add a test for resize_uninitialized(). --- src/prevector.h | 15 +++++++++++++++ src/serialize.h | 6 +++--- src/test/prevector_tests.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 99e5751634..2f368a5c66 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -378,6 +378,21 @@ class prevector { fill(ptr, first, last); } + inline void resize_uninitialized(size_type new_size) { + // resize_uninitialized changes the size of the prevector but does not initialize it. + // If size < new_size, the added elements must be initialized explicitly. + if (capacity() < new_size) { + change_capacity(new_size); + _size += new_size - size(); + return; + } + if (new_size < size()) { + erase(item_ptr(new_size), end()); + } else { + _size += new_size - size(); + } + } + iterator erase(iterator pos) { return erase(pos, pos + 1); } diff --git a/src/serialize.h b/src/serialize.h index 2d0cfbbbf0..cb48dc174a 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -659,7 +659,7 @@ void Unserialize_impl(Stream& is, prevector& v, const unsigned char&) while (i < nSize) { unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); - v.resize(i + blk); + v.resize_uninitialized(i + blk); is.read((char*)&v[i], blk * sizeof(T)); i += blk; } @@ -677,8 +677,8 @@ void Unserialize_impl(Stream& is, prevector& v, const V&) nMid += 5000000 / sizeof(T); if (nMid > nSize) nMid = nSize; - v.resize(nMid); - for (; i < nMid; i++) + v.resize_uninitialized(nMid); + for (; i < nMid; ++i) Unserialize(is, v[i]); } } diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 7341389208..84c1abc14a 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -183,6 +183,26 @@ class prevector_tester { pre_vector = pre_vector_alt; } + void resize_uninitialized(realtype values) { + size_t r = values.size(); + size_t s = real_vector.size() / 2; + if (real_vector.capacity() < s + r) { + real_vector.reserve(s + r); + } + real_vector.resize(s); + pre_vector.resize_uninitialized(s); + for (auto v : values) { + real_vector.push_back(v); + } + auto p = pre_vector.size(); + pre_vector.resize_uninitialized(p + r); + for (auto v : values) { + pre_vector[p] = v; + ++p; + } + test(); + } + ~prevector_tester() { BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString()); } @@ -260,6 +280,14 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) if (InsecureRandBits(5) == 18) { test.move(); } + if (InsecureRandBits(5) == 19) { + unsigned int num = 1 + (InsecureRandBits(4)); + std::vector values(num); + for (auto &v : values) { + v = InsecureRand32(); + } + test.resize_uninitialized(values); + } } } } From fa1d400003e96ed320da88e8d6129e665da901b5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 2 Feb 2019 20:24:10 -0500 Subject: [PATCH 0020/4486] cirrus ci: Inital config --- .cirrus.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000000..9104a0a3d1 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,26 @@ +task: + name: "FreeBsd 12.0 amd64 [GOAL: install] [no depends, only system libs]" + freebsd_instance: + image: freebsd-12-0-release-amd64 + ccache_cache: + folder: "/tmp/ccache_dir" + env: + MAKEJOBS: "-j3" + CONFIGURE_OPTS: "--disable-dependency-tracking" + GOAL: "install" + CCACHE_SIZE: "200M" + CCACHE_COMPRESS: 1 + CCACHE_DIR: "/tmp/ccache_dir" + install_script: + - pkg install -y autoconf automake boost-libs git gmake libevent libtool openssl pkgconf python3 ccache + - ./contrib/install_db4.sh $(pwd) + - ccache --max-size=${CCACHE_SIZE} + configure_script: + - ./autogen.sh + - ./configure ${CONFIGURE_OPTS} BDB_LIBS="-L$(pwd)/db4/lib -ldb_cxx-4.8" BDB_CFLAGS="-I$(pwd)/db4/include" || ( cat config.log && false) + make_script: + - gmake ${MAKEJOBS} ${GOAL} || ( echo "Build failure. Verbose build follows." && gmake ${GOAL} V=1 ; false ) + check_script: + - gmake check ${MAKEJOBS} VERBOSE=1 + functional_test_script: + - ./test/functional/test_runner.py --ci --combinedlogslen=1000 --quiet --failfast From 3407b446cc5ec0725c0505e3b933f43d86286ad5 Mon Sep 17 00:00:00 2001 From: Ben Carman Date: Sat, 9 Feb 2019 12:33:26 -0600 Subject: [PATCH 0021/4486] gui: Uppercase bech32 addresses in qr codes --- src/qt/guiutil.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index ba0a5abdf3..6048b06dca 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -175,7 +175,9 @@ bool parseBitcoinURI(QString uri, SendCoinsRecipient *out) QString formatBitcoinURI(const SendCoinsRecipient &info) { - QString ret = QString("bitcoin:%1").arg(info.address); + bool bech_32 = info.address.startsWith(QString::fromStdString(Params().Bech32HRP() + "1")); + + QString ret = QString("bitcoin:%1").arg(bech_32 ? info.address.toUpper() : info.address); int paramCount = 0; if (info.amount) From 43206239a8fab767849129368560afc4ac901047 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Wed, 30 Jan 2019 21:53:11 +0100 Subject: [PATCH 0022/4486] tests: Add script checking for deterministic line coverage --- .../devtools/test_deterministic_coverage.sh | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100755 contrib/devtools/test_deterministic_coverage.sh diff --git a/contrib/devtools/test_deterministic_coverage.sh b/contrib/devtools/test_deterministic_coverage.sh new file mode 100755 index 0000000000..16d03e1fff --- /dev/null +++ b/contrib/devtools/test_deterministic_coverage.sh @@ -0,0 +1,151 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# +# Test for deterministic coverage across unit test runs. + +export LC_ALL=C + +# Use GCOV_EXECUTABLE="gcov" if compiling with gcc. +# Use GCOV_EXECUTABLE="llvm-cov gcov" if compiling with clang. +GCOV_EXECUTABLE="gcov" + +# Disable tests known to cause non-deterministic behaviour and document the source or point of non-determinism. +NON_DETERMINISTIC_TESTS=( + "coinselector_tests/knapsack_solver_test" # coinselector_tests.cpp: if (equal_sets(setCoinsRet, setCoinsRet2)) + "denialofservice_tests/DoS_mapOrphans" # denialofservice_tests.cpp: it = mapOrphanTransactions.lower_bound(InsecureRand256()); + "fs_tests/fsbridge_fstream" # deterministic test failure? + "miner_tests/CreateNewBlock_validity" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "scheduler_tests/manythreads" # scheduler.cpp: CScheduler::serviceQueue() + "scheduler_tests/singlethreadedscheduler_ordered" # scheduler.cpp: CScheduler::serviceQueue() + "tx_validationcache_tests/checkinputs_test" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "tx_validationcache_tests/tx_mempool_block_doublespend" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "txindex_tests/txindex_initial_sync" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "txvalidation_tests/tx_mempool_reject_coinbase" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "validation_block_tests/processnewblock_signals_ordering" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "wallet_tests/coin_mark_dirty_immature_credit" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "wallet_tests/dummy_input_size_test" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "wallet_tests/importmulti_rescan" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "wallet_tests/importwallet_rescan" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "wallet_tests/ListCoins" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "wallet_tests/scan_for_wallet_transactions" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) + "wallet_tests/wallet_disableprivkeys" # validation.cpp: if (GetMainSignals().CallbacksPending() > 10) +) + +TEST_BITCOIN_BINARY="src/test/test_bitcoin" + +print_usage() { + echo "Usage: $0 [custom test filter (default: all but known non-deterministic tests)] [number of test runs (default: 2)]" +} + +N_TEST_RUNS=2 +BOOST_TEST_RUN_FILTERS="" +if [[ $# != 0 ]]; then + if [[ $1 == "--help" ]]; then + print_usage + exit + fi + PARSED_ARGUMENTS=0 + if [[ $1 =~ [a-z] ]]; then + BOOST_TEST_RUN_FILTERS=$1 + PARSED_ARGUMENTS=$((PARSED_ARGUMENTS + 1)) + shift + fi + if [[ $1 =~ ^[0-9]+$ ]]; then + N_TEST_RUNS=$1 + PARSED_ARGUMENTS=$((PARSED_ARGUMENTS + 1)) + shift + fi + if [[ ${PARSED_ARGUMENTS} == 0 || $# -gt 2 || ${N_TEST_RUNS} -lt 2 ]]; then + print_usage + exit + fi +fi +if [[ ${BOOST_TEST_RUN_FILTERS} == "" ]]; then + BOOST_TEST_RUN_FILTERS="$(IFS=":"; echo "!${NON_DETERMINISTIC_TESTS[*]}" | sed 's/:/:!/g')" +else + echo "Using Boost test filter: ${BOOST_TEST_RUN_FILTERS}" + echo +fi + +if ! command -v gcov > /dev/null; then + echo "Error: gcov not installed. Exiting." + exit 1 +fi + +if ! command -v gcovr > /dev/null; then + echo "Error: gcovr not installed. Exiting." + exit 1 +fi + +if [[ ! -e ${TEST_BITCOIN_BINARY} ]]; then + echo "Error: Executable ${TEST_BITCOIN_BINARY} not found. Run \"./configure --enable-lcov\" and compile." + exit 1 +fi + +get_file_suffix_count() { + find src/ -type f -name "*.$1" | wc -l +} + +if [[ $(get_file_suffix_count gcno) == 0 ]]; then + echo "Error: Could not find any *.gcno files. The *.gcno files are generated by the compiler. Run \"./configure --enable-lcov\" and re-compile." + exit 1 +fi + +get_covr_filename() { + echo "gcovr.run-$1.txt" +} + +TEST_RUN_ID=0 +while [[ ${TEST_RUN_ID} -lt ${N_TEST_RUNS} ]]; do + TEST_RUN_ID=$((TEST_RUN_ID + 1)) + echo "[$(date +"%Y-%m-%d %H:%M:%S")] Measuring coverage, run #${TEST_RUN_ID} of ${N_TEST_RUNS}" + find src/ -type f -name "*.gcda" -exec rm {} \; + if [[ $(get_file_suffix_count gcda) != 0 ]]; then + echo "Error: Stale *.gcda files found. Exiting." + exit 1 + fi + TEST_OUTPUT_TEMPFILE=$(mktemp) + if ! BOOST_TEST_RUN_FILTERS="${BOOST_TEST_RUN_FILTERS}" ${TEST_BITCOIN_BINARY} > "${TEST_OUTPUT_TEMPFILE}" 2>&1; then + cat "${TEST_OUTPUT_TEMPFILE}" + rm "${TEST_OUTPUT_TEMPFILE}" + exit 1 + fi + rm "${TEST_OUTPUT_TEMPFILE}" + if [[ $(get_file_suffix_count gcda) == 0 ]]; then + echo "Error: Running the test suite did not create any *.gcda files. The gcda files are generated when the instrumented test programs are executed. Run \"./configure --enable-lcov\" and re-compile." + exit 1 + fi + GCOVR_TEMPFILE=$(mktemp) + if ! gcovr --gcov-executable "${GCOV_EXECUTABLE}" -r src/ > "${GCOVR_TEMPFILE}"; then + echo "Error: gcovr failed. Output written to ${GCOVR_TEMPFILE}. Exiting." + exit 1 + fi + GCOVR_FILENAME=$(get_covr_filename ${TEST_RUN_ID}) + mv "${GCOVR_TEMPFILE}" "${GCOVR_FILENAME}" + if grep -E "^TOTAL *0 *0 " "${GCOVR_FILENAME}"; then + echo "Error: Spurious gcovr output. Make sure the correct GCOV_EXECUTABLE variable is set in $0 (\"gcov\" for gcc, \"llvm-cov gcov\" for clang)." + exit 1 + fi + if [[ ${TEST_RUN_ID} != 1 ]]; then + COVERAGE_DIFF=$(diff -u "$(get_covr_filename 1)" "${GCOVR_FILENAME}") + if [[ ${COVERAGE_DIFF} != "" ]]; then + echo + echo "The line coverage is non-deterministic between runs. Exiting." + echo + echo "The test suite must be deterministic in the sense that the set of lines executed at least" + echo "once must be identical between runs. This is a necessary condition for meaningful" + echo "coverage measuring." + echo + echo "${COVERAGE_DIFF}" + exit 1 + fi + rm "${GCOVR_FILENAME}" + fi +done + +echo +echo "Coverage test passed: Deterministic coverage across ${N_TEST_RUNS} runs." +exit From 1a7ba84e1194aeeb3c2fc9d79337a84586b834fd Mon Sep 17 00:00:00 2001 From: Akio Nakamura Date: Mon, 4 Feb 2019 12:53:19 +0900 Subject: [PATCH 0023/4486] Fix lack of warning of unrecognized section names 1. Fix lack of warning by collecting all section names by moving m_config_sections.clear() to ArgsManager::ReadConfigFiles(). 2. Add info(file name, line number) to warning message. 3. Add a test code to confirm this situation. 3. Do clear() in ReadConfigString(). --- src/init.cpp | 2 +- src/test/util_tests.cpp | 3 ++- src/util/system.cpp | 30 +++++++++++--------------- src/util/system.h | 13 ++++++++--- test/functional/feature_config_args.py | 12 +++++++++-- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 0013319ad5..f85a0da37e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -815,7 +815,7 @@ void InitParameterInteraction() // Warn if unrecognized section name are present in the config file. for (const auto& section : gArgs.GetUnrecognizedSections()) { - InitWarning(strprintf(_("Section [%s] is not recognized."), section)); + InitWarning(strprintf("%s:%i " + _("Section [%s] is not recognized."), section.m_file, section.m_line, section.m_name)); } } diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 860f64bb11..e17ae7103b 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -180,9 +180,10 @@ struct TestArgsManager : public ArgsManager { LOCK(cs_args); m_config_args.clear(); + m_config_sections.clear(); } std::string error; - BOOST_REQUIRE(ReadConfigStream(streamConfig, error)); + BOOST_REQUIRE(ReadConfigStream(streamConfig, "", error)); } void SetNetworkOnlyArg(const std::string arg) { diff --git a/src/util/system.cpp b/src/util/system.cpp index 27ed24d012..9e02a227cb 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -354,8 +354,7 @@ const std::set ArgsManager::GetUnsuitableSectionOnlyArgs() const return unsuitables; } - -const std::set ArgsManager::GetUnrecognizedSections() const +const std::list ArgsManager::GetUnrecognizedSections() const { // Section names to be recognized in the config file. static const std::set available_sections{ @@ -363,14 +362,11 @@ const std::set ArgsManager::GetUnrecognizedSections() const CBaseChainParams::TESTNET, CBaseChainParams::MAIN }; - std::set diff; LOCK(cs_args); - std::set_difference( - m_config_sections.begin(), m_config_sections.end(), - available_sections.begin(), available_sections.end(), - std::inserter(diff, diff.end())); - return diff; + std::list unrecognized = m_config_sections; + unrecognized.remove_if([](const SectionInfo& appeared){ return available_sections.find(appeared.m_name) != available_sections.end(); }); + return unrecognized; } void ArgsManager::SelectConfigNetwork(const std::string& network) @@ -794,7 +790,7 @@ static std::string TrimString(const std::string& str, const std::string& pattern return str.substr(front, end - front + 1); } -static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector>& options, std::set& sections) +static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector>& options, std::list& sections) { std::string str, prefix; std::string::size_type pos; @@ -810,7 +806,7 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect if (!str.empty()) { if (*str.begin() == '[' && *str.rbegin() == ']') { const std::string section = str.substr(1, str.size() - 2); - sections.insert(section); + sections.emplace_back(SectionInfo{section, filepath, linenr}); prefix = section + '.'; } else if (*str.begin() == '-') { error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str); @@ -823,8 +819,8 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect return false; } options.emplace_back(name, value); - if ((pos = name.rfind('.')) != std::string::npos) { - sections.insert(name.substr(0, pos)); + if ((pos = name.rfind('.')) != std::string::npos && prefix.length() <= pos) { + sections.emplace_back(SectionInfo{name.substr(0, pos), filepath, linenr}); } } else { error = strprintf("parse error on line %i: %s", linenr, str); @@ -839,12 +835,11 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect return true; } -bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys) +bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys) { LOCK(cs_args); std::vector> options; - m_config_sections.clear(); - if (!GetConfigOptions(stream, error, options, m_config_sections)) { + if (!GetConfigOptions(stream, filepath, error, options, m_config_sections)) { return false; } for (const std::pair& option : options) { @@ -875,6 +870,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) { LOCK(cs_args); m_config_args.clear(); + m_config_sections.clear(); } const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME); @@ -882,7 +878,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) // ok to not have a config file if (stream.good()) { - if (!ReadConfigStream(stream, error, ignore_invalid_keys)) { + if (!ReadConfigStream(stream, confPath, error, ignore_invalid_keys)) { return false; } // if there is an -includeconf in the override args, but it is empty, that means the user @@ -913,7 +909,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) for (const std::string& to_include : includeconf) { fsbridge::ifstream include_config(GetConfigFile(to_include)); if (include_config.good()) { - if (!ReadConfigStream(include_config, error, ignore_invalid_keys)) { + if (!ReadConfigStream(include_config, to_include, error, ignore_invalid_keys)) { return false; } LogPrintf("Included configuration file %s\n", to_include.c_str()); diff --git a/src/util/system.h b/src/util/system.h index 8867e49478..cb66c470a6 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -132,6 +132,13 @@ enum class OptionsCategory { HIDDEN // Always the last option to avoid printing these in the help }; +struct SectionInfo +{ + std::string m_name; + std::string m_file; + int m_line; +}; + class ArgsManager { protected: @@ -152,9 +159,9 @@ class ArgsManager std::string m_network GUARDED_BY(cs_args); std::set m_network_only_args GUARDED_BY(cs_args); std::map> m_available_args GUARDED_BY(cs_args); - std::set m_config_sections GUARDED_BY(cs_args); + std::list m_config_sections GUARDED_BY(cs_args); - NODISCARD bool ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys = false); + NODISCARD bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false); public: ArgsManager(); @@ -178,7 +185,7 @@ class ArgsManager /** * Log warnings for unrecognized section names in the config file. */ - const std::set GetUnrecognizedSections() const; + const std::list GetUnrecognizedSections() const; /** * Return a vector of strings of the given argument diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 4b3f6603a2..460e664c48 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -41,13 +41,21 @@ def test_config_file_parser(self): conf.write('server=1\nrpcuser=someuser\n[main]\nrpcpassword=some#pass') self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided') + inc_conf_file2_path = os.path.join(self.nodes[0].datadir, 'include2.conf') + with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf: + conf.write('includeconf={}\n'.format(inc_conf_file2_path)) + with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: - conf.write('testnot.datadir=1\n[testnet]\n') + conf.write('testnot.datadir=1\n') + with open(inc_conf_file2_path, 'w', encoding='utf-8') as conf: + conf.write('[testnet]\n') self.restart_node(0) - self.nodes[0].stop_node(expected_stderr='Warning: Section [testnet] is not recognized.' + os.linesep + 'Warning: Section [testnot] is not recognized.') + self.nodes[0].stop_node(expected_stderr='Warning: ' + inc_conf_file_path + ':1 Section [testnot] is not recognized.' + os.linesep + 'Warning: ' + inc_conf_file2_path + ':1 Section [testnet] is not recognized.') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('') # clear + with open(inc_conf_file2_path, 'w', encoding='utf-8') as conf: + conf.write('') # clear def run_test(self): self.stop_node(0) From bf12093191f8a4ac9f248a1730b0784a7972d171 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Tue, 19 Feb 2019 16:35:56 +0100 Subject: [PATCH 0024/4486] [doc] productivity: fix broken link --- doc/productivity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/productivity.md b/doc/productivity.md index 862017290d..f94bf8da6a 100644 --- a/doc/productivity.md +++ b/doc/productivity.md @@ -76,7 +76,7 @@ Writing code ### Format C/C++/Protobuf diffs with `clang-format-diff.py` -See [contrib/devtools/README.md](contrib/devtools/README.md#clang-format-diff.py). +See [contrib/devtools/README.md](/contrib/devtools/README.md#clang-format-diff.py). ### Format Python diffs with `yapf-diff.py` From fab0d858027844f602e9e6103a66d97fdacc13ab Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 11 Feb 2019 11:18:36 -0500 Subject: [PATCH 0025/4486] qa: Remove mocktime unless required --- test/functional/rpc_blockchain.py | 12 ++++++++++++ .../test_framework/test_framework.py | 19 +------------------ test/functional/test_framework/test_node.py | 5 ++--- test/functional/wallet_create_tx.py | 10 +++++++++- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 31e60f1cea..af150a09af 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -35,6 +35,7 @@ from test_framework.blocktools import ( create_block, create_coinbase, + TIME_GENESIS_BLOCK, ) from test_framework.messages import ( msg_block, @@ -46,9 +47,11 @@ class BlockchainTest(BitcoinTestFramework): def set_test_params(self): + self.setup_clean_chain = True self.num_nodes = 1 def run_test(self): + self.mine_chain() self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete self._test_getblockchaininfo() @@ -61,6 +64,15 @@ def run_test(self): self._test_waitforblockheight() assert self.nodes[0].verifychain(4, 0) + def mine_chain(self): + self.log.info('Create some old blocks') + address = self.nodes[0].get_deterministic_priv_key().address + for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 600, 600): + # ten-minute steps from genesis block time + self.nodes[0].setmocktime(t) + self.nodes[0].generatetoaddress(1, address) + assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200) + def _test_getblockchaininfo(self): self.log.info("Test getblockchaininfo") diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 869b36673e..49c15112b3 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -29,11 +29,11 @@ get_datadir_path, initialize_datadir, p2p_port, - set_node_times, sync_blocks, sync_mempools, ) + class TestStatus(Enum): PASSED = 1 FAILED = 2 @@ -94,7 +94,6 @@ def __init__(self): self.setup_clean_chain = False self.nodes = [] self.network_thread = None - self.mocktime = 0 self.rpc_timeout = 60 # Wait for up to 60 seconds for the RPC server to respond self.supports_cli = False self.bind_to_localhost_only = True @@ -316,7 +315,6 @@ def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, binary=None): timewait=self.rpc_timeout, bitcoind=binary[i], bitcoin_cli=self.options.bitcoincli, - mocktime=self.mocktime, coverage_dir=self.options.coveragedir, cwd=self.options.tmpdir, extra_conf=extra_confs[i], @@ -468,7 +466,6 @@ def _initialize_chain(self): timewait=self.rpc_timeout, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, - mocktime=self.mocktime, coverage_dir=None, cwd=self.options.tmpdir, )) @@ -479,32 +476,18 @@ def _initialize_chain(self): for node in self.nodes: node.wait_for_rpc_connection() - # For backward compatibility of the python scripts with previous - # versions of the cache, set mocktime to Jan 1, - # 2014 + (201 * 10 * 60)""" - self.mocktime = 1388534400 + (201 * 10 * 60) - # Create a 200-block-long chain; each of the 4 first nodes # gets 25 mature blocks and 25 immature. - # Note: To preserve compatibility with older versions of - # initialize_chain, only 4 nodes will generate coins. - # - # blocks are created with timestamps 10 minutes apart - # starting from 2010 minutes in the past - block_time = self.mocktime - (201 * 10 * 60) for i in range(2): for peer in range(4): for j in range(25): - set_node_times(self.nodes, block_time) self.nodes[peer].generatetoaddress(1, self.nodes[peer].get_deterministic_priv_key().address) - block_time += 10 * 60 # Must sync before next peer starts generating blocks sync_blocks(self.nodes) # Shut them down, and clean up cache directories: self.stop_nodes() self.nodes = [] - self.mocktime = 0 def cache_path(n, *paths): return os.path.join(get_datadir_path(self.options.cachedir, n), "regtest", *paths) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 352774914d..37fd2a8744 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -61,7 +61,7 @@ class TestNode(): To make things easier for the test writer, any unrecognised messages will be dispatched to the RPC connection.""" - def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False): + def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False): """ Kwargs: start_perf (bool): If True, begin profiling the node with `perf` as soon as @@ -90,8 +90,7 @@ def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, mock "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", - "-mocktime=" + str(mocktime), - "-uacomment=testnode%d" % i + "-uacomment=testnode%d" % i, ] self.cli = TestNodeCLI(bitcoin_cli, self.datadir) diff --git a/test/functional/wallet_create_tx.py b/test/functional/wallet_create_tx.py index 27dc0fb279..7b749235e2 100755 --- a/test/functional/wallet_create_tx.py +++ b/test/functional/wallet_create_tx.py @@ -7,17 +7,25 @@ from test_framework.util import ( assert_equal, ) +from test_framework.blocktools import ( + TIME_GENESIS_BLOCK, +) class CreateTxWalletTest(BitcoinTestFramework): def set_test_params(self): - self.setup_clean_chain = False + self.setup_clean_chain = True self.num_nodes = 1 def skip_test_if_missing_module(self): self.skip_if_no_wallet() def run_test(self): + self.log.info('Create some old blocks') + self.nodes[0].setmocktime(TIME_GENESIS_BLOCK) + self.nodes[0].generate(200) + self.nodes[0].setmocktime(0) + self.log.info('Check that we have some (old) blocks and that anti-fee-sniping is disabled') assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200) txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) From 3a21905a4ef7d98c8762ec89affa2667e197a118 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Tue, 19 Feb 2019 17:08:01 +0100 Subject: [PATCH 0026/4486] [doc] devtools: mention clang-format dependency --- contrib/devtools/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index 6ee65f40be..49e6c3cb60 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -7,6 +7,8 @@ clang-format-diff.py A script to format unified git diffs according to [.clang-format](../../src/.clang-format). +Requires `clang-format`, installed e.g. via `brew install clang-format` on macOS. + For instance, to format the last commit with 0 lines of context, the script should be called from the git root folder as follows. From ff7f31e07dff676a3bb400e98e0e365eee5aace9 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Tue, 19 Feb 2019 17:15:38 +0100 Subject: [PATCH 0027/4486] [doc] productivity: more advanced git range-diff --- doc/productivity.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/productivity.md b/doc/productivity.md index f94bf8da6a..e0df558944 100644 --- a/doc/productivity.md +++ b/doc/productivity.md @@ -136,7 +136,7 @@ This will add an `upstream-pull` remote to your git repository, which can be fet ### Diff the diffs with `git range-diff` -It is very common for contributors to rebase their pull requests, or make changes to commits (perhaps in response to review) that are not at the head of their branch. This poses a problem for reviewers as when the contributor force pushes, the reviewer is no longer sure that his previous reviews of commits are still valid (as the commit hashes can now be different even though the diff is semantically the same). `git range-diff` can help solve this problem by diffing the diffs. +It is very common for contributors to rebase their pull requests, or make changes to commits (perhaps in response to review) that are not at the head of their branch. This poses a problem for reviewers as when the contributor force pushes, the reviewer is no longer sure that his previous reviews of commits are still valid (as the commit hashes can now be different even though the diff is semantically the same). [git range-diff](https://git-scm.com/docs/git-range-diff) (Git >= 2.19) can help solve this problem by diffing the diffs. For example, to identify the differences between your previously reviewed diffs P1-5, and the new diffs P1-2,N3-4 as illustrated below: ``` @@ -152,7 +152,19 @@ You can do: git range-diff master previously-reviewed-head new-head ``` -Note that `git range-diff` also work for rebases. +Note that `git range-diff` also work for rebases: + +``` + P1--P2--P3--P4--P5 <-- previously-reviewed-head + / +...--m--m1--m2--m3 <-- master + \ + P1--P2--N3--N4 <-- new-head (with P3 modified, P4 & P5 squashed) + +PREV=P5 N=4 && git range-diff `git merge-base --all HEAD $PREV`...$PREV HEAD~$N...HEAD +``` + +Where `P5` is the commit you last reviewed and `4` is the number of commits in the new version. ----- From 1111aecbb58d6e37d430d477ac43f52811fd97d9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 11 Feb 2019 13:56:19 -0500 Subject: [PATCH 0028/4486] qa: Always refresh stale cache to be out of ibd --- test/functional/feature_proxy.py | 3 ++- test/functional/mempool_accept.py | 4 +--- .../test_framework/test_framework.py | 24 +++++++++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index 31d2ee8e13..5453f0be3b 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -41,9 +41,11 @@ RANGE_BEGIN = PORT_MIN + 2 * PORT_RANGE # Start after p2p and rpc ports + class ProxyTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 + self.setup_clean_chain = True def setup_nodes(self): self.have_ipv6 = test_ipv6_local() @@ -198,4 +200,3 @@ def networks_dict(d): if __name__ == '__main__': ProxyTest().main() - diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index e2a219b85a..efe720b9b1 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -29,7 +29,6 @@ assert_raises_rpc_error, bytes_to_hex_str, hex_str_to_bytes, - wait_until, ) @@ -38,7 +37,6 @@ def set_test_params(self): self.num_nodes = 1 self.extra_args = [[ '-txindex', - '-reindex', # Need reindex for txindex '-acceptnonstdtxn=0', # Try to mimic main-net ]] * self.num_nodes @@ -56,7 +54,7 @@ def run_test(self): self.log.info('Start with empty mempool, and 200 blocks') self.mempool_size = 0 - wait_until(lambda: node.getblockcount() == 200) + assert_equal(node.getblockcount(), 200) assert_equal(node.getmempoolinfo()['size'], self.mempool_size) coins = node.listunspent() diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 49c15112b3..24e1a21a28 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -274,6 +274,17 @@ def setup_nodes(self): self.add_nodes(self.num_nodes, extra_args) self.start_nodes() self.import_deterministic_coinbase_privkeys() + if not self.setup_clean_chain: + for n in self.nodes: + assert_equal(n.getblockchaininfo()["blocks"], 199) + self.log.debug('Generate a block with current time to finalize the cache and assert we are out of IBD') + block_hash = self.nodes[0].generate(1)[0] + block = self.nodes[0].getblock(blockhash=block_hash, verbosity=0) + for n in self.nodes: + n.submitblock(block) + chain_info = n.getblockchaininfo() + assert_equal(chain_info["blocks"], 200) + assert_equal(chain_info["initialblockdownload"], False) def import_deterministic_coinbase_privkeys(self): for n in self.nodes: @@ -433,7 +444,7 @@ def _start_logging(self): def _initialize_chain(self): """Initialize a pre-mined blockchain for use by the test. - Create a cache of a 200-block-long chain (with wallet) for MAX_NODES + Create a cache of a 199-block-long chain (with wallet) for MAX_NODES Afterward, create num_nodes copies from the cache.""" assert self.num_nodes <= MAX_NODES @@ -476,15 +487,24 @@ def _initialize_chain(self): for node in self.nodes: node.wait_for_rpc_connection() - # Create a 200-block-long chain; each of the 4 first nodes + # Create a 199-block-long chain; each of the 4 first nodes # gets 25 mature blocks and 25 immature. + # The 4th node gets only 24 immature blocks so that the very last + # block in the cache does not age too much (have an old tip age). + # This is needed so that we are out of IBD when the test starts, + # see the tip age check in IsInitialBlockDownload(). for i in range(2): for peer in range(4): for j in range(25): + if i == 1 and peer == 3 and j == 24: + break self.nodes[peer].generatetoaddress(1, self.nodes[peer].get_deterministic_priv_key().address) # Must sync before next peer starts generating blocks sync_blocks(self.nodes) + for n in self.nodes: + assert_equal(n.getblockchaininfo()["blocks"], 199) + # Shut them down, and clean up cache directories: self.stop_nodes() self.nodes = [] From fa25210d6266d50a6c2bfd6d96062bacb2ae393b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 15 Feb 2019 10:15:28 -0500 Subject: [PATCH 0029/4486] qa: Fix wallet_txn_doublespend issue --- test/functional/feature_proxy.py | 1 - test/functional/wallet_txn_doublespend.py | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index 5453f0be3b..f042adb7aa 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -41,7 +41,6 @@ RANGE_BEGIN = PORT_MIN + 2 * PORT_RANGE # Start after p2p and rpc ports - class ProxyTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index f114d5ab68..9050e21247 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -34,6 +34,14 @@ def setup_network(self): def run_test(self): # All nodes should start with 1,250 BTC: starting_balance = 1250 + + # All nodes should be out of IBD. + # If the nodes are not all out of IBD, that can interfere with + # blockchain sync later in the test when nodes are connected, due to + # timing issues. + for n in self.nodes: + assert n.getblockchaininfo()["initialblockdownload"] == False + for i in range(4): assert_equal(self.nodes[i].getbalance(), starting_balance) self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! From 80f0e05b700f8ad6903f22b3e81f905ccf6b13eb Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Tue, 19 Feb 2019 14:50:07 -0500 Subject: [PATCH 0030/4486] depends: Preprocessing doesn't care about deps --- depends/funcs.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/funcs.mk b/depends/funcs.mk index 15e404e42d..2ec8e47718 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -170,13 +170,13 @@ $($(1)_extracted): | $($(1)_fetched) $(AT)mkdir -p $$(@D) $(AT)cd $$(@D); $(call $(1)_extract_cmds,$(1)) $(AT)touch $$@ -$($(1)_preprocessed): | $($(1)_dependencies) $($(1)_extracted) +$($(1)_preprocessed): | $($(1)_extracted) $(AT)echo Preprocessing $(1)... $(AT)mkdir -p $$(@D) $($(1)_patch_dir) $(AT)$(foreach patch,$($(1)_patches),cd $(PATCHES_PATH)/$(1); cp $(patch) $($(1)_patch_dir) ;) $(AT)cd $$(@D); $(call $(1)_preprocess_cmds, $(1)) $(AT)touch $$@ -$($(1)_configured): | $($(1)_preprocessed) +$($(1)_configured): | $($(1)_dependencies) $($(1)_preprocessed) $(AT)echo Configuring $(1)... $(AT)rm -rf $(host_prefix); mkdir -p $(host_prefix)/lib; cd $(host_prefix); $(foreach package,$($(1)_all_dependencies), tar xf $($(package)_cached); ) $(AT)mkdir -p $$(@D) From 6d44c5ebf97af4b357079fe4bc2130f98e1d0fd2 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Tue, 19 Feb 2019 15:59:36 -0500 Subject: [PATCH 0031/4486] depends: Add commands for each package for each stage --- depends/Makefile | 2 ++ depends/funcs.mk | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/depends/Makefile b/depends/Makefile index 50cc77ddeb..dc2a1e626c 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -192,4 +192,6 @@ download-win: @$(MAKE) -s HOST=x86_64-w64-mingw32 download-one download: download-osx download-linux download-win +$(foreach package,$(all_packages),$(eval $(call ext_add_stages,$(package)))) + .PHONY: install cached clean clean-all download-one download-osx download-linux download-win download check-packages check-sources diff --git a/depends/funcs.mk b/depends/funcs.mk index 2ec8e47718..fbefc890ef 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -213,6 +213,14 @@ $(1): | $($(1)_cached_checksum) endef +stages = fetched extracted preprocessed configured built staged postprocessed cached cached_checksum + +define ext_add_stages +$(foreach stage,$(stages), + $(1)_$(stage): $($(1)_$(stage)) + .PHONY: $(1)_$(stage)) +endef + # These functions create the build targets for each package. They must be # broken down into small steps so that each part is done for all packages # before moving on to the next step. Otherwise, a package's info From fa05626ca7a0fe896ac554c79eaea4c36acdf861 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 12 Feb 2019 20:16:29 -0500 Subject: [PATCH 0032/4486] rpc: Add RPCHelpMan::IsValidNumArgs() --- src/rpc/util.cpp | 29 ++++++++++++++++++++++------- src/rpc/util.h | 8 ++++++-- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 023b4b6746..e37af953fa 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018 The Bitcoin Core developers +// Copyright (c) 2017-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -315,6 +315,17 @@ std::string RPCExamples::ToDescriptionString() const return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples; } +bool RPCHelpMan::IsValidNumArgs(size_t num_args) const +{ + size_t num_required_args = 0; + for (size_t n = m_args.size(); n > 0; --n) { + if (!m_args.at(n - 1).IsOptional()) { + num_required_args = n; + break; + } + } + return num_required_args <= num_args && num_args <= m_args.size(); +} std::string RPCHelpMan::ToString() const { std::string ret; @@ -323,12 +334,7 @@ std::string RPCHelpMan::ToString() const ret += m_name; bool was_optional{false}; for (const auto& arg : m_args) { - bool optional; - if (arg.m_fallback.which() == 1) { - optional = true; - } else { - optional = RPCArg::Optional::NO != boost::get(arg.m_fallback); - } + const bool optional = arg.IsOptional(); ret += " "; if (optional) { if (!was_optional) ret += "( "; @@ -370,6 +376,15 @@ std::string RPCHelpMan::ToString() const return ret; } +bool RPCArg::IsOptional() const +{ + if (m_fallback.which() == 1) { + return true; + } else { + return RPCArg::Optional::NO != boost::get(m_fallback); + } +} + std::string RPCArg::ToDescriptionString() const { std::string ret; diff --git a/src/rpc/util.h b/src/rpc/util.h index 1c9ddcdf44..7b8dd5a9ec 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018 The Bitcoin Core developers +// Copyright (c) 2017-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -53,7 +53,7 @@ struct RPCArg { /** Required arg */ NO, /** - * Optinal arg that is a named argument and has a default value of + * Optional arg that is a named argument and has a default value of * `null`. When possible, the default value should be specified. */ OMITTED_NAMED_ARG, @@ -110,6 +110,8 @@ struct RPCArg { assert(type == Type::ARR || type == Type::OBJ); } + bool IsOptional() const; + /** * Return the type string of the argument. * Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description). @@ -185,6 +187,8 @@ class RPCHelpMan RPCHelpMan(std::string name, std::string description, std::vector args, RPCResults results, RPCExamples examples); std::string ToString() const; + /** If the supplied number of args is neither too small nor too high */ + bool IsValidNumArgs(size_t num_args) const; private: const std::string m_name; From fa4ce7038d444defe0b98a30097174c278054a33 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 13 Feb 2019 16:51:27 -0500 Subject: [PATCH 0033/4486] rpc: Actually throw help when passed invalid number of params --- src/rpc/blockchain.cpp | 10 +++++----- src/rpc/net.cpp | 16 ++++++++-------- test/functional/rpc_getblockstats.py | 5 +++++ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7fb9ff2eaf..c73a8d48cf 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -1778,9 +1778,7 @@ static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t) static UniValue getblockstats(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) { - throw std::runtime_error( - RPCHelpMan{"getblockstats", + const RPCHelpMan help{"getblockstats", "\nCompute per block statistics for a given window. All amounts are in satoshis.\n" "It won't work for some heights with pruning.\n" "It won't work without -txindex for utxo_size_inc, *fee or *feerate stats.\n", @@ -1836,7 +1834,9 @@ static UniValue getblockstats(const JSONRPCRequest& request) HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") + HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") }, - }.ToString()); + }; + if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { + throw std::runtime_error(help.ToString()); } LOCK(cs_main); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 6bbbbc9876..c7b3478f44 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -523,13 +523,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) static UniValue setban(const JSONRPCRequest& request) { - std::string strCommand; - if (!request.params[1].isNull()) - strCommand = request.params[1].get_str(); - if (request.fHelp || request.params.size() < 2 || - (strCommand != "add" && strCommand != "remove")) - throw std::runtime_error( - RPCHelpMan{"setban", + const RPCHelpMan help{"setban", "\nAttempts to add or remove an IP/Subnet from the banned list.\n", { {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"}, @@ -543,7 +537,13 @@ static UniValue setban(const JSONRPCRequest& request) + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") }, - }.ToString()); + }; + std::string strCommand; + if (!request.params[1].isNull()) + strCommand = request.params[1].get_str(); + if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) { + throw std::runtime_error(help.ToString()); + } if (!g_banman) { throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); } diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py index ca9e24367a..feba16f1b3 100755 --- a/test/functional/rpc_getblockstats.py +++ b/test/functional/rpc_getblockstats.py @@ -178,5 +178,10 @@ def run_test(self): assert_raises_rpc_error(-5, 'Block not found', self.nodes[0].getblockstats, hash_or_height='000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f') + # Invalid number of args + assert_raises_rpc_error(-1, 'getblockstats hash_or_height ( stats )', self.nodes[0].getblockstats, '00', 1, 2) + assert_raises_rpc_error(-1, 'getblockstats hash_or_height ( stats )', self.nodes[0].getblockstats) + + if __name__ == '__main__': GetblockstatsTest().main() From 8b8d8eeae9e8feff6d78420ee172c820ccef9db1 Mon Sep 17 00:00:00 2001 From: Graham Krizek Date: Thu, 24 Jan 2019 21:28:27 -0600 Subject: [PATCH 0034/4486] Remove travis_wait from lint script Also adding progress logging to verify-commits.py script to prevent Travis from timing out --- .travis/lint_06_script.sh | 2 +- contrib/verify-commits/verify-commits.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.travis/lint_06_script.sh b/.travis/lint_06_script.sh index 701e6d8005..1a1693a8ce 100755 --- a/.travis/lint_06_script.sh +++ b/.travis/lint_06_script.sh @@ -21,5 +21,5 @@ test/lint/lint-all.sh if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then git log --merges --before="2 days ago" -1 --format='%H' > ./contrib/verify-commits/trusted-sha512-root-commit while read -r LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys && - travis_wait 50 contrib/verify-commits/verify-commits.py --clean-merge=2; + ./contrib/verify-commits/verify-commits.py --clean-merge=2; fi diff --git a/contrib/verify-commits/verify-commits.py b/contrib/verify-commits/verify-commits.py index 6bbed01073..255ce75092 100755 --- a/contrib/verify-commits/verify-commits.py +++ b/contrib/verify-commits/verify-commits.py @@ -5,6 +5,7 @@ """Verify commits against a trusted keys list.""" import argparse import hashlib +import logging import os import subprocess import sys @@ -66,6 +67,11 @@ def tree_sha512sum(commit='HEAD'): return overall.hexdigest() def main(): + + # Enable debug logging if running in CI + if 'CI' in os.environ and os.environ['CI'].lower() == "true": + logging.getLogger().setLevel(logging.DEBUG) + # Parse arguments parser = argparse.ArgumentParser(usage='%(prog)s [options] [commit id]') parser.add_argument('--disable-tree-check', action='store_false', dest='verify_tree', help='disable SHA-512 tree check') @@ -95,6 +101,10 @@ def main(): # Iterate through commits while True: + + # Log a message to prevent Travis from timing out + logging.debug("verify-commits: [in-progress] processing commit {}".format(current_commit[:8])) + if current_commit == verified_root: print('There is a valid path from "{}" to {} where all commits are signed!'.format(initial_commit, verified_root)) sys.exit(0) From 28c86de3b11ec16ba370f07327cf5a5de0e75c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Feb 2019 16:26:00 +0000 Subject: [PATCH 0035/4486] gui: Drop unused return values in WalletFrame --- src/qt/walletframe.cpp | 24 +++++++----------------- src/qt/walletframe.h | 6 +++--- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 466f2278eb..94413547d4 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -40,15 +40,11 @@ void WalletFrame::setClientModel(ClientModel *_clientModel) this->clientModel = _clientModel; } -bool WalletFrame::addWallet(WalletModel *walletModel) +void WalletFrame::addWallet(WalletModel *walletModel) { - if (!gui || !clientModel || !walletModel) { - return false; - } + if (!gui || !clientModel || !walletModel) return; - if (mapWalletViews.count(walletModel) > 0) { - return false; - } + if (mapWalletViews.count(walletModel) > 0) return; WalletView *walletView = new WalletView(platformStyle, this); walletView->setBitcoinGUI(gui); @@ -72,31 +68,25 @@ bool WalletFrame::addWallet(WalletModel *walletModel) }); connect(walletView, &WalletView::outOfSyncWarningClicked, this, &WalletFrame::outOfSyncWarningClicked); - - return true; } -bool WalletFrame::setCurrentWallet(WalletModel* wallet_model) +void WalletFrame::setCurrentWallet(WalletModel* wallet_model) { - if (mapWalletViews.count(wallet_model) == 0) - return false; + if (mapWalletViews.count(wallet_model) == 0) return; WalletView *walletView = mapWalletViews.value(wallet_model); walletStack->setCurrentWidget(walletView); assert(walletView); walletView->updateEncryptionStatus(); - return true; } -bool WalletFrame::removeWallet(WalletModel* wallet_model) +void WalletFrame::removeWallet(WalletModel* wallet_model) { - if (mapWalletViews.count(wallet_model) == 0) - return false; + if (mapWalletViews.count(wallet_model) == 0) return; WalletView *walletView = mapWalletViews.take(wallet_model); walletStack->removeWidget(walletView); delete walletView; - return true; } void WalletFrame::removeAllWallets() diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 6a74fde9fd..156653f47d 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -36,9 +36,9 @@ class WalletFrame : public QFrame void setClientModel(ClientModel *clientModel); - bool addWallet(WalletModel *walletModel); - bool setCurrentWallet(WalletModel* wallet_model); - bool removeWallet(WalletModel* wallet_model); + void addWallet(WalletModel *walletModel); + void setCurrentWallet(WalletModel* wallet_model); + void removeWallet(WalletModel* wallet_model); void removeAllWallets(); bool handlePaymentRequest(const SendCoinsRecipient& recipient); From 80f52a2267f44a9cae4440615df3ff989be1579c Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 18:13:23 -0400 Subject: [PATCH 0036/4486] Remove uses of CheckFinalTx in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 6 ++++++ src/interfaces/chain.h | 4 ++++ src/interfaces/wallet.cpp | 4 ++-- src/wallet/rpcwallet.cpp | 10 +++------- src/wallet/wallet.cpp | 9 +++------ 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index da810bc5e6..c7c2d4e91c 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -132,6 +133,11 @@ class LockImpl : public Chain::Lock } return nullopt; } + bool checkFinalTx(const CTransaction& tx) override + { + LockAnnotation lock(::cs_main); + return CheckFinalTx(tx); + } }; class LockingStateImpl : public LockImpl, public UniqueLock diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 3a54b9164e..453938751d 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -14,6 +14,7 @@ class CBlock; class CScheduler; +class CTransaction; class uint256; struct CBlockLocator; @@ -102,6 +103,9 @@ class Chain //! is guaranteed to be an ancestor of the block used to create the //! locator. virtual Optional findLocatorFork(const CBlockLocator& locator) = 0; + + //! Check if transaction will be final given chain height current time. + virtual bool checkFinalTx(const CTransaction& tx) = 0; }; //! Return Lock interface. Chain is locked when this is called, and diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 0dac75834e..e870d3d537 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -99,7 +99,7 @@ WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, co //! Construct wallet tx status struct. WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx) { - LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit. + LockAnnotation lock(::cs_main); // Temporary, for mapBlockIndex below. Removed in upcoming commit. WalletTxStatus result; auto mi = ::mapBlockIndex.find(wtx.hashBlock); @@ -109,7 +109,7 @@ WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const C result.depth_in_main_chain = wtx.GetDepthInMainChain(locked_chain); result.time_received = wtx.nTimeReceived; result.lock_time = wtx.tx->nLockTime; - result.is_final = CheckFinalTx(*wtx.tx); + result.is_final = locked_chain.checkFinalTx(*wtx.tx); result.is_trusted = wtx.IsTrusted(locked_chain); result.is_abandoned = wtx.isAbandoned(); result.is_coinbase = wtx.IsCoinBase(); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 97c6c38be1..eae0be86d3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -607,7 +607,6 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) // the user could have gotten from another RPC command prior to now pwallet->BlockUntilSyncedToCurrentChain(); - LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit. auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -630,7 +629,7 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) CAmount nAmount = 0; for (const std::pair& pairWtx : pwallet->mapWallet) { const CWalletTx& wtx = pairWtx.second; - if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) + if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) continue; for (const CTxOut& txout : wtx.tx->vout) @@ -679,7 +678,6 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request) // the user could have gotten from another RPC command prior to now pwallet->BlockUntilSyncedToCurrentChain(); - LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit. auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -696,7 +694,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request) CAmount nAmount = 0; for (const std::pair& pairWtx : pwallet->mapWallet) { const CWalletTx& wtx = pairWtx.second; - if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) + if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) continue; for (const CTxOut& txout : wtx.tx->vout) @@ -1051,8 +1049,6 @@ struct tallyitem static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { - LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit. - // Minimum confirmations int nMinDepth = 1; if (!params[0].isNull()) @@ -1083,7 +1079,7 @@ static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * co for (const std::pair& pairWtx : pwallet->mapWallet) { const CWalletTx& wtx = pairWtx.second; - if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) + if (wtx.IsCoinBase() || !locked_chain.checkFinalTx(*wtx.tx)) continue; int nDepth = wtx.GetDepthInMainChain(locked_chain); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 388422bec8..eb99c6cd77 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2075,10 +2075,8 @@ bool CWalletTx::InMempool() const bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const { - LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit. - // Quick answer in most cases - if (!CheckFinalTx(*tx)) + if (!locked_chain.checkFinalTx(*tx)) return false; int nDepth = GetDepthInMainChain(locked_chain); if (nDepth >= 1) @@ -2263,7 +2261,6 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const // trusted. CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) const { - LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit. auto locked_chain = chain().lock(); LOCK(cs_wallet); @@ -2271,7 +2268,7 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) cons for (const auto& entry : mapWallet) { const CWalletTx& wtx = entry.second; const int depth = wtx.GetDepthInMainChain(*locked_chain); - if (depth < 0 || !CheckFinalTx(*wtx.tx) || wtx.IsImmatureCoinBase(*locked_chain)) { + if (depth < 0 || !locked_chain->checkFinalTx(*wtx.tx) || wtx.IsImmatureCoinBase(*locked_chain)) { continue; } @@ -2325,7 +2322,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< const uint256& wtxid = entry.first; const CWalletTx* pcoin = &entry.second; - if (!CheckFinalTx(*pcoin->tx)) + if (!locked_chain.checkFinalTx(*pcoin->tx)) continue; if (pcoin->IsImmatureCoinBase(locked_chain)) From bdc6628683197945326cbdfea3f53ec0b7d1949f Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 19:25:26 -0400 Subject: [PATCH 0037/4486] Remove use of IsRBFOptIn in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 7 +++++++ src/interfaces/chain.h | 6 +++++- src/wallet/rpcwallet.cpp | 3 +-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index c7c2d4e91c..7cab303aad 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -6,9 +6,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -183,6 +185,11 @@ class ChainImpl : public Chain LOCK(cs_main); return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash)); } + RBFTransactionState isRBFOptIn(const CTransaction& tx) override + { + LOCK(::mempool.cs); + return IsRBFOptIn(tx, ::mempool); + } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 453938751d..486f1ea169 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -5,7 +5,8 @@ #ifndef BITCOIN_INTERFACES_CHAIN_H #define BITCOIN_INTERFACES_CHAIN_H -#include +#include // For Optional and nullopt +#include // For RBFTransactionState #include #include @@ -131,6 +132,9 @@ class Chain //! Estimate fraction of total transactions verified if blocks up to //! the specified block hash are verified. virtual double guessVerificationProgress(const uint256& block_hash) = 0; + + //! Check if transaction is RBF opt in. + virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index eae0be86d3..7217799535 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -124,8 +124,7 @@ static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& lo // Add opt-in RBF status std::string rbfStatus = "no"; if (confirms <= 0) { - LOCK(mempool.cs); - RBFTransactionState rbfState = IsRBFOptIn(*wtx.tx, mempool); + RBFTransactionState rbfState = chain.isRBFOptIn(*wtx.tx); if (rbfState == RBFTransactionState::UNKNOWN) rbfStatus = "unknown"; else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) From 291276f7f40df9fcd62e54c016953705bf0ed04a Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 19:29:50 -0400 Subject: [PATCH 0038/4486] Remove use of GetCountWithDescendants in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 6 ++++++ src/interfaces/chain.h | 3 +++ src/wallet/feebumper.cpp | 4 +--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 7cab303aad..8c5921970b 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -190,6 +190,12 @@ class ChainImpl : public Chain LOCK(::mempool.cs); return IsRBFOptIn(tx, ::mempool); } + bool hasDescendantsInMempool(const uint256& txid) override + { + LOCK(::mempool.cs); + auto it_mp = ::mempool.mapTx.find(txid); + return it_mp != ::mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1; + } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 486f1ea169..aa4f17a8ec 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -135,6 +135,9 @@ class Chain //! Check if transaction is RBF opt in. virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0; + + //! Check if transaction has descendants in mempool. + virtual bool hasDescendantsInMempool(const uint256& txid) = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 7a71aea715..f4b419ca2a 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -27,9 +27,7 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai } { - LOCK(mempool.cs); - auto it_mp = mempool.mapTx.find(wtx.GetHash()); - if (it_mp != mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1) { + if (wallet->chain().hasDescendantsInMempool(wtx.GetHash())) { errors.push_back("Transaction has descendants in the mempool"); return feebumper::Result::INVALID_PARAMETER; } From cd32160af0528cc746968ee0eadf4f63c98665f2 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 19:42:27 -0400 Subject: [PATCH 0039/4486] Remove use of GetTransactionAncestry in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 4 ++++ src/interfaces/chain.h | 4 ++++ src/wallet/wallet.cpp | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 8c5921970b..d7bad0543c 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -196,6 +196,10 @@ class ChainImpl : public Chain auto it_mp = ::mempool.mapTx.find(txid); return it_mp != ::mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1; } + void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) override + { + ::mempool.GetTransactionAncestry(txid, ancestors, descendants); + } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index aa4f17a8ec..33bbfefd9f 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -9,6 +9,7 @@ #include // For RBFTransactionState #include +#include #include #include #include @@ -138,6 +139,9 @@ class Chain //! Check if transaction has descendants in mempool. virtual bool hasDescendantsInMempool(const uint256& txid) = 0; + + //! Calculate mempool ancestor and descendant counts for the given transaction. + virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index eb99c6cd77..a77b1c60f2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4528,7 +4528,7 @@ std::vector CWallet::GroupOutputs(const std::vector& outpu CInputCoin input_coin = output.GetInputCoin(); size_t ancestors, descendants; - mempool.GetTransactionAncestry(output.tx->GetHash(), ancestors, descendants); + chain().getTransactionAncestry(output.tx->GetHash(), ancestors, descendants); if (!single_coin && ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) { // Limit output groups to no more than 10 entries, to protect // against inadvertently creating a too-large transaction From 1fb0a4a04e9cda19ed5ad04694a39c83c91b6072 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 19:45:45 -0400 Subject: [PATCH 0040/4486] Remove use of CalculateMemPoolAncestors in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 14 ++++++++++++++ src/interfaces/chain.h | 3 +++ src/wallet/wallet.cpp | 11 +---------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index d7bad0543c..c12215cd60 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -200,6 +200,20 @@ class ChainImpl : public Chain { ::mempool.GetTransactionAncestry(txid, ancestors, descendants); } + bool checkChainLimits(CTransactionRef tx) override + { + LockPoints lp; + CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp); + CTxMemPool::setEntries ancestors; + auto limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); + auto limit_ancestor_size = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000; + auto limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); + auto limit_descendant_size = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000; + std::string unused_error_string; + LOCK(::mempool.cs); + return ::mempool.CalculateMemPoolAncestors(entry, ancestors, limit_ancestor_count, limit_ancestor_size, + limit_descendant_count, limit_descendant_size, unused_error_string); + } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 33bbfefd9f..2e0328eb25 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -142,6 +142,9 @@ class Chain //! Calculate mempool ancestor and descendant counts for the given transaction. virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0; + + //! Check chain limits. + virtual bool checkChainLimits(CTransactionRef tx) = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a77b1c60f2..5c95c7ec61 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3127,16 +3127,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) { // Lastly, ensure this tx will pass the mempool's chain limits - LockPoints lp; - CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp); - CTxMemPool::setEntries setAncestors; - size_t nLimitAncestors = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); - size_t nLimitAncestorSize = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000; - size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); - size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000; - std::string errString; - LOCK(::mempool.cs); - if (!::mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) { + if (!chain().checkChainLimits(tx)) { strFailReason = _("Transaction has too long of a mempool chain"); return false; } From cc02c796d3517931acc861b0f9bc50e36e1c95f9 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 21:40:29 -0400 Subject: [PATCH 0041/4486] Remove uses of fee globals in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 14 ++++++++++++++ src/interfaces/chain.h | 10 ++++++++++ src/interfaces/wallet.cpp | 2 +- src/rpc/mining.cpp | 6 ++++-- src/rpc/util.cpp | 5 +---- src/rpc/util.h | 2 +- src/wallet/feebumper.cpp | 4 ++-- src/wallet/fees.cpp | 17 ++++++++--------- src/wallet/fees.h | 8 +++----- src/wallet/rpcwallet.cpp | 8 ++++---- src/wallet/wallet.cpp | 12 ++++++------ src/wallet/wallet.h | 2 -- 12 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index c12215cd60..f888606879 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -214,6 +216,18 @@ class ChainImpl : public Chain return ::mempool.CalculateMemPoolAncestors(entry, ancestors, limit_ancestor_count, limit_ancestor_size, limit_descendant_count, limit_descendant_size, unused_error_string); } + CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override + { + return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative); + } + unsigned int estimateMaxBlocks() override + { + return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); + } + CFeeRate mempoolMinFee() override + { + return ::mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); + } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 2e0328eb25..d0f74cb100 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -19,6 +19,7 @@ class CScheduler; class CTransaction; class uint256; struct CBlockLocator; +struct FeeCalculation; namespace interfaces { @@ -145,6 +146,15 @@ class Chain //! Check chain limits. virtual bool checkChainLimits(CTransactionRef tx) = 0; + + //! Estimate smart fee. + virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc = nullptr) = 0; + + //! Fee estimator max target. + virtual unsigned int estimateMaxBlocks() = 0; + + //! Pool min fee. + virtual CFeeRate mempoolMinFee() = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index e870d3d537..f3a0b416db 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -457,7 +457,7 @@ class WalletImpl : public Wallet { FeeCalculation fee_calc; CAmount result; - result = GetMinimumFee(*m_wallet, tx_bytes, coin_control, ::mempool, ::feeEstimator, &fee_calc); + result = GetMinimumFee(*m_wallet, tx_bytes, coin_control, &fee_calc); if (returned_target) *returned_target = fee_calc.returnedTarget; if (reason) *reason = fee_calc.reason; return result; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 6625a03bbd..f2acb8fbf5 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -843,7 +843,8 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR}); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); - unsigned int conf_target = ParseConfirmTarget(request.params[0]); + unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); + unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target); bool conservative = true; if (!request.params[1].isNull()) { FeeEstimateMode fee_mode; @@ -915,7 +916,8 @@ static UniValue estimaterawfee(const JSONRPCRequest& request) RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); - unsigned int conf_target = ParseConfirmTarget(request.params[0]); + unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); + unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target); double threshold = 0.95; if (!request.params[1].isNull()) { threshold = request.params[1].get_real(); diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 1eec916abf..fb048311de 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -4,11 +4,9 @@ #include #include -#include #include #include #include -#include InitInterfaces* g_rpc_interfaces = nullptr; @@ -130,10 +128,9 @@ UniValue DescribeAddress(const CTxDestination& dest) return boost::apply_visitor(DescribeAddressVisitor(), dest); } -unsigned int ParseConfirmTarget(const UniValue& value) +unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target) { int target = value.get_int(); - unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); if (target < 1 || (unsigned int)target > max_target) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid conf_target, must be between %u - %u", 1, max_target)); } diff --git a/src/rpc/util.h b/src/rpc/util.h index a83ae98b7e..e1a5491def 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -33,7 +33,7 @@ CScript CreateMultisigRedeemscript(const int required, const std::vectornValue -= nDelta; - if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet, ::feeEstimator))) { + if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet))) { wallet->WalletLogPrintf("Bumping fee and discarding dust output\n"); new_fee += poutput->nValue; mtx.vout.erase(mtx.vout.begin() + nOutput); diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index 9e2984ff05..545adaebc1 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -19,9 +18,9 @@ CAmount GetRequiredFee(const CWallet& wallet, unsigned int nTxBytes) } -CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc) +CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, FeeCalculation* feeCalc) { - CAmount fee_needed = GetMinimumFeeRate(wallet, coin_control, pool, estimator, feeCalc).GetFee(nTxBytes); + CAmount fee_needed = GetMinimumFeeRate(wallet, coin_control, feeCalc).GetFee(nTxBytes); // Always obey the maximum if (fee_needed > maxTxFee) { fee_needed = maxTxFee; @@ -35,7 +34,7 @@ CFeeRate GetRequiredFeeRate(const CWallet& wallet) return std::max(wallet.m_min_fee, ::minRelayTxFee); } -CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc) +CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, FeeCalculation* feeCalc) { /* User control of how to calculate fee uses the following parameter precedence: 1. coin_control.m_feerate @@ -64,7 +63,7 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr if (coin_control.m_fee_mode == FeeEstimateMode::CONSERVATIVE) conservative_estimate = true; else if (coin_control.m_fee_mode == FeeEstimateMode::ECONOMICAL) conservative_estimate = false; - feerate_needed = estimator.estimateSmartFee(target, feeCalc, conservative_estimate); + feerate_needed = wallet.chain().estimateSmartFee(target, conservative_estimate, feeCalc); if (feerate_needed == CFeeRate(0)) { // if we don't have enough data for estimateSmartFee, then use fallback fee feerate_needed = wallet.m_fallback_fee; @@ -74,7 +73,7 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr if (wallet.m_fallback_fee == CFeeRate(0)) return feerate_needed; } // Obey mempool min fee when using smart fee estimation - CFeeRate min_mempool_feerate = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); + CFeeRate min_mempool_feerate = wallet.chain().mempoolMinFee(); if (feerate_needed < min_mempool_feerate) { feerate_needed = min_mempool_feerate; if (feeCalc) feeCalc->reason = FeeReason::MEMPOOL_MIN; @@ -90,10 +89,10 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr return feerate_needed; } -CFeeRate GetDiscardRate(const CWallet& wallet, const CBlockPolicyEstimator& estimator) +CFeeRate GetDiscardRate(const CWallet& wallet) { - unsigned int highest_target = estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); - CFeeRate discard_rate = estimator.estimateSmartFee(highest_target, nullptr /* FeeCalculation */, false /* conservative */); + unsigned int highest_target = wallet.chain().estimateMaxBlocks(); + CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */); // Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate); // Discard rate must be at least dustRelayFee diff --git a/src/wallet/fees.h b/src/wallet/fees.h index 6bfee456c0..434f211dc2 100644 --- a/src/wallet/fees.h +++ b/src/wallet/fees.h @@ -8,10 +8,8 @@ #include -class CBlockPolicyEstimator; class CCoinControl; class CFeeRate; -class CTxMemPool; class CWallet; struct FeeCalculation; @@ -25,7 +23,7 @@ CAmount GetRequiredFee(const CWallet& wallet, unsigned int nTxBytes); * Estimate the minimum fee considering user set parameters * and the required fee */ -CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc); +CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, FeeCalculation* feeCalc); /** * Return the minimum required feerate taking into account the @@ -37,11 +35,11 @@ CFeeRate GetRequiredFeeRate(const CWallet& wallet); * Estimate the minimum fee rate considering user set parameters * and the required fee */ -CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc); +CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, FeeCalculation* feeCalc); /** * Return the maximum feerate for discarding change. */ -CFeeRate GetDiscardRate(const CWallet& wallet, const CBlockPolicyEstimator& estimator); +CFeeRate GetDiscardRate(const CWallet& wallet); #endif // BITCOIN_WALLET_FEES_H diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7217799535..09e91dc588 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -424,7 +424,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) } if (!request.params[6].isNull()) { - coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]); + coin_control.m_confirm_target = ParseConfirmTarget(request.params[6], pwallet->chain().estimateMaxBlocks()); } if (!request.params[7].isNull()) { @@ -884,7 +884,7 @@ static UniValue sendmany(const JSONRPCRequest& request) } if (!request.params[6].isNull()) { - coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]); + coin_control.m_confirm_target = ParseConfirmTarget(request.params[6], pwallet->chain().estimateMaxBlocks()); } if (!request.params[7].isNull()) { @@ -2989,7 +2989,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f if (options.exists("feeRate")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate"); } - coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"]); + coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"], pwallet->chain().estimateMaxBlocks()); } if (options.exists("estimate_mode")) { if (options.exists("feeRate")) { @@ -3279,7 +3279,7 @@ static UniValue bumpfee(const JSONRPCRequest& request) if (options.exists("confTarget") && options.exists("totalFee")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction."); } else if (options.exists("confTarget")) { // TODO: alias this to conf_target - coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"]); + coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"], pwallet->chain().estimateMaxBlocks()); } else if (options.exists("totalFee")) { totalFee = options["totalFee"].get_int64(); if (totalFee <= 0) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5c95c7ec61..75681e2007 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2485,10 +2485,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil FeeCalculation feeCalc; CCoinControl temp; temp.m_confirm_target = 1008; - CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, ::mempool, ::feeEstimator, &feeCalc); + CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, &feeCalc); // Calculate cost of change - CAmount cost_of_change = GetDiscardRate(*this, ::feeEstimator).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size); + CAmount cost_of_change = GetDiscardRate(*this).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size); // Filter by the min conf specs and add to utxo_pool and calculate effective value for (OutputGroup& group : groups) { @@ -2858,10 +2858,10 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std CTxOut change_prototype_txout(0, scriptChange); coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout); - CFeeRate discard_rate = GetDiscardRate(*this, ::feeEstimator); + CFeeRate discard_rate = GetDiscardRate(*this); // Get the fee rate to use effective values in coin selection - CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, ::mempool, ::feeEstimator, &feeCalc); + CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, &feeCalc); nFeeRet = 0; bool pick_new_inputs = true; @@ -2994,7 +2994,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std return false; } - nFeeNeeded = GetMinimumFee(*this, nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc); + nFeeNeeded = GetMinimumFee(*this, nBytes, coin_control, &feeCalc); if (feeCalc.reason == FeeReason::FALLBACK && !m_allow_fallback_fee) { // eventually allow a fallback fee strFailReason = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee."); @@ -3022,7 +3022,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std // change output. Only try this once. if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) { unsigned int tx_size_with_change = nBytes + coin_selection_params.change_output_size + 2; // Add 2 as a buffer in case increasing # of outputs changes compact size - CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, ::mempool, ::feeEstimator, nullptr); + CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, nullptr); CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate); if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) { pick_new_inputs = false; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 2a5d6caaf8..f215765dab 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -100,8 +100,6 @@ class CCoinControl; class COutput; class CReserveKey; class CScript; -class CTxMemPool; -class CBlockPolicyEstimator; class CWalletTx; struct FeeCalculation; enum class FeeEstimateMode; From cc3836e8f90894432db06d9de6b20eac53d93cbe Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 22:45:01 -0400 Subject: [PATCH 0042/4486] Remove uses of fPruneMode in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 1 + src/interfaces/chain.h | 3 +++ src/wallet/rpcdump.cpp | 8 ++++---- src/wallet/wallet.cpp | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index f888606879..bb2af5b8ba 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -228,6 +228,7 @@ class ChainImpl : public Chain { return ::mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); } + bool getPruneMode() override { return ::fPruneMode; } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index d0f74cb100..96e4f8cf0b 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -155,6 +155,9 @@ class Chain //! Pool min fee. virtual CFeeRate mempoolMinFee() = 0; + + //! Check if pruning is enabled. + virtual bool getPruneMode() = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index f38202a2b8..046a6567a5 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -157,7 +157,7 @@ UniValue importprivkey(const JSONRPCRequest& request) if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); - if (fRescan && fPruneMode) + if (fRescan && pwallet->chain().getPruneMode()) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); if (fRescan && !reserver.reserve()) { @@ -313,7 +313,7 @@ UniValue importaddress(const JSONRPCRequest& request) if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); - if (fRescan && fPruneMode) + if (fRescan && pwallet->chain().getPruneMode()) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); WalletRescanReserver reserver(pwallet); @@ -501,7 +501,7 @@ UniValue importpubkey(const JSONRPCRequest& request) if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); - if (fRescan && fPruneMode) + if (fRescan && pwallet->chain().getPruneMode()) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); WalletRescanReserver reserver(pwallet); @@ -562,7 +562,7 @@ UniValue importwallet(const JSONRPCRequest& request) }, }.ToString()); - if (fPruneMode) + if (pwallet->chain().getPruneMode()) throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode"); WalletRescanReserver reserver(pwallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 75681e2007..a0718309b9 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4334,7 +4334,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, //We can't rescan beyond non-pruned blocks, stop and throw an error //this might happen if a user uses an old wallet within a pruned node // or if he ran -disablewallet for a longer time, then decided to re-enable - if (fPruneMode) + if (chain.getPruneMode()) { int block_height = *tip_height; while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) { From 00dfb2a440b94a24b61cafb519fb122f6a0ae176 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 22:50:07 -0400 Subject: [PATCH 0043/4486] Remove uses of g_connman in wallet code This commit does not change behavior. --- src/Makefile.am | 8 ++++++-- src/Makefile.bench.include | 4 +++- src/interfaces/chain.cpp | 2 ++ src/interfaces/chain.h | 3 +++ src/wallet/rpcwallet.cpp | 6 +++--- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d491530ca1..650e347da3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -562,16 +562,20 @@ bitcoin_wallet_LDADD = \ $(LIBBITCOIN_WALLET_TOOL) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_ZMQ) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ - $(LIBSECP256K1) + $(LIBSECP256K1) \ + $(LIBUNIVALUE) -bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) +bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(ZMQ_LIBS) # # bitcoinconsensus library # diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 5e787ca222..829e644643 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -37,6 +37,8 @@ nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES) bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bench_bench_bitcoin_LDADD = \ + $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ @@ -57,7 +59,7 @@ if ENABLE_WALLET bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp endif -bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) +bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index bb2af5b8ba..8493c5de70 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -229,6 +230,7 @@ class ChainImpl : public Chain return ::mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); } bool getPruneMode() override { return ::fPruneMode; } + bool p2pEnabled() override { return g_connman != nullptr; } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 96e4f8cf0b..44a0b1743e 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -158,6 +158,9 @@ class Chain //! Check if pruning is enabled. virtual bool getPruneMode() = 0; + + //! Check if p2p enabled. + virtual bool p2pEnabled() = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 09e91dc588..6e11fe936c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -318,7 +318,7 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet if (nValue > curBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); - if (pwallet->GetBroadcastTransactions() && !g_connman) { + if (pwallet->GetBroadcastTransactions() && !pwallet->chain().p2pEnabled()) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } @@ -858,7 +858,7 @@ static UniValue sendmany(const JSONRPCRequest& request) auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); - if (pwallet->GetBroadcastTransactions() && !g_connman) { + if (pwallet->GetBroadcastTransactions() && !pwallet->chain().p2pEnabled()) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } @@ -2690,7 +2690,7 @@ static UniValue resendwallettransactions(const JSONRPCRequest& request) }.ToString() ); - if (!g_connman) + if (!pwallet->chain().p2pEnabled()) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); auto locked_chain = pwallet->chain().lock(); From 6d6bcc77c058fbcfd39c7e3050bbe82fc89024cf Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 19:34:54 -0400 Subject: [PATCH 0044/4486] Remove use of g_connman / PushInventory in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 6 ++++++ src/interfaces/chain.h | 3 +++ src/interfaces/wallet.cpp | 2 +- src/wallet/feebumper.cpp | 2 +- src/wallet/rpcwallet.cpp | 6 +++--- src/wallet/test/wallet_tests.cpp | 2 +- src/wallet/wallet.cpp | 20 ++++++++------------ src/wallet/wallet.h | 6 +++--- 8 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 8493c5de70..4abb1e638f 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -199,6 +200,11 @@ class ChainImpl : public Chain auto it_mp = ::mempool.mapTx.find(txid); return it_mp != ::mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1; } + void relayTransaction(const uint256& txid) override + { + CInv inv(MSG_TX, txid); + g_connman->ForEachNode([&inv](CNode* node) { node->PushInventory(inv); }); + } void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) override { ::mempool.GetTransactionAncestry(txid, ancestors, descendants); diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 44a0b1743e..b4a458cba6 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -141,6 +141,9 @@ class Chain //! Check if transaction has descendants in mempool. virtual bool hasDescendantsInMempool(const uint256& txid) = 0; + //! Relay transaction. + virtual void relayTransaction(const uint256& txid) = 0; + //! Calculate mempool ancestor and descendant counts for the given transaction. virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0; diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index f3a0b416db..7abbee0912 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -56,7 +56,7 @@ class PendingWalletTxImpl : public PendingWalletTx auto locked_chain = m_wallet.chain().lock(); LOCK(m_wallet.cs_wallet); CValidationState state; - if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_key, g_connman.get(), state)) { + if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_key, state)) { reject_reason = state.GetRejectReason(); return false; } diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index dd4b2fad4b..a1c3a21d4b 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -245,7 +245,7 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti CReserveKey reservekey(wallet); CValidationState state; - if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, reservekey, g_connman.get(), state)) { + if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, reservekey, state)) { // NOTE: CommitTransaction never returns false, so this should never happen. errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state))); return Result::WALLET_ERROR; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 6e11fe936c..8d1bd3a169 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -340,7 +340,7 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet throw JSONRPCError(RPC_WALLET_ERROR, strError); } CValidationState state; - if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, reservekey, g_connman.get(), state)) { + if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, reservekey, state)) { strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } @@ -946,7 +946,7 @@ static UniValue sendmany(const JSONRPCRequest& request) if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); CValidationState state; - if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, keyChange, g_connman.get(), state)) { + if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, keyChange, state)) { strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state)); throw JSONRPCError(RPC_WALLET_ERROR, strFailReason); } @@ -2700,7 +2700,7 @@ static UniValue resendwallettransactions(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet transaction broadcasting is disabled with -walletbroadcast"); } - std::vector txids = pwallet->ResendWalletTransactionsBefore(*locked_chain, GetTime(), g_connman.get()); + std::vector txids = pwallet->ResendWalletTransactionsBefore(*locked_chain, GetTime()); UniValue result(UniValue::VARR); for (const uint256& txid : txids) { diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index e674b2faea..af57dbf5f6 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -368,7 +368,7 @@ class ListCoinsTestingSetup : public TestChain100Setup CCoinControl dummy; BOOST_CHECK(wallet->CreateTransaction(*m_locked_chain, {recipient}, tx, reservekey, fee, changePos, error, dummy)); CValidationState state; - BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, reservekey, nullptr, state)); + BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, reservekey, state)); CMutableTransaction blocktx; { LOCK(wallet->cs_wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a0718309b9..8746fb556b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1890,7 +1890,7 @@ void CWallet::ReacceptWalletTransactions() } } -bool CWalletTx::RelayWalletTransaction(interfaces::Chain::Lock& locked_chain, CConnman* connman) +bool CWalletTx::RelayWalletTransaction(interfaces::Chain::Lock& locked_chain) { assert(pwallet->GetBroadcastTransactions()); if (!IsCoinBase() && !isAbandoned() && GetDepthInMainChain(locked_chain) == 0) @@ -1899,12 +1899,8 @@ bool CWalletTx::RelayWalletTransaction(interfaces::Chain::Lock& locked_chain, CC /* GetDepthInMainChain already catches known conflicts. */ if (InMempool() || AcceptToMemoryPool(locked_chain, maxTxFee, state)) { pwallet->WalletLogPrintf("Relaying wtx %s\n", GetHash().ToString()); - if (connman) { - CInv inv(MSG_TX, GetHash()); - connman->ForEachNode([&inv](CNode* pnode) - { - pnode->PushInventory(inv); - }); + if (pwallet->chain().p2pEnabled()) { + pwallet->chain().relayTransaction(GetHash()); return true; } } @@ -2113,7 +2109,7 @@ bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const return CTransaction(tx1) == CTransaction(tx2); } -std::vector CWallet::ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime, CConnman* connman) +std::vector CWallet::ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime) { std::vector result; @@ -2132,7 +2128,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(interfaces::Chain:: for (const std::pair& item : mapSorted) { CWalletTx& wtx = *item.second; - if (wtx.RelayWalletTransaction(locked_chain, connman)) + if (wtx.RelayWalletTransaction(locked_chain)) result.push_back(wtx.GetHash()); } return result; @@ -2157,7 +2153,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman // Rebroadcast unconfirmed txes older than 5 minutes before the last // block was found: auto locked_chain = chain().assumeLocked(); // Temporary. Removed in upcoming lock cleanup - std::vector relayed = ResendWalletTransactionsBefore(*locked_chain, nBestBlockTime-5*60, connman); + std::vector relayed = ResendWalletTransactionsBefore(*locked_chain, nBestBlockTime-5*60); if (!relayed.empty()) WalletLogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size()); } @@ -3147,7 +3143,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std /** * Call after CreateTransaction unless you want to abort */ -bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector> orderForm, CReserveKey& reservekey, CConnman* connman, CValidationState& state) +bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector> orderForm, CReserveKey& reservekey, CValidationState& state) { { auto locked_chain = chain().lock(); @@ -3188,7 +3184,7 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state)); // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. } else { - wtx.RelayWalletTransaction(*locked_chain, connman); + wtx.RelayWalletTransaction(*locked_chain); } } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f215765dab..41bb4bd8c7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -535,7 +535,7 @@ class CWalletTx : public CMerkleTx int64_t GetTxTime() const; // RelayWalletTransaction may only be called if fBroadcastTransactions! - bool RelayWalletTransaction(interfaces::Chain::Lock& locked_chain, CConnman* connman); + bool RelayWalletTransaction(interfaces::Chain::Lock& locked_chain); /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */ bool AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, const CAmount& nAbsurdFee, CValidationState& state); @@ -944,7 +944,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override EXCLUSIVE_LOCKS_REQUIRED(cs_main); // ResendWalletTransactionsBefore may only be called if fBroadcastTransactions! - std::vector ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime, CConnman* connman); + std::vector ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime); CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE, const int min_depth=0) const; CAmount GetUnconfirmedBalance() const; CAmount GetImmatureBalance() const; @@ -969,7 +969,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface */ bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign = true); - bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector> orderForm, CReserveKey& reservekey, CConnman* connman, CValidationState& state); + bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector> orderForm, CReserveKey& reservekey, CValidationState& state); bool DummySignTx(CMutableTransaction &txNew, const std::set &txouts, bool use_max_sig = false) const { From c5e59a96a8561b6a0bcaba0ede2d53dbaac113b0 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 22:54:31 -0400 Subject: [PATCH 0045/4486] Remove uses of GetAdjustedTime in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 2 ++ src/interfaces/chain.h | 3 +++ src/wallet/wallet.cpp | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 4abb1e638f..a654f55f55 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -237,6 +238,7 @@ class ChainImpl : public Chain } bool getPruneMode() override { return ::fPruneMode; } bool p2pEnabled() override { return g_connman != nullptr; } + int64_t getAdjustedTime() override { return GetAdjustedTime(); } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index b4a458cba6..c5aa67d0d7 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -164,6 +164,9 @@ class Chain //! Check if p2p enabled. virtual bool p2pEnabled() = 0; + + //! Get adjusted time. + virtual int64_t getAdjustedTime() = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8746fb556b..8452104745 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -940,7 +940,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) wtx.BindWallet(this); bool fInsertedNew = ret.second; if (fInsertedNew) { - wtx.nTimeReceived = GetAdjustedTime(); + wtx.nTimeReceived = chain().getAdjustedTime(); wtx.nOrderPos = IncOrderPosNext(&batch); wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx)); wtx.nTimeSmart = ComputeTimeSmart(wtx); From e2c8ba9f6e782e2545b71e9e34b967c69e18c7f0 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 28 Jul 2017 22:59:47 -0400 Subject: [PATCH 0046/4486] Remove uses of InitMessage/Warning/Error in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 4 +++ src/interfaces/chain.h | 9 ++++++ src/wallet/init.cpp | 16 ++++++---- src/wallet/wallet.cpp | 66 ++++++++++++++++++++-------------------- 4 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index a654f55f55..4f60448958 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -239,6 +240,9 @@ class ChainImpl : public Chain bool getPruneMode() override { return ::fPruneMode; } bool p2pEnabled() override { return g_connman != nullptr; } int64_t getAdjustedTime() override { return GetAdjustedTime(); } + void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } + void initWarning(const std::string& message) override { InitWarning(message); } + void initError(const std::string& message) override { InitError(message); } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index c5aa67d0d7..b1e3f59452 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -167,6 +167,15 @@ class Chain //! Get adjusted time. virtual int64_t getAdjustedTime() = 0; + + //! Send init message. + virtual void initMessage(const std::string& message) = 0; + + //! Send init warning. + virtual void initWarning(const std::string& message) = 0; + + //! Send init error. + virtual void initError(const std::string& message) = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 20d540c8db..7ad343c15f 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -138,12 +138,15 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector& wal // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); if (error || !fs::exists(wallet_dir)) { - return InitError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string())); + chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string())); + return false; } else if (!fs::is_directory(wallet_dir)) { - return InitError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string())); + chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string())); + return false; // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version } else if (!wallet_dir.is_absolute()) { - return InitError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string())); + chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string())); + return false; } gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); } @@ -164,14 +167,15 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector& wal WalletLocation location(wallet_file); if (!wallet_paths.insert(location.GetPath()).second) { - return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file)); + chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file)); + return false; } std::string error_string; std::string warning_string; bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warning_string); - if (!error_string.empty()) InitError(error_string); - if (!warning_string.empty()) InitWarning(warning_string); + if (!error_string.empty()) chain.initError(error_string); + if (!warning_string.empty()) chain.initWarning(warning_string); if (!verify_success) return false; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8452104745..2a1744fa68 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4087,17 +4087,17 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, std::vector vWtx; if (gArgs.GetBoolArg("-zapwallettxes", false)) { - uiInterface.InitMessage(_("Zapping all transactions from wallet...")); + chain.initMessage(_("Zapping all transactions from wallet...")); std::unique_ptr tempWallet = MakeUnique(chain, location, WalletDatabase::Create(location.GetPath())); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DBErrors::LOAD_OK) { - InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + chain.initError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); return nullptr; } } - uiInterface.InitMessage(_("Loading wallet...")); + chain.initMessage(_("Loading wallet...")); int64_t nStart = GetTimeMillis(); bool fFirstRun = true; @@ -4108,26 +4108,26 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (nLoadWalletRet != DBErrors::LOAD_OK) { if (nLoadWalletRet == DBErrors::CORRUPT) { - InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + chain.initError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); return nullptr; } else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR) { - InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" - " or address book entries might be missing or incorrect."), + chain.initWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" + " or address book entries might be missing or incorrect."), walletFile)); } else if (nLoadWalletRet == DBErrors::TOO_NEW) { - InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME))); + chain.initError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME))); return nullptr; } else if (nLoadWalletRet == DBErrors::NEED_REWRITE) { - InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); + chain.initError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); return nullptr; } else { - InitError(strprintf(_("Error loading %s"), walletFile)); + chain.initError(strprintf(_("Error loading %s"), walletFile)); return nullptr; } } @@ -4146,7 +4146,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); if (nMaxVersion < walletInstance->GetVersion()) { - InitError(_("Cannot downgrade wallet")); + chain.initError(_("Cannot downgrade wallet")); return nullptr; } walletInstance->SetMaxVersion(nMaxVersion); @@ -4159,7 +4159,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT int max_version = walletInstance->nWalletVersion; if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >=FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) { - InitError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.")); + chain.initError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.")); return nullptr; } @@ -4187,7 +4187,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Regenerate the keypool if upgraded to HD if (hd_upgrade) { if (!walletInstance->TopUpKeyPool()) { - InitError(_("Unable to generate keys")); + chain.initError(_("Unable to generate keys")); return nullptr; } } @@ -4211,7 +4211,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Top up the keypool if (walletInstance->CanGenerateKeys() && !walletInstance->TopUpKeyPool()) { - InitError(_("Unable to generate initial keys")); + chain.initError(_("Unable to generate initial keys")); return nullptr; } @@ -4219,34 +4219,34 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, walletInstance->ChainStateFlushed(locked_chain->getTipLocator()); } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) { // Make it impossible to disable private keys after creation - InitError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile)); + chain.initError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile)); return NULL; } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { LOCK(walletInstance->cs_KeyStore); if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) { - InitWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile)); + chain.initWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile)); } } if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) { - InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", ""))); + chain.initError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", ""))); return nullptr; } if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) { - InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", ""))); + chain.initError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", ""))); return nullptr; } if (gArgs.IsArgSet("-mintxfee")) { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) { - InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", ""))); + chain.initError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", ""))); return nullptr; } if (n > HIGH_TX_FEE_PER_KB) { - InitWarning(AmountHighWarn("-mintxfee") + " " + - _("This is the minimum transaction fee you pay on every transaction.")); + chain.initWarning(AmountHighWarn("-mintxfee") + " " + + _("This is the minimum transaction fee you pay on every transaction.")); } walletInstance->m_min_fee = CFeeRate(n); } @@ -4255,12 +4255,12 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-fallbackfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) { - InitError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), gArgs.GetArg("-fallbackfee", ""))); + chain.initError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), gArgs.GetArg("-fallbackfee", ""))); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - InitWarning(AmountHighWarn("-fallbackfee") + " " + - _("This is the transaction fee you may pay when fee estimates are not available.")); + chain.initWarning(AmountHighWarn("-fallbackfee") + " " + + _("This is the transaction fee you may pay when fee estimates are not available.")); } walletInstance->m_fallback_fee = CFeeRate(nFeePerK); walletInstance->m_allow_fallback_fee = nFeePerK != 0; //disable fallback fee in case value was set to 0, enable if non-null value @@ -4268,28 +4268,28 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-discardfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) { - InitError(strprintf(_("Invalid amount for -discardfee=: '%s'"), gArgs.GetArg("-discardfee", ""))); + chain.initError(strprintf(_("Invalid amount for -discardfee=: '%s'"), gArgs.GetArg("-discardfee", ""))); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - InitWarning(AmountHighWarn("-discardfee") + " " + - _("This is the transaction fee you may discard if change is smaller than dust at this level")); + chain.initWarning(AmountHighWarn("-discardfee") + " " + + _("This is the transaction fee you may discard if change is smaller than dust at this level")); } walletInstance->m_discard_rate = CFeeRate(nFeePerK); } if (gArgs.IsArgSet("-paytxfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) { - InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", ""))); + chain.initError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", ""))); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - InitWarning(AmountHighWarn("-paytxfee") + " " + - _("This is the transaction fee you will pay if you send a transaction.")); + chain.initWarning(AmountHighWarn("-paytxfee") + " " + + _("This is the transaction fee you will pay if you send a transaction.")); } walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000); if (walletInstance->m_pay_tx_fee < ::minRelayTxFee) { - InitError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), + chain.initError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString())); return nullptr; } @@ -4338,12 +4338,12 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, } if (rescan_height != block_height) { - InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); + chain.initError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); return nullptr; } } - uiInterface.InitMessage(_("Rescanning...")); + chain.initMessage(_("Rescanning...")); walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height); // No need to read and scan block if block was created before @@ -4358,7 +4358,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, { WalletRescanReserver reserver(walletInstance.get()); if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) { - InitError(_("Failed to rescan the wallet during initialization")); + chain.initError(_("Failed to rescan the wallet during initialization")); return nullptr; } } From d02b34c8a8bd446c9620fe626b4379617f9a9639 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Mon, 31 Jul 2017 16:31:29 -0400 Subject: [PATCH 0047/4486] Remove use of AcceptToMemoryPool in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 8 ++++++++ src/interfaces/chain.h | 13 ++++++++++++- src/wallet/wallet.cpp | 13 +++++-------- src/wallet/wallet.h | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 4f60448958..9f02514df3 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -146,6 +147,12 @@ class LockImpl : public Chain::Lock LockAnnotation lock(::cs_main); return CheckFinalTx(tx); } + bool submitToMemoryPool(CTransactionRef tx, CAmount absurd_fee, CValidationState& state) override + { + LockAnnotation lock(::cs_main); + return AcceptToMemoryPool(::mempool, state, tx, nullptr /* missing inputs */, nullptr /* txn replaced */, + false /* bypass limits */, absurd_fee); + } }; class LockingStateImpl : public LockImpl, public UniqueLock @@ -237,6 +244,7 @@ class ChainImpl : public Chain { return ::mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); } + CAmount maxTxFee() override { return ::maxTxFee; } bool getPruneMode() override { return ::fPruneMode; } bool p2pEnabled() override { return g_connman != nullptr; } int64_t getAdjustedTime() override { return GetAdjustedTime(); } diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index b1e3f59452..be486bd4fc 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -7,6 +7,7 @@ #include // For Optional and nullopt #include // For RBFTransactionState +#include // For CTransactionRef #include #include @@ -16,7 +17,7 @@ class CBlock; class CScheduler; -class CTransaction; +class CValidationState; class uint256; struct CBlockLocator; struct FeeCalculation; @@ -109,6 +110,10 @@ class Chain //! Check if transaction will be final given chain height current time. virtual bool checkFinalTx(const CTransaction& tx) = 0; + + //! Add transaction to memory pool if the transaction fee is below the + //! amount specified by absurd_fee (as a safeguard). */ + virtual bool submitToMemoryPool(CTransactionRef tx, CAmount absurd_fee, CValidationState& state) = 0; }; //! Return Lock interface. Chain is locked when this is called, and @@ -159,6 +164,12 @@ class Chain //! Pool min fee. virtual CFeeRate mempoolMinFee() = 0; + //! Get node max tx fee setting (-maxtxfee). + //! This could be replaced by a per-wallet max fee, as proposed at + //! https://github.com/bitcoin/bitcoin/issues/15355 + //! But for the time being, wallets call this to access the node setting. + virtual CAmount maxTxFee() = 0; + //! Check if pruning is enabled. virtual bool getPruneMode() = 0; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 2a1744fa68..fb4bd8811f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1886,7 +1886,7 @@ void CWallet::ReacceptWalletTransactions() for (const std::pair& item : mapSorted) { CWalletTx& wtx = *(item.second); CValidationState state; - wtx.AcceptToMemoryPool(*locked_chain, maxTxFee, state); + wtx.AcceptToMemoryPool(*locked_chain, state); } } @@ -1897,7 +1897,7 @@ bool CWalletTx::RelayWalletTransaction(interfaces::Chain::Lock& locked_chain) { CValidationState state; /* GetDepthInMainChain already catches known conflicts. */ - if (InMempool() || AcceptToMemoryPool(locked_chain, maxTxFee, state)) { + if (InMempool() || AcceptToMemoryPool(locked_chain, state)) { pwallet->WalletLogPrintf("Relaying wtx %s\n", GetHash().ToString()); if (pwallet->chain().p2pEnabled()) { pwallet->chain().relayTransaction(GetHash()); @@ -3180,7 +3180,7 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve if (fBroadcastTransactions) { // Broadcast - if (!wtx.AcceptToMemoryPool(*locked_chain, maxTxFee, state)) { + if (!wtx.AcceptToMemoryPool(*locked_chain, state)) { WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state)); // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. } else { @@ -4474,17 +4474,14 @@ bool CMerkleTx::IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const return GetBlocksToMaturity(locked_chain) > 0; } -bool CWalletTx::AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, const CAmount& nAbsurdFee, CValidationState& state) +bool CWalletTx::AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, CValidationState& state) { - LockAnnotation lock(::cs_main); // Temporary, for AcceptToMemoryPool below. Removed in upcoming commit. - // We must set fInMempool here - while it will be re-set to true by the // entered-mempool callback, if we did not there would be a race where a // user could call sendmoney in a loop and hit spurious out of funds errors // because we think that this newly generated transaction's change is // unavailable as we're not yet aware that it is in the mempool. - bool ret = ::AcceptToMemoryPool(mempool, state, tx, nullptr /* pfMissingInputs */, - nullptr /* plTxnReplaced */, false /* bypass_limits */, nAbsurdFee); + bool ret = locked_chain.submitToMemoryPool(tx, pwallet->chain().maxTxFee(), state); fInMempool |= ret; return ret; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 41bb4bd8c7..3cfcf7a27d 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -538,7 +538,7 @@ class CWalletTx : public CMerkleTx bool RelayWalletTransaction(interfaces::Chain::Lock& locked_chain); /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */ - bool AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, const CAmount& nAbsurdFee, CValidationState& state); + bool AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, CValidationState& state); // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation From 318f41fb2cae0a46b4e4be49156562b8ed640f0c Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Sun, 8 Apr 2018 14:37:50 -0400 Subject: [PATCH 0048/4486] circular-dependencies: Avoid treating some .h/.cpp files as a unit This avoids a bogus circular dependency error in the next commit: interfaces/chain -> interfaces/wallet -> wallet/wallet -> interfaces/chain Which is incorrect, because interfaces/chain.cpp depends only on the interfaces/wallet.h file, not the interfaces/wallet.cpp file, and it is wrong to treat these as a unit. Inside the interfaces directory, .h files contain abstract class definitions and .cpp files contain implementations of those classes, so you don't need to link against .cpp files if you're only using the abstract class definition in the .h file. An alternative fix might be to rename all the cpp files in the interfaces directory like: chain.cpp->chain_impl.cpp, node.cpp->node_impl.cpp. But just getting the linter to treat these files as independent dependencies seemed like it would allow keeping code organization straightforward and avoiding the need to rename things. --- contrib/devtools/circular-dependencies.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contrib/devtools/circular-dependencies.py b/contrib/devtools/circular-dependencies.py index abfa5ed5ae..2e4657f1dd 100755 --- a/contrib/devtools/circular-dependencies.py +++ b/contrib/devtools/circular-dependencies.py @@ -8,9 +8,18 @@ 'core_write.cpp': 'core_io.cpp', } +# Directories with header-based modules, where the assumption that .cpp files +# define functions and variables declared in corresponding .h files is +# incorrect. +HEADER_MODULE_PATHS = [ + 'interfaces/' +] + def module_name(path): if path in MAPPING: path = MAPPING[path] + if any(path.startswith(dirpath) for dirpath in HEADER_MODULE_PATHS): + return path if path.endswith(".h"): return path[:-2] if path.endswith(".c"): From 1106a6fde4bfde31a16de45e4cc84ed5da05c5a4 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Sun, 8 Apr 2018 14:37:50 -0400 Subject: [PATCH 0049/4486] Remove use of uiInterface.LoadWallet in wallet code This also changes the uiInterface.LoadWallet signal argument type from shared_ptr to unique_ptr because CWallet is an internal wallet class that shouldn't be used in non-wallet code (and also can't be passed across process boundaries). This commit does not change behavior. --- src/Makefile.am | 2 -- src/Makefile.bench.include | 2 -- src/interfaces/chain.cpp | 2 ++ src/interfaces/chain.h | 5 +++++ src/interfaces/node.cpp | 2 +- src/ui_interface.cpp | 2 +- src/ui_interface.h | 7 +++++-- src/wallet/wallet.cpp | 3 ++- 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 650e347da3..a2418e4793 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -562,8 +562,6 @@ bitcoin_wallet_LDADD = \ $(LIBBITCOIN_WALLET_TOOL) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_WALLET) \ - $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_UTIL) \ diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 829e644643..77fb416b9c 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -37,8 +37,6 @@ nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES) bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bench_bench_bitcoin_LDADD = \ - $(LIBBITCOIN_WALLET) \ - $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 9f02514df3..725b485e51 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -251,6 +252,7 @@ class ChainImpl : public Chain void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } void initWarning(const std::string& message) override { InitWarning(message); } void initError(const std::string& message) override { InitError(message); } + void loadWallet(std::unique_ptr wallet) override { ::uiInterface.LoadWallet(wallet); } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index be486bd4fc..116656fef4 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -24,6 +24,8 @@ struct FeeCalculation; namespace interfaces { +class Wallet; + //! Interface for giving wallet processes access to blockchain state. class Chain { @@ -187,6 +189,9 @@ class Chain //! Send init error. virtual void initError(const std::string& message) = 0; + + //! Send wallet load notification to the GUI. + virtual void loadWallet(std::unique_ptr wallet) = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index 96bde7e9f2..6f7dce0c24 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -275,7 +275,7 @@ class NodeImpl : public Node } std::unique_ptr handleLoadWallet(LoadWalletFn fn) override { - return MakeHandler(::uiInterface.LoadWallet_connect([fn](std::shared_ptr wallet) { fn(MakeWallet(wallet)); })); + return MakeHandler(::uiInterface.LoadWallet_connect([fn](std::unique_ptr& wallet) { fn(std::move(wallet)); })); } std::unique_ptr handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override { diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index 947d7e2308..16ab24686b 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -52,7 +52,7 @@ void CClientUIInterface::InitMessage(const std::string& message) { return g_ui_s void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { return g_ui_signals.NotifyNumConnectionsChanged(newNumConnections); } void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); } void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); } -void CClientUIInterface::LoadWallet(std::shared_ptr wallet) { return g_ui_signals.LoadWallet(wallet); } +void CClientUIInterface::LoadWallet(std::unique_ptr& wallet) { return g_ui_signals.LoadWallet(wallet); } void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); } void CClientUIInterface::NotifyBlockTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(b, i); } void CClientUIInterface::NotifyHeaderTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyHeaderTip(b, i); } diff --git a/src/ui_interface.h b/src/ui_interface.h index fe466b3ca4..f1aebce3bb 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -11,7 +11,6 @@ #include #include -class CWallet; class CBlockIndex; namespace boost { namespace signals2 { @@ -19,6 +18,10 @@ class connection; } } // namespace boost +namespace interfaces { +class Wallet; +} // namespace interfaces + /** General change type (added, updated, removed). */ enum ChangeType { @@ -102,7 +105,7 @@ class CClientUIInterface ADD_SIGNALS_DECL_WRAPPER(NotifyAlertChanged, void, ); /** A wallet has been loaded. */ - ADD_SIGNALS_DECL_WRAPPER(LoadWallet, void, std::shared_ptr wallet); + ADD_SIGNALS_DECL_WRAPPER(LoadWallet, void, std::unique_ptr& wallet); /** * Show progress e.g. for verifychain. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fb4bd8811f..3d64adec53 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -4391,7 +4392,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, } } - uiInterface.LoadWallet(walletInstance); + chain.loadWallet(interfaces::MakeWallet(walletInstance)); // Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main. RegisterValidationInterface(walletInstance.get()); From a1df1b48a80bf122efa73677ff72577ec0103a3b Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Tue, 10 Jul 2018 15:48:03 -0400 Subject: [PATCH 0050/4486] Remove use of IsInitialBlockDownload in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 1 + src/interfaces/chain.h | 3 +++ src/wallet/rpcwallet.cpp | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 725b485e51..fb634e73da 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -248,6 +248,7 @@ class ChainImpl : public Chain CAmount maxTxFee() override { return ::maxTxFee; } bool getPruneMode() override { return ::fPruneMode; } bool p2pEnabled() override { return g_connman != nullptr; } + bool isInitialBlockDownload() override { return IsInitialBlockDownload(); } int64_t getAdjustedTime() override { return GetAdjustedTime(); } void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } void initWarning(const std::string& message) override { InitWarning(message); } diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 116656fef4..60f8570e36 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -178,6 +178,9 @@ class Chain //! Check if p2p enabled. virtual bool p2pEnabled() = 0; + // Check if in IBD. + virtual bool isInitialBlockDownload() = 0; + //! Get adjusted time. virtual int64_t getAdjustedTime() = 0; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8d1bd3a169..a30df9f037 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3889,7 +3889,7 @@ UniValue sethdseed(const JSONRPCRequest& request) }.ToString()); } - if (IsInitialBlockDownload()) { + if (pwallet->chain().isInitialBlockDownload()) { throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download"); } From f7efd87c8fb49f82e268a95e989909d453500e2b Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 1 Feb 2019 17:35:51 -0500 Subject: [PATCH 0051/4486] Change brace formatting Suggested https://github.com/bitcoin/bitcoin/pull/15288#pullrequestreview-197915100 --- src/wallet/rpcdump.cpp | 12 ++++++++---- src/wallet/rpcwallet.cpp | 12 ++++++++---- src/wallet/wallet.cpp | 12 +++++++----- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 046a6567a5..b8d5c9d0e1 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -157,8 +157,9 @@ UniValue importprivkey(const JSONRPCRequest& request) if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); - if (fRescan && pwallet->chain().getPruneMode()) + if (fRescan && pwallet->chain().getPruneMode()) { throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); + } if (fRescan && !reserver.reserve()) { throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); @@ -313,8 +314,9 @@ UniValue importaddress(const JSONRPCRequest& request) if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); - if (fRescan && pwallet->chain().getPruneMode()) + if (fRescan && pwallet->chain().getPruneMode()) { throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); + } WalletRescanReserver reserver(pwallet); if (fRescan && !reserver.reserve()) { @@ -501,8 +503,9 @@ UniValue importpubkey(const JSONRPCRequest& request) if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); - if (fRescan && pwallet->chain().getPruneMode()) + if (fRescan && pwallet->chain().getPruneMode()) { throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); + } WalletRescanReserver reserver(pwallet); if (fRescan && !reserver.reserve()) { @@ -562,8 +565,9 @@ UniValue importwallet(const JSONRPCRequest& request) }, }.ToString()); - if (pwallet->chain().getPruneMode()) + if (pwallet->chain().getPruneMode()) { throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode"); + } WalletRescanReserver reserver(pwallet); if (!reserver.reserve()) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a30df9f037..2e1fb50e70 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -628,8 +628,9 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) CAmount nAmount = 0; for (const std::pair& pairWtx : pwallet->mapWallet) { const CWalletTx& wtx = pairWtx.second; - if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) + if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) { continue; + } for (const CTxOut& txout : wtx.tx->vout) if (txout.scriptPubKey == scriptPubKey) @@ -693,8 +694,9 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request) CAmount nAmount = 0; for (const std::pair& pairWtx : pwallet->mapWallet) { const CWalletTx& wtx = pairWtx.second; - if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) + if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) { continue; + } for (const CTxOut& txout : wtx.tx->vout) { @@ -1078,8 +1080,9 @@ static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * co for (const std::pair& pairWtx : pwallet->mapWallet) { const CWalletTx& wtx = pairWtx.second; - if (wtx.IsCoinBase() || !locked_chain.checkFinalTx(*wtx.tx)) + if (wtx.IsCoinBase() || !locked_chain.checkFinalTx(*wtx.tx)) { continue; + } int nDepth = wtx.GetDepthInMainChain(locked_chain); if (nDepth < nMinDepth) @@ -2690,8 +2693,9 @@ static UniValue resendwallettransactions(const JSONRPCRequest& request) }.ToString() ); - if (!pwallet->chain().p2pEnabled()) + if (!pwallet->chain().p2pEnabled()) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + } auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3d64adec53..daf99ad341 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2073,8 +2073,9 @@ bool CWalletTx::InMempool() const bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const { // Quick answer in most cases - if (!locked_chain.checkFinalTx(*tx)) + if (!locked_chain.checkFinalTx(*tx)) { return false; + } int nDepth = GetDepthInMainChain(locked_chain); if (nDepth >= 1) return true; @@ -2129,8 +2130,9 @@ std::vector CWallet::ResendWalletTransactionsBefore(interfaces::Chain:: for (const std::pair& item : mapSorted) { CWalletTx& wtx = *item.second; - if (wtx.RelayWalletTransaction(locked_chain)) + if (wtx.RelayWalletTransaction(locked_chain)) { result.push_back(wtx.GetHash()); + } } return result; } @@ -2319,8 +2321,9 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< const uint256& wtxid = entry.first; const CWalletTx* pcoin = &entry.second; - if (!locked_chain.checkFinalTx(*pcoin->tx)) + if (!locked_chain.checkFinalTx(*pcoin->tx)) { continue; + } if (pcoin->IsImmatureCoinBase(locked_chain)) continue; @@ -4331,8 +4334,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, //We can't rescan beyond non-pruned blocks, stop and throw an error //this might happen if a user uses an old wallet within a pruned node // or if he ran -disablewallet for a longer time, then decided to re-enable - if (chain.getPruneMode()) - { + if (chain.getPruneMode()) { int block_height = *tip_height; while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) { --block_height; From 62e7addb632cad77cbd5fbccbaee51c7b32505d0 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sat, 1 Sep 2018 15:18:02 -0700 Subject: [PATCH 0052/4486] util: Move CheckDiskSpace to util. --- src/init.cpp | 4 ++-- src/util/system.cpp | 8 ++++++++ src/util/system.h | 1 + src/validation.cpp | 32 ++++++++++++-------------------- src/validation.h | 5 ----- 5 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8b831a726f..5111baddd2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1675,11 +1675,11 @@ bool AppInitMain(InitInterfaces& interfaces) // ********************************************************* Step 11: import blocks - if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ false)) { + if (!CheckDiskSpace(GetDataDir())) { InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir())); return false; } - if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ true)) { + if (!CheckDiskSpace(GetBlocksDir())) { InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir())); return false; } diff --git a/src/util/system.cpp b/src/util/system.cpp index 6e82de743a..3e6c2ae5d4 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -135,6 +135,14 @@ bool DirIsWritable(const fs::path& directory) return true; } +bool CheckDiskSpace(const fs::path& dir, uint64_t nAdditionalBytes) +{ + constexpr uint64_t nMinDiskSpace = 52428800; // 50 MiB + + uint64_t nFreeBytesAvailable = fs::space(dir).available; + return nFreeBytesAvailable >= nMinDiskSpace + nAdditionalBytes; +} + /** * Interpret a string argument as a boolean. * diff --git a/src/util/system.h b/src/util/system.h index 69ae11d1ed..2a2ee9bc1d 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -72,6 +72,7 @@ bool RenameOver(fs::path src, fs::path dest); bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false); void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name); bool DirIsWritable(const fs::path& directory); +bool CheckDiskSpace(const fs::path& dir, uint64_t nAdditionalBytes = 0); /** Release all directory locks. This is used for unit testing only, at runtime * the global destructor will take care of the locks. diff --git a/src/validation.cpp b/src/validation.cpp index 1806bc1268..06e0e99290 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2134,8 +2134,9 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & // Write blocks and block index to disk. if (fDoFullFlush || fPeriodicWrite) { // Depend on nMinDiskSpace to ensure we can write block index - if (!CheckDiskSpace(0, true)) - return state.Error("out of disk space"); + if (!CheckDiskSpace(GetBlocksDir())) { + return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); + } // First make sure all block and undo data is flushed to disk. FlushBlockFile(); // Then update all block file information (which may refer to block and undo files). @@ -2168,8 +2169,9 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & // twice (once in the log, and once in the tables). This is already // an overestimation, as most will delete an existing entry or // overwrite one. Still, use a conservative safety factor of 2. - if (!CheckDiskSpace(48 * 2 * 2 * pcoinsTip->GetCacheSize())) - return state.Error("out of disk space"); + if (!CheckDiskSpace(GetDataDir(), 48 * 2 * 2 * pcoinsTip->GetCacheSize())) { + return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); + } // Flush the chainstate (which may refer to block index entries). if (!pcoinsTip->Flush()) return AbortNode(state, "Failed to write to coin database"); @@ -3014,7 +3016,7 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int if (nNewChunks > nOldChunks) { if (fPruneMode) fCheckForPruning = true; - if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos, true)) { + if (CheckDiskSpace(GetBlocksDir(), nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) { FILE *file = OpenBlockFile(pos); if (file) { LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile); @@ -3023,7 +3025,7 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int } } else - return error("out of disk space"); + return AbortNode("Disk space is low!", _("Error: Disk space is low!")); } } @@ -3047,7 +3049,7 @@ static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, if (nNewChunks > nOldChunks) { if (fPruneMode) fCheckForPruning = true; - if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos, true)) { + if (CheckDiskSpace(GetBlocksDir(), nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos)) { FILE *file = OpenUndoFile(pos); if (file) { LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile); @@ -3055,8 +3057,9 @@ static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, fclose(file); } } - else - return state.Error("out of disk space"); + else { + return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); + } } return true; @@ -3763,17 +3766,6 @@ static void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfte nLastBlockWeCanPrune, count); } -bool CheckDiskSpace(uint64_t nAdditionalBytes, bool blocks_dir) -{ - uint64_t nFreeBytesAvailable = fs::space(blocks_dir ? GetBlocksDir() : GetDataDir()).available; - - // Check for nMinDiskSpace bytes (currently 50MB) - if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) - return AbortNode("Disk space is low!", _("Error: Disk space is low!")); - - return true; -} - static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { if (pos.IsNull()) diff --git a/src/validation.h b/src/validation.h index 1975846b69..1beee7869f 100644 --- a/src/validation.h +++ b/src/validation.h @@ -181,9 +181,6 @@ extern arith_uint256 nMinimumChainWork; /** Best header we've seen so far (used for getheaders queries' starting points). */ extern CBlockIndex *pindexBestHeader; -/** Minimum disk space required - used in CheckDiskSpace() */ -static const uint64_t nMinDiskSpace = 52428800; - /** Pruning-related variables and constants */ /** True if any block files have ever been pruned. */ extern bool fHavePruned; @@ -245,8 +242,6 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr, CBlockHeader* first_invalid = nullptr) LOCKS_EXCLUDED(cs_main); -/** Check whether enough disk space is available for an incoming block */ -bool CheckDiskSpace(uint64_t nAdditionalBytes = 0, bool blocks_dir = false); /** Open a block file (blk?????.dat) */ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ From 9183d6ef656c8f3ed406821b99827f9b5f047665 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 6 Jan 2019 11:06:31 -0800 Subject: [PATCH 0053/4486] validation: Extract basic block file logic into FlatFileSeq class. --- src/Makefile.am | 2 ++ src/flatfile.cpp | 23 +++++++++++++++++++++++ src/flatfile.h | 36 ++++++++++++++++++++++++++++++++++++ src/init.cpp | 2 +- src/validation.cpp | 21 +++++++++++++++++---- src/validation.h | 2 +- 6 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/flatfile.cpp create mode 100644 src/flatfile.h diff --git a/src/Makefile.am b/src/Makefile.am index d491530ca1..2e297d3dac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -128,6 +128,7 @@ BITCOIN_CORE_H = \ core_io.h \ core_memusage.h \ cuckoocache.h \ + flatfile.h \ fs.h \ httprpc.h \ httpserver.h \ @@ -247,6 +248,7 @@ libbitcoin_server_a_SOURCES = \ chain.cpp \ checkpoints.cpp \ consensus/tx_verify.cpp \ + flatfile.cpp \ httprpc.cpp \ httpserver.cpp \ index/base.cpp \ diff --git a/src/flatfile.cpp b/src/flatfile.cpp new file mode 100644 index 0000000000..c9ca9aa869 --- /dev/null +++ b/src/flatfile.cpp @@ -0,0 +1,23 @@ +// Copyright (c) 2019 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 + +#include +#include + +FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) : + m_dir(std::move(dir)), + m_prefix(prefix), + m_chunk_size(chunk_size) +{ + if (chunk_size == 0) { + throw std::invalid_argument("chunk_size must be positive"); + } +} + +fs::path FlatFileSeq::FileName(const CDiskBlockPos& pos) const +{ + return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); +} diff --git a/src/flatfile.h b/src/flatfile.h new file mode 100644 index 0000000000..9c7131d201 --- /dev/null +++ b/src/flatfile.h @@ -0,0 +1,36 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_FLATFILE_H +#define BITCOIN_FLATFILE_H + +#include +#include + +/** + * FlatFileSeq represents a sequence of numbered files storing raw data. This class facilitates + * access to and efficient management of these files. + */ +class FlatFileSeq +{ +private: + const fs::path m_dir; + const char* const m_prefix; + const size_t m_chunk_size; + +public: + /** + * Constructor + * + * @param dir The base directory that all files live in. + * @param prefix A short prefix given to all file names. + * @param chunk_size Disk space is pre-allocated in multiples of this amount. + */ + FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size); + + /** Get the name of the file at the given position. */ + fs::path FileName(const CDiskBlockPos& pos) const; +}; + +#endif // BITCOIN_FLATFILE_H diff --git a/src/init.cpp b/src/init.cpp index 5111baddd2..66c5995651 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -673,7 +673,7 @@ static void ThreadImport(std::vector vImportFiles) int nFile = 0; while (true) { CDiskBlockPos pos(nFile, 0); - if (!fs::exists(GetBlockPosFilename(pos, "blk"))) + if (!fs::exists(GetBlockPosFilename(pos))) break; // No block files left to reindex FILE *file = OpenBlockFile(pos, true); if (!file) diff --git a/src/validation.cpp b/src/validation.cpp index 06e0e99290..3abe8b2fa1 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -318,6 +319,8 @@ static void FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPr static void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight); bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector *pvChecks = nullptr); static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); +static FlatFileSeq BlockFileSeq(); +static FlatFileSeq UndoFileSeq(); bool CheckFinalTx(const CTransaction &tx, int flags) { @@ -3657,8 +3660,8 @@ void UnlinkPrunedFiles(const std::set& setFilesToPrune) { for (std::set::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) { CDiskBlockPos pos(*it, 0); - fs::remove(GetBlockPosFilename(pos, "blk")); - fs::remove(GetBlockPosFilename(pos, "rev")); + fs::remove(BlockFileSeq().FileName(pos)); + fs::remove(UndoFileSeq().FileName(pos)); LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it); } } @@ -3789,6 +3792,16 @@ static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fRe return file; } +static FlatFileSeq BlockFileSeq() +{ + return FlatFileSeq(GetBlocksDir(), "blk", BLOCKFILE_CHUNK_SIZE); +} + +static FlatFileSeq UndoFileSeq() +{ + return FlatFileSeq(GetBlocksDir(), "rev", UNDOFILE_CHUNK_SIZE); +} + FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "blk", fReadOnly); } @@ -3798,9 +3811,9 @@ static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "rev", fReadOnly); } -fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) +fs::path GetBlockPosFilename(const CDiskBlockPos &pos) { - return GetBlocksDir() / strprintf("%s%05u.dat", prefix, pos.nFile); + return BlockFileSeq().FileName(pos); } CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash) diff --git a/src/validation.h b/src/validation.h index 1beee7869f..19f8e8ab7a 100644 --- a/src/validation.h +++ b/src/validation.h @@ -245,7 +245,7 @@ bool ProcessNewBlockHeaders(const std::vector& block, CValidationS /** Open a block file (blk?????.dat) */ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ -fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); +fs::path GetBlockPosFilename(const CDiskBlockPos &pos); /** Import blocks from an external file */ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = nullptr); /** Ensures we have a genesis block in the block tree, possibly writing one to disk. */ From e2d2abb99fe353ffc2ff3bc1ff578fad31065335 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 6 Jan 2019 11:14:22 -0800 Subject: [PATCH 0054/4486] validation: Refactor OpenDiskFile into method on FlatFileSeq. --- src/flatfile.cpp | 24 ++++++++++++++++++++++++ src/flatfile.h | 3 +++ src/validation.cpp | 27 ++------------------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/flatfile.cpp b/src/flatfile.cpp index c9ca9aa869..535f4eda91 100644 --- a/src/flatfile.cpp +++ b/src/flatfile.cpp @@ -5,6 +5,7 @@ #include #include +#include #include FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) : @@ -21,3 +22,26 @@ fs::path FlatFileSeq::FileName(const CDiskBlockPos& pos) const { return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); } + +FILE* FlatFileSeq::Open(const CDiskBlockPos& pos, bool fReadOnly) +{ + if (pos.IsNull()) + return nullptr; + fs::path path = FileName(pos); + fs::create_directories(path.parent_path()); + FILE* file = fsbridge::fopen(path, fReadOnly ? "rb": "rb+"); + if (!file && !fReadOnly) + file = fsbridge::fopen(path, "wb+"); + if (!file) { + LogPrintf("Unable to open file %s\n", path.string()); + return nullptr; + } + if (pos.nPos) { + if (fseek(file, pos.nPos, SEEK_SET)) { + LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); + fclose(file); + return nullptr; + } + } + return file; +} diff --git a/src/flatfile.h b/src/flatfile.h index 9c7131d201..b1eea93140 100644 --- a/src/flatfile.h +++ b/src/flatfile.h @@ -31,6 +31,9 @@ class FlatFileSeq /** Get the name of the file at the given position. */ fs::path FileName(const CDiskBlockPos& pos) const; + + /** Open a handle to the file at the given position. */ + FILE* Open(const CDiskBlockPos& pos, bool fReadOnly = false); }; #endif // BITCOIN_FLATFILE_H diff --git a/src/validation.cpp b/src/validation.cpp index 3abe8b2fa1..4135063505 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3769,29 +3769,6 @@ static void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfte nLastBlockWeCanPrune, count); } -static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) -{ - if (pos.IsNull()) - return nullptr; - fs::path path = GetBlockPosFilename(pos, prefix); - fs::create_directories(path.parent_path()); - FILE* file = fsbridge::fopen(path, fReadOnly ? "rb": "rb+"); - if (!file && !fReadOnly) - file = fsbridge::fopen(path, "wb+"); - if (!file) { - LogPrintf("Unable to open file %s\n", path.string()); - return nullptr; - } - if (pos.nPos) { - if (fseek(file, pos.nPos, SEEK_SET)) { - LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); - fclose(file); - return nullptr; - } - } - return file; -} - static FlatFileSeq BlockFileSeq() { return FlatFileSeq(GetBlocksDir(), "blk", BLOCKFILE_CHUNK_SIZE); @@ -3803,12 +3780,12 @@ static FlatFileSeq UndoFileSeq() } FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) { - return OpenDiskFile(pos, "blk", fReadOnly); + return BlockFileSeq().Open(pos, fReadOnly); } /** Open an undo file (rev?????.dat) */ static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { - return OpenDiskFile(pos, "rev", fReadOnly); + return UndoFileSeq().Open(pos, fReadOnly); } fs::path GetBlockPosFilename(const CDiskBlockPos &pos) From 992404b31ed2f8cabeed59d074552f0ae10fda94 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 6 Jan 2019 11:27:31 -0800 Subject: [PATCH 0055/4486] validation: Refactor block file pre-allocation into FlatFileSeq. --- src/flatfile.cpp | 27 ++++++++++++++++++++++++++ src/flatfile.h | 11 +++++++++++ src/validation.cpp | 48 +++++++++++++++------------------------------- 3 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/flatfile.cpp b/src/flatfile.cpp index 535f4eda91..d9fd4041b7 100644 --- a/src/flatfile.cpp +++ b/src/flatfile.cpp @@ -7,6 +7,7 @@ #include #include #include +#include FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) : m_dir(std::move(dir)), @@ -45,3 +46,29 @@ FILE* FlatFileSeq::Open(const CDiskBlockPos& pos, bool fReadOnly) } return file; } + +size_t FlatFileSeq::Allocate(const CDiskBlockPos& pos, size_t add_size, bool& out_of_space) +{ + out_of_space = false; + + unsigned int n_old_chunks = (pos.nPos + m_chunk_size - 1) / m_chunk_size; + unsigned int n_new_chunks = (pos.nPos + add_size + m_chunk_size - 1) / m_chunk_size; + if (n_new_chunks > n_old_chunks) { + size_t old_size = pos.nPos; + size_t new_size = n_new_chunks * m_chunk_size; + size_t inc_size = new_size - old_size; + + if (CheckDiskSpace(m_dir, inc_size)) { + FILE *file = Open(pos); + if (file) { + LogPrintf("Pre-allocating up to position 0x%x in %s%05u.dat\n", new_size, m_prefix, pos.nFile); + AllocateFileRange(file, pos.nPos, inc_size); + fclose(file); + return inc_size; + } + } else { + out_of_space = true; + } + } + return 0; +} diff --git a/src/flatfile.h b/src/flatfile.h index b1eea93140..1b5d83e8e6 100644 --- a/src/flatfile.h +++ b/src/flatfile.h @@ -34,6 +34,17 @@ class FlatFileSeq /** Open a handle to the file at the given position. */ FILE* Open(const CDiskBlockPos& pos, bool fReadOnly = false); + + /** + * Allocate additional space in a file after the given starting position. The amount allocated + * will be the minimum multiple of the sequence chunk size greater than add_size. + * + * @param[in] pos The starting position that bytes will be allocated after. + * @param[in] add_size The minimum number of bytes to be allocated. + * @param[out] out_of_space Whether the allocation failed due to insufficient disk space. + * @return The number of bytes successfully allocated. + */ + size_t Allocate(const CDiskBlockPos& pos, size_t add_size, bool& out_of_space); }; #endif // BITCOIN_FLATFILE_H diff --git a/src/validation.cpp b/src/validation.cpp index 4135063505..aca555ee0a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3014,21 +3014,13 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int vinfoBlockFile[nFile].nSize += nAddSize; if (!fKnown) { - unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; - unsigned int nNewChunks = (vinfoBlockFile[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; - if (nNewChunks > nOldChunks) { - if (fPruneMode) - fCheckForPruning = true; - if (CheckDiskSpace(GetBlocksDir(), nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) { - FILE *file = OpenBlockFile(pos); - if (file) { - LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile); - AllocateFileRange(file, pos.nPos, nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos); - fclose(file); - } - } - else - return AbortNode("Disk space is low!", _("Error: Disk space is low!")); + bool out_of_space; + size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space); + if (out_of_space) { + return AbortNode("Disk space is low!", _("Error: Disk space is low!")); + } + if (bytes_allocated != 0 && fPruneMode) { + fCheckForPruning = true; } } @@ -3042,27 +3034,17 @@ static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, LOCK(cs_LastBlockFile); - unsigned int nNewSize; pos.nPos = vinfoBlockFile[nFile].nUndoSize; - nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize; + vinfoBlockFile[nFile].nUndoSize += nAddSize; setDirtyFileInfo.insert(nFile); - unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; - unsigned int nNewChunks = (nNewSize + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; - if (nNewChunks > nOldChunks) { - if (fPruneMode) - fCheckForPruning = true; - if (CheckDiskSpace(GetBlocksDir(), nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos)) { - FILE *file = OpenUndoFile(pos); - if (file) { - LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile); - AllocateFileRange(file, pos.nPos, nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos); - fclose(file); - } - } - else { - return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); - } + bool out_of_space; + size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space); + if (out_of_space) { + return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); + } + if (bytes_allocated != 0 && fPruneMode) { + fCheckForPruning = true; } return true; From e0380933e3745214331d358bda8c5e79299c84d2 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 6 Jan 2019 10:14:35 -0800 Subject: [PATCH 0056/4486] validation: Refactor file flush logic into FlatFileSeq. --- src/flatfile.cpp | 19 +++++++++++++++++++ src/flatfile.h | 9 +++++++++ src/validation.cpp | 23 +++++------------------ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/flatfile.cpp b/src/flatfile.cpp index d9fd4041b7..1cdead6bf5 100644 --- a/src/flatfile.cpp +++ b/src/flatfile.cpp @@ -72,3 +72,22 @@ size_t FlatFileSeq::Allocate(const CDiskBlockPos& pos, size_t add_size, bool& ou } return 0; } + +bool FlatFileSeq::Flush(const CDiskBlockPos& pos, bool finalize) +{ + FILE* file = Open(FlatFilePos(pos.nFile, 0)); // Avoid fseek to nPos + if (!file) { + return error("%s: failed to open file %d", __func__, pos.nFile); + } + if (finalize && !TruncateFile(file, pos.nPos)) { + fclose(file); + return error("%s: failed to truncate file %d", __func__, pos.nFile); + } + if (!FileCommit(file)) { + fclose(file); + return error("%s: failed to commit file %d", __func__, pos.nFile); + } + + fclose(file); + return true; +} diff --git a/src/flatfile.h b/src/flatfile.h index 1b5d83e8e6..eea41ddf84 100644 --- a/src/flatfile.h +++ b/src/flatfile.h @@ -45,6 +45,15 @@ class FlatFileSeq * @return The number of bytes successfully allocated. */ size_t Allocate(const CDiskBlockPos& pos, size_t add_size, bool& out_of_space); + + /** + * Commit a file to disk, and optionally truncate off extra pre-allocated bytes if final. + * + * @param[in] pos The first unwritten position in the file to be flushed. + * @param[in] finalize True if no more data will be written to this file. + * @return true on success, false on failure. + */ + bool Flush(const CDiskBlockPos& pos, bool finalize = false); }; #endif // BITCOIN_FLATFILE_H diff --git a/src/validation.cpp b/src/validation.cpp index aca555ee0a..98d89599f1 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1630,25 +1630,12 @@ void static FlushBlockFile(bool fFinalize = false) { LOCK(cs_LastBlockFile); - CDiskBlockPos posOld(nLastBlockFile, 0); - bool status = true; - - FILE *fileOld = OpenBlockFile(posOld); - if (fileOld) { - if (fFinalize) - status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize); - status &= FileCommit(fileOld); - fclose(fileOld); - } - - fileOld = OpenUndoFile(posOld); - if (fileOld) { - if (fFinalize) - status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize); - status &= FileCommit(fileOld); - fclose(fileOld); - } + CDiskBlockPos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize); + CDiskBlockPos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize); + bool status = true; + status &= BlockFileSeq().Flush(block_pos_old, fFinalize); + status &= UndoFileSeq().Flush(undo_pos_old, fFinalize); if (!status) { AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error."); } From d6d8a78f26f52fdfe43293686135e2fc6919926c Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 6 Jan 2019 11:43:38 -0800 Subject: [PATCH 0057/4486] Move CDiskBlockPos from chain to flatfile. --- src/chain.h | 41 +---------------------------------------- src/flatfile.cpp | 8 +++++++- src/flatfile.h | 43 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/chain.h b/src/chain.h index 5a6f10b84f..583c46c58c 100644 --- a/src/chain.h +++ b/src/chain.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -90,46 +91,6 @@ class CBlockFileInfo } }; -struct CDiskBlockPos -{ - int nFile; - unsigned int nPos; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED)); - READWRITE(VARINT(nPos)); - } - - CDiskBlockPos() { - SetNull(); - } - - CDiskBlockPos(int nFileIn, unsigned int nPosIn) { - nFile = nFileIn; - nPos = nPosIn; - } - - friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) { - return (a.nFile == b.nFile && a.nPos == b.nPos); - } - - friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) { - return !(a == b); - } - - void SetNull() { nFile = -1; nPos = 0; } - bool IsNull() const { return (nFile == -1); } - - std::string ToString() const - { - return strprintf("CDiskBlockPos(nFile=%i, nPos=%i)", nFile, nPos); - } - -}; - enum BlockStatus: uint32_t { //! Unused. BLOCK_VALID_UNKNOWN = 0, diff --git a/src/flatfile.cpp b/src/flatfile.cpp index 1cdead6bf5..b1ea257da1 100644 --- a/src/flatfile.cpp +++ b/src/flatfile.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2019 The Bitcoin Core developers +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,6 +20,11 @@ FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) : } } +std::string CDiskBlockPos::ToString() const +{ + return strprintf("CDiskBlockPos(nFile=%i, nPos=%i)", nFile, nPos); +} + fs::path FlatFileSeq::FileName(const CDiskBlockPos& pos) const { return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); diff --git a/src/flatfile.h b/src/flatfile.h index eea41ddf84..d599b8cc42 100644 --- a/src/flatfile.h +++ b/src/flatfile.h @@ -1,12 +1,51 @@ -// Copyright (c) 2019 The Bitcoin Core developers +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_FLATFILE_H #define BITCOIN_FLATFILE_H -#include +#include + #include +#include + +struct CDiskBlockPos +{ + int nFile; + unsigned int nPos; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED)); + READWRITE(VARINT(nPos)); + } + + CDiskBlockPos() { + SetNull(); + } + + CDiskBlockPos(int nFileIn, unsigned int nPosIn) { + nFile = nFileIn; + nPos = nPosIn; + } + + friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) { + return (a.nFile == b.nFile && a.nPos == b.nPos); + } + + friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) { + return !(a == b); + } + + void SetNull() { nFile = -1; nPos = 0; } + bool IsNull() const { return (nFile == -1); } + + std::string ToString() const; +}; /** * FlatFileSeq represents a sequence of numbered files storing raw data. This class facilitates From 65a489e93d181d3c0f7a9cf79f7c11ff8cf2b0f0 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 6 Jan 2019 11:46:30 -0800 Subject: [PATCH 0058/4486] scripted-diff: Rename CBlockDiskPos to FlatFilePos. -BEGIN VERIFY SCRIPT- sed -i 's/CDiskBlockPos/FlatFilePos/g' $(git ls-files 'src/*.h' 'src/*.cpp') -END VERIFY SCRIPT- --- src/chain.h | 8 ++--- src/flatfile.cpp | 12 ++++---- src/flatfile.h | 18 ++++++------ src/index/txindex.cpp | 8 ++--- src/init.cpp | 2 +- src/validation.cpp | 68 +++++++++++++++++++++---------------------- src/validation.h | 10 +++---- 7 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/chain.h b/src/chain.h index 583c46c58c..2b6d2d082c 100644 --- a/src/chain.h +++ b/src/chain.h @@ -227,8 +227,8 @@ class CBlockIndex nNonce = block.nNonce; } - CDiskBlockPos GetBlockPos() const { - CDiskBlockPos ret; + FlatFilePos GetBlockPos() const { + FlatFilePos ret; if (nStatus & BLOCK_HAVE_DATA) { ret.nFile = nFile; ret.nPos = nDataPos; @@ -236,8 +236,8 @@ class CBlockIndex return ret; } - CDiskBlockPos GetUndoPos() const { - CDiskBlockPos ret; + FlatFilePos GetUndoPos() const { + FlatFilePos ret; if (nStatus & BLOCK_HAVE_UNDO) { ret.nFile = nFile; ret.nPos = nUndoPos; diff --git a/src/flatfile.cpp b/src/flatfile.cpp index b1ea257da1..d2e11825d5 100644 --- a/src/flatfile.cpp +++ b/src/flatfile.cpp @@ -20,17 +20,17 @@ FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) : } } -std::string CDiskBlockPos::ToString() const +std::string FlatFilePos::ToString() const { - return strprintf("CDiskBlockPos(nFile=%i, nPos=%i)", nFile, nPos); + return strprintf("FlatFilePos(nFile=%i, nPos=%i)", nFile, nPos); } -fs::path FlatFileSeq::FileName(const CDiskBlockPos& pos) const +fs::path FlatFileSeq::FileName(const FlatFilePos& pos) const { return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); } -FILE* FlatFileSeq::Open(const CDiskBlockPos& pos, bool fReadOnly) +FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool fReadOnly) { if (pos.IsNull()) return nullptr; @@ -53,7 +53,7 @@ FILE* FlatFileSeq::Open(const CDiskBlockPos& pos, bool fReadOnly) return file; } -size_t FlatFileSeq::Allocate(const CDiskBlockPos& pos, size_t add_size, bool& out_of_space) +size_t FlatFileSeq::Allocate(const FlatFilePos& pos, size_t add_size, bool& out_of_space) { out_of_space = false; @@ -79,7 +79,7 @@ size_t FlatFileSeq::Allocate(const CDiskBlockPos& pos, size_t add_size, bool& ou return 0; } -bool FlatFileSeq::Flush(const CDiskBlockPos& pos, bool finalize) +bool FlatFileSeq::Flush(const FlatFilePos& pos, bool finalize) { FILE* file = Open(FlatFilePos(pos.nFile, 0)); // Avoid fseek to nPos if (!file) { diff --git a/src/flatfile.h b/src/flatfile.h index d599b8cc42..6051970490 100644 --- a/src/flatfile.h +++ b/src/flatfile.h @@ -11,7 +11,7 @@ #include #include -struct CDiskBlockPos +struct FlatFilePos { int nFile; unsigned int nPos; @@ -24,20 +24,20 @@ struct CDiskBlockPos READWRITE(VARINT(nPos)); } - CDiskBlockPos() { + FlatFilePos() { SetNull(); } - CDiskBlockPos(int nFileIn, unsigned int nPosIn) { + FlatFilePos(int nFileIn, unsigned int nPosIn) { nFile = nFileIn; nPos = nPosIn; } - friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) { + friend bool operator==(const FlatFilePos &a, const FlatFilePos &b) { return (a.nFile == b.nFile && a.nPos == b.nPos); } - friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) { + friend bool operator!=(const FlatFilePos &a, const FlatFilePos &b) { return !(a == b); } @@ -69,10 +69,10 @@ class FlatFileSeq FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size); /** Get the name of the file at the given position. */ - fs::path FileName(const CDiskBlockPos& pos) const; + fs::path FileName(const FlatFilePos& pos) const; /** Open a handle to the file at the given position. */ - FILE* Open(const CDiskBlockPos& pos, bool fReadOnly = false); + FILE* Open(const FlatFilePos& pos, bool fReadOnly = false); /** * Allocate additional space in a file after the given starting position. The amount allocated @@ -83,7 +83,7 @@ class FlatFileSeq * @param[out] out_of_space Whether the allocation failed due to insufficient disk space. * @return The number of bytes successfully allocated. */ - size_t Allocate(const CDiskBlockPos& pos, size_t add_size, bool& out_of_space); + size_t Allocate(const FlatFilePos& pos, size_t add_size, bool& out_of_space); /** * Commit a file to disk, and optionally truncate off extra pre-allocated bytes if final. @@ -92,7 +92,7 @@ class FlatFileSeq * @param[in] finalize True if no more data will be written to this file. * @return true on success, false on failure. */ - bool Flush(const CDiskBlockPos& pos, bool finalize = false); + bool Flush(const FlatFilePos& pos, bool finalize = false); }; #endif // BITCOIN_FLATFILE_H diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 10bc8419dd..7367ec7cb6 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -16,7 +16,7 @@ constexpr char DB_TXINDEX_BLOCK = 'T'; std::unique_ptr g_txindex; -struct CDiskTxPos : public CDiskBlockPos +struct CDiskTxPos : public FlatFilePos { unsigned int nTxOffset; // after header @@ -24,11 +24,11 @@ struct CDiskTxPos : public CDiskBlockPos template inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITEAS(CDiskBlockPos, *this); + READWRITEAS(FlatFilePos, *this); READWRITE(VARINT(nTxOffset)); } - CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { + CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { } CDiskTxPos() { @@ -36,7 +36,7 @@ struct CDiskTxPos : public CDiskBlockPos } void SetNull() { - CDiskBlockPos::SetNull(); + FlatFilePos::SetNull(); nTxOffset = 0; } }; diff --git a/src/init.cpp b/src/init.cpp index 66c5995651..8a849d2815 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -672,7 +672,7 @@ static void ThreadImport(std::vector vImportFiles) if (fReindex) { int nFile = 0; while (true) { - CDiskBlockPos pos(nFile, 0); + FlatFilePos pos(nFile, 0); if (!fs::exists(GetBlockPosFilename(pos))) break; // No block files left to reindex FILE *file = OpenBlockFile(pos, true); diff --git a/src/validation.cpp b/src/validation.cpp index 98d89599f1..86775bb391 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -166,7 +166,7 @@ class CChainState { * that it doesn't descend from an invalid block, and then add it to mapBlockIndex. */ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - bool AcceptBlock(const std::shared_ptr& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + bool AcceptBlock(const std::shared_ptr& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main); // Block (dis)connection on a given view: DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view); @@ -205,7 +205,7 @@ class CChainState { void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); - void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -318,7 +318,7 @@ static bool FlushStateToDisk(const CChainParams& chainParams, CValidationState & static void FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPruneHeight); static void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight); bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector *pvChecks = nullptr); -static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); +static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly = false); static FlatFileSeq BlockFileSeq(); static FlatFileSeq UndoFileSeq(); @@ -1045,7 +1045,7 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus // CBlock and CBlockIndex // -static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) +static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) { // Open history file to append CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); @@ -1066,7 +1066,7 @@ static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMes return true; } -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) +bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams) { block.SetNull(); @@ -1092,7 +1092,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus: bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) { - CDiskBlockPos blockPos; + FlatFilePos blockPos; { LOCK(cs_main); blockPos = pindex->GetBlockPos(); @@ -1106,9 +1106,9 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus return true; } -bool ReadRawBlockFromDisk(std::vector& block, const CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& message_start) +bool ReadRawBlockFromDisk(std::vector& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start) { - CDiskBlockPos hpos = pos; + FlatFilePos hpos = pos; hpos.nPos -= 8; // Seek back 8 bytes for meta header CAutoFile filein(OpenBlockFile(hpos, true), SER_DISK, CLIENT_VERSION); if (filein.IsNull()) { @@ -1143,7 +1143,7 @@ bool ReadRawBlockFromDisk(std::vector& block, const CDiskBlockPos& pos, bool ReadRawBlockFromDisk(std::vector& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start) { - CDiskBlockPos block_pos; + FlatFilePos block_pos; { LOCK(cs_main); block_pos = pindex->GetBlockPos(); @@ -1455,7 +1455,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi namespace { -bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) +bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) { // Open history file to append CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); @@ -1484,7 +1484,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint static bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex *pindex) { - CDiskBlockPos pos = pindex->GetUndoPos(); + FlatFilePos pos = pindex->GetUndoPos(); if (pos.IsNull()) { return error("%s: no undo data available", __func__); } @@ -1630,8 +1630,8 @@ void static FlushBlockFile(bool fFinalize = false) { LOCK(cs_LastBlockFile); - CDiskBlockPos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize); - CDiskBlockPos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize); + FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize); + FlatFilePos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize); bool status = true; status &= BlockFileSeq().Flush(block_pos_old, fFinalize); @@ -1641,13 +1641,13 @@ void static FlushBlockFile(bool fFinalize = false) } } -static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); +static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize); static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams) { // Write undo information to disk if (pindex->GetUndoPos().IsNull()) { - CDiskBlockPos _pos; + FlatFilePos _pos; if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40)) return error("ConnectBlock(): FindUndoPos failed"); if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) @@ -2920,7 +2920,7 @@ CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block) } /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ -void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) +void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) { pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; @@ -2966,7 +2966,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi } } -static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) +static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) { LOCK(cs_LastBlockFile); @@ -3015,7 +3015,7 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int return true; } -static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize) +static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize) { pos.nFile = nFile; @@ -3416,26 +3416,26 @@ bool ProcessNewBlockHeaders(const std::vector& headers, CValidatio } /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ -static CDiskBlockPos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const CDiskBlockPos* dbp) { +static FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const FlatFilePos* dbp) { unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION); - CDiskBlockPos blockPos; + FlatFilePos blockPos; if (dbp != nullptr) blockPos = *dbp; if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) { error("%s: FindBlockPos failed", __func__); - return CDiskBlockPos(); + return FlatFilePos(); } if (dbp == nullptr) { if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) { AbortNode("Failed to write block"); - return CDiskBlockPos(); + return FlatFilePos(); } } return blockPos; } /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ -bool CChainState::AcceptBlock(const std::shared_ptr& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) +bool CChainState::AcceptBlock(const std::shared_ptr& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) { const CBlock& block = *pblock; @@ -3497,7 +3497,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, CVali // Write block to history file if (fNewBlock) *fNewBlock = true; try { - CDiskBlockPos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp); + FlatFilePos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp); if (blockPos.IsNull()) { state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__)); return false; @@ -3628,7 +3628,7 @@ void PruneOneBlockFile(const int fileNumber) void UnlinkPrunedFiles(const std::set& setFilesToPrune) { for (std::set::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) { - CDiskBlockPos pos(*it, 0); + FlatFilePos pos(*it, 0); fs::remove(BlockFileSeq().FileName(pos)); fs::remove(UndoFileSeq().FileName(pos)); LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it); @@ -3748,16 +3748,16 @@ static FlatFileSeq UndoFileSeq() return FlatFileSeq(GetBlocksDir(), "rev", UNDOFILE_CHUNK_SIZE); } -FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) { +FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly) { return BlockFileSeq().Open(pos, fReadOnly); } /** Open an undo file (rev?????.dat) */ -static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { +static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly) { return UndoFileSeq().Open(pos, fReadOnly); } -fs::path GetBlockPosFilename(const CDiskBlockPos &pos) +fs::path GetBlockPosFilename(const FlatFilePos &pos) { return BlockFileSeq().FileName(pos); } @@ -3866,7 +3866,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE } for (std::set::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) { - CDiskBlockPos pos(*it, 0); + FlatFilePos pos(*it, 0); if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) { return false; } @@ -4299,7 +4299,7 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams) try { const CBlock& block = chainparams.GenesisBlock(); - CDiskBlockPos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr); + FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr); if (blockPos.IsNull()) return error("%s: writing genesis block to disk failed", __func__); CBlockIndex *pindex = AddToBlockIndex(block); @@ -4316,10 +4316,10 @@ bool LoadGenesisBlock(const CChainParams& chainparams) return g_chainstate.LoadGenesisBlock(chainparams); } -bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp) +bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos *dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) - static std::multimap mapBlocksUnknownParent; + static std::multimap mapBlocksUnknownParent; int64_t nStart = GetTimeMillis(); int nLoaded = 0; @@ -4405,9 +4405,9 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB while (!queue.empty()) { uint256 head = queue.front(); queue.pop_front(); - std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); + std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); while (range.first != range.second) { - std::multimap::iterator it = range.first; + std::multimap::iterator it = range.first; std::shared_ptr pblockrecursive = std::make_shared(); if (ReadBlockFromDisk(*pblockrecursive, it->second, chainparams.GetConsensus())) { diff --git a/src/validation.h b/src/validation.h index 19f8e8ab7a..4ef82ee2c7 100644 --- a/src/validation.h +++ b/src/validation.h @@ -243,11 +243,11 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr, CBlockHeader* first_invalid = nullptr) LOCKS_EXCLUDED(cs_main); /** Open a block file (blk?????.dat) */ -FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); +FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ -fs::path GetBlockPosFilename(const CDiskBlockPos &pos); +fs::path GetBlockPosFilename(const FlatFilePos &pos); /** Import blocks from an external file */ -bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = nullptr); +bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos *dbp = nullptr); /** Ensures we have a genesis block in the block tree, possibly writing one to disk. */ bool LoadGenesisBlock(const CChainParams& chainparams); /** Load the block tree and coins database from disk, @@ -386,9 +386,9 @@ void InitScriptExecutionCache(); /** Functions for disk access for blocks */ -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams); +bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams); bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams); -bool ReadRawBlockFromDisk(std::vector& block, const CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& message_start); +bool ReadRawBlockFromDisk(std::vector& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start); bool ReadRawBlockFromDisk(std::vector& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start); /** Functions for validating blocks and updating the block tree */ From 4c01e4e159db82ce4b2acce75f709cac996367d7 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 6 Jan 2019 22:23:34 -0800 Subject: [PATCH 0059/4486] flatfile: Unit tests for FlatFileSeq methods. --- src/Makefile.test.include | 1 + src/test/flatfile_tests.cpp | 123 ++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/test/flatfile_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 84bc326cfe..09fef5a1dd 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -83,6 +83,7 @@ BITCOIN_TESTS =\ test/cuckoocache_tests.cpp \ test/denialofservice_tests.cpp \ test/descriptor_tests.cpp \ + test/flatfile_tests.cpp \ test/fs_tests.cpp \ test/getarg_tests.cpp \ test/hash_tests.cpp \ diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp new file mode 100644 index 0000000000..079a09f8f9 --- /dev/null +++ b/src/test/flatfile_tests.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2019 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 +#include + +#include + +BOOST_FIXTURE_TEST_SUITE(flatfile_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(flatfile_filename) +{ + auto data_dir = SetDataDir("flatfile_test"); + + FlatFilePos pos(456, 789); + + FlatFileSeq seq1(data_dir, "a", 16 * 1024); + BOOST_CHECK_EQUAL(seq1.FileName(pos), data_dir / "a00456.dat"); + + FlatFileSeq seq2(data_dir / "a", "b", 16 * 1024); + BOOST_CHECK_EQUAL(seq2.FileName(pos), data_dir / "a" / "b00456.dat"); +} + +BOOST_AUTO_TEST_CASE(flatfile_open) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 16 * 1024); + + std::string line1("A purely peer-to-peer version of electronic cash would allow online " + "payments to be sent directly from one party to another without going " + "through a financial institution."); + std::string line2("Digital signatures provide part of the solution, but the main benefits are " + "lost if a trusted third party is still required to prevent double-spending."); + + size_t pos1 = 0; + size_t pos2 = pos1 + GetSerializeSize(line1, CLIENT_VERSION); + + // Write first line to file. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos1)), SER_DISK, CLIENT_VERSION); + file << LIMITED_STRING(line1, 256); + } + + // Attempt to append to file opened in read-only mode. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos2), true), SER_DISK, CLIENT_VERSION); + BOOST_CHECK_THROW(file << LIMITED_STRING(line2, 256), std::ios_base::failure); + } + + // Append second line to file. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION); + file << LIMITED_STRING(line2, 256); + } + + // Read text from file in read-only mode. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(0, pos1), true), SER_DISK, CLIENT_VERSION); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line1); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line2); + } + + // Read text from file with position offset. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line2); + } + + // Ensure another file in the sequence has no data. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(1, pos2)), SER_DISK, CLIENT_VERSION); + BOOST_CHECK_THROW(file >> LIMITED_STRING(text, 256), std::ios_base::failure); + } +} + +BOOST_AUTO_TEST_CASE(flatfile_allocate) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 100); + + bool out_of_space; + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 0), 1, out_of_space), 100); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 0))), 100); + BOOST_CHECK(!out_of_space); + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 1, out_of_space), 0); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 100); + BOOST_CHECK(!out_of_space); + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 2, out_of_space), 101); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 200); + BOOST_CHECK(!out_of_space); +} + +BOOST_AUTO_TEST_CASE(flatfile_flush) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 100); + + bool out_of_space; + seq.Allocate(FlatFilePos(0, 0), 1, out_of_space); + + // Flush without finalize should not truncate file. + seq.Flush(FlatFilePos(0, 1)); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 100); + + // Flush with finalize should truncate file. + seq.Flush(FlatFilePos(0, 1), true); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 1); +} + +BOOST_AUTO_TEST_SUITE_END() From 04cca330944f859b4ed68cb8da8a79f5206fd630 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 24 Jan 2019 11:20:57 -0800 Subject: [PATCH 0060/4486] Style cleanup. --- src/flatfile.cpp | 19 +++++++++---------- src/flatfile.h | 14 ++++++-------- src/util/system.cpp | 8 ++++---- src/util/system.h | 2 +- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/flatfile.cpp b/src/flatfile.cpp index d2e11825d5..8a8f7b681c 100644 --- a/src/flatfile.cpp +++ b/src/flatfile.cpp @@ -30,25 +30,24 @@ fs::path FlatFileSeq::FileName(const FlatFilePos& pos) const return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); } -FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool fReadOnly) +FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool read_only) { - if (pos.IsNull()) + if (pos.IsNull()) { return nullptr; + } fs::path path = FileName(pos); fs::create_directories(path.parent_path()); - FILE* file = fsbridge::fopen(path, fReadOnly ? "rb": "rb+"); - if (!file && !fReadOnly) + FILE* file = fsbridge::fopen(path, read_only ? "rb": "rb+"); + if (!file && !read_only) file = fsbridge::fopen(path, "wb+"); if (!file) { LogPrintf("Unable to open file %s\n", path.string()); return nullptr; } - if (pos.nPos) { - if (fseek(file, pos.nPos, SEEK_SET)) { - LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); - fclose(file); - return nullptr; - } + if (pos.nPos && fseek(file, pos.nPos, SEEK_SET)) { + LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); + fclose(file); + return nullptr; } return file; } diff --git a/src/flatfile.h b/src/flatfile.h index 6051970490..374ceff411 100644 --- a/src/flatfile.h +++ b/src/flatfile.h @@ -24,14 +24,12 @@ struct FlatFilePos READWRITE(VARINT(nPos)); } - FlatFilePos() { - SetNull(); - } + FlatFilePos() : nFile(-1), nPos(0) {} - FlatFilePos(int nFileIn, unsigned int nPosIn) { - nFile = nFileIn; - nPos = nPosIn; - } + FlatFilePos(int nFileIn, unsigned int nPosIn) : + nFile(nFileIn), + nPos(nPosIn) + {} friend bool operator==(const FlatFilePos &a, const FlatFilePos &b) { return (a.nFile == b.nFile && a.nPos == b.nPos); @@ -72,7 +70,7 @@ class FlatFileSeq fs::path FileName(const FlatFilePos& pos) const; /** Open a handle to the file at the given position. */ - FILE* Open(const FlatFilePos& pos, bool fReadOnly = false); + FILE* Open(const FlatFilePos& pos, bool read_only = false); /** * Allocate additional space in a file after the given starting position. The amount allocated diff --git a/src/util/system.cpp b/src/util/system.cpp index 3e6c2ae5d4..1f0a097e3d 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -135,12 +135,12 @@ bool DirIsWritable(const fs::path& directory) return true; } -bool CheckDiskSpace(const fs::path& dir, uint64_t nAdditionalBytes) +bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes) { - constexpr uint64_t nMinDiskSpace = 52428800; // 50 MiB + constexpr uint64_t min_disk_space = 52428800; // 50 MiB - uint64_t nFreeBytesAvailable = fs::space(dir).available; - return nFreeBytesAvailable >= nMinDiskSpace + nAdditionalBytes; + uint64_t free_bytes_available = fs::space(dir).available; + return free_bytes_available >= min_disk_space + additional_bytes; } /** diff --git a/src/util/system.h b/src/util/system.h index 2a2ee9bc1d..bcfcaaaed0 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -72,7 +72,7 @@ bool RenameOver(fs::path src, fs::path dest); bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false); void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name); bool DirIsWritable(const fs::path& directory); -bool CheckDiskSpace(const fs::path& dir, uint64_t nAdditionalBytes = 0); +bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0); /** Release all directory locks. This is used for unit testing only, at runtime * the global destructor will take care of the locks. From a720a983015c9ef8cc814c16a5b9ef6379695817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Feb 2019 15:46:32 +0000 Subject: [PATCH 0061/4486] gui: Fix async open wallet call order --- src/qt/bitcoingui.cpp | 2 ++ src/qt/walletcontroller.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index bc88dd5e0a..abf9136eee 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -396,6 +396,8 @@ void BitcoinGUI::createActions() connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet); connect(activity, &OpenWalletActivity::finished, activity, &QObject::deleteLater); connect(activity, &OpenWalletActivity::finished, dialog, &QObject::deleteLater); + bool invoked = QMetaObject::invokeMethod(activity, "open"); + assert(invoked); }); } }); diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index c532ffbbfe..fab86a7912 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -59,7 +59,6 @@ OpenWalletActivity* WalletController::openWallet(const std::string& name, QWidge { OpenWalletActivity* activity = new OpenWalletActivity(this, name); activity->moveToThread(&m_activity_thread); - QMetaObject::invokeMethod(activity, "open", Qt::QueuedConnection); return activity; } From 6ad79cbd562d04ebbcb61c774fb3389e70fedb7c Mon Sep 17 00:00:00 2001 From: Chun Kuan Lee Date: Sat, 23 Feb 2019 22:25:24 +0800 Subject: [PATCH 0062/4486] wallet: Use fsbridge::ifstream to fix Windows path issue --- src/fs.cpp | 2 ++ src/wallet/walletutil.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fs.cpp b/src/fs.cpp index 3c8f4c0247..f937f64e04 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -160,6 +160,7 @@ static std::string openmodeToStr(std::ios_base::openmode mode) void ifstream::open(const fs::path& p, std::ios_base::openmode mode) { close(); + mode |= std::ios_base::in; m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str()); if (m_file == nullptr) { return; @@ -183,6 +184,7 @@ void ifstream::close() void ofstream::open(const fs::path& p, std::ios_base::openmode mode) { close(); + mode |= std::ios_base::out; m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str()); if (m_file == nullptr) { return; diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index 6db4c63acb..d779251d56 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -35,7 +35,7 @@ static bool IsBerkeleyBtree(const fs::path& path) boost::system::error_code ec; if (fs::file_size(path, ec) < 4096) return false; - fs::ifstream file(path.string(), std::ios::binary); + fsbridge::ifstream file(path, std::ios::binary); if (!file.is_open()) return false; file.seekg(12, std::ios::beg); // Magic bytes start at offset 12 From 3f5ad622e5fe0781a70bee9e3322b23c2352e956 Mon Sep 17 00:00:00 2001 From: riordant Date: Mon, 25 Feb 2019 16:00:34 +0700 Subject: [PATCH 0063/4486] Enable PID file creation on Windows - Add available WIN PID function - Consider WIN32 in each relevant case - Add new preprocessor definitions to suppress warning - Update error message for generic OS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörn Röder --- .../libbitcoin_server.vcxproj.in | 8 ++++---- src/init.cpp | 16 +++++----------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in b/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in index acb827bd95..913f3c35da 100644 --- a/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in +++ b/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in @@ -89,7 +89,7 @@ NotUsing Level3 Disabled - WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreadedDebug @@ -104,7 +104,7 @@ NotUsing Level3 Disabled - WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreadedDebug @@ -122,7 +122,7 @@ MaxSpeed true true - WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) + WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreaded @@ -141,7 +141,7 @@ MaxSpeed true true - WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) + WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreaded diff --git a/src/init.cpp b/src/init.cpp index caab4a5674..9ba9b2803a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -97,7 +97,6 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; /** * The PID file facilities. */ -#ifndef WIN32 static const char* BITCOIN_PID_FILENAME = "bitcoind.pid"; static fs::path GetPidFile() @@ -109,14 +108,17 @@ NODISCARD static bool CreatePidFile() { FILE* file = fsbridge::fopen(GetPidFile(), "w"); if (file) { +#ifdef WIN32 + fprintf(file, "%d\n", GetCurrentProcessId()); +#else fprintf(file, "%d\n", getpid()); +#endif fclose(file); return true; } else { return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno))); } } -#endif ////////////////////////////////////////////////////////////////////////////// // @@ -286,15 +288,13 @@ void Shutdown(InitInterfaces& interfaces) } #endif -#ifndef WIN32 try { if (!fs::remove(GetPidFile())) { LogPrintf("%s: Unable to remove PID file: File does not exist\n", __func__); } } catch (const fs::filesystem_error& e) { - LogPrintf("%s: Unable to remove PID file: %s\n", __func__, e.what()); + LogPrintf("%s: Unable to remove PID file: %s\n", __func__, fsbridge::get_filesystem_error_message(e)); } -#endif interfaces.chain_clients.clear(); UnregisterAllValidationInterfaces(); GetMainSignals().UnregisterBackgroundSignalScheduler(); @@ -392,11 +392,7 @@ void SetupServerArgs() gArgs.AddArg("-par=", strprintf("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)", -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), false, OptionsCategory::OPTIONS); gArgs.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), false, OptionsCategory::OPTIONS); -#ifndef WIN32 gArgs.AddArg("-pid=", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), false, OptionsCategory::OPTIONS); -#else - hidden_args.emplace_back("-pid"); -#endif gArgs.AddArg("-prune=", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. " "Warning: Reverting this setting requires re-downloading the entire blockchain. " "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS); @@ -1228,12 +1224,10 @@ bool AppInitMain(InitInterfaces& interfaces) { const CChainParams& chainparams = Params(); // ********************************************************* Step 4a: application initialization -#ifndef WIN32 if (!CreatePidFile()) { // Detailed error printed inside CreatePidFile(). return false; } -#endif if (LogInstance().m_print_to_file) { if (gArgs.GetBoolArg("-shrinkdebugfile", LogInstance().DefaultShrinkDebugFile())) { // Do this first since it both loads a bunch of debug.log into memory, From ef362f27733e9281062b4e65a26e5696f34692b4 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 25 Feb 2019 10:14:28 +0100 Subject: [PATCH 0064/4486] rpc/gui: Remove 'Unknown block versions being mined' warning Due to miners inserting garbage into the version numbers, the current version signalling has become completely useless. This removes the "unknown block versions" warning which has the tendency to scare users unnecessarily (and might get them to "update" to something bad). It preserves the warning in the logs. Whether this is desirable can be a point of discussion. --- src/validation.cpp | 6 ------ test/functional/feature_notifications.py | 18 +----------------- test/functional/feature_versionbits_warning.py | 6 ------ 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 1806bc1268..f3d34dca70 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2259,12 +2259,6 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar } if (nUpgraded > 0) AppendWarning(warningMessages, strprintf(_("%d of last 100 blocks have unexpected version"), nUpgraded)); - if (nUpgraded > 100/2) - { - std::string strWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect"); - // notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user: - DoWarning(strWarning); - } } LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, /* Continued */ pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py index d8083b2840..b98dd6d26c 100755 --- a/test/functional/feature_notifications.py +++ b/test/functional/feature_notifications.py @@ -66,23 +66,7 @@ def run_test(self): txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count))) assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir))) - # Mine another 41 up-version blocks. -alertnotify should trigger on the 51st. - self.log.info("test -alertnotify") - self.nodes[1].generatetoaddress(41, ADDRESS_BCRT1_UNSPENDABLE) - self.sync_all() - - # Give bitcoind 10 seconds to write the alert notification - wait_until(lambda: len(os.listdir(self.alertnotify_dir)), timeout=10) - - for notify_file in os.listdir(self.alertnotify_dir): - os.remove(os.path.join(self.alertnotify_dir, notify_file)) - - # Mine more up-version blocks, should not get more alerts: - self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE) - self.sync_all() - - self.log.info("-alertnotify should not continue notifying for more unknown version blocks") - assert_equal(len(os.listdir(self.alertnotify_dir)), 0) + # TODO: add test for `-alertnotify` large fork notifications if __name__ == '__main__': NotificationsTest().main() diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index 88df61cabc..1ced618d47 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -22,7 +22,6 @@ VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment VB_UNKNOWN_VERSION = VB_TOP_BITS | (1 << VB_UNKNOWN_BIT) -WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible unknown rules are in effect" WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT) VB_PATTERN = re.compile("Warning: unknown new rules activated.*versionbit") @@ -78,15 +77,10 @@ def run_test(self): assert(not VB_PATTERN.match(node.getmininginfo()["warnings"])) assert(not VB_PATTERN.match(node.getnetworkinfo()["warnings"])) - self.log.info("Check that there is a warning if >50 blocks in the last 100 were an unknown version") # Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit self.send_blocks_with_version(node.p2p, VB_THRESHOLD, VB_UNKNOWN_VERSION) node.generatetoaddress(VB_PERIOD - VB_THRESHOLD, node_deterministic_address) - # Check that get*info() shows the 51/100 unknown block version error. - assert(WARN_UNKNOWN_RULES_MINED in node.getmininginfo()["warnings"]) - assert(WARN_UNKNOWN_RULES_MINED in node.getnetworkinfo()["warnings"]) - self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.") # Mine a period worth of expected blocks so the generic block-version warning # is cleared. This will move the versionbit state to ACTIVE. From fa5dc3534be1d58bbca641a32cd87cd97ce8882a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 23 Feb 2019 11:04:20 -0500 Subject: [PATCH 0065/4486] rpc: Pass mempool into MempoolToJSON --- src/policy/rbf.cpp | 2 +- src/policy/rbf.h | 2 +- src/rest.cpp | 4 ++-- src/rpc/blockchain.cpp | 52 +++++++++++++++++++----------------------- src/rpc/blockchain.h | 5 ++-- src/txmempool.cpp | 2 +- src/txmempool.h | 4 ++-- 7 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp index 0dc130d104..c73a97fd7d 100644 --- a/src/policy/rbf.cpp +++ b/src/policy/rbf.cpp @@ -14,7 +14,7 @@ bool SignalsOptInRBF(const CTransaction &tx) return false; } -RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool) +RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool) { AssertLockHeld(pool.cs); diff --git a/src/policy/rbf.h b/src/policy/rbf.h index 581f489e12..a4f8777310 100644 --- a/src/policy/rbf.h +++ b/src/policy/rbf.h @@ -23,6 +23,6 @@ bool SignalsOptInRBF(const CTransaction &tx); // according to BIP 125 // This involves checking sequence numbers of the transaction, as well // as the sequence numbers of all in-mempool ancestors. -RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs); +RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs); #endif // BITCOIN_POLICY_RBF_H diff --git a/src/rest.cpp b/src/rest.cpp index 326f7ae1d2..baad3b2ce9 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -300,7 +300,7 @@ static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart) switch (rf) { case RetFormat::JSON: { - UniValue mempoolInfoObject = mempoolInfoToJSON(); + UniValue mempoolInfoObject = MempoolInfoToJSON(::mempool); std::string strJSON = mempoolInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); @@ -322,7 +322,7 @@ static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPar switch (rf) { case RetFormat::JSON: { - UniValue mempoolObject = mempoolToJSON(true); + UniValue mempoolObject = MempoolToJSON(::mempool, true); std::string strJSON = mempoolObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7fb9ff2eaf..27f23921a0 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -405,9 +405,9 @@ static std::string EntryDescriptionString() " \"bip125-replaceable\" : true|false, (boolean) Whether this transaction could be replaced due to BIP125 (replace-by-fee)\n"; } -static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs) +static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs) { - AssertLockHeld(mempool.cs); + AssertLockHeld(pool.cs); UniValue fees(UniValue::VOBJ); fees.pushKV("base", ValueFromAmount(e.GetFee())); @@ -427,12 +427,12 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK info.pushKV("ancestorcount", e.GetCountWithAncestors()); info.pushKV("ancestorsize", e.GetSizeWithAncestors()); info.pushKV("ancestorfees", e.GetModFeesWithAncestors()); - info.pushKV("wtxid", mempool.vTxHashes[e.vTxHashesIdx].first.ToString()); + info.pushKV("wtxid", pool.vTxHashes[e.vTxHashesIdx].first.ToString()); const CTransaction& tx = e.GetTx(); std::set setDepends; for (const CTxIn& txin : tx.vin) { - if (mempool.exists(txin.prevout.hash)) + if (pool.exists(txin.prevout.hash)) setDepends.insert(txin.prevout.hash.ToString()); } @@ -445,8 +445,8 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK info.pushKV("depends", depends); UniValue spent(UniValue::VARR); - const CTxMemPool::txiter &it = mempool.mapTx.find(tx.GetHash()); - const CTxMemPool::setEntries &setChildren = mempool.GetMemPoolChildren(it); + const CTxMemPool::txiter& it = pool.mapTx.find(tx.GetHash()); + const CTxMemPool::setEntries& setChildren = pool.GetMemPoolChildren(it); for (CTxMemPool::txiter childiter : setChildren) { spent.push_back(childiter->GetTx().GetHash().ToString()); } @@ -455,7 +455,7 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK // Add opt-in RBF status bool rbfStatus = false; - RBFTransactionState rbfState = IsRBFOptIn(tx, mempool); + RBFTransactionState rbfState = IsRBFOptIn(tx, pool); if (rbfState == RBFTransactionState::UNKNOWN) { throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool"); } else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) { @@ -465,25 +465,21 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK info.pushKV("bip125-replaceable", rbfStatus); } -UniValue mempoolToJSON(bool fVerbose) +UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose) { - if (fVerbose) - { - LOCK(mempool.cs); + if (verbose) { + LOCK(pool.cs); UniValue o(UniValue::VOBJ); - for (const CTxMemPoolEntry& e : mempool.mapTx) - { + for (const CTxMemPoolEntry& e : pool.mapTx) { const uint256& hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(pool, info, e); o.pushKV(hash.ToString(), info); } return o; - } - else - { + } else { std::vector vtxid; - mempool.queryHashes(vtxid); + pool.queryHashes(vtxid); UniValue a(UniValue::VARR); for (const uint256& hash : vtxid) @@ -525,7 +521,7 @@ static UniValue getrawmempool(const JSONRPCRequest& request) if (!request.params[0].isNull()) fVerbose = request.params[0].get_bool(); - return mempoolToJSON(fVerbose); + return MempoolToJSON(::mempool, fVerbose); } static UniValue getmempoolancestors(const JSONRPCRequest& request) @@ -591,7 +587,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) const CTxMemPoolEntry &e = *ancestorIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(::mempool, info, e); o.pushKV(_hash.ToString(), info); } return o; @@ -661,7 +657,7 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) const CTxMemPoolEntry &e = *descendantIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(::mempool, info, e); o.pushKV(_hash.ToString(), info); } return o; @@ -700,7 +696,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) const CTxMemPoolEntry &e = *it; UniValue info(UniValue::VOBJ); - entryToJSON(info, e); + entryToJSON(::mempool, info, e); return info; } @@ -1485,15 +1481,15 @@ static UniValue getchaintips(const JSONRPCRequest& request) return res; } -UniValue mempoolInfoToJSON() +UniValue MempoolInfoToJSON(const CTxMemPool& pool) { UniValue ret(UniValue::VOBJ); - ret.pushKV("size", (int64_t) mempool.size()); - ret.pushKV("bytes", (int64_t) mempool.GetTotalTxSize()); - ret.pushKV("usage", (int64_t) mempool.DynamicMemoryUsage()); + ret.pushKV("size", (int64_t)pool.size()); + ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize()); + ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage()); size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; ret.pushKV("maxmempool", (int64_t) maxmempool); - ret.pushKV("mempoolminfee", ValueFromAmount(std::max(mempool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK())); + ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK())); ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())); return ret; @@ -1522,7 +1518,7 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request) }, }.ToString()); - return mempoolInfoToJSON(); + return MempoolInfoToJSON(::mempool); } static UniValue preciousblock(const JSONRPCRequest& request) diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h index 529132d033..55d1de453f 100644 --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -11,6 +11,7 @@ class CBlock; class CBlockIndex; +class CTxMemPool; class UniValue; static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5; @@ -30,10 +31,10 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false); /** Mempool information to JSON */ -UniValue mempoolInfoToJSON(); +UniValue MempoolInfoToJSON(const CTxMemPool& pool); /** Mempool to JSON */ -UniValue mempoolToJSON(bool fVerbose = false); +UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose = false); /** Block header to JSON */ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 68f47d5cce..ca556bdc7b 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -764,7 +764,7 @@ std::vector CTxMemPool::Get return iters; } -void CTxMemPool::queryHashes(std::vector& vtxid) +void CTxMemPool::queryHashes(std::vector& vtxid) const { LOCK(cs); auto iters = GetSortedDepthAndScore(); diff --git a/src/txmempool.h b/src/txmempool.h index f7afaec8fc..a8a0f7fa45 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -184,7 +184,7 @@ struct update_lock_points const LockPoints& lp; }; -// extracts a transaction hash from CTxMempoolEntry or CTransactionRef +// extracts a transaction hash from CTxMemPoolEntry or CTransactionRef struct mempoolentry_txid { typedef uint256 result_type; @@ -588,7 +588,7 @@ class CTxMemPool void clear(); void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); //lock free bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb); - void queryHashes(std::vector& vtxid); + void queryHashes(std::vector& vtxid) const; bool isSpent(const COutPoint& outpoint) const; unsigned int GetTransactionsUpdated() const; void AddTransactionsUpdated(unsigned int n); From fa38535130266896c430d146b05d0069e525dbe6 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 23 Feb 2019 11:11:14 -0500 Subject: [PATCH 0066/4486] bench: Benchmark MempoolToJSON --- .../bench_bitcoin/bench_bitcoin.vcxproj | 1 + src/Makefile.bench.include | 6 ++- src/bench/rpc_mempool.cpp | 43 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/bench/rpc_mempool.cpp diff --git a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj index 771e8a56f4..44152bad7a 100644 --- a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj +++ b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj @@ -32,6 +32,7 @@ + diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 5e787ca222..6e4597e2da 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -26,6 +26,7 @@ bench_bench_bitcoin_SOURCES = \ bench/gcs_filter.cpp \ bench/merkle_root.cpp \ bench/mempool_eviction.cpp \ + bench/rpc_mempool.cpp \ bench/verify_script.cpp \ bench/base58.cpp \ bench/bech32.cpp \ @@ -37,6 +38,7 @@ nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES) bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bench_bench_bitcoin_LDADD = \ + $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ @@ -47,7 +49,9 @@ bench_bench_bitcoin_LDADD = \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ $(LIBSECP256K1) \ - $(LIBUNIVALUE) + $(LIBUNIVALUE) \ + $(EVENT_PTHREADS_LIBS) \ + $(EVENT_LIBS) if ENABLE_ZMQ bench_bench_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp new file mode 100644 index 0000000000..67d8a25564 --- /dev/null +++ b/src/bench/rpc_mempool.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2011-2019 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 +#include +#include +#include + +#include + +#include +#include + +static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) +{ + LockPoints lp; + pool.addUnchecked(CTxMemPoolEntry(tx, fee, /* time */ 0, /* height */ 1, /* spendsCoinbase */ false, /* sigOpCost */ 4, lp)); +} + +static void RpcMempool(benchmark::State& state) +{ + CTxMemPool pool; + LOCK2(cs_main, pool.cs); + + for (int i = 0; i < 1000; ++i) { + CMutableTransaction tx = CMutableTransaction(); + tx.vin.resize(1); + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vin[0].scriptWitness.stack.push_back({1}); + tx.vout.resize(1); + tx.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; + tx.vout[0].nValue = i; + const CTransactionRef tx_r{MakeTransactionRef(tx)}; + AddTx(tx_r, /* fee */ i, pool); + } + + while (state.KeepRunning()) { + (void)MempoolToJSON(pool, /*verbose*/ true); + } +} + +BENCHMARK(RpcMempool, 40); From fa2cdc9ac2672301591cafceb8ff230b95425ad0 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 23 Feb 2019 12:56:54 -0500 Subject: [PATCH 0067/4486] test: Simplify create_cache --- test/functional/test_framework/test_framework.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 24e1a21a28..09d7d877a7 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -277,7 +277,9 @@ def setup_nodes(self): if not self.setup_clean_chain: for n in self.nodes: assert_equal(n.getblockchaininfo()["blocks"], 199) - self.log.debug('Generate a block with current time to finalize the cache and assert we are out of IBD') + # To ensure that all nodes are out of IBD, the most recent block + # must have a timestamp not too old (see IsInitialBlockDownload()). + self.log.debug('Generate a block with current time') block_hash = self.nodes[0].generate(1)[0] block = self.nodes[0].getblock(blockhash=block_hash, verbosity=0) for n in self.nodes: @@ -493,14 +495,9 @@ def _initialize_chain(self): # block in the cache does not age too much (have an old tip age). # This is needed so that we are out of IBD when the test starts, # see the tip age check in IsInitialBlockDownload(). - for i in range(2): - for peer in range(4): - for j in range(25): - if i == 1 and peer == 3 and j == 24: - break - self.nodes[peer].generatetoaddress(1, self.nodes[peer].get_deterministic_priv_key().address) - # Must sync before next peer starts generating blocks - sync_blocks(self.nodes) + for i in range(8): + self.nodes[0].generatetoaddress(25 if i != 7 else 24, self.nodes[i % 4].get_deterministic_priv_key().address) + sync_blocks(self.nodes) for n in self.nodes: assert_equal(n.getblockchaininfo()["blocks"], 199) From fa9ff8fe212ae40a1ef4980455bf916bc044fee2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 25 Feb 2019 23:49:20 -0500 Subject: [PATCH 0068/4486] doc: Remove misleading hint in getrawtransaction --- src/rpc/rawtransaction.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 5a714a137e..f5543f63f6 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -79,8 +79,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) "will return the transaction if it is in the mempool, or if -txindex is enabled and the transaction\n" "is in a block in the blockchain.\n" - "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n" - "Or use gettransaction for wallet transactions.\n" + "\nHint: Use gettransaction for wallet transactions.\n" "\nIf verbose is 'true', returns an Object with information about 'txid'.\n" "If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'.\n", From 9999879f56c88ca2837f5d18e6688917ba96e9e2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 25 Feb 2019 14:54:22 -0500 Subject: [PATCH 0069/4486] refactor: Use RPCHelpMan::IsValidNumArgs in getrawtransaction --- src/rpc/rawtransaction.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index f5543f63f6..d19afaa8a1 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -67,9 +67,7 @@ static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& static UniValue getrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{ + const RPCHelpMan help{ "getrawtransaction", "\nReturn the raw transaction data.\n" @@ -147,7 +145,11 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"") + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") }, - }.ToString()); + }; + + if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { + throw std::runtime_error(help.ToString()); + } bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); From 4d834018e368c3481a5421891395f64aa9002185 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 26 Feb 2019 14:59:30 -0500 Subject: [PATCH 0070/4486] [addrman] Improve tried table collision logging --- src/addrman.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index 06c342ba73..468618095c 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -239,7 +239,9 @@ void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime // Will moving this address into tried evict another entry? if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) { - LogPrint(BCLog::ADDRMAN, "Collision inserting element into tried table, moving %s to m_tried_collisions=%d\n", addr.ToString(), m_tried_collisions.size()); + // Output the entry we'd be colliding with, for debugging purposes + auto colliding_entry = mapInfo.find(vvTried[tried_bucket][tried_bucket_pos]); + LogPrint(BCLog::ADDRMAN, "Collision inserting element into tried table (%s), moving %s to m_tried_collisions=%d\n", colliding_entry != mapInfo.end() ? colliding_entry->second.ToString() : "", addr.ToString(), m_tried_collisions.size()); if (m_tried_collisions.size() < ADDRMAN_SET_TRIED_COLLISION_SIZE) { m_tried_collisions.insert(nId); } From 2fa85ebd1c2d7579ea005300e9101fbb48805c2f Mon Sep 17 00:00:00 2001 From: Adam Jonas Date: Thu, 31 Jan 2019 14:45:27 -0500 Subject: [PATCH 0071/4486] add rpc_misc.py, mv test getmemoryinfo, add test mallocinfo --- test/functional/rpc_misc.py | 48 +++++++++++++++++++++++++++++++++ test/functional/test_runner.py | 1 + test/functional/wallet_basic.py | 6 ----- 3 files changed, 49 insertions(+), 6 deletions(-) create mode 100755 test/functional/rpc_misc.py diff --git a/test/functional/rpc_misc.py b/test/functional/rpc_misc.py new file mode 100755 index 0000000000..ab216bc467 --- /dev/null +++ b/test/functional/rpc_misc.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test RPC misc output.""" +import xml.etree.ElementTree as ET + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_raises_rpc_error, + assert_equal, + assert_greater_than, +) + +from test_framework.authproxy import JSONRPCException + + +class RpcMiscTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + + def run_test(self): + node = self.nodes[0] + + self.log.info("test getmemoryinfo") + memory = node.getmemoryinfo()['locked'] + assert_greater_than(memory['used'], 0) + assert_greater_than(memory['free'], 0) + assert_greater_than(memory['total'], 0) + assert_greater_than(memory['locked'], 0) + assert_greater_than(memory['chunks_used'], 0) + assert_greater_than(memory['chunks_free'], 0) + assert_equal(memory['used'] + memory['free'], memory['total']) + + self.log.info("test mallocinfo") + try: + mallocinfo = node.getmemoryinfo(mode="mallocinfo") + self.log.info('getmemoryinfo(mode="mallocinfo") call succeeded') + tree = ET.fromstring(mallocinfo) + assert_equal(tree.tag, 'malloc') + except JSONRPCException: + self.log.info('getmemoryinfo(mode="mallocinfo") not available') + assert_raises_rpc_error(-8, 'mallocinfo is only available when compiled with glibc 2.10+', node.getmemoryinfo, mode="mallocinfo") + + assert_raises_rpc_error(-8, "unknown mode foobar", node.getmemoryinfo, mode="foobar") + +if __name__ == '__main__': + RpcMiscTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 5c92370b85..057fd175b7 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -112,6 +112,7 @@ 'wallet_txn_clone.py', 'wallet_txn_clone.py --segwit', 'rpc_getchaintips.py', + 'rpc_misc.py', 'interface_rest.py', 'mempool_spend_coinbase.py', 'mempool_reorg.py', diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index daae2ed3c0..10b51ecdac 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -11,7 +11,6 @@ assert_array_result, assert_equal, assert_fee_amount, - assert_greater_than, assert_raises_rpc_error, connect_nodes_bi, sync_blocks, @@ -85,13 +84,8 @@ def run_test(self): assert_equal(txout['value'], 50) # Send 21 BTC from 0 to 2 using sendtoaddress call. - # Locked memory should increase to sign transactions - self.log.info("test getmemoryinfo") - memory_before = self.nodes[0].getmemoryinfo() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) - memory_after = self.nodes[0].getmemoryinfo() - assert_greater_than(memory_after['locked']['used'], memory_before['locked']['used']) self.log.info("test gettxout (second part)") # utxo spent in mempool should be visible if you exclude mempool From fa45123f66f42efc32bebae39bd1296908aaabdc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 25 Feb 2019 15:08:56 -0500 Subject: [PATCH 0072/4486] test: Add .style.yapf --- .style.yapf | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 .style.yapf diff --git a/.style.yapf b/.style.yapf new file mode 100644 index 0000000000..fe6227baf6 --- /dev/null +++ b/.style.yapf @@ -0,0 +1,261 @@ +[style] +# Align closing bracket with visual indentation. +align_closing_bracket_with_visual_indent=True + +# Allow dictionary keys to exist on multiple lines. For example: +# +# x = { +# ('this is the first element of a tuple', +# 'this is the second element of a tuple'): +# value, +# } +allow_multiline_dictionary_keys=False + +# Allow lambdas to be formatted on more than one line. +allow_multiline_lambdas=False + +# Allow splits before the dictionary value. +allow_split_before_dict_value=True + +# Number of blank lines surrounding top-level function and class +# definitions. +blank_lines_around_top_level_definition=2 + +# Insert a blank line before a class-level docstring. +blank_line_before_class_docstring=False + +# Insert a blank line before a module docstring. +blank_line_before_module_docstring=False + +# Insert a blank line before a 'def' or 'class' immediately nested +# within another 'def' or 'class'. For example: +# +# class Foo: +# # <------ this blank line +# def method(): +# ... +blank_line_before_nested_class_or_def=False + +# Do not split consecutive brackets. Only relevant when +# dedent_closing_brackets is set. For example: +# +# call_func_that_takes_a_dict( +# { +# 'key1': 'value1', +# 'key2': 'value2', +# } +# ) +# +# would reformat to: +# +# call_func_that_takes_a_dict({ +# 'key1': 'value1', +# 'key2': 'value2', +# }) +coalesce_brackets=False + +# The column limit. +column_limit=79 + +# The style for continuation alignment. Possible values are: +# +# - SPACE: Use spaces for continuation alignment. This is default behavior. +# - FIXED: Use fixed number (CONTINUATION_INDENT_WIDTH) of columns +# (ie: CONTINUATION_INDENT_WIDTH/INDENT_WIDTH tabs) for continuation +# alignment. +# - LESS: Slightly left if cannot vertically align continuation lines with +# indent characters. +# - VALIGN-RIGHT: Vertically align continuation lines with indent +# characters. Slightly right (one more indent character) if cannot +# vertically align continuation lines with indent characters. +# +# For options FIXED, and VALIGN-RIGHT are only available when USE_TABS is +# enabled. +continuation_align_style=SPACE + +# Indent width used for line continuations. +continuation_indent_width=4 + +# Put closing brackets on a separate line, dedented, if the bracketed +# expression can't fit in a single line. Applies to all kinds of brackets, +# including function definitions and calls. For example: +# +# config = { +# 'key1': 'value1', +# 'key2': 'value2', +# } # <--- this bracket is dedented and on a separate line +# +# time_series = self.remote_client.query_entity_counters( +# entity='dev3246.region1', +# key='dns.query_latency_tcp', +# transform=Transformation.AVERAGE(window=timedelta(seconds=60)), +# start_ts=now()-timedelta(days=3), +# end_ts=now(), +# ) # <--- this bracket is dedented and on a separate line +dedent_closing_brackets=False + +# Disable the heuristic which places each list element on a separate line +# if the list is comma-terminated. +disable_ending_comma_heuristic=False + +# Place each dictionary entry onto its own line. +each_dict_entry_on_separate_line=True + +# The regex for an i18n comment. The presence of this comment stops +# reformatting of that line, because the comments are required to be +# next to the string they translate. +i18n_comment= + +# The i18n function call names. The presence of this function stops +# reformattting on that line, because the string it has cannot be moved +# away from the i18n comment. +i18n_function_call= + +# Indent the dictionary value if it cannot fit on the same line as the +# dictionary key. For example: +# +# config = { +# 'key1': +# 'value1', +# 'key2': value1 + +# value2, +# } +indent_dictionary_value=False + +# The number of columns to use for indentation. +indent_width=4 + +# Join short lines into one line. E.g., single line 'if' statements. +join_multiple_lines=True + +# Do not include spaces around selected binary operators. For example: +# +# 1 + 2 * 3 - 4 / 5 +# +# will be formatted as follows when configured with "*,/": +# +# 1 + 2*3 - 4/5 +# +no_spaces_around_selected_binary_operators= + +# Use spaces around default or named assigns. +spaces_around_default_or_named_assign=False + +# Use spaces around the power operator. +spaces_around_power_operator=False + +# The number of spaces required before a trailing comment. +spaces_before_comment=2 + +# Insert a space between the ending comma and closing bracket of a list, +# etc. +space_between_ending_comma_and_closing_bracket=True + +# Split before arguments +split_all_comma_separated_values=False + +# Split before arguments if the argument list is terminated by a +# comma. +split_arguments_when_comma_terminated=False + +# Set to True to prefer splitting before '&', '|' or '^' rather than +# after. +split_before_bitwise_operator=True + +# Split before the closing bracket if a list or dict literal doesn't fit on +# a single line. +split_before_closing_bracket=True + +# Split before a dictionary or set generator (comp_for). For example, note +# the split before the 'for': +# +# foo = { +# variable: 'Hello world, have a nice day!' +# for variable in bar if variable != 42 +# } +split_before_dict_set_generator=True + +# Split before the '.' if we need to split a longer expression: +# +# foo = ('This is a really long string: {}, {}, {}, {}'.format(a, b, c, d)) +# +# would reformat to something like: +# +# foo = ('This is a really long string: {}, {}, {}, {}' +# .format(a, b, c, d)) +split_before_dot=False + +# Split after the opening paren which surrounds an expression if it doesn't +# fit on a single line. +split_before_expression_after_opening_paren=False + +# If an argument / parameter list is going to be split, then split before +# the first argument. +split_before_first_argument=False + +# Set to True to prefer splitting before 'and' or 'or' rather than +# after. +split_before_logical_operator=True + +# Split named assignments onto individual lines. +split_before_named_assigns=True + +# Set to True to split list comprehensions and generators that have +# non-trivial expressions and multiple clauses before each of these +# clauses. For example: +# +# result = [ +# a_long_var + 100 for a_long_var in xrange(1000) +# if a_long_var % 10] +# +# would reformat to something like: +# +# result = [ +# a_long_var + 100 +# for a_long_var in xrange(1000) +# if a_long_var % 10] +split_complex_comprehension=False + +# The penalty for splitting right after the opening bracket. +split_penalty_after_opening_bracket=30 + +# The penalty for splitting the line after a unary operator. +split_penalty_after_unary_operator=10000 + +# The penalty for splitting right before an if expression. +split_penalty_before_if_expr=0 + +# The penalty of splitting the line around the '&', '|', and '^' +# operators. +split_penalty_bitwise_operator=300 + +# The penalty for splitting a list comprehension or generator +# expression. +split_penalty_comprehension=80 + +# The penalty for characters over the column limit. +split_penalty_excess_character=7000 + +# The penalty incurred by adding a line split to the unwrapped line. The +# more line splits added the higher the penalty. +split_penalty_for_added_line_split=30 + +# The penalty of splitting a list of "import as" names. For example: +# +# from a_very_long_or_indented_module_name_yada_yad import (long_argument_1, +# long_argument_2, +# long_argument_3) +# +# would reformat to something like: +# +# from a_very_long_or_indented_module_name_yada_yad import ( +# long_argument_1, long_argument_2, long_argument_3) +split_penalty_import_names=0 + +# The penalty of splitting the line around the 'and' and 'or' +# operators. +split_penalty_logical_operator=300 + +# Use the Tab character for indentation. +use_tabs=False + From fa466cbc5016aa8dff40e63a273a077f76c1cdcb Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 26 Feb 2019 19:03:35 -0500 Subject: [PATCH 0073/4486] doc: Update release process for snap package --- doc/release-process.md | 44 ++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index d20a3dc6b3..eb1f5ad222 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -291,24 +291,48 @@ bitcoin.org (see below for bitcoin.org update instructions). - After the pull request is merged, the website will automatically show the newest version within 15 minutes, as well as update the OS download links. Ping @saivann/@harding (saivann/harding on Freenode) in case anything goes wrong -- Announce the release: - - - bitcoin-dev and bitcoin-core-dev mailing list - - - Bitcoin Core announcements list https://bitcoincore.org/en/list/announcements/join/ +- Update other repositories and websites for new version - bitcoincore.org blog post - bitcoincore.org RPC documentation update - - Update title of #bitcoin on Freenode IRC + - Update packaging repo - - Optionally twitter, reddit /r/Bitcoin, ... but this will usually sort out itself + - Notify BlueMatt so that he can start building [the PPAs](https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin) + + - Create a new branch for the major release "0.xx" (used to build the snap package) + + - Notify MarcoFalke so that he can start building the snap package + + - https://code.launchpad.net/~bitcoin-core/bitcoin-core-snap/+git/packaging (Click "Import Now" to fetch the branch) + - https://code.launchpad.net/~bitcoin-core/bitcoin-core-snap/+git/packaging/+ref/0.xx (Click "Create snap package") + - Name it "bitcoin-core-snap-0.xx" + - Leave owner and series as-is + - Select architectures that are compiled via gitian + - Leave "automatically build when branch changes" unticked + - Tick "automatically upload to store" + - Put "bitcoin-core" in the registered store package name field + - Tick the "edge" box + - Put "0.xx" in the track field + - Click "create snap package" + - Click "Request builds" for every new release on this branch (after updating the snapcraft.yml in the branch to reflect the latest gitian results) + - Promote release on https://snapcraft.io/bitcoin-core/releases if it passes sanity checks - - Notify BlueMatt so that he can start building [the PPAs](https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin) + - This repo - - Archive release notes for the new version to `doc/release-notes/` (branch `master` and branch of the release) + - Archive release notes for the new version to `doc/release-notes/` (branch `master` and branch of the release) - - Create a [new GitHub release](https://github.com/bitcoin/bitcoin/releases/new) with a link to the archived release notes. + - Create a [new GitHub release](https://github.com/bitcoin/bitcoin/releases/new) with a link to the archived release notes. + +- Announce the release: + + - bitcoin-dev and bitcoin-core-dev mailing list + + - Bitcoin Core announcements list https://bitcoincore.org/en/list/announcements/join/ + + - Update title of #bitcoin on Freenode IRC + + - Optionally twitter, reddit /r/Bitcoin, ... but this will usually sort out itself - Celebrate From 4991e3c813c9848d3b3957ea3ad433f02fca9e81 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 26 Feb 2019 15:04:48 -0500 Subject: [PATCH 0074/4486] [net] feeler connections can be made to outbound peers in same netgroup Fixes a bug where feelers could be stuck trying to resolve a collision in the tried table that is to an address in the same netgroup as an existing outbound peer. Thanks to Muoi Tran for the original bug report and detailed debug logs to track this down. --- src/net.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 87f1ef0577..3f87dc6357 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1765,9 +1765,15 @@ void CConnman::ThreadOpenConnections(const std::vector connect) addr = addrman.Select(fFeeler); } + // Require outbound connections to be to distinct network groups + if (!fFeeler && setConnected.count(addr.GetGroup())) { + break; + } + // if we selected an invalid address, restart - if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr)) + if (!addr.IsValid() || IsLocal(addr)) { break; + } // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman, // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates From 8bb3e4c487500a580e3e18791b1f4e7dcdd35442 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Wed, 27 Feb 2019 10:32:12 +0100 Subject: [PATCH 0075/4486] [rpc] remove deprecated generate method --- doc/release-notes-15492.md | 11 ++++++ src/rpc/client.cpp | 2 -- src/wallet/rpcwallet.cpp | 58 ------------------------------- test/functional/rpc_deprecated.py | 23 ++++++------ 4 files changed, 21 insertions(+), 73 deletions(-) create mode 100644 doc/release-notes-15492.md diff --git a/doc/release-notes-15492.md b/doc/release-notes-15492.md new file mode 100644 index 0000000000..1149eb0dbc --- /dev/null +++ b/doc/release-notes-15492.md @@ -0,0 +1,11 @@ +Deprecated or removed RPCs +-------------------------- +- The wallet's `generate` RPC method was deprecated in v0.18 and has now + been fully removed. This RPC is only used for + testing, but its implementation reached across multiple subsystems + (wallet and mining), so it has been removed to simplify the + wallet-node interface. Projects that are using `generate` for testing + purposes should transition to using the `generatetoaddress` RPC, which + does not require or use the wallet component. Calling + `generatetoaddress` with an address returned by the `getnewaddress` + RPC gives the same functionality as the old `generate` RPC. diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 1cdc9f87a7..55f4229624 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -28,8 +28,6 @@ class CRPCConvertParam static const CRPCConvertParam vRPCConvertParams[] = { { "setmocktime", 0, "timestamp" }, - { "generate", 0, "nblocks" }, - { "generate", 1, "maxtries" }, { "generatetoaddress", 0, "nblocks" }, { "generatetoaddress", 2, "maxtries" }, { "getnetworkhashps", 0, "nblocks" }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 97c6c38be1..47790fbf92 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -3358,62 +3357,6 @@ static UniValue bumpfee(const JSONRPCRequest& request) return result; } -UniValue generate(const JSONRPCRequest& request) -{ - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( - RPCHelpMan{"generate", - "\nMine up to nblocks blocks immediately (before the RPC call returns) to an address in the wallet.\n", - { - {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."}, - {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."}, - }, - RPCResult{ - "[ blockhashes ] (array) hashes of blocks generated\n" - }, - RPCExamples{ - "\nGenerate 11 blocks\n" - + HelpExampleCli("generate", "11") - }, - }.ToString()); - } - - if (!IsDeprecatedRPCEnabled("generate")) { - throw JSONRPCError(RPC_METHOD_DEPRECATED, "The wallet generate rpc method is deprecated and will be fully removed in v0.19. " - "To use generate in v0.18, restart bitcoind with -deprecatedrpc=generate.\n" - "Clients should transition to using the node rpc method generatetoaddress\n"); - } - - int num_generate = request.params[0].get_int(); - uint64_t max_tries = 1000000; - if (!request.params[1].isNull()) { - max_tries = request.params[1].get_int(); - } - - std::shared_ptr coinbase_script; - pwallet->GetScriptForMining(coinbase_script); - - // If the keypool is exhausted, no script is returned at all. Catch this. - if (!coinbase_script) { - throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); - } - - //throw an error if no script was provided - if (coinbase_script->reserveScript.empty()) { - throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available"); - } - - return generateBlocks(coinbase_script, num_generate, max_tries, true); -} - UniValue rescanblockchain(const JSONRPCRequest& request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); @@ -4156,7 +4099,6 @@ UniValue importmulti(const JSONRPCRequest& request); static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- - { "generating", "generate", &generate, {"nblocks","maxtries"} }, { "hidden", "resendwallettransactions", &resendwallettransactions, {} }, { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} }, { "wallet", "abandontransaction", &abandontransaction, {"txid"} }, diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index 588bfbe083..530f457ae7 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -4,29 +4,26 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test deprecation of RPC calls.""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_raises_rpc_error +# from test_framework.util import assert_raises_rpc_error class DeprecatedRpcTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [[], ["-deprecatedrpc=generate"]] - - def skip_test_if_missing_module(self): - # The generate RPC method requires the wallet to be compiled - self.skip_if_no_wallet() + self.extra_args = [[], []] def run_test(self): # This test should be used to verify correct behaviour of deprecated # RPC methods with and without the -deprecatedrpc flags. For example: # - # self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses") - # assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()]) - # self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) - - self.log.info("Test generate RPC") - assert_raises_rpc_error(-32, 'The wallet generate rpc method is deprecated', self.nodes[0].rpc.generate, 1) - self.nodes[1].generate(1) + # In set_test_params: + # self.extra_args = [[], ["-deprecatedrpc=generate"]] + # + # In run_test: + # self.log.info("Test generate RPC") + # assert_raises_rpc_error(-32, 'The wallet generate rpc method is deprecated', self.nodes[0].rpc.generate, 1) + # self.nodes[1].generate(1) + self.log.info("No tested deprecated RPC methods") if __name__ == '__main__': DeprecatedRpcTest().main() From f71fdda3bc2e7acd2a8b74e882364866b8b0f55b Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 26 Feb 2019 16:34:26 -0500 Subject: [PATCH 0076/4486] [addrman] Ensure collisions eventually get resolved After 40 minutes, time out a test-before-evict entry and just evict without testing. Otherwise, if we were unable to test an entry for some reason, we might break using feelers altogether. --- src/addrman.cpp | 7 +++++++ src/addrman.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/addrman.cpp b/src/addrman.cpp index 468618095c..45b686e1de 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -569,6 +569,13 @@ void CAddrMan::ResolveCollisions_() Good_(info_new, false, GetAdjustedTime()); erase_collision = true; } + } else if (GetAdjustedTime() - info_new.nLastSuccess > ADDRMAN_TEST_WINDOW) { + // If the collision hasn't resolved in some reasonable amount of time, + // just evict the old entry -- we must not be able to + // connect to it for some reason. + LogPrint(BCLog::ADDRMAN, "Unable to test; swapping %s for %s in tried table anyway\n", info_new.ToString(), info_old.ToString()); + Good_(info_new, false, GetAdjustedTime()); + erase_collision = true; } } else { // Collision is not actually a collision anymore Good_(info_new, false, GetAdjustedTime()); diff --git a/src/addrman.h b/src/addrman.h index 003bd059f8..e54184ce35 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -166,6 +166,9 @@ class CAddrInfo : public CAddress //! the maximum number of tried addr collisions to store #define ADDRMAN_SET_TRIED_COLLISION_SIZE 10 +//! the maximum time we'll spend trying to resolve a tried table collision, in seconds +static const int64_t ADDRMAN_TEST_WINDOW = 40*60; // 40 minutes + /** * Stochastical (IP) address manager */ From 4a5e52cb51c2981914edb9e048e2c25461cf68df Mon Sep 17 00:00:00 2001 From: Chun Kuan Lee Date: Fri, 1 Mar 2019 02:30:07 +0800 Subject: [PATCH 0077/4486] msvc: Use a single file to specify the include path --- build_msvc/bench_bitcoin/bench_bitcoin.vcxproj | 4 ---- build_msvc/bitcoin-cli/bitcoin-cli.vcxproj | 4 ---- build_msvc/bitcoin-tx/bitcoin-tx.vcxproj | 4 ---- build_msvc/bitcoin-wallet/bitcoin-wallet.vcxproj | 4 ---- build_msvc/bitcoind/bitcoind.vcxproj | 4 ---- build_msvc/common.vcxproj | 1 + build_msvc/libbitcoin_cli/libbitcoin_cli.vcxproj.in | 4 ---- build_msvc/libbitcoin_common/libbitcoin_common.vcxproj.in | 4 ---- build_msvc/libbitcoin_crypto/libbitcoin_crypto.vcxproj.in | 4 ---- build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in | 4 ---- build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in | 4 ---- build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in | 4 ---- .../libbitcoin_wallet_tool/libbitcoin_wallet_tool.vcxproj.in | 4 ---- build_msvc/libbitcoin_zmq/libbitcoin_zmq.vcxproj.in | 4 ---- build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj | 4 ---- build_msvc/test_bitcoin/test_bitcoin.vcxproj | 4 ---- build_msvc/testconsensus/testconsensus.vcxproj | 4 ---- 17 files changed, 1 insertion(+), 64 deletions(-) diff --git a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj index 771e8a56f4..368fe7ead5 100644 --- a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj +++ b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj @@ -146,7 +146,6 @@ true NOMINMAX;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src; MultiThreaded @@ -164,7 +163,6 @@ Disabled NOMINMAX;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src; MultiThreadedDebug @@ -180,7 +178,6 @@ Disabled NOMINMAX;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src; MultiThreadedDebug @@ -198,7 +195,6 @@ true NOMINMAX;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src; MultiThreaded diff --git a/build_msvc/bitcoin-cli/bitcoin-cli.vcxproj b/build_msvc/bitcoin-cli/bitcoin-cli.vcxproj index 6c82b1e7de..6b668054a3 100644 --- a/build_msvc/bitcoin-cli/bitcoin-cli.vcxproj +++ b/build_msvc/bitcoin-cli/bitcoin-cli.vcxproj @@ -113,7 +113,6 @@ true HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded @@ -131,7 +130,6 @@ Disabled HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -147,7 +145,6 @@ Disabled HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -165,7 +162,6 @@ true HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded diff --git a/build_msvc/bitcoin-tx/bitcoin-tx.vcxproj b/build_msvc/bitcoin-tx/bitcoin-tx.vcxproj index c52dfdb28c..1d0174e319 100644 --- a/build_msvc/bitcoin-tx/bitcoin-tx.vcxproj +++ b/build_msvc/bitcoin-tx/bitcoin-tx.vcxproj @@ -116,7 +116,6 @@ true HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded @@ -134,7 +133,6 @@ Disabled HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -150,7 +148,6 @@ Disabled HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -168,7 +165,6 @@ true HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded diff --git a/build_msvc/bitcoin-wallet/bitcoin-wallet.vcxproj b/build_msvc/bitcoin-wallet/bitcoin-wallet.vcxproj index a83529c782..fa86da7bae 100644 --- a/build_msvc/bitcoin-wallet/bitcoin-wallet.vcxproj +++ b/build_msvc/bitcoin-wallet/bitcoin-wallet.vcxproj @@ -134,7 +134,6 @@ true HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded @@ -152,7 +151,6 @@ Disabled HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -168,7 +166,6 @@ Disabled HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -186,7 +183,6 @@ true HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded diff --git a/build_msvc/bitcoind/bitcoind.vcxproj b/build_msvc/bitcoind/bitcoind.vcxproj index 9a42f141c9..bb212af52e 100644 --- a/build_msvc/bitcoind/bitcoind.vcxproj +++ b/build_msvc/bitcoind/bitcoind.vcxproj @@ -79,7 +79,6 @@ Disabled WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -96,7 +95,6 @@ Disabled WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -115,7 +113,6 @@ true WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded @@ -138,7 +135,6 @@ true WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded diff --git a/build_msvc/common.vcxproj b/build_msvc/common.vcxproj index 93004dda7c..889dc6c2ad 100644 --- a/build_msvc/common.vcxproj +++ b/build_msvc/common.vcxproj @@ -24,6 +24,7 @@ 4018;4244;4267;4715;4805; true _WIN32_WINNT=0x0601;%(PreprocessorDefinitions) + ..\..\src;..\..\src\univalue\include;..\..\src\secp256k1\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv;%(AdditionalIncludeDirectories) diff --git a/build_msvc/libbitcoin_cli/libbitcoin_cli.vcxproj.in b/build_msvc/libbitcoin_cli/libbitcoin_cli.vcxproj.in index 1b24acd8ce..5849e463a6 100644 --- a/build_msvc/libbitcoin_cli/libbitcoin_cli.vcxproj.in +++ b/build_msvc/libbitcoin_cli/libbitcoin_cli.vcxproj.in @@ -99,7 +99,6 @@ true _SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded @@ -116,7 +115,6 @@ Disabled _SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -131,7 +129,6 @@ Disabled _SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -148,7 +145,6 @@ true _SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded diff --git a/build_msvc/libbitcoin_common/libbitcoin_common.vcxproj.in b/build_msvc/libbitcoin_common/libbitcoin_common.vcxproj.in index 459e81eb0c..292e193f5d 100644 --- a/build_msvc/libbitcoin_common/libbitcoin_common.vcxproj.in +++ b/build_msvc/libbitcoin_common/libbitcoin_common.vcxproj.in @@ -91,7 +91,6 @@ Disabled WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\secp256k1\include; false MultiThreadedDebug @@ -109,7 +108,6 @@ Disabled WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\secp256k1\include; false MultiThreadedDebug @@ -129,7 +127,6 @@ true WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\secp256k1\include; false MultiThreaded @@ -151,7 +148,6 @@ true WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\secp256k1\include; false MultiThreaded diff --git a/build_msvc/libbitcoin_crypto/libbitcoin_crypto.vcxproj.in b/build_msvc/libbitcoin_crypto/libbitcoin_crypto.vcxproj.in index ad183d4904..e7002036ad 100644 --- a/build_msvc/libbitcoin_crypto/libbitcoin_crypto.vcxproj.in +++ b/build_msvc/libbitcoin_crypto/libbitcoin_crypto.vcxproj.in @@ -89,7 +89,6 @@ Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src MultiThreadedDebug @@ -104,7 +103,6 @@ Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src MultiThreadedDebug @@ -121,7 +119,6 @@ true WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src MultiThreaded @@ -140,7 +137,6 @@ true _CONSOLE;%(PreprocessorDefinitions) true - ..\..\src MultiThreaded diff --git a/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in b/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in index 913f3c35da..48a117bcfe 100644 --- a/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in +++ b/build_msvc/libbitcoin_server/libbitcoin_server.vcxproj.in @@ -91,7 +91,6 @@ Disabled WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreadedDebug @@ -106,7 +105,6 @@ Disabled WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreadedDebug false @@ -124,7 +122,6 @@ true WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreaded @@ -143,7 +140,6 @@ true WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv; MultiThreaded diff --git a/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in b/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in index 855c9353fc..dbd91cf4db 100644 --- a/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in +++ b/build_msvc/libbitcoin_util/libbitcoin_util.vcxproj.in @@ -92,7 +92,6 @@ Disabled HAVE_CONFIG_H;WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -112,7 +111,6 @@ Disabled HAVE_CONFIG_H;WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug @@ -134,7 +132,6 @@ true HAVE_CONFIG_H;WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded @@ -158,7 +155,6 @@ true HAVE_CONFIG_H;WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded diff --git a/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in b/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in index b19f1e2396..33f4054546 100644 --- a/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in +++ b/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in @@ -97,7 +97,6 @@ Disabled HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\wallet;..\..\src\univalue\include; MultiThreadedDebug /bigobj %(AdditionalOptions) @@ -113,7 +112,6 @@ Disabled HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\wallet;..\..\src\univalue\include; MultiThreadedDebug /bigobj %(AdditionalOptions) @@ -131,7 +129,6 @@ true HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\wallet;..\..\src\univalue\include; MultiThreaded /bigobj %(AdditionalOptions) @@ -151,7 +148,6 @@ true HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\wallet;..\..\src\univalue\include; MultiThreaded /bigobj %(AdditionalOptions) diff --git a/build_msvc/libbitcoin_wallet_tool/libbitcoin_wallet_tool.vcxproj.in b/build_msvc/libbitcoin_wallet_tool/libbitcoin_wallet_tool.vcxproj.in index 2e32c25762..187d955687 100644 --- a/build_msvc/libbitcoin_wallet_tool/libbitcoin_wallet_tool.vcxproj.in +++ b/build_msvc/libbitcoin_wallet_tool/libbitcoin_wallet_tool.vcxproj.in @@ -97,7 +97,6 @@ Disabled NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug false @@ -113,7 +112,6 @@ Disabled NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug false @@ -131,7 +129,6 @@ true NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded false @@ -151,7 +148,6 @@ true NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded false diff --git a/build_msvc/libbitcoin_zmq/libbitcoin_zmq.vcxproj.in b/build_msvc/libbitcoin_zmq/libbitcoin_zmq.vcxproj.in index 7aba987cd1..c877a280c0 100644 --- a/build_msvc/libbitcoin_zmq/libbitcoin_zmq.vcxproj.in +++ b/build_msvc/libbitcoin_zmq/libbitcoin_zmq.vcxproj.in @@ -97,7 +97,6 @@ Disabled NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug false @@ -113,7 +112,6 @@ Disabled NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreadedDebug false @@ -131,7 +129,6 @@ true NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded false @@ -151,7 +148,6 @@ true NOMINMAX;ZMQ_STATIC;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include; MultiThreaded false diff --git a/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj b/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj index 32ea070a05..a32aafbd74 100644 --- a/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj +++ b/build_msvc/libbitcoinconsensus/libbitcoinconsensus.vcxproj @@ -126,7 +126,6 @@ Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) false - ..\..\src;..\..\src\secp256k1\include; Sync false MultiThreadedDebug @@ -143,7 +142,6 @@ Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) false - ..\..\src;..\..\src\secp256k1\include; Sync false MultiThreadedDebug @@ -162,7 +160,6 @@ true WIN32;_CONSOLE;%(PreprocessorDefinitions) false - ..\..\src;..\..\src\secp256k1\include; Sync false MultiThreaded @@ -183,7 +180,6 @@ true WIN32;_CONSOLE;%(PreprocessorDefinitions) false - ..\..\src;..\..\src\secp256k1\include; Sync false MultiThreaded diff --git a/build_msvc/test_bitcoin/test_bitcoin.vcxproj b/build_msvc/test_bitcoin/test_bitcoin.vcxproj index 03db97c647..d05a03699f 100644 --- a/build_msvc/test_bitcoin/test_bitcoin.vcxproj +++ b/build_msvc/test_bitcoin/test_bitcoin.vcxproj @@ -135,7 +135,6 @@ Disabled _CRT_SECURE_NO_WARNINGS;NOMINMAX;WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\test; MultiThreadedDebug @@ -152,7 +151,6 @@ Disabled _CRT_SECURE_NO_WARNINGS;NOMINMAX;WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\test; MultiThreadedDebug @@ -170,7 +168,6 @@ true _CRT_SECURE_NO_WARNINGS;NOMINMAX;WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\test; MultiThreaded @@ -190,7 +187,6 @@ true _CRT_SECURE_NO_WARNINGS;NOMINMAX;WIN32;HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src;..\..\src\univalue\include;..\..\src\leveldb\include;..\..\src\test; MultiThreaded diff --git a/build_msvc/testconsensus/testconsensus.vcxproj b/build_msvc/testconsensus/testconsensus.vcxproj index db2f8a6216..a2f5659049 100644 --- a/build_msvc/testconsensus/testconsensus.vcxproj +++ b/build_msvc/testconsensus/testconsensus.vcxproj @@ -95,7 +95,6 @@ Disabled HAVE_CONFIG_H;WIN32;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src\; MultiThreadedDebug @@ -110,7 +109,6 @@ Disabled HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src\; MultiThreadedDebug @@ -129,7 +127,6 @@ true HAVE_CONFIG_H;_SCL_SECURE_NO_WARNINGS;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src\; MultiThreaded @@ -148,7 +145,6 @@ true HAVE_CONFIG_H;WIN32;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\src\; MultiThreaded From fab2daa026494cdacda530f1253eb43cf0f1576c Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 28 Feb 2019 15:45:26 -0500 Subject: [PATCH 0078/4486] test: Add missing LIBBITCOIN_ZMQ to test_test_bitcoin_LDADD --- src/Makefile.test.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 84bc326cfe..ff7719ee4b 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -169,7 +169,7 @@ test_test_bitcoin_LDADD += $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(RAPIDC test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ -test_test_bitcoin_LDADD += $(ZMQ_LIBS) +test_test_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif if ENABLE_FUZZ From fa02b222459d46219c23366218c5b4e9ba768aeb Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 28 Feb 2019 14:51:11 -0500 Subject: [PATCH 0079/4486] test: Remove useless test_bitcoin_main.cpp --- build_msvc/test_bitcoin/test_bitcoin.vcxproj | 2 +- src/Makefile.test.include | 2 +- src/test/main.cpp | 7 +++ src/test/test_bitcoin.cpp | 60 ++++++++++---------- src/test/test_bitcoin.h | 4 -- src/test/test_bitcoin_main.cpp | 30 ---------- 6 files changed, 39 insertions(+), 66 deletions(-) create mode 100644 src/test/main.cpp delete mode 100644 src/test/test_bitcoin_main.cpp diff --git a/build_msvc/test_bitcoin/test_bitcoin.vcxproj b/build_msvc/test_bitcoin/test_bitcoin.vcxproj index d05a03699f..a08e708f81 100644 --- a/build_msvc/test_bitcoin/test_bitcoin.vcxproj +++ b/build_msvc/test_bitcoin/test_bitcoin.vcxproj @@ -25,7 +25,7 @@ - + diff --git a/src/Makefile.test.include b/src/Makefile.test.include index ff7719ee4b..8593d361b5 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -51,7 +51,7 @@ RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) BITCOIN_TEST_SUITE = \ - test/test_bitcoin_main.cpp \ + test/main.cpp \ test/test_bitcoin.h \ test/test_bitcoin.cpp diff --git a/src/test/main.cpp b/src/test/main.cpp new file mode 100644 index 0000000000..ff3f36b561 --- /dev/null +++ b/src/test/main.cpp @@ -0,0 +1,7 @@ +// Copyright (c) 2011-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#define BOOST_TEST_MODULE Bitcoin Core Test Suite + +#include diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 0c3fb7c398..cdfd4db589 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -66,36 +66,36 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha { 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(); - - // We have to run a scheduler thread to prevent ActivateBestChain - // from blocking due to queue overrun. - threadGroup.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler)); - GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); - - mempool.setSanityCheck(1.0); - pblocktree.reset(new CBlockTreeDB(1 << 20, true)); - pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); - pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); - if (!LoadGenesisBlock(chainparams)) { - throw std::runtime_error("LoadGenesisBlock failed."); - } - { - CValidationState state; - if (!ActivateBestChain(state, chainparams)) { - throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state))); - } - } - nScriptCheckThreads = 3; - for (int i=0; i < nScriptCheckThreads-1; i++) - threadGroup.create_thread(&ThreadScriptCheck); - - g_banman = MakeUnique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); - g_connman = MakeUnique(0x1337, 0x1337); // Deterministic randomness for tests. + // 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(); + + // We have to run a scheduler thread to prevent ActivateBestChain + // from blocking due to queue overrun. + threadGroup.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler)); + GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); + + mempool.setSanityCheck(1.0); + pblocktree.reset(new CBlockTreeDB(1 << 20, true)); + pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); + pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); + if (!LoadGenesisBlock(chainparams)) { + throw std::runtime_error("LoadGenesisBlock failed."); + } + + CValidationState state; + if (!ActivateBestChain(state, chainparams)) { + throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state))); + } + + nScriptCheckThreads = 3; + for (int i = 0; i < nScriptCheckThreads - 1; i++) + threadGroup.create_thread(&ThreadScriptCheck); + + g_banman = MakeUnique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + g_connman = MakeUnique(0x1337, 0x1337); // Deterministic randomness for tests. } TestingSetup::~TestingSetup() diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 4a06845683..38c6d85a8d 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -71,10 +71,6 @@ struct BasicTestingSetup { /** Testing setup that configures a complete environment. * Included are data directory, coins database, script check threads setup. */ -class CConnman; -class CNode; - -class PeerLogicValidation; struct TestingSetup : public BasicTestingSetup { boost::thread_group threadGroup; CScheduler scheduler; diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp deleted file mode 100644 index 46b63b93b4..0000000000 --- a/src/test/test_bitcoin_main.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2011-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. - -#define BOOST_TEST_MODULE Bitcoin Test Suite - -#include -#include - -#include - -#include - -std::unique_ptr g_connman; -std::unique_ptr g_banman; - -[[noreturn]] void Shutdown(void* parg) -{ - std::exit(EXIT_SUCCESS); -} - -[[noreturn]] void StartShutdown() -{ - std::exit(EXIT_SUCCESS); -} - -bool ShutdownRequested() -{ - return false; -} From fa85468cd252f51ad5328272a1bc19b7517e204e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 28 Feb 2019 15:02:35 -0500 Subject: [PATCH 0080/4486] test: Move main_tests to validation_tests --- src/Makefile.test.include | 2 +- src/test/{main_tests.cpp => validation_tests.cpp} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/test/{main_tests.cpp => validation_tests.cpp} (95%) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 8593d361b5..635130bcae 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -90,7 +90,7 @@ BITCOIN_TESTS =\ test/key_tests.cpp \ test/limitedmap_tests.cpp \ test/dbwrapper_tests.cpp \ - test/main_tests.cpp \ + test/validation_tests.cpp \ test/mempool_tests.cpp \ test/merkle_tests.cpp \ test/merkleblock_tests.cpp \ diff --git a/src/test/main_tests.cpp b/src/test/validation_tests.cpp similarity index 95% rename from src/test/main_tests.cpp rename to src/test/validation_tests.cpp index 5b3f2bc578..8d06ecd3a9 100644 --- a/src/test/main_tests.cpp +++ b/src/test/validation_tests.cpp @@ -1,17 +1,17 @@ -// Copyright (c) 2014-2018 The Bitcoin Core developers +// Copyright (c) 2014-2019 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 -#include #include +#include #include #include #include -BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup) +BOOST_FIXTURE_TEST_SUITE(validation_tests, TestingSetup) static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) { From faa9b88199c382c04e3aaa2b63479f9066ce8f9c Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 28 Feb 2019 15:04:03 -0500 Subject: [PATCH 0081/4486] fuzz: Link BasicTestingSetup (shared with unit tests) --- src/Makefile.test.include | 291 +++++--------------------------------- src/test/fuzz/fuzz.h | 2 - 2 files changed, 39 insertions(+), 254 deletions(-) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 635130bcae..2034c3670d 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -56,9 +56,27 @@ BITCOIN_TEST_SUITE = \ test/test_bitcoin.cpp FUZZ_SUITE = \ + test/test_bitcoin.h \ + test/test_bitcoin.cpp \ test/fuzz/fuzz.cpp \ test/fuzz/fuzz.h +FUZZ_SUITE_LD_COMMON = \ + $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_CONSENSUS) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBUNIVALUE) \ + $(LIBLEVELDB) \ + $(LIBLEVELDB_SSE42) \ + $(BOOST_LIBS) \ + $(LIBMEMENV) \ + $(LIBSECP256K1) \ + $(EVENT_LIBS) \ + $(CRYPTO_LIBS) \ + $(EVENT_PTHREADS_LIBS) + # test_bitcoin binary # BITCOIN_TESTS =\ test/arith_uint256_tests.cpp \ @@ -177,358 +195,127 @@ test_fuzz_block_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_DESERIALIZE=1 test_fuzz_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_block_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_block_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTRANSACTION_DESERIALIZE=1 test_fuzz_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_transaction_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_transaction_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_blocklocator_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1 test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blocklocator_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_blocklocator_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_blocklocator_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_blocklocator_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_blockmerkleroot_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blockmerkleroot_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKMERKLEROOT=1 test_fuzz_blockmerkleroot_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blockmerkleroot_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_blockmerkleroot_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_blockmerkleroot_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_blockmerkleroot_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_addrman_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_addrman_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRMAN_DESERIALIZE=1 test_fuzz_addrman_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_addrman_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_addrman_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_addrman_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_addrman_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_blockheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blockheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKHEADER_DESERIALIZE=1 test_fuzz_blockheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blockheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_blockheader_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_blockheader_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_blockheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_banentry_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1 test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_banentry_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_banentry_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_banentry_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_txundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_txundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXUNDO_DESERIALIZE=1 test_fuzz_txundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_txundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_txundo_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_txundo_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_blockundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blockundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKUNDO_DESERIALIZE=1 test_fuzz_blockundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blockundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_blockundo_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_blockundo_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_blockundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_coins_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1 test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_coins_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_coins_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1 test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_netaddr_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_netaddr_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_netaddr_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_script_flags_SOURCES = $(FUZZ_SUITE) test/fuzz/script_flags.cpp test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_script_flags_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_script_flags_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_script_flags_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_script_flags_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_service_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_service_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSERVICE_DESERIALIZE=1 test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_service_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_service_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_service_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_messageheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1 test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_messageheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_messageheader_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_messageheader_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_messageheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_address_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_address_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRESS_DESERIALIZE=1 test_fuzz_address_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_address_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_address_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_address_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_inv_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_inv_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DINV_DESERIALIZE=1 test_fuzz_inv_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_inv_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_inv_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_inv_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_inv_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_bloomfilter_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_bloomfilter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOOMFILTER_DESERIALIZE=1 test_fuzz_bloomfilter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_bloomfilter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_bloomfilter_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_bloomfilter_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_diskblockindex_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_diskblockindex_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DDISKBLOCKINDEX_DESERIALIZE=1 test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_diskblockindex_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_diskblockindex_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_diskblockindex_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1 test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_txoutcompressor_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_txoutcompressor_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_txoutcompressor_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_txoutcompressor_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_blocktransactions_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blocktransactions_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONS_DESERIALIZE=1 test_fuzz_blocktransactions_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blocktransactions_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_blocktransactions_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_blocktransactions_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_blocktransactions_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_blocktransactionsrequest_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blocktransactionsrequest_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONSREQUEST_DESERIALIZE=1 test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_blocktransactionsrequest_deserialize_LDADD = \ - $(LIBUNIVALUE) \ - $(LIBBITCOIN_SERVER) \ - $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBBITCOIN_CRYPTO_SSE41) \ - $(LIBBITCOIN_CRYPTO_AVX2) \ - $(LIBBITCOIN_CRYPTO_SHANI) \ - $(LIBSECP256K1) -test_fuzz_blocktransactionsrequest_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) endif # ENABLE_FUZZ nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h index ad62a5faf0..8b03a7e46e 100644 --- a/src/test/fuzz/fuzz.h +++ b/src/test/fuzz/fuzz.h @@ -10,8 +10,6 @@ #include -const std::function G_TRANSLATION_FUN = nullptr; - void test_one_input(std::vector buffer); #endif // BITCOIN_TEST_FUZZ_FUZZ_H From 7aa6a8aefbb2013ef3dc87ecbdf5d947d4b413af Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Feb 2019 13:41:41 -0800 Subject: [PATCH 0082/4486] Add ParseRange function to parse args of the form int/[int,int] --- src/rpc/util.cpp | 14 ++++++++++++++ src/rpc/util.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 86695bc1a5..7fb139f93c 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -523,3 +523,17 @@ std::string RPCArg::ToString(const bool oneline) const } assert(false); } + +std::pair ParseRange(const UniValue& value) +{ + if (value.isNum()) { + return {0, value.get_int64()}; + } + if (value.isArray() && value.size() == 2 && value[0].isNum() && value[1].isNum()) { + int64_t low = value[0].get_int64(); + int64_t high = value[1].get_int64(); + if (low > high) throw JSONRPCError(RPC_INVALID_PARAMETER, "Range specified as [begin,end] must not have begin after end"); + return {low, high}; + } + throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified as end or as [begin,end]"); +} diff --git a/src/rpc/util.h b/src/rpc/util.h index 06800ad63c..f11998bafa 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -38,6 +38,9 @@ unsigned int ParseConfirmTarget(const UniValue& value); RPCErrorCode RPCErrorFromTransactionError(TransactionError terr); UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_string = ""); +//! Parse a JSON range specified as int64, or [int64, int64] +std::pair ParseRange(const UniValue& value); + struct RPCArg { enum class Type { OBJ, From 6b9f45e81bfe7472493b6df66133c929780ef2fb Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Feb 2019 13:45:47 -0800 Subject: [PATCH 0083/4486] Support ranges arguments in RPC help --- src/rpc/util.cpp | 8 ++++++++ src/rpc/util.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 7fb139f93c..40ac133186 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -200,6 +200,7 @@ struct Sections { case RPCArg::Type::STR: case RPCArg::Type::NUM: case RPCArg::Type::AMOUNT: + case RPCArg::Type::RANGE: case RPCArg::Type::BOOL: { if (outer_type == OuterType::NAMED_ARG) return; // Nothing more to do for non-recursive types on first recursion auto left = indent; @@ -405,6 +406,10 @@ std::string RPCArg::ToDescriptionString() const ret += "numeric or string"; break; } + case Type::RANGE: { + ret += "numeric or array"; + break; + } case Type::BOOL: { ret += "boolean"; break; @@ -464,6 +469,8 @@ std::string RPCArg::ToStringObj(const bool oneline) const return res + "\"hex\""; case Type::NUM: return res + "n"; + case Type::RANGE: + return res + "n or [n,n]"; case Type::AMOUNT: return res + "amount"; case Type::BOOL: @@ -494,6 +501,7 @@ std::string RPCArg::ToString(const bool oneline) const return "\"" + m_name + "\""; } case Type::NUM: + case Type::RANGE: case Type::AMOUNT: case Type::BOOL: { return m_name; diff --git a/src/rpc/util.h b/src/rpc/util.h index f11998bafa..f1bd2c89df 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -51,6 +51,7 @@ struct RPCArg { OBJ_USER_KEYS, //!< Special type where the user must set the keys e.g. to define multiple addresses; as opposed to e.g. an options object where the keys are predefined AMOUNT, //!< Special type representing a floating point amount (can be either NUM or STR) STR_HEX, //!< Special type that is a STR with only hex chars + RANGE, //!< Special type that is a NUM or [NUM,NUM] }; enum class Optional { From 45660116311dc4cbb73e2ddecb1d0cc407d7aeb7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Feb 2019 13:51:24 -0800 Subject: [PATCH 0084/4486] Add support for stop/[start,stop] ranges to scantxoutset --- src/rpc/blockchain.cpp | 15 +++++++++------ test/functional/rpc_scantxoutset.py | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c73a8d48cf..7e8e5e07d0 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2159,7 +2159,7 @@ UniValue scantxoutset(const JSONRPCRequest& request) {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with output descriptor and metadata", { {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"}, - {"range", RPCArg::Type::NUM, /* default */ "1000", "Up to what child index HD chains should be explored"}, + {"range", RPCArg::Type::RANGE, /* default */ "1000", "The range of HD chain indexes to explore (either end or [begin,end])"}, }, }, }, @@ -2216,7 +2216,7 @@ UniValue scantxoutset(const JSONRPCRequest& request) // loop through the scan objects for (const UniValue& scanobject : request.params[1].get_array().getValues()) { std::string desc_str; - int range = 1000; + std::pair range = {0, 1000}; if (scanobject.isStr()) { desc_str = scanobject.get_str(); } else if (scanobject.isObject()) { @@ -2225,8 +2225,8 @@ UniValue scantxoutset(const JSONRPCRequest& request) desc_str = desc_uni.get_str(); UniValue range_uni = find_value(scanobject, "range"); if (!range_uni.isNull()) { - range = range_uni.get_int(); - if (range < 0 || range > 1000000) throw JSONRPCError(RPC_INVALID_PARAMETER, "range out of range"); + range = ParseRange(range_uni); + if (range.first < 0 || (range.second >> 31) != 0 || range.second >= range.first + 1000000) throw JSONRPCError(RPC_INVALID_PARAMETER, "range out of range"); } } else { throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan object needs to be either a string or an object"); @@ -2237,8 +2237,11 @@ UniValue scantxoutset(const JSONRPCRequest& request) if (!desc) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor '%s'", desc_str)); } - if (!desc->IsRange()) range = 0; - for (int i = 0; i <= range; ++i) { + if (!desc->IsRange()) { + range.first = 0; + range.second = 0; + } + for (int i = range.first; i <= range.second; ++i) { std::vector scripts; if (!desc->Expand(i, provider, scripts, provider)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys: '%s'", desc_str)); diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py index 29074c6af3..18258f5df3 100755 --- a/test/functional/rpc_scantxoutset.py +++ b/test/functional/rpc_scantxoutset.py @@ -95,6 +95,7 @@ def run_test(self): assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672")) assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1499}])['total_amount'], Decimal("12.288")) assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672")) + assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": [1500,1500]}])['total_amount'], Decimal("16.384")) # Test the reported descriptors for a few matches assert_equal(descriptors(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", "range": 1499}])), ["pkh([0c5f9a1e/0'/0'/0]026dbd8b2315f296d36e6b6920b1579ca75569464875c7ebe869b536a7d9503c8c)#dzxw429x", "pkh([0c5f9a1e/0'/0'/1]033e6f25d76c00bedb3a8993c7d5739ee806397f0529b1b31dda31ef890f19a60c)#43rvceed"]) From 1675b7ce5559d4796c81cb18a522d242be34d996 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Feb 2019 13:59:35 -0800 Subject: [PATCH 0085/4486] Use stop/[start,stop] notation in importmulti desc range --- src/wallet/rpcdump.cpp | 18 +++++------------- test/functional/wallet_importmulti.py | 4 ++-- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index f38202a2b8..5b0592e06d 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1132,13 +1132,10 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map> 31) != 0 || range_end - range_start >= 1000000) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid descriptor range specified"); } } @@ -1373,12 +1370,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) {"key", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""}, } }, - {"range", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the start and end of the range to import", - { - {"start", RPCArg::Type::NUM, /* default */ "0", "Start of the range to import"}, - {"end", RPCArg::Type::NUM, RPCArg::Optional::NO, "End of the range to import (inclusive)"}, - } - }, + {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in the form [begin,end]) to import"}, {"internal", RPCArg::Type::BOOL, /* default */ "false", "Stating whether matching outputs should be treated as not incoming payments (also known as change)"}, {"watchonly", RPCArg::Type::BOOL, /* default */ "false", "Stating whether matching outputs should be considered watchonly."}, {"label", RPCArg::Type::STR, /* default */ "''", "Label to assign to the address, only allowed with internal=false"}, diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index 8e25aa7337..c6d0425f22 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -584,7 +584,7 @@ def run_test(self): self.log.info("Should import the ranged descriptor with specified range as solvable") self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", - "range": {"end": 1}}, + "range": 1}, success=True, warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) for address in addresses: @@ -807,7 +807,7 @@ def run_test(self): 'desc': descsum_create('wpkh([80002067/0h/0h]' + xpub + '/*)'), 'keypool': True, 'timestamp': 'now', - 'range' : {'start': 0, 'end': 4} + 'range' : [0, 4], }] ) for i in range(0, 5): From aeb7fbfd69d08639eb340d679c0451b2dbba5887 Mon Sep 17 00:00:00 2001 From: Chun Kuan Lee Date: Fri, 1 Mar 2019 02:44:01 +0800 Subject: [PATCH 0086/4486] appveyor: Don't build debug libraries instead of "build and delete" --- .appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index cb6a920060..ac39fe235b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -11,15 +11,15 @@ environment: PATH: 'C:\Python37-x64;C:\Python37-x64\Scripts;%PATH%' PYTHONUTF8: 1 cache: -- C:\tools\vcpkg\installed -> appveyor.yml -- C:\Users\appveyor\clcache -> appveyor.yml, build_msvc\**, **\Makefile.am, **\*.vcxproj.in +- C:\tools\vcpkg\installed -> .appveyor.yml +- C:\Users\appveyor\clcache -> .appveyor.yml, build_msvc\**, **\Makefile.am, **\*.vcxproj.in install: - cmd: pip install --quiet git+https://github.com/frerich/clcache.git@v4.2.0 # Disable zmq test for now since python zmq library on Windows would cause Access violation sometimes. # - cmd: pip install zmq +- cmd: echo set(VCPKG_BUILD_TYPE release) >> C:\tools\vcpkg\triplets\%PLATFORM%-windows-static.cmake - cmd: vcpkg remove --outdated --recurse - cmd: vcpkg install --triplet %PLATFORM%-windows-static %PACKAGES% > NUL -- cmd: del /s /q C:\Tools\vcpkg\installed\%PLATFORM%-windows-static\debug # Remove unused debug library before_build: - ps: clcache -M 536870912 - cmd: python build_msvc\msvc-autogen.py From fa852f0e8d35ec520e34ef4206573da025986862 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 28 Feb 2019 18:42:57 -0500 Subject: [PATCH 0087/4486] test: Bump timeout on tests that timeout on windows --- test/functional/feature_assumevalid.py | 2 +- test/functional/feature_cltv.py | 1 + test/functional/feature_dersig.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py index 12a4ce9aff..0eb3dd440b 100755 --- a/test/functional/feature_assumevalid.py +++ b/test/functional/feature_assumevalid.py @@ -180,7 +180,7 @@ def run_test(self): for i in range(2202): p2p1.send_message(msg_block(self.blocks[i])) # Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync. - p2p1.sync_with_ping(150) + p2p1.sync_with_ping(200) assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202) # Send blocks to node2. Block 102 will be rejected. diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index 302a5ec1cb..96c5e49b0e 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -60,6 +60,7 @@ def set_test_params(self): self.num_nodes = 1 self.extra_args = [['-whitelist=127.0.0.1', '-par=1']] # Use only one script thread to get the exact reject reason for testing self.setup_clean_chain = True + self.rpc_timeout = 120 def skip_test_if_missing_module(self): self.skip_if_no_wallet() diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 9cbc1b39bd..8ff9498ef3 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -47,6 +47,7 @@ def set_test_params(self): self.num_nodes = 1 self.extra_args = [['-whitelist=127.0.0.1', '-par=1', '-enablebip61']] # Use only one script thread to get the exact reject reason for testing self.setup_clean_chain = True + self.rpc_timeout = 120 def skip_test_if_missing_module(self): self.skip_if_no_wallet() From ca253f6ebf2c9a12f5cb2b4c9f575178d058a612 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Feb 2019 14:11:38 -0800 Subject: [PATCH 0088/4486] Make deriveaddresses use stop/[start,stop] notation for ranges --- src/rpc/misc.cpp | 32 +++++++++++++------------- test/functional/rpc_deriveaddresses.py | 13 +++++++---- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 999a307e2b..765fd772fe 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -185,7 +185,7 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request) UniValue deriveaddresses(const JSONRPCRequest& request) { - if (request.fHelp || request.params.empty() || request.params.size() > 3) { + if (request.fHelp || request.params.empty() || request.params.size() > 2) { throw std::runtime_error( RPCHelpMan{"deriveaddresses", {"\nDerives one or more addresses corresponding to an output descriptor.\n" @@ -199,37 +199,37 @@ UniValue deriveaddresses(const JSONRPCRequest& request) "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n"}, { {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."}, - {"begin", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the beginning of the range to import."}, - {"end", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end of the range to import."} + {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."}, }, RPCResult{ "[ address ] (array) the derived addresses\n" }, RPCExamples{ "First three native segwit receive addresses\n" + - HelpExampleCli("deriveaddresses", "\"wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#trd0mf0l\" 0 2") + HelpExampleCli("deriveaddresses", "\"wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#trd0mf0l\" \"[0,2]\"") }}.ToString() ); } - RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VNUM, UniValue::VNUM}); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later const std::string desc_str = request.params[0].get_str(); - int range_begin = 0; - int range_end = 0; + int64_t range_begin = 0; + int64_t range_end = 0; - if (request.params.size() >= 2) { - if (request.params.size() == 2) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing range end parameter"); - } - range_begin = request.params[1].get_int(); - range_end = request.params[2].get_int(); - if (range_begin < 0) { + if (request.params.size() >= 2 && !request.params[1].isNull()) { + auto range = ParseRange(request.params[1]); + if (range.first < 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should be greater or equal than 0"); } - if (range_begin > range_end) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Range end should be equal to or greater than begin"); + if ((range.second >> 31) != 0) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "End of range is too high"); + } + if (range.second >= range.first + 1000000) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Range is too large"); } + range_begin = range.first; + range_end = range.second; } FlatSigningProvider provider; diff --git a/test/functional/rpc_deriveaddresses.py b/test/functional/rpc_deriveaddresses.py index c8b58cfc74..185dffd51c 100755 --- a/test/functional/rpc_deriveaddresses.py +++ b/test/functional/rpc_deriveaddresses.py @@ -27,17 +27,20 @@ def run_test(self): assert_equal(self.nodes[0].deriveaddresses(descriptor_pubkey), [address]) ranged_descriptor = "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)#kft60nuy" - assert_equal(self.nodes[0].deriveaddresses(ranged_descriptor, 0, 2), [address, "bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy", "bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"]) + assert_equal(self.nodes[0].deriveaddresses(ranged_descriptor, [1, 2]), ["bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy", "bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"]) + assert_equal(self.nodes[0].deriveaddresses(ranged_descriptor, 2), [address, "bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy", "bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"]) - assert_raises_rpc_error(-8, "Range should not be specified for an un-ranged descriptor", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"), 0, 2) + assert_raises_rpc_error(-8, "Range should not be specified for an un-ranged descriptor", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"), [0, 2]) assert_raises_rpc_error(-8, "Range must be specified for a ranged descriptor", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)")) - assert_raises_rpc_error(-8, "Missing range end parameter", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), 0) + assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), 10000000000) - assert_raises_rpc_error(-8, "Range end should be equal to or greater than begin", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), 2, 0) + assert_raises_rpc_error(-8, "Range is too large", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), [1000000000, 2000000000]) - assert_raises_rpc_error(-8, "Range should be greater or equal than 0", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), -1, 0) + assert_raises_rpc_error(-8, "Range specified as [begin,end] must not have begin after end", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), [2, 0]) + + assert_raises_rpc_error(-8, "Range should be greater or equal than 0", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), [-1, 0]) combo_descriptor = descsum_create("combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)") assert_equal(self.nodes[0].deriveaddresses(combo_descriptor), ["mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", "mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", address, "2NDvEwGfpEqJWfybzpKPHF2XH3jwoQV3D7x"]) From 8f5d9431a36740aa12abc0acea64df48fe32d2a6 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Wed, 27 Feb 2019 15:37:45 +0100 Subject: [PATCH 0089/4486] Add regtests for HTTP status codes. This adds explicit tests for the returned HTTP status codes to interface_rpc.py (for error cases) and the HTTP JSON-RPC client in general for success. PR 15381 brought up discussion about the HTTP status codes in general, and the general opinion was that the current choice may not be ideal but should not be changed to preserve compatibility with existing JSON-RPC clients. Thus it makes sense to actually test the current status to ensure this desired compatibility is not broken accidentally. --- test/functional/interface_rpc.py | 19 ++++++++++++++- test/functional/test_framework/authproxy.py | 26 ++++++++++++++------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/test/functional/interface_rpc.py b/test/functional/interface_rpc.py index b6955d4492..49ae0fb1a9 100755 --- a/test/functional/interface_rpc.py +++ b/test/functional/interface_rpc.py @@ -1,12 +1,22 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Tests some generic aspects of the RPC interface.""" +from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_greater_than_or_equal +def expect_http_status(expected_http_status, expected_rpc_code, + fcn, *args): + try: + fcn(*args) + raise AssertionError("Expected RPC error %d, got none" % expected_rpc_code) + except JSONRPCException as exc: + assert_equal(exc.error["code"], expected_rpc_code) + assert_equal(exc.http_status, expected_http_status) + class RPCInterfaceTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -48,9 +58,16 @@ def test_batch_request(self): assert_equal(result_by_id[3]['error'], None) assert result_by_id[3]['result'] is not None + def test_http_status_codes(self): + self.log.info("Testing HTTP status codes for JSON-RPC requests...") + + expect_http_status(404, -32601, self.nodes[0].invalidmethod) + expect_http_status(500, -8, self.nodes[0].getblockhash, 42) + def run_test(self): self.test_getrpcinfo() self.test_batch_request() + self.test_http_status_codes() if __name__ == '__main__': diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py index 1140fe9b3e..d039f7d6fe 100644 --- a/test/functional/test_framework/authproxy.py +++ b/test/functional/test_framework/authproxy.py @@ -35,6 +35,7 @@ import base64 import decimal +from http import HTTPStatus import http.client import json import logging @@ -49,13 +50,14 @@ log = logging.getLogger("BitcoinRPC") class JSONRPCException(Exception): - def __init__(self, rpc_error): + def __init__(self, rpc_error, http_status=None): try: errmsg = '%(message)s (%(code)i)' % rpc_error except (KeyError, TypeError): errmsg = '' super().__init__(errmsg) self.error = rpc_error + self.http_status = http_status def EncodeDecimal(o): @@ -131,19 +133,26 @@ def get_request(self, *args, **argsn): def __call__(self, *args, **argsn): postdata = json.dumps(self.get_request(*args, **argsn), default=EncodeDecimal, ensure_ascii=self.ensure_ascii) - response = self._request('POST', self.__url.path, postdata.encode('utf-8')) + response, status = self._request('POST', self.__url.path, postdata.encode('utf-8')) if response['error'] is not None: - raise JSONRPCException(response['error']) + raise JSONRPCException(response['error'], status) elif 'result' not in response: raise JSONRPCException({ - 'code': -343, 'message': 'missing JSON-RPC result'}) + 'code': -343, 'message': 'missing JSON-RPC result'}, status) + elif status != HTTPStatus.OK: + raise JSONRPCException({ + 'code': -342, 'message': 'non-200 HTTP status code but no JSON-RPC error'}, status) else: return response['result'] def batch(self, rpc_call_list): postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal, ensure_ascii=self.ensure_ascii) log.debug("--> " + postdata) - return self._request('POST', self.__url.path, postdata.encode('utf-8')) + response, status = self._request('POST', self.__url.path, postdata.encode('utf-8')) + if status != HTTPStatus.OK: + raise JSONRPCException({ + 'code': -342, 'message': 'non-200 HTTP status code but no JSON-RPC error'}, status) + return response def _get_response(self): req_start_time = time.time() @@ -162,8 +171,9 @@ def _get_response(self): content_type = http_response.getheader('Content-Type') if content_type != 'application/json': - raise JSONRPCException({ - 'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)}) + raise JSONRPCException( + {'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)}, + http_response.status) responsedata = http_response.read().decode('utf8') response = json.loads(responsedata, parse_float=decimal.Decimal) @@ -172,7 +182,7 @@ def _get_response(self): log.debug("<-%s- [%.6f] %s" % (response["id"], elapsed, json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) else: log.debug("<-- [%.6f] %s" % (elapsed, responsedata)) - return response + return response, http_response.status def __truediv__(self, relative_uri): return AuthServiceProxy("{}/{}".format(self.__service_url, relative_uri), self._service_name, connection=self.__conn) From 07cae5287c4409e9e597b891899403220905881d Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Fri, 1 Mar 2019 13:14:08 +0100 Subject: [PATCH 0090/4486] [wallet] remove unused GetScriptForMining --- src/wallet/wallet.cpp | 11 ----------- src/wallet/wallet.h | 2 -- 2 files changed, 13 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 388422bec8..cee31d5ac2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3819,17 +3819,6 @@ void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id) } } -void CWallet::GetScriptForMining(std::shared_ptr &script) -{ - std::shared_ptr rKey = std::make_shared(this); - CPubKey pubkey; - if (!rKey->GetReservedKey(pubkey)) - return; - - script = rKey; - script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; -} - void CWallet::LockCoin(const COutPoint& output) { AssertLockHeld(cs_wallet); // setLockedCoins diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 2a5d6caaf8..5173f957c7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1065,8 +1065,6 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface const std::string& GetLabelName(const CScript& scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - void GetScriptForMining(std::shared_ptr &script); - unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool From 9586157c0f9c12d3cfa55926ccc6c022324fa60a Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Fri, 1 Mar 2019 13:45:16 +0100 Subject: [PATCH 0091/4486] [rpc] deriveaddresses: add range to CRPCConvertParam --- src/rpc/client.cpp | 3 +-- src/rpc/misc.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 1cdc9f87a7..82424ab521 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -68,8 +68,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendmany", 4, "subtractfeefrom" }, { "sendmany", 5 , "replaceable" }, { "sendmany", 6 , "conf_target" }, - { "deriveaddresses", 1, "begin" }, - { "deriveaddresses", 2, "end" }, + { "deriveaddresses", 1, "range" }, { "scantxoutset", 1, "scanobjects" }, { "addmultisigaddress", 0, "nrequired" }, { "addmultisigaddress", 1, "keys" }, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 765fd772fe..822a0beef9 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -603,7 +603,7 @@ static const CRPCCommand commands[] = { "control", "logging", &logging, {"include", "exclude"}}, { "util", "validateaddress", &validateaddress, {"address"} }, { "util", "createmultisig", &createmultisig, {"nrequired","keys","address_type"} }, - { "util", "deriveaddresses", &deriveaddresses, {"descriptor", "begin", "end"} }, + { "util", "deriveaddresses", &deriveaddresses, {"descriptor", "range"} }, { "util", "getdescriptorinfo", &getdescriptorinfo, {"descriptor"} }, { "util", "verifymessage", &verifymessage, {"address","signature","message"} }, { "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} }, From f13ad1cae04fc1c364b7704a7434a69f0147a2ad Mon Sep 17 00:00:00 2001 From: Adam Jonas Date: Fri, 1 Mar 2019 10:19:56 -0500 Subject: [PATCH 0092/4486] modify test for memory locked in case locking pages failed at some point --- test/functional/rpc_misc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/functional/rpc_misc.py b/test/functional/rpc_misc.py index ab216bc467..7bf8e68176 100755 --- a/test/functional/rpc_misc.py +++ b/test/functional/rpc_misc.py @@ -10,6 +10,7 @@ assert_raises_rpc_error, assert_equal, assert_greater_than, + assert_greater_than_or_equal, ) from test_framework.authproxy import JSONRPCException @@ -27,7 +28,8 @@ def run_test(self): assert_greater_than(memory['used'], 0) assert_greater_than(memory['free'], 0) assert_greater_than(memory['total'], 0) - assert_greater_than(memory['locked'], 0) + # assert_greater_than_or_equal() for locked in case locking pages failed at some point + assert_greater_than_or_equal(memory['locked'], 0) assert_greater_than(memory['chunks_used'], 0) assert_greater_than(memory['chunks_free'], 0) assert_equal(memory['used'] + memory['free'], memory['total']) From 20e6ea259b222b10f066f22695a5f56c52071f63 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 1 Mar 2019 16:15:50 -0500 Subject: [PATCH 0093/4486] [addrman] Improve collision logging and address nits --- src/addrman.cpp | 4 ++-- src/net.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index 45b686e1de..8a5f78d1c5 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -563,7 +563,7 @@ void CAddrMan::ResolveCollisions_() // Give address at least 60 seconds to successfully connect if (GetAdjustedTime() - info_old.nLastTry > 60) { - LogPrint(BCLog::ADDRMAN, "Swapping %s for %s in tried table\n", info_new.ToString(), info_old.ToString()); + LogPrint(BCLog::ADDRMAN, "Replacing %s with %s in tried table\n", info_old.ToString(), info_new.ToString()); // Replaces an existing address already in the tried table with the new address Good_(info_new, false, GetAdjustedTime()); @@ -573,7 +573,7 @@ void CAddrMan::ResolveCollisions_() // If the collision hasn't resolved in some reasonable amount of time, // just evict the old entry -- we must not be able to // connect to it for some reason. - LogPrint(BCLog::ADDRMAN, "Unable to test; swapping %s for %s in tried table anyway\n", info_new.ToString(), info_old.ToString()); + LogPrint(BCLog::ADDRMAN, "Unable to test; replacing %s with %s in tried table anyway\n", info_old.ToString(), info_new.ToString()); Good_(info_new, false, GetAdjustedTime()); erase_collision = true; } diff --git a/src/net.cpp b/src/net.cpp index 3f87dc6357..ccab4a1718 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1765,12 +1765,12 @@ void CConnman::ThreadOpenConnections(const std::vector connect) addr = addrman.Select(fFeeler); } - // Require outbound connections to be to distinct network groups + // Require outbound connections, other than feelers, to be to distinct network groups if (!fFeeler && setConnected.count(addr.GetGroup())) { break; } - // if we selected an invalid address, restart + // if we selected an invalid or local address, restart if (!addr.IsValid() || IsLocal(addr)) { break; } From 3eac2d57b1ff563bc9cfe123f6ded2764cc50da0 Mon Sep 17 00:00:00 2001 From: Alistair Mann Date: Tue, 12 Feb 2019 06:25:36 +0000 Subject: [PATCH 0094/4486] docs: add "sections" info to example bitcoin.conf Most bitcoin.conf options apply to all three networks, however some apply only to mainnet unless specified in a section. As stands, conf file has no indication that sections are now in use or are in some circumstances mandatory (eg, changing rpcport for testnet.) Proposed change notifies the reader early which options are affected, specifically adds those options affected but not already in the example, adds brief explanation as to what's going on and provides a skeleton template for the sections themselves. --- share/examples/bitcoin.conf | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/share/examples/bitcoin.conf b/share/examples/bitcoin.conf index 6062d49c40..b5475dc1c6 100644 --- a/share/examples/bitcoin.conf +++ b/share/examples/bitcoin.conf @@ -4,6 +4,10 @@ # Network-related settings: +# Note that if you use testnet or regtest, particularly with the options +# addnode, connect, port, bind, rpcport, rpcbind or wallet, you will also +# want to read "[Sections]" further down. + # Run on the test network instead of the real bitcoin network. #testnet=0 @@ -53,6 +57,9 @@ # Listening mode, enabled by default except when 'connect' is being used #listen=1 +# Port on which to listen for connections (default: 8333, testnet: 18333, regtest: 18444) +#port= + # Maximum number of inbound+outbound connections. #maxconnections= @@ -115,6 +122,10 @@ # Wallet options +# Specify where to find wallet, lockfile and logs. If not present, those files will be +# created as new. +#wallet= + # Create transactions that have enough fees so they are likely to begin confirmation within n blocks (default: 6). # This setting is over-ridden by the -paytxfee option. #txconfirmtarget=n @@ -142,3 +153,19 @@ # Minimize to the system tray #minimizetotray=1 + +# [Sections] +# Most options apply to mainnet, testnet and regtest. +# If you want to confine an option to just one network, you should add it in the +# relevant section below. +# EXCEPTIONS: The options addnode, connect, port, bind, rpcport, rpcbind and wallet +# only apply to mainnet unless they appear in the appropriate section below. + +# Options only for mainnet +[main] + +# Options only for testnet +[test] + +# Options only for regtest +[regtest] From 10c7642a57b2834251448ba08b1b0c25850c4a31 Mon Sep 17 00:00:00 2001 From: marcuswin <46599751+marcuswin@users.noreply.github.com> Date: Thu, 14 Feb 2019 13:48:53 +0300 Subject: [PATCH 0095/4486] docs: Update Transifex links --- README.md | 2 +- doc/developer-notes.md | 4 ++-- doc/release-notes.md | 2 +- doc/translation_process.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 23577d54f9..db79043665 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Translations ------------ Changes to translations as well as new translations can be submitted to -[Bitcoin Core's Transifex page](https://www.transifex.com/projects/p/bitcoin/). +[Bitcoin Core's Transifex page](https://www.transifex.com/bitcoin/bitcoin/). Translations are periodically pulled from Transifex and merged into the git repository. See the [translation process](doc/translation_process.md) for details on how this works. diff --git a/doc/developer-notes.md b/doc/developer-notes.md index f765346cd8..2662eea8fc 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -144,7 +144,7 @@ For example, to describe a function use: */ bool function(int arg1, const char *arg2) ``` -A complete list of `@xxx` commands can be found at http://www.stack.nl/~dimitri/doxygen/manual/commands.html. +A complete list of `@xxx` commands can be found at http://www.doxygen.nl/manual/commands.html. As Doxygen recognizes the comments by the delimiters (`/**` and `*/` in this case), you don't *need* to provide any commands for a comment to be valid; just a description text is fine. @@ -185,7 +185,7 @@ Not OK (used plenty in the current source, but not picked up): // ``` -A full list of comment syntaxes picked up by Doxygen can be found at https://www.stack.nl/~dimitri/doxygen/manual/docblocks.html, +A full list of comment syntaxes picked up by Doxygen can be found at http://www.doxygen.nl/manual/docblocks.html, but the above styles are favored. Documentation can be generated with `make docs` and cleaned up with `make clean-docs`. The resulting files are located in `doc/doxygen/html`; open `index.html` to view the homepage. diff --git a/doc/release-notes.md b/doc/release-notes.md index a6408cf1e6..03b3121ecb 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -380,4 +380,4 @@ Credits Thanks to everyone who directly contributed to this release: -As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). +As well as everyone that helped translating on [Transifex](https://www.transifex.com/bitcoin/bitcoin/). diff --git a/doc/translation_process.md b/doc/translation_process.md index 9692832842..b9a10b6527 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -8,7 +8,7 @@ Transifex is setup to monitor the GitHub repo for updates, and when code contain Multiple language support is critical in assisting Bitcoin’s global adoption, and growth. One of Bitcoin’s greatest strengths is cross-border money transfers, any help making that easier is greatly appreciated. -See the [Transifex Bitcoin project](https://www.transifex.com/projects/p/bitcoin/) to assist in translations. You should also join the translation mailing list for announcements - see details below. +See the [Transifex Bitcoin project](https://www.transifex.com/bitcoin/bitcoin/) to assist in translations. You should also join the translation mailing list for announcements - see details below. ### Writing code with translations We use automated scripts to help extract translations in both Qt, and non-Qt source files. It is rarely necessary to manually edit the files in `src/qt/locale/`. The translation source files must adhere to the following format: @@ -43,7 +43,7 @@ git commit ### Creating a Transifex account Visit the [Transifex Signup](https://www.transifex.com/signup/) page to create an account. Take note of your username and password, as they will be required to configure the command-line tool. -You can find the Bitcoin translation project at [https://www.transifex.com/projects/p/bitcoin/](https://www.transifex.com/projects/p/bitcoin/). +You can find the Bitcoin translation project at [https://www.transifex.com/bitcoin/bitcoin/](https://www.transifex.com/bitcoin/bitcoin/). ### Installing the Transifex client command-line tool The client is used to fetch updated translations. If you are having problems, or need more details, see [https://docs.transifex.com/client/installing-the-client](https://docs.transifex.com/client/installing-the-client) From c9985c84f9c1d493320283bffc5f1ea99e0d0014 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 2 Mar 2019 14:28:09 +0100 Subject: [PATCH 0096/4486] build: Bump version to 0.18.99 Now that 0.18 branch has been split off, master is 0.18.99 (pre-0.19). Also clean out release notes. Tree-SHA512: ed5ca8bed37027aa852ba16f3f1e7fcd4ebaf74fa77a2a265cb33a9c710511019c577fae7a3b1e33259e245274d5cd4601d4774948396d0cf299b38ba634346a --- configure.ac | 2 +- doc/release-notes.md | 304 +------------------------------------------ 2 files changed, 4 insertions(+), 302 deletions(-) diff --git a/configure.ac b/configure.ac index dec6d4fac3..984c595ead 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) -define(_CLIENT_VERSION_MINOR, 17) +define(_CLIENT_VERSION_MINOR, 18) define(_CLIENT_VERSION_REVISION, 99) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_RC, 0) diff --git a/doc/release-notes.md b/doc/release-notes.md index a6408cf1e6..51094ebcb8 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -66,313 +66,15 @@ platform. Notable changes =============== -Mining ------- - -- Calls to `getblocktemplate` will fail if the segwit rule is not specified. - Calling `getblocktemplate` without segwit specified is almost certainly - a misconfiguration since doing so results in lower rewards for the miner. - Failed calls will produce an error message describing how to enable the - segwit rule. - -Configuration option changes ----------------------------- - -- A warning is printed if an unrecognized section name is used in the - configuration file. Recognized sections are `[test]`, `[main]`, and - `[regtest]`. - -- Four new options are available for configuring the maximum number of - messages that ZMQ will queue in memory (the "high water mark") before - dropping additional messages. The default value is 1,000, the same as - was used for previous releases. See the [ZMQ - documentation](https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md#usage) - for details. - -- The `enablebip61` option (introduced in Bitcoin Core 0.17.0) is - used to toggle sending of BIP 61 reject messages. Reject messages have no use - case on the P2P network and are only logged for debugging by most network - nodes. The option will now by default be off for improved privacy and security - as well as reduced upload usage. The option can explicitly be turned on for - local-network debugging purposes. - -- The `rpcallowip` option can no longer be used to automatically listen - on all network interfaces. Instead, the `rpcbind` parameter must also - be used to specify the IP addresses to listen on. Listening for RPC - commands over a public network connection is insecure and should be - disabled, so a warning is now printed if a user selects such a - configuration. If you need to expose RPC in order to use a tool - like Docker, ensure you only bind RPC to your localhost, e.g. `docker - run [...] -p 127.0.0.1:8332:8332` (this is an extra `:8332` over the - normal Docker port specification). - -- The `rpcpassword` option now causes a startup error if the password - set in the configuration file contains a hash character (#), as it's - ambiguous whether the hash character is meant for the password or as a - comment. - -- The `whitelistforcerelay` option is used to relay transactions from - whitelisted peers even when not accepted to the mempool. This option now - defaults to being off, so that changes in policy and disconnect/ban behavior - will not cause a node that is whitelisting another to be dropped by peers. - Users can still explicitly enable this behavior with the command line option - (and may want to consider [contacting](https://bitcoincore.org/en/contact/) - the Bitcoin Core project to let us know about their - use-case, as this feature could be deprecated in the future). - -Documentation -------------- - -- A new short - [document](https://github.com/bitcoin/bitcoin/blob/master/doc/JSON-RPC-interface.md) - about the JSON-RPC interface describes cases where the results of an - RPC might contain inconsistencies between data sourced from different - subsystems, such as wallet state and mempool state. A note is added - to the [REST interface documentation](https://github.com/bitcoin/bitcoin/blob/master/doc/REST-interface.md) - indicating that the same rules apply. - -- Further information is added to the [JSON-RPC - documentation](https://github.com/bitcoin/bitcoin/blob/master/doc/JSON-RPC-interface.md) - about how to secure this interface. - -- A new [document](https://github.com/bitcoin/bitcoin/blob/master/doc/bitcoin-conf.md) - about the `bitcoin.conf` file describes how to use it to configure - Bitcoin Core. - -- A new document introduces Bitcoin Core's BIP174 - [Partially-Signed Bitcoin Transactions (PSBT)](https://github.com/bitcoin/bitcoin/blob/master/doc/psbt.md) - interface, which is used to allow multiple programs to collaboratively - work to create, sign, and broadcast new transactions. This is useful - for offline (cold storage) wallets, multisig wallets, coinjoin - implementations, and many other cases where two or more programs need - to interact to generate a complete transaction. - -- The [output script descriptor](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) - documentation has been updated with information about new features in - this still-developing language for describing the output scripts that - a wallet or other program wants to receive notifications for, such as - which addresses it wants to know received payments. The language is - currently used in the `scantxoutset` RPC and is expected to be adapted - to other RPCs and to the underlying wallet structure. - -Build system changes --------------------- - -- A new `--disable-bip70` option may be passed to `./configure` to - prevent Bitcoin-Qt from being built with support for the BIP70 payment - protocol or from linking libssl. As the payment protocol has exposed - Bitcoin Core to libssl vulnerabilities in the past, builders who don't - need BIP70 support are encouraged to use this option to reduce their - exposure to future vulnerabilities. - -Deprecated or removed RPCs --------------------------- - -- The `signrawtransaction` RPC is removed after being deprecated and - hidden behind a special configuration option in version 0.17.0. - -- The 'account' API is removed after being deprecated in v0.17. The - 'label' API was introduced in v0.17 as a replacement for accounts. - See the [release notes from v0.17](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.17.0.md#label-and-account-apis-for-wallet) - for a full description of the changes from the 'account' API to the - 'label' API. - -- The `addwitnessaddress` RPC is removed after being deprecated in - version 0.13.0. - -- The wallet's `generate` RPC method is deprecated and will be fully - removed in a subsequent major version. This RPC is only used for - testing, but its implementation reached across multiple subsystems - (wallet and mining), so it is being deprecated to simplify the - wallet-node interface. Projects that are using `generate` for testing - purposes should transition to using the `generatetoaddress` RPC, which - does not require or use the wallet component. Calling - `generatetoaddress` with an address returned by the `getnewaddress` - RPC gives the same functionality as the old `generate` RPC. To - continue using `generate` in this version, restart bitcoind with the - `-deprecatedrpc=generate` configuration option. - -New RPCs --------- - -- The `getnodeaddresses` RPC returns peer addresses known to this - node. It may be used to find nodes to connect to without using a DNS - seeder. - -- The `listwalletdir` RPC returns a list of wallets in the wallet - directory (either the default wallet directory or the directory - configured by the `-walletdir` parameter). - -- The `getrpcinfo` returns runtime details of the RPC server. At the - moment, it returns an array of the currently active commands and how - long they've been running. - -Updated RPCs ------------- - -Note: some low-level RPC changes mainly useful for testing are described -in the Low-level Changes section below. - -- The `getpeerinfo` RPC now returns an additional `minfeefilter` field - set to the peer's BIP133 fee filter. You can use this to detect that - you have peers that are willing to accept transactions below the - default minimum relay fee. - -- The mempool RPCs, such as `getrawmempool` with `verbose=true`, now - return an additional "bip125-replaceable" value indicating whether the - transaction (or its unconfirmed ancestors) opts-in to asking nodes and - miners to replace it with a higher-feerate transaction spending any of - the same inputs. - -- The `settxfee` RPC previously silently ignored attempts to set the fee - below the allowed minimums. It now prints a warning. The special - value of "0" may still be used to request the minimum value. - -- The `getaddressinfo` RPC now provides an `ischange` field indicating - whether the wallet used the address in a change output. - -- The `importmulti` RPC has been updated to support P2WSH, P2WPKH, - P2SH-P2WPKH, and P2SH-P2WSH. Requests for P2WSH and P2SH-P2WSH accept - an additional `witnessscript` parameter. - -- The `importmulti` RPC now returns an additional `warnings` field for - each request with an array of strings explaining when fields are being - ignored or are inconsistent, if there are any. - -- The `getaddressinfo` RPC now returns an additional `solvable` boolean - field when Bitcoin Core knows enough about the address's scriptPubKey, - optional redeemScript, and optional witnessScript in order for the - wallet to be able to generate an unsigned input spending funds sent to - that address. - -- The `getaddressinfo`, `listunspent`, and `scantxoutset` RPCs now - return an additional `desc` field that contains an output descriptor - containing all key paths and signing information for the address - (except for the private key). The `desc` field is only returned for - `getaddressinfo` and `listunspent` when the address is solvable. - -- The `importprivkey` RPC will preserve previously-set labels for - addresses or public keys corresponding to the private key being - imported. For example, if you imported a watch-only address with the - label "cold wallet" in earlier releases of Bitcoin Core, subsequently - importing the private key would default to resetting the address's - label to the default empty-string label (""). In this release, the - previous label of "cold wallet" will be retained. If you optionally - specify any label besides the default when calling `importprivkey`, - the new label will be applied to the address. - -- See the [Mining](#mining) section for changes to `getblocktemplate`. - -- The `getmininginfo` RPC now omits `currentblockweight` and `currentblocktx` - when a block was never assembled via RPC on this node. - -- The `getrawtransaction` RPC & REST endpoints no longer check the - unspent UTXO set for a transaction. The remaining behaviors are as - follows: 1. If a blockhash is provided, check the corresponding block. - 2. If no blockhash is provided, check the mempool. 3. If no blockhash - is provided but txindex is enabled, also check txindex. - -- The `unloadwallet` RPC is now synchronous, meaning it will not return - until the wallet is fully unloaded. - -REST changes +Example item ------------ -- A new `/rest/blockhashbyheight/` endpoint is added for fetching the - hash of the block in the current best blockchain based on its height - (how many blocks it is after the Genesis Block). - -Graphical User Interface (GUI) ------------------------------- - -- A new Window menu is added alongside the existing File, Settings, and - Help menus. Several items from the other menus that opened new - windows have been moved to this new Window menu. - -- In the Send tab, the checkbox for "pay only the required fee" - has been removed. Instead, the user can simply decrease the value in - the Custom Feerate field all the way down to the node's configured - minimum relay fee. - -- In the Overview tab, the watch-only balance will be the only - balance shown if the wallet was created using the `createwallet` RPC - and the `disable_private_keys` parameter was set to true. - -- The launch-on-startup option is no longer available on macOS if - compiled with macosx min version greater than 10.11 (use - CXXFLAGS="-mmacosx-version-min=10.11" - CFLAGS="-mmacosx-version-min=10.11" for setting the deployment - sdk version) - -Tools ----- - -- A new `bitcoin-wallet` tool is now distributed alongside Bitcoin - Core's other executables. Without needing to use any RPCs, this tool - can currently create a new wallet file or display some basic - information about an existing wallet, such as whether the wallet is - encrypted, whether it uses an HD seed, how many transactions it - contains, and how many address book entries it has. Low-level changes ================= -RPC ---- - -- The `submitblock` RPC previously returned the reason a rejected block - was invalid the first time it processed that block but returned a - generic "duplicate" rejection message on subsequent occasions it - processed the same block. It now always returns the fundamental - reason for rejecting an invalid block and only returns "duplicate" for - valid blocks it has already accepted. - -- A new `submitheader` RPC allows submitting block headers independently - from their block. This is likely only useful for testing. - -Configuration -------------- - -- The `-usehd` configuration option was removed in version 0.16. From - that version onwards, all new wallets created are hierarchical - deterministic wallets. This release makes specifying `-usehd` an - invalid configuration option. - -Network -------- - -- This release allows peers that your node automatically disconnected - for misbehavior (e.g. sending invalid data) to reconnect to your node - if you have unused incoming connection slots. If your slots fill up, - a misbehaving node will be disconnected to make room for nodes without - a history of problems (unless the misbehaving node helps your node in - some other way, such as by connecting to a part of the Internet from - which you don't have many other peers). Previously, Bitcoin Core - banned the IP addresses of misbehaving peers for a period of time - (default of 1 day); this was easily circumvented by attackers with - multiple IP addresses. If you manually ban a peer, such as by using - the `setban` RPC, all connections from that peer will still be - rejected. - -Security --------- - -- This release changes the Random Number Generator (RNG) used from - OpenSSL to Bitcoin Core's own implementation, although entropy - gathered by Bitcoin Core is fed out to OpenSSL and then read back in - when the program needs strong randomness. This moves Bitcoin Core a - little closer to no longer needing to depend on OpenSSL, a dependency - that has caused security issues in the past. - -Changes for particular platforms --------------------------------- - -- On macOS, Bitcoin Core now opts out of application CPU throttling - ("app nap") during initial blockchain download, when catching up from - over 100 blocks behind the current chain tip, or when reindexing chain - data. This helps prevent these operations from taking an excessively - long time because the operating system is attempting to conserve - power. +Example item +------------ Credits ======= From fa6bf21f5ef8b27e8525cabba9738f8e1f246bf5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 18 Feb 2019 10:35:48 -0500 Subject: [PATCH 0097/4486] scripted-diff: test: Use py3.5 bytes::hex() method -BEGIN VERIFY SCRIPT- sed -i -e "s/def bytes_to_hex_str/def b_2_x/g" $(git grep -l bytes_to_hex_str) export RE_B_0="[^()]*" # match no bracket export RE_B_1="${RE_B_0}\(${RE_B_0}\)${RE_B_0}" # match exactly one () export RE_B_2="${RE_B_0}\(${RE_B_1}\)${RE_B_0}" # match wrapped (()) export RE_M="(b2x|bytes_to_hex_str)\(((${RE_B_0}|${RE_B_1}|${RE_B_2})*)\)" sed -i --regexp-extended -e "s/${RE_M}/\2.hex()/g" $(git grep -l -E '(b2x|bytes_to_hex_str)') sed -i --regexp-extended -e "/ +bytes_to_hex_str( as b2x)?,/d" $(git grep -l bytes_to_hex_str) sed -i --regexp-extended -e "s/ +bytes_to_hex_str( as b2x)?,//g" $(git grep -l bytes_to_hex_str) sed -i --regexp-extended -e "s/, bytes_to_hex_str( as b2x)?//g" $(git grep -l bytes_to_hex_str) export RE_M="(binascii\.)?hexlify\(((${RE_B_0}|${RE_B_1}|${RE_B_2})*)\).decode\(${RE_B_0}\)" sed -i --regexp-extended -e "s/${RE_M}/\2.hex()/g" $(git grep -l hexlify -- ':(exclude)share') sed -i --regexp-extended -e "/from binascii import hexlify$/d" $(git grep -l hexlify -- ':(exclude)share') sed -i --regexp-extended -e "s/(from binascii import) .*hexlify/\1 unhexlify/g" $(git grep -l hexlify -- ':(exclude)share') sed -i -e 's/ignore-names "/ignore-names "b_2_x,/g' ./test/lint/lint-python-dead-code.sh -END VERIFY SCRIPT- --- contrib/linearize/linearize-data.py | 6 +-- test/functional/feature_bip68_sequence.py | 4 +- test/functional/feature_cltv.py | 3 +- test/functional/feature_dersig.py | 3 +- test/functional/feature_nulldummy.py | 18 ++++---- test/functional/feature_rbf.py | 4 +- test/functional/feature_segwit.py | 30 ++++++------- test/functional/interface_rest.py | 4 +- test/functional/interface_zmq.py | 13 +++--- test/functional/mempool_accept.py | 47 ++++++++++---------- test/functional/mining_basic.py | 47 ++++++++++---------- test/functional/p2p_segwit.py | 20 ++++----- test/functional/rpc_decodescript.py | 16 +++---- test/functional/rpc_rawtransaction.py | 8 ++-- test/functional/rpc_signrawtransaction.py | 4 +- test/functional/test_framework/address.py | 8 ++-- test/functional/test_framework/blocktools.py | 3 +- test/functional/test_framework/messages.py | 10 ++--- test/functional/test_framework/netutil.py | 4 +- test/functional/test_framework/script.py | 5 +-- test/functional/test_framework/util.py | 6 +-- test/functional/wallet_bumpfee.py | 4 +- test/functional/wallet_importmulti.py | 3 +- test/functional/wallet_listtransactions.py | 5 +-- test/functional/wallet_txn_clone.py | 3 +- test/lint/lint-python-dead-code.sh | 2 +- 26 files changed, 134 insertions(+), 146 deletions(-) diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 56c1fbfc92..468aec04b5 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -16,7 +16,7 @@ import datetime import time from collections import namedtuple -from binascii import hexlify, unhexlify +from binascii import unhexlify settings = {} @@ -61,7 +61,7 @@ def calc_hash_str(blk_hdr): hash = calc_hdr_hash(blk_hdr) hash = bufreverse(hash) hash = wordreverse(hash) - hash_str = hexlify(hash).decode('utf-8') + hash_str = hash.hex() return hash_str def get_blk_dt(blk_hdr): @@ -213,7 +213,7 @@ def run(self): inMagic = inhdr[:4] if (inMagic != self.settings['netmagic']): - print("Invalid magic: " + hexlify(inMagic).decode('utf-8')) + print("Invalid magic: " + inMagic.hex()) return inLenLE = inhdr[4:] su = struct.unpack(" 0: diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 15f4502994..9d7b4b2702 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -20,7 +20,6 @@ CTxOut, FromHex, ToHex, - bytes_to_hex_str, hash256, hex_str_to_bytes, ser_string, @@ -190,7 +189,7 @@ def witness_script(use_p2wsh, pubkey): witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG]) scripthash = sha256(witness_program) pkscript = CScript([OP_0, scripthash]) - return bytes_to_hex_str(pkscript) + return pkscript.hex() def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): """Return a transaction (in hex) that spends the given utxo to a segwit output. diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 4bd58519c5..3413a94f7e 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -28,7 +28,7 @@ import time from test_framework.siphash import siphash256 -from test_framework.util import hex_str_to_bytes, bytes_to_hex_str, assert_equal +from test_framework.util import hex_str_to_bytes, assert_equal MIN_VERSION_SUPPORTED = 60001 MY_VERSION = 70014 # past bip-31 for ping/pong @@ -181,7 +181,7 @@ def FromHex(obj, hex_string): # Convert a binary-serializable object to hex (eg for submission via RPC) def ToHex(obj): - return bytes_to_hex_str(obj.serialize()) + return obj.serialize().hex() # Objects that map to bitcoind objects, which can be serialized/deserialized @@ -319,7 +319,7 @@ def serialize(self): def __repr__(self): return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \ - % (repr(self.prevout), bytes_to_hex_str(self.scriptSig), + % (repr(self.prevout), self.scriptSig.hex(), self.nSequence) @@ -343,7 +343,7 @@ def serialize(self): def __repr__(self): return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \ % (self.nValue // COIN, self.nValue % COIN, - bytes_to_hex_str(self.scriptPubKey)) + self.scriptPubKey.hex()) class CScriptWitness: @@ -355,7 +355,7 @@ def __init__(self): def __repr__(self): return "CScriptWitness(%s)" % \ - (",".join([bytes_to_hex_str(x) for x in self.stack])) + (",".join([x.hex() for x in self.stack])) def is_null(self): if self.stack: diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py index 45c182f630..1a3efcd1ac 100644 --- a/test/functional/test_framework/netutil.py +++ b/test/functional/test_framework/netutil.py @@ -12,7 +12,7 @@ import struct import array import os -from binascii import unhexlify, hexlify +from binascii import unhexlify # STATE_ESTABLISHED = '01' # STATE_SYN_SENT = '02' @@ -139,7 +139,7 @@ def addr_to_hex(addr): addr = sub[0] + ([0] * nullbytes) + sub[1] else: raise ValueError('Could not parse address %s' % addr) - return hexlify(bytearray(addr)).decode('ascii') + return bytearray(addr).hex() def test_ipv6_local(): ''' diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 012c80a1be..f7df7d23f5 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -9,7 +9,6 @@ from .messages import CTransaction, CTxOut, sha256, hash256, uint256_from_str, ser_uint256, ser_string -from binascii import hexlify import hashlib import struct @@ -452,7 +451,7 @@ def join(self, iterable): # Python 3.4 compatibility def hex(self): - return hexlify(self).decode('ascii') + return self.hex() def __new__(cls, value=b''): if isinstance(value, bytes) or isinstance(value, bytearray): @@ -545,7 +544,7 @@ def __iter__(self): def __repr__(self): def _repr(o): if isinstance(o, bytes): - return "x('%s')" % hexlify(o).decode('ascii') + return "x('%s')" % o.hex() else: return repr(o) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index fef9982412..fb2ee8e90c 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -5,7 +5,7 @@ """Helpful routines for regression testing.""" from base64 import b64encode -from binascii import hexlify, unhexlify +from binascii import unhexlify from decimal import Decimal, ROUND_DOWN import hashlib import inspect @@ -182,8 +182,8 @@ def check_json_precision(): def count_bytes(hex_string): return len(bytearray.fromhex(hex_string)) -def bytes_to_hex_str(byte_str): - return hexlify(byte_str).decode('ascii') +def b_2_x(byte_str): + return byte_str.hex() def hash256(byte_str): sha256 = hashlib.sha256() diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 7d3d9b61e2..67af495023 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -19,7 +19,7 @@ from test_framework.blocktools import add_witness_commitment, create_block, create_coinbase, send_to_witness from test_framework.messages import BIP125_SEQUENCE_NUMBER, CTransaction from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_greater_than, assert_raises_rpc_error, bytes_to_hex_str, connect_nodes_bi, hex_str_to_bytes, sync_mempools +from test_framework.util import assert_equal, assert_greater_than, assert_raises_rpc_error, connect_nodes_bi, hex_str_to_bytes, sync_mempools WALLET_PASSPHRASE = "test" WALLET_PASSPHRASE_TIMEOUT = 3600 @@ -298,7 +298,7 @@ def submit_block_with_tx(node, tx): block.hashMerkleRoot = block.calc_merkle_root() add_witness_commitment(block) block.solve() - node.submitblock(bytes_to_hex_str(block.serialize(True))) + node.submitblock(block.serialize(True).hex()) return block diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index c6d0425f22..e6c01e99e9 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -25,7 +25,6 @@ assert_equal, assert_greater_than, assert_raises_rpc_error, - bytes_to_hex_str, ) from test_framework.wallet_util import ( get_key, @@ -127,7 +126,7 @@ def run_test(self): # Nonstandard scriptPubKey + !internal self.log.info("Should not import a nonstandard scriptPubKey without internal flag") - nonstandardScriptPubKey = key.p2pkh_script + bytes_to_hex_str(CScript([OP_NOP])) + nonstandardScriptPubKey = key.p2pkh_script + CScript([OP_NOP]).hex() key = get_key(self.nodes[0]) self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, "timestamp": "now"}, diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py index 17f044bf65..ce76d06d2b 100755 --- a/test/functional/wallet_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -11,7 +11,6 @@ from test_framework.util import ( assert_array_result, assert_equal, - bytes_to_hex_str, hex_str_to_bytes, sync_mempools, ) @@ -158,7 +157,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): tx3 = self.nodes[0].createrawtransaction(inputs, outputs) tx3_modified = tx_from_hex(tx3) tx3_modified.vin[0].nSequence = 0 - tx3 = bytes_to_hex_str(tx3_modified.serialize()) + tx3 = tx3_modified.serialize().hex() tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex'] txid_3 = self.nodes[0].sendrawtransaction(tx3_signed) @@ -184,7 +183,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): # Replace tx3, and check that tx4 becomes unknown tx3_b = tx3_modified tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee - tx3_b = bytes_to_hex_str(tx3_b.serialize()) + tx3_b = tx3_b.serialize().hex() tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex'] txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True) assert(is_opt_in(self.nodes[0], txid_3b)) diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index a0a35bf43d..2f927502ff 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -8,7 +8,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, - bytes_to_hex_str as b2x, connect_nodes, disconnect_nodes, sync_blocks, @@ -82,7 +81,7 @@ def run_test(self): # Use a different signature hash type to sign. This creates an equivalent but malleated clone. # Don't send the clone anywhere yet - tx1_clone = self.nodes[0].signrawtransactionwithwallet(b2x(clone_tx.serialize()), None, "ALL|ANYONECANPAY") + tx1_clone = self.nodes[0].signrawtransactionwithwallet(clone_tx.serialize().hex(), None, "ALL|ANYONECANPAY") assert_equal(tx1_clone["complete"], True) # Have node0 mine a block, if requested: diff --git a/test/lint/lint-python-dead-code.sh b/test/lint/lint-python-dead-code.sh index 863caa9d5c..2ec7574718 100755 --- a/test/lint/lint-python-dead-code.sh +++ b/test/lint/lint-python-dead-code.sh @@ -15,5 +15,5 @@ fi vulture \ --min-confidence 60 \ - --ignore-names "argtypes,connection_lost,connection_made,converter,data_received,daemon,errcheck,get_ecdh_key,get_privkey,is_compressed,is_fullyvalid,msg_generic,on_*,optionxform,restype,set_privkey,profile_with_perf" \ + --ignore-names "b_2_x,argtypes,connection_lost,connection_made,converter,data_received,daemon,errcheck,get_ecdh_key,get_privkey,is_compressed,is_fullyvalid,msg_generic,on_*,optionxform,restype,set_privkey,profile_with_perf" \ $(git ls-files -- "*.py" ":(exclude)contrib/" ":(exclude)test/functional/data/invalid_txs.py") From fab5a1e0f492f920270c661954802749dfac5fa1 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 20 Feb 2019 18:13:43 -0500 Subject: [PATCH 0098/4486] build: Require python 3.5 --- .python-version | 2 +- .travis.yml | 4 +- configure.ac | 4 +- contrib/devtools/README.md | 2 +- contrib/devtools/symbol-check.py | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 6 +- contrib/gitian-descriptors/gitian-win.yml | 2 +- contrib/linearize/README.md | 3 +- contrib/zmq/zmq_sub3.4.py | 90 --------------------- depends/README.md | 2 +- doc/dependencies.md | 2 +- test/functional/test_framework/mininode.py | 5 +- test/functional/test_framework/script.py | 4 - test/functional/test_framework/test_node.py | 5 +- test/functional/test_framework/util.py | 3 - test/lint/lint-python-dead-code.sh | 2 +- 17 files changed, 18 insertions(+), 122 deletions(-) delete mode 100644 contrib/zmq/zmq_sub3.4.py diff --git a/.python-version b/.python-version index 7bcbb3808b..5a958026da 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.4.9 +3.5 diff --git a/.travis.yml b/.travis.yml index 0ede31b4a6..fea6b6d7bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,7 @@ jobs: env: cache: false language: python - python: '3.4' # Oldest supported version according to doc/dependencies.md + python: '3.5' # Oldest supported version according to doc/dependencies.md install: - set -o errexit; source .travis/lint_04_install.sh before_script: @@ -158,7 +158,7 @@ jobs: name: 'macOS 10.10 [GOAL: deploy] [no functional tests]' env: >- HOST=x86_64-apple-darwin14 - PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git" + PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools-git" OSX_SDK=10.11 RUN_UNIT_TESTS=false RUN_FUNCTIONAL_TESTS=false diff --git a/configure.ac b/configure.ac index 984c595ead..a3ba8ce808 100644 --- a/configure.ac +++ b/configure.ac @@ -85,8 +85,8 @@ AC_PATH_TOOL(RANLIB, ranlib) AC_PATH_TOOL(STRIP, strip) AC_PATH_TOOL(GCOV, gcov) AC_PATH_PROG(LCOV, lcov) -dnl Python 3.4 is specified in .python-version and should be used if available, see doc/dependencies.md -AC_PATH_PROGS([PYTHON], [python3.4 python3.5 python3.6 python3.7 python3 python]) +dnl Python 3.5 is specified in .python-version and should be used if available, see doc/dependencies.md +AC_PATH_PROGS([PYTHON], [python3.5 python3.6 python3.7 python3.8 python3 python]) AC_PATH_PROG(GENHTML, genhtml) AC_PATH_PROG([GIT], [git]) AC_PATH_PROG(CCACHE,ccache) diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index 6ee65f40be..d66eff66be 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -167,7 +167,7 @@ still compatible with the minimum supported Linux distribution versions. Example usage after a gitian build: - find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py + find ../gitian-builder/build -type f -executable | xargs python3 contrib/devtools/symbol-check.py If only supported symbols are used the return value will be 0 and the output will be empty. diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index c6158c9422..7729dd7257 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -9,7 +9,7 @@ Example usage: - find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py + find ../gitian-builder/build -type f -executable | xargs python3 contrib/devtools/symbol-check.py ''' import subprocess import re diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index e97072c80a..1fc1ce98a9 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -30,7 +30,7 @@ packages: - "faketime" - "bsdmainutils" - "ca-certificates" -- "python" +- "python3" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 87d8007ccb..1d9c31f9e7 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -23,9 +23,9 @@ packages: - "libcap-dev" - "libz-dev" - "libbz2-dev" -- "python" -- "python-dev" -- "python-setuptools" +- "python3" +- "python3-dev" +- "python3-setuptools" - "fonts-tuffy" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 31b9c309c7..2f1fb14c10 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -20,7 +20,7 @@ packages: - "nsis" - "zip" - "ca-certificates" -- "python" +- "python3" - "rename" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md index 2985106982..25a1c7351a 100644 --- a/contrib/linearize/README.md +++ b/contrib/linearize/README.md @@ -1,6 +1,5 @@ # Linearize -Construct a linear, no-fork, best version of the Bitcoin blockchain. The scripts -run using Python 3 but are compatible with Python 2. +Construct a linear, no-fork, best version of the Bitcoin blockchain. ## Step 1: Download hash list diff --git a/contrib/zmq/zmq_sub3.4.py b/contrib/zmq/zmq_sub3.4.py deleted file mode 100644 index 66fdf7887f..0000000000 --- a/contrib/zmq/zmq_sub3.4.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -""" - ZMQ example using python3's asyncio - - Bitcoin should be started with the command line arguments: - bitcoind -testnet -daemon \ - -zmqpubrawtx=tcp://127.0.0.1:28332 \ - -zmqpubrawblock=tcp://127.0.0.1:28332 \ - -zmqpubhashtx=tcp://127.0.0.1:28332 \ - -zmqpubhashblock=tcp://127.0.0.1:28332 - - We use the asyncio library here. `self.handle()` installs itself as a - future at the end of the function. Since it never returns with the event - loop having an empty stack of futures, this creates an infinite loop. An - alternative is to wrap the contents of `handle` inside `while True`. - - The `@asyncio.coroutine` decorator and the `yield from` syntax found here - was introduced in python 3.4 and has been deprecated in favor of the `async` - and `await` keywords respectively. - - A blocking example using python 2.7 can be obtained from the git history: - https://github.com/bitcoin/bitcoin/blob/37a7fe9e440b83e2364d5498931253937abe9294/contrib/zmq/zmq_sub.py -""" - -import binascii -import asyncio -import zmq -import zmq.asyncio -import signal -import struct -import sys - -if (sys.version_info.major, sys.version_info.minor) < (3, 4): - print("This example only works with Python 3.4 and greater") - sys.exit(1) - -port = 28332 - -class ZMQHandler(): - def __init__(self): - self.loop = asyncio.get_event_loop() - self.zmqContext = zmq.asyncio.Context() - - self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) - self.zmqSubSocket.setsockopt(zmq.RCVHWM, 0) - self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashblock") - self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtx") - self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock") - self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx") - self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % port) - - @asyncio.coroutine - def handle(self) : - msg = yield from self.zmqSubSocket.recv_multipart() - topic = msg[0] - body = msg[1] - sequence = "Unknown" - if len(msg[-1]) == 4: - msgSequence = struct.unpack(' Date: Tue, 19 Feb 2019 17:43:44 -0500 Subject: [PATCH 0099/4486] scripted-diff: test: Remove brackets after assert -BEGIN VERIFY SCRIPT- sed -i --regexp-extended -e 's/assert ?\((.+)\)(( )*)?(#.*)?$/assert \1\3\3\4/g' $(git grep -l --extended-regexp 'assert ?\(' test) -END VERIFY SCRIPT- --- test/functional/feature_bip68_sequence.py | 24 +++---- test/functional/feature_block.py | 8 +-- test/functional/feature_csv_activation.py | 4 +- test/functional/feature_nulldummy.py | 2 +- test/functional/feature_proxy.py | 8 +-- test/functional/feature_pruning.py | 10 +-- test/functional/feature_rbf.py | 16 ++--- test/functional/feature_segwit.py | 60 ++++++++-------- .../functional/feature_versionbits_warning.py | 8 +-- test/functional/interface_bitcoin_cli.py | 2 +- test/functional/interface_http.py | 26 +++---- test/functional/mempool_limit.py | 4 +- test/functional/mempool_packages.py | 6 +- test/functional/mempool_resurrect.py | 6 +- .../mining_getblocktemplate_longpoll.py | 10 +-- .../mining_prioritisetransaction.py | 24 +++---- test/functional/p2p_compactblocks.py | 44 ++++++------ test/functional/p2p_feefilter.py | 8 +-- test/functional/p2p_leak.py | 6 +- test/functional/p2p_segwit.py | 70 +++++++++---------- test/functional/p2p_unrequested_blocks.py | 8 +-- test/functional/rpc_blockchain.py | 6 +- test/functional/rpc_fundrawtransaction.py | 30 ++++---- test/functional/rpc_named_arguments.py | 2 +- test/functional/rpc_preciousblock.py | 6 +- test/functional/rpc_psbt.py | 4 +- test/functional/rpc_signmessage.py | 8 +-- test/functional/rpc_uptime.py | 2 +- test/functional/test_framework/address.py | 8 +-- test/functional/test_framework/blocktools.py | 4 +- test/functional/test_framework/netutil.py | 4 +- test/functional/test_framework/socks5.py | 2 +- test/functional/test_framework/util.py | 6 +- test/functional/wallet_address_types.py | 56 +++++++-------- test/functional/wallet_createwallet.py | 4 +- test/functional/wallet_disable.py | 4 +- test/functional/wallet_dump.py | 4 +- test/functional/wallet_keypool.py | 8 +-- test/functional/wallet_keypool_topup.py | 6 +- test/functional/wallet_listtransactions.py | 12 ++-- test/lint/lint-format-strings.py | 16 ++--- 41 files changed, 273 insertions(+), 273 deletions(-) diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index a1e2259bed..206c8a88ad 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -63,7 +63,7 @@ def test_disable_flag(self): self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC utxos = self.nodes[0].listunspent(0, 0) - assert(len(utxos) > 0) + assert len(utxos) > 0 utxo = utxos[0] @@ -253,7 +253,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): self.nodes[0].generate(1) cur_time += 600 - assert(tx2.hash in self.nodes[0].getrawmempool()) + assert tx2.hash in self.nodes[0].getrawmempool() test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True) test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False) @@ -264,23 +264,23 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # Advance the time on the node so that we can test timelocks self.nodes[0].setmocktime(cur_time+600) self.nodes[0].generate(1) - assert(tx2.hash not in self.nodes[0].getrawmempool()) + assert tx2.hash not in self.nodes[0].getrawmempool() # Now that tx2 is not in the mempool, a sequence locked spend should # succeed tx3 = test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False) - assert(tx3.hash in self.nodes[0].getrawmempool()) + assert tx3.hash in self.nodes[0].getrawmempool() self.nodes[0].generate(1) - assert(tx3.hash not in self.nodes[0].getrawmempool()) + assert tx3.hash not in self.nodes[0].getrawmempool() # One more test, this time using height locks tx4 = test_nonzero_locks(tx3, self.nodes[0], self.relayfee, use_height_lock=True) - assert(tx4.hash in self.nodes[0].getrawmempool()) + assert tx4.hash in self.nodes[0].getrawmempool() # Now try combining confirmed and unconfirmed inputs tx5 = test_nonzero_locks(tx4, self.nodes[0], self.relayfee, use_height_lock=True) - assert(tx5.hash not in self.nodes[0].getrawmempool()) + assert tx5.hash not in self.nodes[0].getrawmempool() utxos = self.nodes[0].listunspent() tx5.vin.append(CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1)) @@ -299,8 +299,8 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # If we invalidate the tip, tx3 should get added to the mempool, causing # tx4 to be removed (fails sequence-lock). self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) - assert(tx4.hash not in self.nodes[0].getrawmempool()) - assert(tx3.hash in self.nodes[0].getrawmempool()) + assert tx4.hash not in self.nodes[0].getrawmempool() + assert tx3.hash in self.nodes[0].getrawmempool() # Now mine 2 empty blocks to reorg out the current tip (labeled tip-1 in # diagram above). @@ -319,8 +319,8 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): cur_time += 1 mempool = self.nodes[0].getrawmempool() - assert(tx3.hash not in mempool) - assert(tx2.hash in mempool) + assert tx3.hash not in mempool + assert tx2.hash in mempool # Reset the chain and get rid of the mocktimed-blocks self.nodes[0].setmocktime(0) @@ -332,7 +332,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # being run, then it's possible the test has activated the soft fork, and # this test should be moved to run earlier, or deleted. def test_bip68_not_consensus(self): - assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active') + assert get_bip9_status(self.nodes[0], 'csv')['status'] != 'active' txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2) tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid)) diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 5253ff7aaa..faf7f20257 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -773,7 +773,7 @@ def run_test(self): self.move_tip(57) b58 = self.next_block(58, spend=out[17]) tx = CTransaction() - assert(len(out[17].vout) < 42) + assert len(out[17].vout) < 42 tx.vin.append(CTxIn(COutPoint(out[17].sha256, 42), CScript([OP_TRUE]), 0xffffffff)) tx.vout.append(CTxOut(0, b"")) tx.calc_sha256() @@ -824,7 +824,7 @@ def run_test(self): tx.nLockTime = 0xffffffff # this locktime is non-final tx.vin.append(CTxIn(COutPoint(out[18].sha256, 0))) # don't set nSequence tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) - assert(tx.vin[0].nSequence < 0xffffffff) + assert tx.vin[0].nSequence < 0xffffffff tx.calc_sha256() b62 = self.update_block(62, [tx]) self.sync_blocks([b62], success=False, reject_reason='bad-txns-nonfinal') @@ -1143,8 +1143,8 @@ def run_test(self): # now check that tx78 and tx79 have been put back into the peer's mempool mempool = self.nodes[0].getrawmempool() assert_equal(len(mempool), 2) - assert(tx78.hash in mempool) - assert(tx79.hash in mempool) + assert tx78.hash in mempool + assert tx79.hash in mempool # Test invalid opcodes in dead execution paths. # diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py index df79c4312c..d98d2aa992 100755 --- a/test/functional/feature_csv_activation.py +++ b/test/functional/feature_csv_activation.py @@ -106,7 +106,7 @@ def send_generic_input_tx(node, coinbases, address): def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0): """Returns a list of bip68 transactions with different bits set.""" txs = [] - assert(len(bip68inputs) >= 16) + assert len(bip68inputs) >= 16 for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)): locktime = relative_locktime(sdf, srhb, stf, srlb) tx = create_transaction(node, bip68inputs[i], address, amount=Decimal("49.98")) @@ -121,7 +121,7 @@ def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0): def create_bip112txs(node, bip112inputs, varyOP_CSV, txversion, address, locktime_delta=0): """Returns a list of bip68 transactions with different bits set.""" txs = [] - assert(len(bip112inputs) >= 16) + assert len(bip112inputs) >= 16 for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)): locktime = relative_locktime(sdf, srhb, stf, srlb) tx = create_transaction(node, bip112inputs[i], address, amount=Decimal("49.98")) diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index 08a0911470..c564c7fe2b 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -27,7 +27,7 @@ def trueDummy(tx): newscript = [] for i in scriptSig: if (len(newscript) == 0): - assert(len(i) == 0) + assert len(i) == 0 newscript.append(b'\x51') else: newscript.append(i) diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index f042adb7aa..2ff773bf6e 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -95,7 +95,7 @@ def node_test(self, node, proxies, auth, test_onion=True): # Test: outgoing IPv4 connection through node node.addnode("15.61.23.23:1234", "onetry") cmd = proxies[0].queue.get() - assert(isinstance(cmd, Socks5Command)) + assert isinstance(cmd, Socks5Command) # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 assert_equal(cmd.atyp, AddressType.DOMAINNAME) assert_equal(cmd.addr, b"15.61.23.23") @@ -109,7 +109,7 @@ def node_test(self, node, proxies, auth, test_onion=True): # Test: outgoing IPv6 connection through node node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry") cmd = proxies[1].queue.get() - assert(isinstance(cmd, Socks5Command)) + assert isinstance(cmd, Socks5Command) # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 assert_equal(cmd.atyp, AddressType.DOMAINNAME) assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534") @@ -123,7 +123,7 @@ def node_test(self, node, proxies, auth, test_onion=True): # Test: outgoing onion connection through node node.addnode("bitcoinostk4e4re.onion:8333", "onetry") cmd = proxies[2].queue.get() - assert(isinstance(cmd, Socks5Command)) + assert isinstance(cmd, Socks5Command) assert_equal(cmd.atyp, AddressType.DOMAINNAME) assert_equal(cmd.addr, b"bitcoinostk4e4re.onion") assert_equal(cmd.port, 8333) @@ -135,7 +135,7 @@ def node_test(self, node, proxies, auth, test_onion=True): # Test: outgoing DNS name connection through node node.addnode("node.noumenon:8333", "onetry") cmd = proxies[3].queue.get() - assert(isinstance(cmd, Socks5Command)) + assert isinstance(cmd, Socks5Command) assert_equal(cmd.atyp, AddressType.DOMAINNAME) assert_equal(cmd.addr, b"node.noumenon") assert_equal(cmd.port, 8333) diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index 3e1ba88f0a..fe8e1cde2f 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -151,7 +151,7 @@ def reorg_test(self): self.nodes[1].invalidateblock(curhash) curhash = self.nodes[1].getblockhash(invalidheight - 1) - assert(self.nodes[1].getblockcount() == invalidheight - 1) + assert self.nodes[1].getblockcount() == invalidheight - 1 self.log.info("New best height: %d" % self.nodes[1].getblockcount()) # Reboot node1 to clear those giant tx's from mempool @@ -219,17 +219,17 @@ def reorg_back(self): blocks_to_mine = first_reorg_height + 1 - self.mainchainheight self.log.info("Rewind node 0 to prev main chain to mine longer chain to trigger redownload. Blocks needed: %d" % blocks_to_mine) self.nodes[0].invalidateblock(curchainhash) - assert(self.nodes[0].getblockcount() == self.mainchainheight) - assert(self.nodes[0].getbestblockhash() == self.mainchainhash2) + assert self.nodes[0].getblockcount() == self.mainchainheight + assert self.nodes[0].getbestblockhash() == self.mainchainhash2 goalbesthash = self.nodes[0].generate(blocks_to_mine)[-1] 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") # 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) + 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) + assert self.nodes[2].getblock(self.forkhash)["height"] == self.forkheight def manual_test(self, node_number, use_timestamp): # at this point, node has 995 blocks and has not yet run in prune mode diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index 274c4922dc..1c8fc438d1 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -56,7 +56,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): new_size = len(node.getrawmempool()) # Error out if we have something stuck in the mempool, as this # would likely be a bug. - assert(new_size < mempool_size) + assert new_size < mempool_size mempool_size = new_size return COutPoint(int(txid, 16), 0) @@ -163,8 +163,8 @@ def test_simple_doublespend(self): mempool = self.nodes[0].getrawmempool() - assert (tx1a_txid not in mempool) - assert (tx1b_txid in mempool) + assert tx1a_txid not in mempool + assert tx1b_txid in mempool assert_equal(tx1b_hex, self.nodes[0].getrawtransaction(tx1b_txid)) @@ -211,7 +211,7 @@ def test_doublespend_chain(self): mempool = self.nodes[0].getrawmempool() for doublespent_txid in chain_txids: - assert(doublespent_txid not in mempool) + assert doublespent_txid not in mempool def test_doublespend_tree(self): """Doublespend of a big tree of transactions""" @@ -236,7 +236,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota tx.vout = vout tx_hex = txToHex(tx) - assert(len(tx.serialize()) < 100000) + assert len(tx.serialize()) < 100000 txid = self.nodes[0].sendrawtransaction(tx_hex, True) yield tx _total_txs[0] += 1 @@ -274,7 +274,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota for tx in tree_txs: tx.rehash() - assert (tx.hash not in mempool) + assert tx.hash not in mempool # Try again, but with more total transactions than the "max txs # double-spent at once" anti-DoS limit. @@ -529,7 +529,7 @@ def test_prioritised_transactions(self): # Now tx1b should be able to replace tx1a tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) - assert(tx1b_txid in self.nodes[0].getrawmempool()) + assert tx1b_txid in self.nodes[0].getrawmempool() # 2. Check that absolute fee checks use modified fee. tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) @@ -556,7 +556,7 @@ def test_prioritised_transactions(self): # tx2b should now be accepted tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True) - assert(tx2b_txid in self.nodes[0].getrawmempool()) + assert tx2b_txid in self.nodes[0].getrawmempool() def test_rpc(self): us0 = self.nodes[0].listunspent()[0] diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index c8505f34ab..8157ef69fe 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -93,17 +93,17 @@ def run_test(self): self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork") txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - assert(tmpl['sizelimit'] == 1000000) - assert('weightlimit' not in tmpl) - assert(tmpl['sigoplimit'] == 20000) - assert(tmpl['transactions'][0]['hash'] == txid) - assert(tmpl['transactions'][0]['sigops'] == 2) + assert tmpl['sizelimit'] == 1000000 + assert 'weightlimit' not in tmpl + assert tmpl['sigoplimit'] == 20000 + assert tmpl['transactions'][0]['hash'] == txid + assert tmpl['transactions'][0]['sigops'] == 2 tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - assert(tmpl['sizelimit'] == 1000000) - assert('weightlimit' not in tmpl) - assert(tmpl['sigoplimit'] == 20000) - assert(tmpl['transactions'][0]['hash'] == txid) - assert(tmpl['transactions'][0]['sigops'] == 2) + assert tmpl['sizelimit'] == 1000000 + assert 'weightlimit' not in tmpl + assert tmpl['sigoplimit'] == 20000 + assert tmpl['transactions'][0]['hash'] == txid + assert tmpl['transactions'][0]['sigops'] == 2 self.nodes[0].generate(1) # block 162 balance_presetup = self.nodes[0].getbalance() @@ -172,16 +172,16 @@ def run_test(self): self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0])) self.log.info("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag") - assert(self.nodes[2].getblock(blockhash, False) != self.nodes[0].getblock(blockhash, False)) - assert(self.nodes[1].getblock(blockhash, False) == self.nodes[2].getblock(blockhash, False)) + assert self.nodes[2].getblock(blockhash, False) != self.nodes[0].getblock(blockhash, False) + assert self.nodes[1].getblock(blockhash, False) == self.nodes[2].getblock(blockhash, False) for tx_id in segwit_tx_list: tx = FromHex(CTransaction(), self.nodes[2].gettransaction(tx_id)["hex"]) - assert(self.nodes[2].getrawtransaction(tx_id, False, blockhash) != self.nodes[0].getrawtransaction(tx_id, False, blockhash)) - assert(self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].getrawtransaction(tx_id, False, blockhash)) - assert(self.nodes[0].getrawtransaction(tx_id, False, blockhash) != self.nodes[2].gettransaction(tx_id)["hex"]) - assert(self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].gettransaction(tx_id)["hex"]) - assert(self.nodes[0].getrawtransaction(tx_id, False, blockhash) == tx.serialize_without_witness().hex()) + assert self.nodes[2].getrawtransaction(tx_id, False, blockhash) != self.nodes[0].getrawtransaction(tx_id, False, blockhash) + assert self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].getrawtransaction(tx_id, False, blockhash) + assert self.nodes[0].getrawtransaction(tx_id, False, blockhash) != self.nodes[2].gettransaction(tx_id)["hex"] + assert self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].gettransaction(tx_id)["hex"] + assert self.nodes[0].getrawtransaction(tx_id, False, blockhash) == tx.serialize_without_witness().hex() self.log.info("Verify witness txs without witness data are invalid after the fork") self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch) (code 64)', wit_ids[NODE_2][WIT_V0][2], sign=False) @@ -198,11 +198,11 @@ def run_test(self): self.log.info("Verify sigops are counted in GBT with BIP141 rules after the fork") txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - assert(tmpl['sizelimit'] >= 3999577) # actual maximum size is lower due to minimum mandatory non-witness data - assert(tmpl['weightlimit'] == 4000000) - assert(tmpl['sigoplimit'] == 80000) - assert(tmpl['transactions'][0]['txid'] == txid) - assert(tmpl['transactions'][0]['sigops'] == 8) + assert tmpl['sizelimit'] >= 3999577 # actual maximum size is lower due to minimum mandatory non-witness data + assert tmpl['weightlimit'] == 4000000 + assert tmpl['sigoplimit'] == 80000 + assert tmpl['transactions'][0]['txid'] == txid + assert tmpl['transactions'][0]['sigops'] == 8 self.nodes[0].generate(1) # Mine a block to clear the gbt cache @@ -214,8 +214,8 @@ def run_test(self): txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996")) hex_tx = self.nodes[0].gettransaction(txid)['hex'] tx = FromHex(CTransaction(), hex_tx) - assert(tx.wit.is_null()) # This should not be a segwit input - assert(txid1 in self.nodes[0].getrawmempool()) + assert tx.wit.is_null() # This should not be a segwit input + assert txid1 in self.nodes[0].getrawmempool() # Now create tx2, which will spend from txid1. tx = CTransaction() @@ -224,7 +224,7 @@ def run_test(self): tx2_hex = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))['hex'] txid2 = self.nodes[0].sendrawtransaction(tx2_hex) tx = FromHex(CTransaction(), tx2_hex) - assert(not tx.wit.is_null()) + assert not tx.wit.is_null() # Now create tx3, which will spend from txid2 tx = CTransaction() @@ -232,15 +232,15 @@ def run_test(self): tx.vout.append(CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee tx.calc_sha256() txid3 = self.nodes[0].sendrawtransaction(ToHex(tx)) - assert(tx.wit.is_null()) - assert(txid3 in self.nodes[0].getrawmempool()) + assert tx.wit.is_null() + assert txid3 in self.nodes[0].getrawmempool() # Check that getblocktemplate includes all transactions. template = self.nodes[0].getblocktemplate({"rules": ["segwit"]}) template_txids = [t['txid'] for t in template['transactions']] - assert(txid1 in template_txids) - assert(txid2 in template_txids) - assert(txid3 in template_txids) + assert txid1 in template_txids + assert txid2 in template_txids + assert txid3 in template_txids # Check that wtxid is properly reported in mempool entry assert_equal(int(self.nodes[0].getmempoolentry(txid3)["wtxid"], 16), tx.calc_sha256(True)) diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index 1ced618d47..753287ac7a 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -74,8 +74,8 @@ def run_test(self): node.generatetoaddress(VB_PERIOD - VB_THRESHOLD + 1, node_deterministic_address) # Check that we're not getting any versionbit-related errors in get*info() - assert(not VB_PATTERN.match(node.getmininginfo()["warnings"])) - assert(not VB_PATTERN.match(node.getnetworkinfo()["warnings"])) + assert not VB_PATTERN.match(node.getmininginfo()["warnings"]) + assert not VB_PATTERN.match(node.getnetworkinfo()["warnings"]) # Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit self.send_blocks_with_version(node.p2p, VB_THRESHOLD, VB_UNKNOWN_VERSION) @@ -95,8 +95,8 @@ def run_test(self): # Generating one more block will be enough to generate an error. node.generatetoaddress(1, node_deterministic_address) # Check that get*info() shows the versionbits unknown rules warning - assert(WARN_UNKNOWN_RULES_ACTIVE in node.getmininginfo()["warnings"]) - assert(WARN_UNKNOWN_RULES_ACTIVE in node.getnetworkinfo()["warnings"]) + assert WARN_UNKNOWN_RULES_ACTIVE in node.getmininginfo()["warnings"] + assert WARN_UNKNOWN_RULES_ACTIVE in node.getnetworkinfo()["warnings"] # Check that the alert file shows the versionbits unknown rules warning wait_until(lambda: self.versionbits_in_alert_file(), timeout=60) diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index aed439339f..75583cb56c 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -16,7 +16,7 @@ def run_test(self): """Main test logic""" cli_response = self.nodes[0].cli("-version").send_cli() - assert("Bitcoin Core RPC client version" in cli_response) + assert "Bitcoin Core RPC client version" in cli_response self.log.info("Compare responses from getwalletinfo RPC and `bitcoin-cli getwalletinfo`") if self.is_wallet_compiled(): diff --git a/test/functional/interface_http.py b/test/functional/interface_http.py index 20889366e5..f18ccb4aca 100755 --- a/test/functional/interface_http.py +++ b/test/functional/interface_http.py @@ -30,14 +30,14 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert(b'"error":null' in out1) - assert(conn.sock is not None) #according to http/1.1 connection must still be open! + assert b'"error":null' in out1 + assert conn.sock is not None #according to http/1.1 connection must still be open! #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out1 = conn.getresponse().read() - assert(b'"error":null' in out1) #must also response with a correct json-rpc message - assert(conn.sock is not None) #according to http/1.1 connection must still be open! + assert b'"error":null' in out1 #must also response with a correct json-rpc message + assert conn.sock is not None #according to http/1.1 connection must still be open! conn.close() #same should be if we add keep-alive because this should be the std. behaviour @@ -47,14 +47,14 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert(b'"error":null' in out1) - assert(conn.sock is not None) #according to http/1.1 connection must still be open! + assert b'"error":null' in out1 + assert conn.sock is not None #according to http/1.1 connection must still be open! #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out1 = conn.getresponse().read() - assert(b'"error":null' in out1) #must also response with a correct json-rpc message - assert(conn.sock is not None) #according to http/1.1 connection must still be open! + assert b'"error":null' in out1 #must also response with a correct json-rpc message + assert conn.sock is not None #according to http/1.1 connection must still be open! conn.close() #now do the same with "Connection: close" @@ -64,8 +64,8 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert(b'"error":null' in out1) - assert(conn.sock is None) #now the connection must be closed after the response + assert b'"error":null' in out1 + assert conn.sock is None #now the connection must be closed after the response #node1 (2nd node) is running with disabled keep-alive option urlNode1 = urllib.parse.urlparse(self.nodes[1].url) @@ -76,7 +76,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert(b'"error":null' in out1) + assert b'"error":null' in out1 #node2 (third node) is running with standard keep-alive parameters which means keep-alive is on urlNode2 = urllib.parse.urlparse(self.nodes[2].url) @@ -87,8 +87,8 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert(b'"error":null' in out1) - assert(conn.sock is not None) #connection must be closed because bitcoind should use keep-alive by default + assert b'"error":null' in out1 + assert conn.sock is not None #connection must be closed because bitcoind should use keep-alive by default # Check excessive request size conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port) diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index c0918893cd..976f39c32b 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -47,9 +47,9 @@ def run_test(self): txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) self.log.info('The tx should be evicted by now') - assert(txid not in self.nodes[0].getrawmempool()) + assert txid not in self.nodes[0].getrawmempool() txdata = self.nodes[0].gettransaction(txid) - assert(txdata['confirmations'] == 0) #confirmation should still be 0 + assert txdata['confirmations'] == 0 #confirmation should still be 0 self.log.info('Check that mempoolminfee is larger than minrelytxfee') assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000')) diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index 9336547a6b..b98bb7ec28 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -33,7 +33,7 @@ def chain_transaction(self, node, parent_txid, vout, value, fee, num_outputs): signedtx = node.signrawtransactionwithwallet(rawtx) txid = node.sendrawtransaction(signedtx['hex']) fulltx = node.getrawtransaction(txid, 1) - assert(len(fulltx['vout']) == num_outputs) # make sure we didn't generate a change output + assert len(fulltx['vout']) == num_outputs # make sure we didn't generate a change output return (txid, send_value) def run_test(self): @@ -125,13 +125,13 @@ def run_test(self): assert_equal(len(v_ancestors), len(chain)-1) for x in v_ancestors.keys(): assert_equal(mempool[x], v_ancestors[x]) - assert(chain[-1] not in v_ancestors.keys()) + assert chain[-1] not in v_ancestors.keys() v_descendants = self.nodes[0].getmempooldescendants(chain[0], True) assert_equal(len(v_descendants), len(chain)-1) for x in v_descendants.keys(): assert_equal(mempool[x], v_descendants[x]) - assert(chain[0] not in v_descendants.keys()) + assert chain[0] not in v_descendants.keys() # Check that ancestor modified fees includes fee deltas from # prioritisetransaction diff --git a/test/functional/mempool_resurrect.py b/test/functional/mempool_resurrect.py index 845beb551e..b606fccec9 100755 --- a/test/functional/mempool_resurrect.py +++ b/test/functional/mempool_resurrect.py @@ -45,7 +45,7 @@ def run_test(self): assert_equal(set(self.nodes[0].getrawmempool()), set()) for txid in spends1_id+spends2_id: tx = self.nodes[0].gettransaction(txid) - assert(tx["confirmations"] > 0) + assert tx["confirmations"] > 0 # Use invalidateblock to re-org back for node in self.nodes: @@ -55,7 +55,7 @@ def run_test(self): assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id)) for txid in spends1_id+spends2_id: tx = self.nodes[0].gettransaction(txid) - assert(tx["confirmations"] == 0) + assert tx["confirmations"] == 0 # Generate another block, they should all get mined self.nodes[0].generate(1) @@ -63,7 +63,7 @@ def run_test(self): assert_equal(set(self.nodes[0].getrawmempool()), set()) for txid in spends1_id+spends2_id: tx = self.nodes[0].gettransaction(txid) - assert(tx["confirmations"] > 0) + assert tx["confirmations"] > 0 if __name__ == '__main__': diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py index 72cde8e811..0c4e29561d 100755 --- a/test/functional/mining_getblocktemplate_longpoll.py +++ b/test/functional/mining_getblocktemplate_longpoll.py @@ -38,27 +38,27 @@ def run_test(self): longpollid = template['longpollid'] # longpollid should not change between successive invocations if nothing else happens template2 = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - assert(template2['longpollid'] == longpollid) + assert template2['longpollid'] == longpollid # Test 1: test that the longpolling wait if we do nothing thr = LongpollThread(self.nodes[0]) thr.start() # check that thread still lives thr.join(5) # wait 5 seconds or until thread exits - assert(thr.is_alive()) + assert thr.is_alive() # Test 2: test that longpoll will terminate if another node generates a block self.nodes[1].generate(1) # generate a block on another node # check that thread will exit now that new transaction entered mempool thr.join(5) # wait 5 seconds or until thread exits - assert(not thr.is_alive()) + assert not thr.is_alive() # Test 3: test that longpoll will terminate if we generate a block ourselves thr = LongpollThread(self.nodes[0]) thr.start() self.nodes[0].generate(1) # generate a block on another node thr.join(5) # wait 5 seconds or until thread exits - assert(not thr.is_alive()) + assert not thr.is_alive() # Test 4: test that introducing a new transaction into the mempool will terminate the longpoll thr = LongpollThread(self.nodes[0]) @@ -69,7 +69,7 @@ def run_test(self): (txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"), min_relay_fee, Decimal("0.001"), 20) # after one minute, every 10 seconds the mempool is probed, so in 80 seconds it should have returned thr.join(60 + 20) - assert(not thr.is_alive()) + assert not thr.is_alive() if __name__ == '__main__': GetBlockTemplateLPTest().main() diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py index ca4b621a78..975d1e6a6b 100755 --- a/test/functional/mining_prioritisetransaction.py +++ b/test/functional/mining_prioritisetransaction.py @@ -63,9 +63,9 @@ def run_test(self): sizes = [0, 0, 0] for i in range(3): for j in txids[i]: - assert(j in mempool) + assert j in mempool sizes[i] += mempool[j]['size'] - assert(sizes[i] > MAX_BLOCK_BASE_SIZE) # Fail => raise utxo_count + assert sizes[i] > MAX_BLOCK_BASE_SIZE # Fail => raise utxo_count # add a fee delta to something in the cheapest bucket and make sure it gets mined # also check that a different entry in the cheapest bucket is NOT mined @@ -75,8 +75,8 @@ def run_test(self): mempool = self.nodes[0].getrawmempool() self.log.info("Assert that prioritised transaction was mined") - assert(txids[0][0] not in mempool) - assert(txids[0][1] in mempool) + assert txids[0][0] not in mempool + assert txids[0][1] in mempool high_fee_tx = None for x in txids[2]: @@ -84,7 +84,7 @@ def run_test(self): high_fee_tx = x # Something high-fee should have been mined! - assert(high_fee_tx is not None) + assert high_fee_tx is not None # Add a prioritisation before a tx is in the mempool (de-prioritising a # high-fee transaction so that it's now low fee). @@ -95,7 +95,7 @@ def run_test(self): # Check to make sure our high fee rate tx is back in the mempool mempool = self.nodes[0].getrawmempool() - assert(high_fee_tx in mempool) + assert high_fee_tx in mempool # Now verify the modified-high feerate transaction isn't mined before # the other high fee transactions. Keep mining until our mempool has @@ -107,14 +107,14 @@ def run_test(self): # transactions should have been. mempool = self.nodes[0].getrawmempool() self.log.info("Assert that de-prioritised transaction is still in mempool") - assert(high_fee_tx in mempool) + assert high_fee_tx in mempool for x in txids[2]: if (x != high_fee_tx): - assert(x not in mempool) + assert x not in mempool # Create a free transaction. Should be rejected. utxo_list = self.nodes[0].listunspent() - assert(len(utxo_list) > 0) + assert len(utxo_list) > 0 utxo = utxo_list[0] inputs = [] @@ -127,7 +127,7 @@ def run_test(self): # This will raise an exception due to min relay fee not being met assert_raises_rpc_error(-26, "min relay fee not met", self.nodes[0].sendrawtransaction, tx_hex) - assert(tx_id not in self.nodes[0].getrawmempool()) + assert tx_id not in self.nodes[0].getrawmempool() # This is a less than 1000-byte transaction, so just set the fee # to be the minimum for a 1000-byte transaction and check that it is @@ -136,7 +136,7 @@ def run_test(self): self.log.info("Assert that prioritised free transaction is accepted to mempool") assert_equal(self.nodes[0].sendrawtransaction(tx_hex), tx_id) - assert(tx_id in self.nodes[0].getrawmempool()) + assert tx_id in self.nodes[0].getrawmempool() # Test that calling prioritisetransaction is sufficient to trigger # getblocktemplate to (eventually) return a new block. @@ -147,7 +147,7 @@ def run_test(self): self.nodes[0].setmocktime(mock_time+10) new_template = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - assert(template != new_template) + assert template != new_template if __name__ == '__main__': PrioritiseTransactionTest().main() diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py index f0dee59b5c..47c05e2a6a 100755 --- a/test/functional/p2p_compactblocks.py +++ b/test/functional/p2p_compactblocks.py @@ -120,7 +120,7 @@ def make_utxos(self): # Doesn't matter which node we use, just use node0. block = self.build_block_on_tip(self.nodes[0]) self.test_node.send_and_ping(msg_block(block)) - assert(int(self.nodes[0].getbestblockhash(), 16) == block.sha256) + assert int(self.nodes[0].getbestblockhash(), 16) == block.sha256 self.nodes[0].generate(100) total_value = block.vtx[0].vout[0].nValue @@ -167,7 +167,7 @@ def check_announcement_of_new_block(node, peer, predicate): peer.clear_block_announcement() block_hash = int(node.generate(1)[0], 16) peer.wait_for_block_announcement(block_hash, timeout=30) - assert(peer.block_announced) + assert peer.block_announced with mininode_lock: assert predicate(peer), ( @@ -303,7 +303,7 @@ def test_compactblock_construction(self, node, test_node, version, use_witness_a # Now fetch and check the compact block header_and_shortids = None with mininode_lock: - assert("cmpctblock" in test_node.last_message) + assert "cmpctblock" in test_node.last_message # Convert the on-the-wire representation to absolute indexes header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) @@ -319,7 +319,7 @@ def test_compactblock_construction(self, node, test_node, version, use_witness_a # Now fetch and check the compact block header_and_shortids = None with mininode_lock: - assert("cmpctblock" in test_node.last_message) + assert "cmpctblock" in test_node.last_message # Convert the on-the-wire representation to absolute indexes header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) @@ -330,7 +330,7 @@ def check_compactblock_construction_from_block(self, version, header_and_shortid assert_equal(header_and_shortids.header.sha256, block_hash) # Make sure the prefilled_txn appears to have included the coinbase - assert(len(header_and_shortids.prefilled_txn) >= 1) + assert len(header_and_shortids.prefilled_txn) >= 1 assert_equal(header_and_shortids.prefilled_txn[0].index, 0) # Check that all prefilled_txn entries match what's in the block. @@ -345,7 +345,7 @@ def check_compactblock_construction_from_block(self, version, header_and_shortid assert_equal(wtxid, block.vtx[entry.index].calc_sha256(True)) else: # Shouldn't have received a witness - assert(entry.tx.wit.is_null()) + assert entry.tx.wit.is_null() # Check that the cmpctblock message announced all the transactions. assert_equal(len(header_and_shortids.prefilled_txn) + len(header_and_shortids.shortids), len(block.vtx)) @@ -407,7 +407,7 @@ def test_compactblock_requests(self, node, test_node, version, segwit): assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # Expect a getblocktxn message. with mininode_lock: - assert("getblocktxn" in test_node.last_message) + assert "getblocktxn" in test_node.last_message absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, [0]) # should be a coinbase request @@ -447,7 +447,7 @@ def test_getblocktxn_response(compact_block, peer, expected_result): msg = msg_cmpctblock(compact_block.to_p2p()) peer.send_and_ping(msg) with mininode_lock: - assert("getblocktxn" in peer.last_message) + assert "getblocktxn" in peer.last_message absolute_indexes = peer.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, expected_result) @@ -487,7 +487,7 @@ def test_tip_after_message(node, peer, msg, tip): block = self.build_block_with_transactions(node, utxo, 5) self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) test_node.send_and_ping(msg_tx(block.vtx[1])) - assert(block.vtx[1].hash in node.getrawmempool()) + assert block.vtx[1].hash in node.getrawmempool() # Prefill 4 out of the 6 transactions, and verify that only the one # that was not in the mempool is requested. @@ -508,7 +508,7 @@ def test_tip_after_message(node, peer, msg, tip): # Make sure all transactions were accepted. mempool = node.getrawmempool() for tx in block.vtx[1:]: - assert(tx.hash in mempool) + assert tx.hash in mempool # Clear out last request. with mininode_lock: @@ -519,7 +519,7 @@ def test_tip_after_message(node, peer, msg, tip): test_tip_after_message(node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256) with mininode_lock: # Shouldn't have gotten a request for any transaction - assert("getblocktxn" not in test_node.last_message) + assert "getblocktxn" not in test_node.last_message # Incorrectly responding to a getblocktxn shouldn't cause the block to be # permanently failed. @@ -537,7 +537,7 @@ def test_incorrect_blocktxn_response(self, node, test_node, version): # Make sure all transactions were accepted. mempool = node.getrawmempool() for tx in block.vtx[1:6]: - assert(tx.hash in mempool) + assert tx.hash in mempool # Send compact block comp_block = HeaderAndShortIDs() @@ -545,7 +545,7 @@ def test_incorrect_blocktxn_response(self, node, test_node, version): test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) absolute_indexes = [] with mininode_lock: - assert("getblocktxn" in test_node.last_message) + assert "getblocktxn" in test_node.last_message absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, [6, 7, 8, 9, 10]) @@ -569,7 +569,7 @@ def test_incorrect_blocktxn_response(self, node, test_node, version): # We should receive a getdata request wait_until(lambda: "getdata" in test_node.last_message, timeout=10, lock=mininode_lock) assert_equal(len(test_node.last_message["getdata"].inv), 1) - assert(test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2 | MSG_WITNESS_FLAG) + assert test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2 | MSG_WITNESS_FLAG assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) # Deliver the block @@ -606,7 +606,7 @@ def test_getblocktxn_handler(self, node, test_node, version): assert_equal(tx.sha256, block.vtx[index].sha256) if version == 1: # Witnesses should have been stripped - assert(tx.wit.is_null()) + assert tx.wit.is_null() else: # Check that the witness matches assert_equal(tx.calc_sha256(True), block.vtx[index].calc_sha256(True)) @@ -669,7 +669,7 @@ def test_compactblocks_not_at_tip(self, node, test_node): assert_equal(x["status"], "headers-only") found = True break - assert(found) + assert found # Requesting this block via getblocktxn should silently fail # (to avoid fingerprinting attacks). @@ -707,7 +707,7 @@ def test_end_to_end_block_relay(self, node, listeners): # Test that we don't get disconnected if we relay a compact block with valid header, # but invalid transactions. def test_invalid_tx_in_compactblock(self, node, test_node, use_segwit): - assert(len(self.utxos)) + assert len(self.utxos) utxo = self.utxos[0] block = self.build_block_with_transactions(node, utxo, 5) @@ -728,7 +728,7 @@ def test_invalid_tx_in_compactblock(self, node, test_node, use_segwit): test_node.send_and_ping(msg) # Check that the tip didn't advance - assert(int(node.getbestblockhash(), 16) is not block.sha256) + assert int(node.getbestblockhash(), 16) is not block.sha256 test_node.sync_with_ping() # Helper for enabling cb announcements @@ -743,7 +743,7 @@ def request_cb_announcements(self, peer, node, version): peer.send_and_ping(msg) def test_compactblock_reconstruction_multiple_peers(self, node, stalling_peer, delivery_peer): - assert(len(self.utxos)) + assert len(self.utxos) def announce_cmpct_block(node, peer): utxo = self.utxos.pop(0) @@ -764,7 +764,7 @@ def announce_cmpct_block(node, peer): delivery_peer.sync_with_ping() mempool = node.getrawmempool() for tx in block.vtx[1:]: - assert(tx.hash in mempool) + assert tx.hash in mempool delivery_peer.send_and_ping(msg_cmpctblock(cmpct_block.to_p2p())) assert_equal(int(node.getbestblockhash(), 16), block.sha256) @@ -783,7 +783,7 @@ def announce_cmpct_block(node, peer): cmpct_block.use_witness = True delivery_peer.send_and_ping(msg_cmpctblock(cmpct_block.to_p2p())) - assert(int(node.getbestblockhash(), 16) != block.sha256) + assert int(node.getbestblockhash(), 16) != block.sha256 msg = msg_blocktxn() msg.block_transactions.blockhash = block.sha256 @@ -882,7 +882,7 @@ def run_test(self): # Need to manually sync node0 and node1, because post-segwit activation, # node1 will not download blocks from node0. self.log.info("Syncing nodes...") - assert(self.nodes[0].getbestblockhash() != self.nodes[1].getbestblockhash()) + assert self.nodes[0].getbestblockhash() != self.nodes[1].getbestblockhash() while (self.nodes[0].getblockcount() > self.nodes[1].getblockcount()): block_hash = self.nodes[0].getblockhash(self.nodes[1].getblockcount() + 1) self.nodes[1].submitblock(self.nodes[0].getblock(block_hash, False)) diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py index d589519e45..e907cc600f 100755 --- a/test/functional/p2p_feefilter.py +++ b/test/functional/p2p_feefilter.py @@ -57,7 +57,7 @@ def run_test(self): # Test that invs are received for all txs at feerate of 20 sat/byte node1.settxfee(Decimal("0.00020000")) txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] - assert(allInvsMatch(txids, self.nodes[0].p2p)) + assert allInvsMatch(txids, self.nodes[0].p2p) self.nodes[0].p2p.clear_invs() # Set a filter of 15 sat/byte @@ -65,7 +65,7 @@ def run_test(self): # Test that txs are still being received (paying 20 sat/byte) txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] - assert(allInvsMatch(txids, self.nodes[0].p2p)) + assert allInvsMatch(txids, self.nodes[0].p2p) self.nodes[0].p2p.clear_invs() # Change tx fee rate to 10 sat/byte and test they are no longer received @@ -82,13 +82,13 @@ def run_test(self): # as well. node0.settxfee(Decimal("0.00020000")) txids = [node0.sendtoaddress(node0.getnewaddress(), 1)] - assert(allInvsMatch(txids, self.nodes[0].p2p)) + assert allInvsMatch(txids, self.nodes[0].p2p) self.nodes[0].p2p.clear_invs() # Remove fee filter and check that txs are received again self.nodes[0].p2p.send_and_ping(msg_feefilter(0)) txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] - assert(allInvsMatch(txids, self.nodes[0].p2p)) + assert allInvsMatch(txids, self.nodes[0].p2p) self.nodes[0].p2p.clear_invs() if __name__ == '__main__': diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py index 336d34a81d..fdc51f25c3 100755 --- a/test/functional/p2p_leak.py +++ b/test/functional/p2p_leak.py @@ -117,9 +117,9 @@ def run_test(self): wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0) # Make sure no unexpected messages came in - assert(no_version_bannode.unexpected_msg == False) - assert(no_version_idlenode.unexpected_msg == False) - assert(no_verack_idlenode.unexpected_msg == False) + assert no_version_bannode.unexpected_msg == False + assert no_version_idlenode.unexpected_msg == False + assert no_verack_idlenode.unexpected_msg == False if __name__ == '__main__': diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index 14ebd297fc..7d38fbb00d 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -315,7 +315,7 @@ def test_non_witness_transaction(self): self.test_node.send_message(msg_witness_tx(tx)) self.test_node.sync_with_ping() # make sure the tx was processed - assert(tx.hash in self.nodes[0].getrawmempool()) + assert tx.hash in self.nodes[0].getrawmempool() # Save this transaction for later self.utxo.append(UTXO(tx.sha256, 0, 49 * 100000000)) self.nodes[0].generate(1) @@ -333,7 +333,7 @@ def test_unnecessary_witness_before_segwit_activation(self): # Verify the hash with witness differs from the txid # (otherwise our testing framework must be broken!) tx.rehash() - assert(tx.sha256 != tx.calc_sha256(with_witness=True)) + assert tx.sha256 != tx.calc_sha256(with_witness=True) # Construct a segwit-signaling block that includes the transaction. block = self.build_next_block(version=(VB_TOP_BITS | (1 << VB_WITNESS_BIT))) @@ -369,20 +369,20 @@ def test_block_relay(self): block1.solve() self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False) - assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) + assert self.test_node.last_message["getdata"].inv[0].type == blocktype test_witness_block(self.nodes[0], self.test_node, block1, True) block2 = self.build_next_block(version=4) block2.solve() self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True) - assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) + assert self.test_node.last_message["getdata"].inv[0].type == blocktype test_witness_block(self.nodes[0], self.test_node, block2, True) block3 = self.build_next_block(version=(VB_TOP_BITS | (1 << 15))) block3.solve() self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True) - assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) + assert self.test_node.last_message["getdata"].inv[0].type == blocktype test_witness_block(self.nodes[0], self.test_node, block3, True) # Check that we can getdata for witness blocks or regular blocks, @@ -411,8 +411,8 @@ def test_block_relay(self): block = self.build_next_block() self.update_witness_block_with_transactions(block, []) # This gives us a witness commitment. - assert(len(block.vtx[0].wit.vtxinwit) == 1) - assert(len(block.vtx[0].wit.vtxinwit[0].scriptWitness.stack) == 1) + assert len(block.vtx[0].wit.vtxinwit) == 1 + assert len(block.vtx[0].wit.vtxinwit[0].scriptWitness.stack) == 1 test_witness_block(self.nodes[0], self.test_node, block, accepted=True) # Now try to retrieve it... rpc_block = self.nodes[0].getblock(block.hash, False) @@ -446,7 +446,7 @@ def test_block_relay(self): msg.headers = [CBlockHeader(block4)] self.old_node.send_message(msg) self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0]) - assert(block4.sha256 not in self.old_node.getdataset) + assert block4.sha256 not in self.old_node.getdataset @subtest def test_v0_outputs_arent_spendable(self): @@ -535,7 +535,7 @@ def advance_to_segwit_started(self): """Mine enough blocks for segwit's vb state to be 'started'.""" height = self.nodes[0].getblockcount() # Will need to rewrite the tests here if we are past the first period - assert(height < VB_PERIOD - 1) + assert height < VB_PERIOD - 1 # Advance to end of period, status should now be 'started' self.nodes[0].generate(VB_PERIOD - height - 1) assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started') @@ -552,12 +552,12 @@ def test_getblocktemplate_before_lockin(self): # If this is a non-segwit node, we should not get a witness # commitment, nor a version bit signalling segwit. assert_equal(block_version & (1 << VB_WITNESS_BIT), 0) - assert('default_witness_commitment' not in gbt_results) + assert 'default_witness_commitment' not in gbt_results else: # For segwit-aware nodes, check the version bit and the witness # commitment are correct. - assert(block_version & (1 << VB_WITNESS_BIT) != 0) - assert('default_witness_commitment' in gbt_results) + assert block_version & (1 << VB_WITNESS_BIT) != 0 + assert 'default_witness_commitment' in gbt_results witness_commitment = gbt_results['default_witness_commitment'] # Check that default_witness_commitment is present. @@ -573,7 +573,7 @@ def advance_to_segwit_lockin(self): # Advance to end of period, and verify lock-in happens at the end self.nodes[0].generate(VB_PERIOD - 1) height = self.nodes[0].getblockcount() - assert((height % VB_PERIOD) == VB_PERIOD - 2) + assert (height % VB_PERIOD) == VB_PERIOD - 2 assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started') self.nodes[0].generate(1) assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in') @@ -598,7 +598,7 @@ def test_witness_tx_relay_before_segwit_activation(self): # Verify that if a peer doesn't set nServices to include NODE_WITNESS, # the getdata is just for the non-witness portion. self.old_node.announce_tx_and_wait_for_getdata(tx) - assert(self.old_node.last_message["getdata"].inv[0].type == 1) + assert self.old_node.last_message["getdata"].inv[0].type == 1 # Since we haven't delivered the tx yet, inv'ing the same tx from # a witness transaction ought not result in a getdata. @@ -790,7 +790,7 @@ def test_witness_commitments(self): block.solve() # Test the test -- witness serialization should be different - assert(msg_witness_block(block).serialize() != msg_block(block).serialize()) + assert msg_witness_block(block).serialize() != msg_block(block).serialize() # This empty block should be valid. test_witness_block(self.nodes[0], self.test_node, block, accepted=True) @@ -801,7 +801,7 @@ def test_witness_commitments(self): block_2.solve() # The commitment should have changed! - assert(block_2.vtx[0].vout[-1] != block.vtx[0].vout[-1]) + assert block_2.vtx[0].vout[-1] != block.vtx[0].vout[-1] # This should also be valid. test_witness_block(self.nodes[0], self.test_node, block_2, accepted=True) @@ -848,7 +848,7 @@ def test_witness_commitments(self): block_3.vtx[0].rehash() block_3.hashMerkleRoot = block_3.calc_merkle_root() block_3.rehash() - assert(len(block_3.vtx[0].vout) == 4) # 3 OP_returns + assert len(block_3.vtx[0].vout) == 4 # 3 OP_returns block_3.solve() test_witness_block(self.nodes[0], self.test_node, block_3, accepted=True) @@ -879,19 +879,19 @@ def test_block_malleability(self): block.solve() block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a' * 5000000) - assert(get_virtual_size(block) > MAX_BLOCK_BASE_SIZE) + assert get_virtual_size(block) > MAX_BLOCK_BASE_SIZE # We can't send over the p2p network, because this is too big to relay # TODO: repeat this test with a block that can be relayed self.nodes[0].submitblock(block.serialize(True).hex()) - assert(self.nodes[0].getbestblockhash() != block.hash) + assert self.nodes[0].getbestblockhash() != block.hash block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.pop() - assert(get_virtual_size(block) < MAX_BLOCK_BASE_SIZE) + assert get_virtual_size(block) < MAX_BLOCK_BASE_SIZE self.nodes[0].submitblock(block.serialize(True).hex()) - assert(self.nodes[0].getbestblockhash() == block.hash) + assert self.nodes[0].getbestblockhash() == block.hash # Now make sure that malleating the witness reserved value doesn't # result in a block permanently marked bad. @@ -916,7 +916,7 @@ def test_witness_block_size(self): # Test that witness-bearing blocks are limited at ceil(base + wit/4) <= 1MB. block = self.build_next_block() - assert(len(self.utxo) > 0) + assert len(self.utxo) > 0 # Create a P2WSH transaction. # The witness program will be a bunch of OP_2DROP's, followed by OP_TRUE. @@ -938,7 +938,7 @@ def test_witness_block_size(self): for i in range(NUM_OUTPUTS): parent_tx.vout.append(CTxOut(child_value, script_pubkey)) parent_tx.vout[0].nValue -= 50000 - assert(parent_tx.vout[0].nValue > 0) + assert parent_tx.vout[0].nValue > 0 parent_tx.rehash() child_tx = CTransaction() @@ -968,7 +968,7 @@ def test_witness_block_size(self): assert_equal(vsize, MAX_BLOCK_BASE_SIZE + 1) # Make sure that our test case would exceed the old max-network-message # limit - assert(len(block.serialize(True)) > 2 * 1024 * 1024) + assert len(block.serialize(True)) > 2 * 1024 * 1024 test_witness_block(self.nodes[0], self.test_node, block, accepted=False) @@ -978,7 +978,7 @@ def test_witness_block_size(self): block.vtx[0].vout.pop() add_witness_commitment(block) block.solve() - assert(get_virtual_size(block) == MAX_BLOCK_BASE_SIZE) + assert get_virtual_size(block) == MAX_BLOCK_BASE_SIZE test_witness_block(self.nodes[0], self.test_node, block, accepted=True) @@ -997,7 +997,7 @@ def test_submit_block(self): block.vtx[0].wit = CTxWitness() # drop the nonce block.solve() self.nodes[0].submitblock(block.serialize(True).hex()) - assert(self.nodes[0].getbestblockhash() != block.hash) + assert self.nodes[0].getbestblockhash() != block.hash # Now redo commitment with the standard nonce, but let bitcoind fill it in. add_witness_commitment(block, nonce=0) @@ -1020,7 +1020,7 @@ def test_submit_block(self): self.nodes[0].submitblock(block_2.serialize(True).hex()) # Tip should not advance! - assert(self.nodes[0].getbestblockhash() != block_2.hash) + assert self.nodes[0].getbestblockhash() != block_2.hash @subtest def test_extra_witness_data(self): @@ -1140,7 +1140,7 @@ def test_max_witness_program_length(self): # This program is 19 max pushes (9937 bytes), then 64 more opcode-bytes. long_witness_program = CScript([b'a' * 520] * 19 + [OP_DROP] * 63 + [OP_TRUE]) - assert(len(long_witness_program) == MAX_PROGRAM_LENGTH + 1) + assert len(long_witness_program) == MAX_PROGRAM_LENGTH + 1 long_witness_hash = sha256(long_witness_program) long_script_pubkey = CScript([OP_0, long_witness_hash]) @@ -1164,7 +1164,7 @@ def test_max_witness_program_length(self): # Try again with one less byte in the witness program witness_program = CScript([b'a' * 520] * 19 + [OP_DROP] * 62 + [OP_TRUE]) - assert(len(witness_program) == MAX_PROGRAM_LENGTH) + assert len(witness_program) == MAX_PROGRAM_LENGTH witness_hash = sha256(witness_program) script_pubkey = CScript([OP_0, witness_hash]) @@ -1195,7 +1195,7 @@ def test_witness_input_length(self): for i in range(10): tx.vout.append(CTxOut(int(value / 10), script_pubkey)) tx.vout[0].nValue -= 1000 - assert(tx.vout[0].nValue >= 0) + assert tx.vout[0].nValue >= 0 block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) @@ -1346,7 +1346,7 @@ def test_tx_relay_after_segwit_activation(self): assert_equal(raw_tx["weight"], weight) assert_equal(len(raw_tx["vin"][0]["txinwitness"]), 1) assert_equal(raw_tx["vin"][0]["txinwitness"][0], witness_program.hex()) - assert(vsize != raw_tx["size"]) + assert vsize != raw_tx["size"] # Cleanup: mine the transactions and update utxo for next test self.nodes[0].generate(1) @@ -1396,7 +1396,7 @@ def test_segwit_versions(self): self.nodes[0].generate(1) # Mine all the transactions sync_blocks(self.nodes) - assert(len(self.nodes[0].getrawmempool()) == 0) + assert len(self.nodes[0].getrawmempool()) == 0 # Finally, verify that version 0 -> version 1 transactions # are non-standard @@ -1665,7 +1665,7 @@ def test_signature_version_1(self): # Create a slight bias for producing more utxos num_outputs = random.randint(1, 11) random.shuffle(temp_utxos) - assert(len(temp_utxos) > num_inputs) + assert len(temp_utxos) > num_inputs tx = CTransaction() total_value = 0 for i in range(num_inputs): @@ -1926,7 +1926,7 @@ def test_upgrade_after_activation(self): sync_blocks(self.nodes) # Make sure that this peer thinks segwit has activated. - assert(get_bip9_status(self.nodes[2], 'segwit')['status'] == "active") + assert get_bip9_status(self.nodes[2], 'segwit')['status'] == "active" # Make sure this peer's blocks match those of node0. height = self.nodes[2].getblockcount() @@ -1953,7 +1953,7 @@ def test_witness_sigops(self): extra_sigops_available = MAX_SIGOP_COST % sigops_per_script # We chose the number of checkmultisigs/checksigs to make this work: - assert(extra_sigops_available < 100) # steer clear of MAX_OPS_PER_SCRIPT + assert extra_sigops_available < 100 # steer clear of MAX_OPS_PER_SCRIPT # This script, when spent with the first # N(=MAX_SIGOP_COST//sigops_per_script) outputs of our transaction, diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py index 11299cbc00..a118b891e5 100755 --- a/test/functional/p2p_unrequested_blocks.py +++ b/test/functional/p2p_unrequested_blocks.py @@ -114,7 +114,7 @@ def run_test(self): if x['hash'] == block_h1f.hash: assert_equal(x['status'], "headers-only") tip_entry_found = True - assert(tip_entry_found) + assert tip_entry_found assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, block_h1f.hash) # 4. Send another two block that build on the fork. @@ -131,7 +131,7 @@ def run_test(self): if x['hash'] == block_h2f.hash: assert_equal(x['status'], "headers-only") tip_entry_found = True - assert(tip_entry_found) + assert tip_entry_found # But this block should be accepted by node since it has equal work. self.nodes[0].getblock(block_h2f.hash) @@ -150,7 +150,7 @@ def run_test(self): if x['hash'] == block_h3.hash: assert_equal(x['status'], "headers-only") tip_entry_found = True - assert(tip_entry_found) + assert tip_entry_found self.nodes[0].getblock(block_h3.hash) # But this block should be accepted by node since it has more work. @@ -263,7 +263,7 @@ def run_test(self): if x['hash'] == block_292.hash: assert_equal(x['status'], "headers-only") tip_entry_found = True - assert(tip_entry_found) + assert tip_entry_found assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, block_292.hash) test_node.send_message(msg_block(block_289f)) diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index af150a09af..6693042f84 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -172,9 +172,9 @@ def _test_getchaintxstats(self): assert_equal(chaintxstats['txcount'], 2) assert_equal(chaintxstats['window_final_block_hash'], b1_hash) assert_equal(chaintxstats['window_block_count'], 0) - assert('window_tx_count' not in chaintxstats) - assert('window_interval' not in chaintxstats) - assert('txrate' not in chaintxstats) + assert 'window_tx_count' not in chaintxstats + assert 'window_interval' not in chaintxstats + assert 'txrate' not in chaintxstats def _test_gettxoutsetinfo(self): node = self.nodes[0] diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 4f350953b2..4d3c452f33 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -94,7 +94,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert(len(dec_tx['vin']) > 0) #test that we have enough inputs + assert len(dec_tx['vin']) > 0 #test that we have enough inputs ############################## # simple test with two coins # @@ -107,7 +107,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert(len(dec_tx['vin']) > 0) #test if we have enough inputs + assert len(dec_tx['vin']) > 0 #test if we have enough inputs ############################## # simple test with two coins # @@ -120,7 +120,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert(len(dec_tx['vin']) > 0) + assert len(dec_tx['vin']) > 0 assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') @@ -139,7 +139,7 @@ def run_test(self): for out in dec_tx['vout']: totalOut += out['value'] - assert(len(dec_tx['vin']) > 0) + assert len(dec_tx['vin']) > 0 assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') @@ -363,7 +363,7 @@ def run_test(self): #compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) - assert(feeDelta >= 0 and feeDelta <= feeTolerance) + assert feeDelta >= 0 and feeDelta <= feeTolerance ############################################################ ############################################################ @@ -378,7 +378,7 @@ def run_test(self): #compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) - assert(feeDelta >= 0 and feeDelta <= feeTolerance) + assert feeDelta >= 0 and feeDelta <= feeTolerance ############################################################ @@ -405,7 +405,7 @@ def run_test(self): #compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) - assert(feeDelta >= 0 and feeDelta <= feeTolerance) + assert feeDelta >= 0 and feeDelta <= feeTolerance ############################################################ @@ -438,7 +438,7 @@ def run_test(self): #compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) - assert(feeDelta >= 0 and feeDelta <= feeTolerance) + assert feeDelta >= 0 and feeDelta <= feeTolerance ############################################################ @@ -558,7 +558,7 @@ def run_test(self): #compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) - assert(feeDelta >= 0 and feeDelta <= feeTolerance*19) #~19 inputs + assert feeDelta >= 0 and feeDelta <= feeTolerance*19 #~19 inputs ############################################# @@ -620,7 +620,7 @@ def run_test(self): assert_equal(len(res_dec["vin"]), 1) assert_equal(res_dec["vin"][0]["txid"], watchonly_txid) - assert("fee" in result.keys()) + assert "fee" in result.keys() assert_greater_than(result["changepos"], -1) ############################################################### @@ -635,16 +635,16 @@ def run_test(self): result = self.nodes[3].fundrawtransaction(rawtx, True) res_dec = self.nodes[0].decoderawtransaction(result["hex"]) assert_equal(len(res_dec["vin"]), 2) - assert(res_dec["vin"][0]["txid"] == watchonly_txid or res_dec["vin"][1]["txid"] == watchonly_txid) + assert res_dec["vin"][0]["txid"] == watchonly_txid or res_dec["vin"][1]["txid"] == watchonly_txid assert_greater_than(result["fee"], 0) assert_greater_than(result["changepos"], -1) assert_equal(result["fee"] + res_dec["vout"][result["changepos"]]["value"], watchonly_amount / 10) signedtx = self.nodes[3].signrawtransactionwithwallet(result["hex"]) - assert(not signedtx["complete"]) + assert not signedtx["complete"] signedtx = self.nodes[0].signrawtransactionwithwallet(signedtx["hex"]) - assert(signedtx["complete"]) + assert signedtx["complete"] self.nodes[0].sendrawtransaction(signedtx["hex"]) self.nodes[0].generate(1) self.sync_all() @@ -676,10 +676,10 @@ def run_test(self): for out in res_dec['vout']: if out['value'] > 1.0: changeaddress += out['scriptPubKey']['addresses'][0] - assert(changeaddress != "") + assert changeaddress != "" nextaddr = self.nodes[3].getnewaddress() # Now the change address key should be removed from the keypool - assert(changeaddress != nextaddr) + assert changeaddress != nextaddr ###################################### # Test subtractFeeFromOutputs option # diff --git a/test/functional/rpc_named_arguments.py b/test/functional/rpc_named_arguments.py index 6c5c29dfdf..734c5a7779 100755 --- a/test/functional/rpc_named_arguments.py +++ b/test/functional/rpc_named_arguments.py @@ -17,7 +17,7 @@ def set_test_params(self): def run_test(self): node = self.nodes[0] h = node.help(command='getblockchaininfo') - assert(h.startswith('getblockchaininfo\n')) + assert h.startswith('getblockchaininfo\n') assert_raises_rpc_error(-8, 'Unknown named parameter', node.help, random='getblockchaininfo') diff --git a/test/functional/rpc_preciousblock.py b/test/functional/rpc_preciousblock.py index 72e6e6329f..bfa15f69f2 100755 --- a/test/functional/rpc_preciousblock.py +++ b/test/functional/rpc_preciousblock.py @@ -16,7 +16,7 @@ def unidirectional_node_sync_via_rpc(node_src, node_dest): blockhash = node_src.getbestblockhash() while True: try: - assert(len(node_dest.getblock(blockhash, False)) > 0) + assert len(node_dest.getblock(blockhash, False)) > 0 break except: blocks_to_copy.append(blockhash) @@ -24,7 +24,7 @@ def unidirectional_node_sync_via_rpc(node_src, node_dest): blocks_to_copy.reverse() for blockhash in blocks_to_copy: blockdata = node_src.getblock(blockhash, False) - assert(node_dest.submitblock(blockdata) in (None, 'inconclusive')) + assert node_dest.submitblock(blockdata) in (None, 'inconclusive') def node_sync_via_rpc(nodes): for node_src in nodes: @@ -57,7 +57,7 @@ def run_test(self): self.log.info("Mine competing blocks E-F-G on Node 1") hashG = self.nodes[1].generatetoaddress(3, gen_address(1))[-1] assert_equal(self.nodes[1].getblockcount(), 5) - assert(hashC != hashG) + assert hashC != hashG self.log.info("Connect nodes and check no reorg occurs") # Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync) node_sync_via_rpc(self.nodes[0:2]) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index e9098e4f5a..165746f1f8 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -47,11 +47,11 @@ def test_utxo_conversion(self): utxos = online_node.listunspent(addresses=[offline_addr]) raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}]) psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"] - assert("non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0]) + assert "non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0] # Have the offline node sign the PSBT (which will update the UTXO to segwit) signed_psbt = offline_node.walletprocesspsbt(psbt)["psbt"] - assert("witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0]) + assert "witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0] # Make sure we can mine the resulting transaction txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"]) diff --git a/test/functional/rpc_signmessage.py b/test/functional/rpc_signmessage.py index ad0e29b451..2e39774a92 100755 --- a/test/functional/rpc_signmessage.py +++ b/test/functional/rpc_signmessage.py @@ -25,18 +25,18 @@ def run_test(self): expected_signature = 'INbVnW4e6PeRmsv2Qgu8NuopvrVjkcxob+sX8OcZG0SALhWybUjzMLPdAsXI46YZGb0KQTRii+wWIQzRpG/U+S0=' signature = self.nodes[0].signmessagewithprivkey(priv_key, message) assert_equal(expected_signature, signature) - assert(self.nodes[0].verifymessage(address, signature, message)) + assert self.nodes[0].verifymessage(address, signature, message) self.log.info('test signing with an address with wallet') address = self.nodes[0].getnewaddress() signature = self.nodes[0].signmessage(address, message) - assert(self.nodes[0].verifymessage(address, signature, message)) + assert self.nodes[0].verifymessage(address, signature, message) self.log.info('test verifying with another address should not work') other_address = self.nodes[0].getnewaddress() other_signature = self.nodes[0].signmessage(other_address, message) - assert(not self.nodes[0].verifymessage(other_address, signature, message)) - assert(not self.nodes[0].verifymessage(address, other_signature, message)) + assert not self.nodes[0].verifymessage(other_address, signature, message) + assert not self.nodes[0].verifymessage(address, other_signature, message) if __name__ == '__main__': SignMessagesTest().main() diff --git a/test/functional/rpc_uptime.py b/test/functional/rpc_uptime.py index 20b6341550..d03775f04e 100755 --- a/test/functional/rpc_uptime.py +++ b/test/functional/rpc_uptime.py @@ -23,7 +23,7 @@ def run_test(self): def _test_uptime(self): wait_time = 10 self.nodes[0].setmocktime(int(time.time() + wait_time)) - assert(self.nodes[0].uptime() >= wait_time) + assert self.nodes[0].uptime() >= wait_time if __name__ == '__main__': diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index 0ebc5efb7e..6a17d8480e 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -32,12 +32,12 @@ def byte_to_base58(b, version): # TODO: def base58_decode def keyhash_to_p2pkh(hash, main = False): - assert (len(hash) == 20) + assert len(hash) == 20 version = 0 if main else 111 return byte_to_base58(hash, version) def scripthash_to_p2sh(hash, main = False): - assert (len(hash) == 20) + assert len(hash) == 20 version = 5 if main else 196 return byte_to_base58(hash, version) @@ -80,11 +80,11 @@ def check_key(key): key = hex_str_to_bytes(key) # Assuming this is hex string if (type(key) is bytes and (len(key) == 33 or len(key) == 65)): return key - assert(False) + assert False def check_script(script): if (type(script) is str): script = hex_str_to_bytes(script) # Assuming this is hex string if (type(script) is bytes or type(script) is CScript): return script - assert(False) + assert False diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 9d7b4b2702..7ac044d0d0 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -131,7 +131,7 @@ def create_tx_with_script(prevtx, n, script_sig=b"", *, amount, script_pub_key=C Can optionally pass scriptPubKey and scriptSig, default is anyone-can-spend output. """ tx = CTransaction() - assert(n < len(prevtx.vout)) + assert n < len(prevtx.vout) tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), script_sig, 0xffffffff)) tx.vout.append(CTxOut(amount, script_pub_key)) tx.calc_sha256() @@ -214,7 +214,7 @@ def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=Tru tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount) if (sign): signed = node.signrawtransactionwithwallet(tx_to_witness) - assert("errors" not in signed or len(["errors"]) == 0) + assert "errors" not in signed or len(["errors"]) == 0 return node.sendrawtransaction(signed["hex"]) else: if (insert_redeem_script): diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py index 1a3efcd1ac..bf80d632cb 100644 --- a/test/functional/test_framework/netutil.py +++ b/test/functional/test_framework/netutil.py @@ -129,13 +129,13 @@ def addr_to_hex(addr): if i == 0 or i == (len(addr)-1): # skip empty component at beginning or end continue x += 1 # :: skips to suffix - assert(x < 2) + assert x < 2 else: # two bytes per component val = int(comp, 16) sub[x].append(val >> 8) sub[x].append(val & 0xff) nullbytes = 16 - len(sub[0]) - len(sub[1]) - assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0)) + assert (x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0) addr = sub[0] + ([0] * nullbytes) + sub[1] else: raise ValueError('Could not parse address %s' % addr) diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py index a21c864e75..959f0023b1 100644 --- a/test/functional/test_framework/socks5.py +++ b/test/functional/test_framework/socks5.py @@ -144,7 +144,7 @@ def run(self): thread.start() def start(self): - assert(not self.running) + assert not self.running self.running = True self.thread = threading.Thread(None, self.run) self.thread.daemon = True diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index f7f1b277e4..b51239ae0f 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -264,7 +264,7 @@ def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): return coverage.AuthServiceProxyWrapper(proxy, coverage_logfile) def p2p_port(n): - assert(n <= MAX_NODES) + assert n <= MAX_NODES return PORT_MIN + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) def rpc_port(n): @@ -422,7 +422,7 @@ def gather_inputs(from_node, amount_needed, confirmations_required=1): """ Return a random set of unspent txouts that are enough to pay amount_needed """ - assert(confirmations_required >= 0) + assert confirmations_required >= 0 utxo = from_node.listunspent(confirmations_required) random.shuffle(utxo) inputs = [] @@ -500,7 +500,7 @@ def create_confirmed_utxos(fee, node, count): node.generate(1) utxos = node.listunspent() - assert(len(utxos) >= count) + assert len(utxos) >= count return utxos # Create large OP_RETURN txouts that can be appended to a transaction diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py index 380dd9c0ad..f213de1bb0 100755 --- a/test/functional/wallet_address_types.py +++ b/test/functional/wallet_address_types.py @@ -102,62 +102,62 @@ def get_balances(self, confirmed=True): def test_address(self, node, address, multisig, typ): """Run sanity checks on an address.""" info = self.nodes[node].getaddressinfo(address) - assert(self.nodes[node].validateaddress(address)['isvalid']) + assert self.nodes[node].validateaddress(address)['isvalid'] assert_equal(info.get('solvable'), True) if not multisig and typ == 'legacy': # P2PKH - assert(not info['isscript']) - assert(not info['iswitness']) - assert('pubkey' in info) + assert not info['isscript'] + assert not info['iswitness'] + assert 'pubkey' in info elif not multisig and typ == 'p2sh-segwit': # P2SH-P2WPKH - assert(info['isscript']) - assert(not info['iswitness']) + assert info['isscript'] + assert not info['iswitness'] assert_equal(info['script'], 'witness_v0_keyhash') - assert('pubkey' in info) + assert 'pubkey' in info elif not multisig and typ == 'bech32': # P2WPKH - assert(not info['isscript']) - assert(info['iswitness']) + assert not info['isscript'] + assert info['iswitness'] assert_equal(info['witness_version'], 0) assert_equal(len(info['witness_program']), 40) - assert('pubkey' in info) + assert 'pubkey' in info elif typ == 'legacy': # P2SH-multisig - assert(info['isscript']) + assert info['isscript'] assert_equal(info['script'], 'multisig') - assert(not info['iswitness']) - assert('pubkeys' in info) + assert not info['iswitness'] + assert 'pubkeys' in info elif typ == 'p2sh-segwit': # P2SH-P2WSH-multisig - assert(info['isscript']) + assert info['isscript'] assert_equal(info['script'], 'witness_v0_scripthash') - assert(not info['iswitness']) - assert(info['embedded']['isscript']) + assert not info['iswitness'] + assert info['embedded']['isscript'] assert_equal(info['embedded']['script'], 'multisig') - assert(info['embedded']['iswitness']) + assert info['embedded']['iswitness'] assert_equal(info['embedded']['witness_version'], 0) assert_equal(len(info['embedded']['witness_program']), 64) - assert('pubkeys' in info['embedded']) + assert 'pubkeys' in info['embedded'] elif typ == 'bech32': # P2WSH-multisig - assert(info['isscript']) + assert info['isscript'] assert_equal(info['script'], 'multisig') - assert(info['iswitness']) + assert info['iswitness'] assert_equal(info['witness_version'], 0) assert_equal(len(info['witness_program']), 64) - assert('pubkeys' in info) + assert 'pubkeys' in info else: # Unknown type - assert(False) + assert False def test_desc(self, node, address, multisig, typ, utxo): """Run sanity checks on a descriptor reported by getaddressinfo.""" info = self.nodes[node].getaddressinfo(address) - assert('desc' in info) + assert 'desc' in info assert_equal(info['desc'], utxo['desc']) - assert(self.nodes[node].validateaddress(address)['isvalid']) + assert self.nodes[node].validateaddress(address)['isvalid'] # Use a ridiculously roundabout way to find the key origin info through # the PSBT logic. However, this does test consistency between the PSBT reported @@ -172,11 +172,11 @@ def test_desc(self, node, address, multisig, typ, utxo): key_descs[deriv['pubkey']] = '[' + deriv['master_fingerprint'] + deriv['path'][1:] + ']' + deriv['pubkey'] # Verify the descriptor checksum against the Python implementation - assert(descsum_check(info['desc'])) + assert descsum_check(info['desc']) # Verify that stripping the checksum and recreating it using Python roundtrips - assert(info['desc'] == descsum_create(info['desc'][:-9])) + assert info['desc'] == descsum_create(info['desc'][:-9]) # Verify that stripping the checksum and feeding it to getdescriptorinfo roundtrips - assert(info['desc'] == self.nodes[0].getdescriptorinfo(info['desc'][:-9])['descriptor']) + assert info['desc'] == self.nodes[0].getdescriptorinfo(info['desc'][:-9])['descriptor'] if not multisig and typ == 'legacy': # P2PKH @@ -198,7 +198,7 @@ def test_desc(self, node, address, multisig, typ, utxo): assert_equal(info['desc'], descsum_create("wsh(multi(2,%s,%s))" % (key_descs[info['pubkeys'][0]], key_descs[info['pubkeys'][1]]))) else: # Unknown type - assert(False) + assert False def test_change_output_type(self, node_sender, destinations, expected_type): txid = self.nodes[node_sender].sendmany(dummy="", amounts=dict.fromkeys(destinations, 0.001)) diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index 7ec72b8649..fb964c718c 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -40,8 +40,8 @@ def run_test(self): privkey = w0.dumpprivkey(addr) assert_raises_rpc_error(-4, 'Cannot import private keys to a wallet with private keys disabled', w1.importprivkey, privkey) result = w1.importmulti([{'scriptPubKey': {'address': addr}, 'timestamp': 'now', 'keys': [privkey]}]) - assert(not result[0]['success']) - assert('warning' not in result[0]) + assert not result[0]['success'] + assert 'warning' not in result[0] assert_equal(result[0]['error']['code'], -4) assert_equal(result[0]['error']['message'], 'Cannot import private keys to a wallet with private keys disabled') diff --git a/test/functional/wallet_disable.py b/test/functional/wallet_disable.py index 6530c58c78..22efaed18e 100755 --- a/test/functional/wallet_disable.py +++ b/test/functional/wallet_disable.py @@ -21,9 +21,9 @@ def run_test (self): # Make sure wallet is really disabled assert_raises_rpc_error(-32601, 'Method not found', self.nodes[0].getwalletinfo) x = self.nodes[0].validateaddress('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy') - assert(x['isvalid'] == False) + assert x['isvalid'] == False x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') - assert(x['isvalid'] == True) + assert x['isvalid'] == True # Checking mining to an address without a wallet. Generating to a valid address should succeed # but generating to an invalid address will fail. diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py index 3f39654bb8..5cf0e613d8 100755 --- a/test/functional/wallet_dump.py +++ b/test/functional/wallet_dump.py @@ -46,10 +46,10 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): keypath = None if keytype == "inactivehdseed=1": # ensure the old master is still available - assert (hd_master_addr_old == addr) + assert hd_master_addr_old == addr elif keytype == "hdseed=1": # ensure we have generated a new hd master key - assert (hd_master_addr_old != addr) + assert hd_master_addr_old != addr hd_master_addr_ret = addr elif keytype == "script=1": # scripts don't have keypaths diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index 1116196268..2b34cff8a6 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -21,7 +21,7 @@ def run_test(self): addr_before_encrypting = nodes[0].getnewaddress() addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting) wallet_info_old = nodes[0].getwalletinfo() - assert(addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid']) + assert addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid'] # Encrypt wallet and wait to terminate nodes[0].encryptwallet('test') @@ -29,8 +29,8 @@ def run_test(self): addr = nodes[0].getnewaddress() addr_data = nodes[0].getaddressinfo(addr) wallet_info = nodes[0].getwalletinfo() - assert(addr_before_encrypting_data['hdseedid'] != wallet_info['hdseedid']) - assert(addr_data['hdseedid'] == wallet_info['hdseedid']) + assert addr_before_encrypting_data['hdseedid'] != wallet_info['hdseedid'] + assert addr_data['hdseedid'] == wallet_info['hdseedid'] assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) # put six (plus 2) new keys in the keypool (100% external-, +100% internal-keys, 1 in min) @@ -59,7 +59,7 @@ def run_test(self): addr.add(nodes[0].getnewaddress()) addr.add(nodes[0].getnewaddress()) addr.add(nodes[0].getnewaddress()) - assert(len(addr) == 6) + assert len(addr) == 6 # the next one should fail assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py index b7c8d3098d..8300d12752 100755 --- a/test/functional/wallet_keypool_topup.py +++ b/test/functional/wallet_keypool_topup.py @@ -55,11 +55,11 @@ def run_test(self): # Make sure we're creating the outputs we expect address_details = self.nodes[idx].validateaddress(addr_extpool) if i == 0: - assert(not address_details["isscript"] and not address_details["iswitness"]) + assert not address_details["isscript"] and not address_details["iswitness"] elif i == 1: - assert(address_details["isscript"] and not address_details["iswitness"]) + assert address_details["isscript"] and not address_details["iswitness"] else: - assert(not address_details["isscript"] and address_details["iswitness"]) + assert not address_details["isscript"] and address_details["iswitness"] self.log.info("Send funds to wallet") diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py index ce76d06d2b..459dbc6612 100755 --- a/test/functional/wallet_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -125,7 +125,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): # 1. Chain a few transactions that don't opt-in. txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1) - assert(not is_opt_in(self.nodes[0], txid_1)) + assert not is_opt_in(self.nodes[0], txid_1) assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"}) sync_mempools(self.nodes) assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"}) @@ -145,7 +145,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): txid_2 = self.nodes[1].sendrawtransaction(tx2_signed) # ...and check the result - assert(not is_opt_in(self.nodes[1], txid_2)) + assert not is_opt_in(self.nodes[1], txid_2) assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"}) sync_mempools(self.nodes) assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"}) @@ -161,7 +161,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex'] txid_3 = self.nodes[0].sendrawtransaction(tx3_signed) - assert(is_opt_in(self.nodes[0], txid_3)) + assert is_opt_in(self.nodes[0], txid_3) assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"}) sync_mempools(self.nodes) assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"}) @@ -175,7 +175,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"] txid_4 = self.nodes[1].sendrawtransaction(tx4_signed) - assert(not is_opt_in(self.nodes[1], txid_4)) + assert not is_opt_in(self.nodes[1], txid_4) assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"}) sync_mempools(self.nodes) assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"}) @@ -186,7 +186,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): tx3_b = tx3_b.serialize().hex() tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex'] txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True) - assert(is_opt_in(self.nodes[0], txid_3b)) + assert is_opt_in(self.nodes[0], txid_3b) assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"}) sync_mempools(self.nodes) @@ -202,7 +202,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): # After mining a transaction, it's no longer BIP125-replaceable self.nodes[0].generate(1) - assert(txid_3b not in self.nodes[0].getrawmempool()) + assert txid_3b not in self.nodes[0].getrawmempool() assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no") assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown") diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py index f5d4780b6d..459b7fc413 100755 --- a/test/lint/lint-format-strings.py +++ b/test/lint/lint-format-strings.py @@ -39,7 +39,7 @@ def parse_function_calls(function_name, source_code): >>> len(parse_function_calls("foo", "#define FOO foo();")) 0 """ - assert(type(function_name) is str and type(source_code) is str and function_name) + assert type(function_name) is str and type(source_code) is str and function_name lines = [re.sub("// .*", " ", line).strip() for line in source_code.split("\n") if not line.strip().startswith("#")] @@ -53,7 +53,7 @@ def normalize(s): >>> normalize(" /* nothing */ foo\tfoo /* bar */ foo ") 'foo foo foo' """ - assert(type(s) is str) + assert type(s) is str s = s.replace("\n", " ") s = s.replace("\t", " ") s = re.sub("/\*.*?\*/", " ", s) @@ -77,7 +77,7 @@ def escape(s): >>> escape(r'foo \\t foo \\n foo \\\\ foo \\ foo \\"bar\\"') 'foo [escaped-tab] foo [escaped-newline] foo \\\\\\\\ foo \\\\ foo [escaped-quote]bar[escaped-quote]' """ - assert(type(s) is str) + assert type(s) is str for raw_value, escaped_value in ESCAPE_MAP.items(): s = s.replace(raw_value, escaped_value) return s @@ -92,7 +92,7 @@ def unescape(s): >>> unescape("foo [escaped-tab] foo [escaped-newline] foo \\\\\\\\ foo \\\\ foo [escaped-quote]bar[escaped-quote]") 'foo \\\\t foo \\\\n foo \\\\\\\\ foo \\\\ foo \\\\"bar\\\\"' """ - assert(type(s) is str) + assert type(s) is str for raw_value, escaped_value in ESCAPE_MAP.items(): s = s.replace(escaped_value, raw_value) return s @@ -151,10 +151,10 @@ def parse_function_call_and_arguments(function_name, function_call): >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo>foo<1,2>(1,2),err)'); ['strprintf(', '"%s (%d)",', ' foo>foo<1,2>(1,2),', 'err', ')'] """ - assert(type(function_name) is str and type(function_call) is str and function_name) + assert type(function_name) is str and type(function_call) is str and function_name remaining = normalize(escape(function_call)) expected_function_call = "{}(".format(function_name) - assert(remaining.startswith(expected_function_call)) + assert remaining.startswith(expected_function_call) parts = [expected_function_call] remaining = remaining[len(expected_function_call):] open_parentheses = 1 @@ -213,7 +213,7 @@ def parse_string_content(argument): >>> parse_string_content('1 2 3') '' """ - assert(type(argument) is str) + assert type(argument) is str string_content = "" in_string = False for char in normalize(escape(argument)): @@ -240,7 +240,7 @@ def count_format_specifiers(format_string): >>> count_format_specifiers("foo %d bar %i foo %% foo %*d foo") 4 """ - assert(type(format_string) is str) + assert type(format_string) is str format_string = format_string.replace('%%', 'X') n = 0 in_specifier = False From faa7cdf764a651975fa3c780df7df206a08254c2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 20 Feb 2019 20:03:13 -0500 Subject: [PATCH 0100/4486] scripted-diff: Update copyright in ./test -BEGIN VERIFY SCRIPT- ./contrib/devtools/copyright_header.py update ./test/ -END VERIFY SCRIPT- --- test/functional/example_test.py | 2 +- test/functional/feature_assumevalid.py | 2 +- test/functional/feature_bip68_sequence.py | 2 +- test/functional/feature_cltv.py | 2 +- test/functional/feature_config_args.py | 2 +- test/functional/feature_csv_activation.py | 2 +- test/functional/feature_dersig.py | 2 +- test/functional/feature_notifications.py | 2 +- test/functional/feature_nulldummy.py | 2 +- test/functional/feature_proxy.py | 2 +- test/functional/feature_pruning.py | 2 +- test/functional/feature_rbf.py | 2 +- test/functional/feature_segwit.py | 2 +- test/functional/feature_versionbits_warning.py | 2 +- test/functional/interface_bitcoin_cli.py | 2 +- test/functional/interface_http.py | 2 +- test/functional/interface_rest.py | 2 +- test/functional/interface_rpc.py | 2 +- test/functional/interface_zmq.py | 2 +- test/functional/mempool_accept.py | 2 +- test/functional/mempool_limit.py | 2 +- test/functional/mempool_packages.py | 2 +- test/functional/mempool_resurrect.py | 2 +- test/functional/mining_getblocktemplate_longpoll.py | 2 +- test/functional/mining_prioritisetransaction.py | 2 +- test/functional/p2p_compactblocks.py | 2 +- test/functional/p2p_feefilter.py | 2 +- test/functional/p2p_leak.py | 2 +- test/functional/p2p_segwit.py | 2 +- test/functional/p2p_unrequested_blocks.py | 2 +- test/functional/rpc_bind.py | 2 +- test/functional/rpc_blockchain.py | 2 +- test/functional/rpc_decodescript.py | 2 +- test/functional/rpc_deprecated.py | 2 +- test/functional/rpc_deriveaddresses.py | 2 +- test/functional/rpc_fundrawtransaction.py | 2 +- test/functional/rpc_getblockstats.py | 2 +- test/functional/rpc_named_arguments.py | 2 +- test/functional/rpc_preciousblock.py | 2 +- test/functional/rpc_psbt.py | 2 +- test/functional/rpc_rawtransaction.py | 2 +- test/functional/rpc_scantxoutset.py | 2 +- test/functional/rpc_signmessage.py | 2 +- test/functional/rpc_signrawtransaction.py | 2 +- test/functional/rpc_uptime.py | 2 +- test/functional/test_framework/address.py | 2 +- test/functional/test_framework/messages.py | 2 +- test/functional/test_framework/mininode.py | 2 +- test/functional/test_framework/netutil.py | 2 +- test/functional/test_framework/script.py | 2 +- test/functional/test_framework/socks5.py | 2 +- test/functional/test_framework/test_framework.py | 2 +- test/functional/test_framework/test_node.py | 2 +- test/functional/test_framework/util.py | 2 +- test/functional/test_runner.py | 2 +- test/functional/wallet_address_types.py | 2 +- test/functional/wallet_bumpfee.py | 2 +- test/functional/wallet_create_tx.py | 2 +- test/functional/wallet_createwallet.py | 2 +- test/functional/wallet_disable.py | 2 +- test/functional/wallet_dump.py | 2 +- test/functional/wallet_hd.py | 2 +- test/functional/wallet_importmulti.py | 2 +- test/functional/wallet_keypool.py | 2 +- test/functional/wallet_keypool_topup.py | 2 +- test/functional/wallet_listtransactions.py | 2 +- test/functional/wallet_multiwallet.py | 2 +- test/functional/wallet_txn_clone.py | 2 +- test/functional/wallet_txn_doublespend.py | 2 +- test/lint/check-doc.py | 2 +- test/lint/lint-format-strings.py | 2 +- 71 files changed, 71 insertions(+), 71 deletions(-) diff --git a/test/functional/example_test.py b/test/functional/example_test.py index f367e4fca8..0e70ebba6d 100755 --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """An example functional test diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py index 0eb3dd440b..e7e4f84ad9 100755 --- a/test/functional/feature_assumevalid.py +++ b/test/functional/feature_assumevalid.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test logic for skipping signature validation on old blocks. diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index 206c8a88ad..21c832c1a9 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test BIP68 implementation.""" diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index b422bf2873..070242c1df 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test BIP65 (CHECKLOCKTIMEVERIFY). diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 4b3f6603a2..5fe3e3a849 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test various command line arguments and configuration file parameters.""" diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py index d98d2aa992..ecc68217bb 100755 --- a/test/functional/feature_csv_activation.py +++ b/test/functional/feature_csv_activation.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test activation of the first version bits soft fork. diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 18416c3ab1..4ddfd80b07 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test BIP66 (DER SIG). diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py index b98dd6d26c..13cf951550 100755 --- a/test/functional/feature_notifications.py +++ b/test/functional/feature_notifications.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the -alertnotify, -blocknotify and -walletnotify options.""" diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index c564c7fe2b..e5d2f8dc46 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test NULLDUMMY softfork. diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index 2ff773bf6e..be323d355e 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test bitcoind with different proxy configuration. diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index fe8e1cde2f..12da2655ee 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the pruning code. diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index 1c8fc438d1..a9c7226e46 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the RBF code.""" diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index 8157ef69fe..0128af8b65 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the SegWit changeover logic.""" diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index 753287ac7a..0713925141 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test version bits warning system. diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index 75583cb56c..f44fc768dc 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test bitcoin-cli""" diff --git a/test/functional/interface_http.py b/test/functional/interface_http.py index f18ccb4aca..bb868d7115 100755 --- a/test/functional/interface_http.py +++ b/test/functional/interface_http.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the RPC HTTP basics.""" diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index 2844e42f62..a036dfc790 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the REST API.""" diff --git a/test/functional/interface_rpc.py b/test/functional/interface_rpc.py index b6955d4492..67ab1f0130 100755 --- a/test/functional/interface_rpc.py +++ b/test/functional/interface_rpc.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Tests some generic aspects of the RPC interface.""" diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index e59c0f32b3..8e58c85c15 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the ZMQ notification interface.""" diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index f6a17eaf40..fc81119050 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test mempool acceptance of raw transactions.""" diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index 976f39c32b..351b27e94a 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test mempool limiting together/eviction with the wallet.""" diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index b98bb7ec28..7cee215d54 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test descendant package tracking code.""" diff --git a/test/functional/mempool_resurrect.py b/test/functional/mempool_resurrect.py index b606fccec9..187c9026f6 100755 --- a/test/functional/mempool_resurrect.py +++ b/test/functional/mempool_resurrect.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test resurrection of mined transactions when the blockchain is re-organized.""" diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py index 0c4e29561d..445ec124ce 100755 --- a/test/functional/mining_getblocktemplate_longpoll.py +++ b/test/functional/mining_getblocktemplate_longpoll.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test longpolling with getblocktemplate.""" diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py index 975d1e6a6b..687a5b527b 100755 --- a/test/functional/mining_prioritisetransaction.py +++ b/test/functional/mining_prioritisetransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the prioritisetransaction mining RPC.""" diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py index 47c05e2a6a..82a14af9da 100755 --- a/test/functional/p2p_compactblocks.py +++ b/test/functional/p2p_compactblocks.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test compact blocks (BIP 152). diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py index e907cc600f..b9863cf215 100755 --- a/test/functional/p2p_feefilter.py +++ b/test/functional/p2p_feefilter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test processing of feefilter messages.""" diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py index fdc51f25c3..06049db54c 100755 --- a/test/functional/p2p_leak.py +++ b/test/functional/p2p_leak.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test message sending before handshake completion. diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index 7d38fbb00d..73bfdc868c 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test segwit transactions and blocks on P2P network.""" diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py index a118b891e5..027852809b 100755 --- a/test/functional/p2p_unrequested_blocks.py +++ b/test/functional/p2p_unrequested_blocks.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test processing of unrequested blocks. diff --git a/test/functional/rpc_bind.py b/test/functional/rpc_bind.py index 3938ca98dd..acc7cd811c 100755 --- a/test/functional/rpc_bind.py +++ b/test/functional/rpc_bind.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test running bitcoind with the -rpcbind and -rpcallowip options.""" diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 6693042f84..facb05b54c 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test RPCs related to blockchainstate. diff --git a/test/functional/rpc_decodescript.py b/test/functional/rpc_decodescript.py index fbd273ab00..01b8cb1854 100755 --- a/test/functional/rpc_decodescript.py +++ b/test/functional/rpc_decodescript.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test decoding scripts via decodescript RPC command.""" diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index 530f457ae7..9a21998d11 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test deprecation of RPC calls.""" diff --git a/test/functional/rpc_deriveaddresses.py b/test/functional/rpc_deriveaddresses.py index 185dffd51c..1984694692 100755 --- a/test/functional/rpc_deriveaddresses.py +++ b/test/functional/rpc_deriveaddresses.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the deriveaddresses rpc call.""" diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 4d3c452f33..d89fd6461f 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the fundrawtransaction RPC.""" diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py index feba16f1b3..e17a8f6421 100755 --- a/test/functional/rpc_getblockstats.py +++ b/test/functional/rpc_getblockstats.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 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/functional/rpc_named_arguments.py b/test/functional/rpc_named_arguments.py index 734c5a7779..ecac9c2f82 100755 --- a/test/functional/rpc_named_arguments.py +++ b/test/functional/rpc_named_arguments.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test using named arguments for RPCs.""" diff --git a/test/functional/rpc_preciousblock.py b/test/functional/rpc_preciousblock.py index bfa15f69f2..da228df9c3 100755 --- a/test/functional/rpc_preciousblock.py +++ b/test/functional/rpc_preciousblock.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the preciousblock RPC.""" diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 165746f1f8..885e07c4dd 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the Partially Signed Transaction RPCs. diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index 5f9bdb4703..fba9e75268 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the rawtransaction RPCs. diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py index 18258f5df3..6346477922 100755 --- a/test/functional/rpc_scantxoutset.py +++ b/test/functional/rpc_scantxoutset.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the scantxoutset rpc call.""" diff --git a/test/functional/rpc_signmessage.py b/test/functional/rpc_signmessage.py index 2e39774a92..0cb3ce4215 100755 --- a/test/functional/rpc_signmessage.py +++ b/test/functional/rpc_signmessage.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test RPC commands for signing and verifying messages.""" diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py index e603b5cb4f..dcafc82857 100755 --- a/test/functional/rpc_signrawtransaction.py +++ b/test/functional/rpc_signrawtransaction.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test transaction signing using the signrawtransaction* RPCs.""" diff --git a/test/functional/rpc_uptime.py b/test/functional/rpc_uptime.py index d03775f04e..e86f91b1d0 100755 --- a/test/functional/rpc_uptime.py +++ b/test/functional/rpc_uptime.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the RPC call related to the uptime command. diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index 6a17d8480e..f36cffe957 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Encode and decode BASE58, P2PKH and P2SH addresses.""" diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 3413a94f7e..7cf51d9223 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Copyright (c) 2010 ArtForz -- public domain half-a-node # Copyright (c) 2012 Jeff Garzik -# Copyright (c) 2010-2018 The Bitcoin Core developers +# Copyright (c) 2010-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Bitcoin test framework primitive and message structures diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index ee070981ed..52a840941b 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Copyright (c) 2010 ArtForz -- public domain half-a-node # Copyright (c) 2012 Jeff Garzik -# Copyright (c) 2010-2018 The Bitcoin Core developers +# Copyright (c) 2010-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Bitcoin P2P network half-a-node. diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py index bf80d632cb..c98424e8e2 100644 --- a/test/functional/test_framework/netutil.py +++ b/test/functional/test_framework/netutil.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Linux network utilities. diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 0661367a45..384062b808 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Functionality to build scripts, as well as SignatureHash(). diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py index 959f0023b1..799b1c74b8 100644 --- a/test/functional/test_framework/socks5.py +++ b/test/functional/test_framework/socks5.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Dummy Socks5 server for testing.""" diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 09d7d877a7..15d2e08c93 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Base class for RPC testing.""" diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 9d8560c4d8..ec5d3b267e 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Class for bitcoind node under test""" diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index b51239ae0f..034ed893f4 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Helpful routines for regression testing.""" diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index bb9ac58e46..a0d9f820e6 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Run regression test suite. diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py index f213de1bb0..a44aa5a18e 100755 --- a/test/functional/wallet_address_types.py +++ b/test/functional/wallet_address_types.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test that the wallet can send and receive using all combinations of address types. diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 67af495023..fc752e5ac0 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the bumpfee RPC. diff --git a/test/functional/wallet_create_tx.py b/test/functional/wallet_create_tx.py index 7b749235e2..0b584a0bb2 100755 --- a/test/functional/wallet_create_tx.py +++ b/test/functional/wallet_create_tx.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 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/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index fb964c718c..8ec4b98b6e 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test createwallet arguments. diff --git a/test/functional/wallet_disable.py b/test/functional/wallet_disable.py index 22efaed18e..7c2ec56b5a 100755 --- a/test/functional/wallet_disable.py +++ b/test/functional/wallet_disable.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test a node with the -disablewallet option. diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py index 5cf0e613d8..53edf710b9 100755 --- a/test/functional/wallet_dump.py +++ b/test/functional/wallet_dump.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the dumpwallet RPC.""" diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py index 61245e5104..97172d8b82 100755 --- a/test/functional/wallet_hd.py +++ b/test/functional/wallet_hd.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test Hierarchical Deterministic wallet function.""" diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index e6c01e99e9..5bfbaa2f0b 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the importmulti RPC. diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index 2b34cff8a6..e3aeb61197 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet keypool and interaction with wallet encryption/locking.""" diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py index 8300d12752..e099bab6a3 100755 --- a/test/functional/wallet_keypool_topup.py +++ b/test/functional/wallet_keypool_topup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test HD Wallet keypool restore function. diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py index 459dbc6612..f8268fab35 100755 --- a/test/functional/wallet_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the listtransactions API.""" diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index df778f57df..984ffab5a4 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test multiwallet. diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index 2f927502ff..af1b321a07 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet accounts properly when there are cloned transactions with malleated scriptsigs.""" diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index 9050e21247..8dcfd74f56 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2018 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet accounts properly when there is a double-spend conflict.""" diff --git a/test/lint/check-doc.py b/test/lint/check-doc.py index c370ce0c04..3b05d5055c 100755 --- a/test/lint/check-doc.py +++ b/test/lint/check-doc.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2018 The Bitcoin Core developers +# Copyright (c) 2015-2019 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-format-strings.py b/test/lint/lint-format-strings.py index 459b7fc413..263962f580 100755 --- a/test/lint/lint-format-strings.py +++ b/test/lint/lint-format-strings.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # From dddd1d05d3df06865f5e0b1442d7425c0955de4e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 2 Mar 2019 12:08:41 -0500 Subject: [PATCH 0101/4486] .python-version: Specify full version 3.5.6 --- .python-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.python-version b/.python-version index 5a958026da..c49282585a 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.5 +3.5.6 From fa3148aacbea0e1a0ba8016b66b8d6b876c267b2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Mar 2019 11:22:36 -0500 Subject: [PATCH 0102/4486] doc: Remove ppa from linux build instructions --- doc/build-unix.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/doc/build-unix.md b/doc/build-unix.md index 522e3069ce..da65bc347a 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -78,19 +78,13 @@ Now, you can either build from self-compiled [depends](/depends/README.md) or in BerkeleyDB is required for the wallet. -**For Ubuntu only:** db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin). -You can add the repository and install using the following commands: - - sudo apt-get install software-properties-common - sudo add-apt-repository ppa:bitcoin/bitcoin - sudo apt-get update - sudo apt-get install libdb4.8-dev libdb4.8++-dev - Ubuntu and Debian have their own libdb-dev and libdb++-dev packages, but these will install BerkeleyDB 5.1 or later. This will break binary wallet compatibility with the distributed executables, which are based on BerkeleyDB 4.8. If you do not care about wallet compatibility, pass `--with-incompatible-bdb` to configure. +Otherwise, you can build from self-compiled `depends` (see above). + To build Bitcoin Core without wallet, see [*Disable-wallet mode*](/doc/build-unix.md#disable-wallet-mode) From 73aaf4ecf825a4d18c802ca5dd3856ce9096915e Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Sun, 15 Jul 2018 12:19:12 -0400 Subject: [PATCH 0103/4486] Make SignatureExtractorChecker private to its own file It's only used here in DataFromTransaction --- src/script/sign.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 320956d0c4..4af66008d6 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -243,6 +243,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato return sigdata.complete; } +namespace { class SignatureExtractorChecker final : public BaseSignatureChecker { private: @@ -251,21 +252,17 @@ class SignatureExtractorChecker final : public BaseSignatureChecker public: SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : sigdata(sigdata), checker(checker) {} - bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override; -}; - -bool SignatureExtractorChecker::CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const -{ - if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) { - CPubKey pubkey(vchPubKey); - sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig)); - return true; + bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override + { + if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) { + CPubKey pubkey(vchPubKey); + sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig)); + return true; + } + return false; } - return false; -} +}; -namespace -{ struct Stacks { std::vector script; From 47101bbb27d0e13ea2b40ce1c7ff0dba9030f369 Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Thu, 12 Apr 2018 13:30:04 -0700 Subject: [PATCH 0104/4486] scripted-diff: Rename CPubKey and CKey::*_KEY_SIZE and COMPRESSED_*_KEY_SIZE To SIZE and COMPRESSED_SIZE -BEGIN VERIFY SCRIPT- sed -i 's/PRIVATE_KEY_SIZE/SIZE/g' src/*.h src/*.cpp src/**/*.h src/**/*.cpp sed -i 's/COMPRESSED_PRIVATE_KEY_SIZE/COMPRESSED_SIZE/g' src/*.h src/**/*.cpp src/**/*.h src/**/*.cpp sed -i 's/PUBLIC_KEY_SIZE/SIZE/g' src/*.h src/*.cpp src/**/*.h src/**/*.cpp sed -i 's/COMPRESSED_PUBLIC_KEY_SIZE/COMPRESSED_SIZE/g' src/*.h src/*.cpp src/**/*.h src/**/*.cpp -END VERIFY SCRIPT- --- src/key.cpp | 20 ++++++++++---------- src/key.h | 10 +++++----- src/psbt.h | 2 +- src/pubkey.cpp | 18 +++++++++--------- src/pubkey.h | 18 +++++++++--------- src/script/interpreter.cpp | 8 ++++---- src/script/sign.h | 2 +- src/script/standard.cpp | 8 ++++---- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 9d982fc44f..652041f4fb 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -84,13 +84,13 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou * . The optional parameters and publicKey fields are * included. * - * privkey must point to an output buffer of length at least CKey::PRIVATE_KEY_SIZE bytes. + * privkey must point to an output buffer of length at least CKey::SIZE bytes. * privkeylen must initially be set to the size of the privkey buffer. Upon return it * will be set to the number of bytes used in the buffer. * key32 must point to a 32-byte raw private key. */ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, bool compressed) { - assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE); + assert(*privkeylen >= CKey::SIZE); secp256k1_pubkey pubkey; size_t pubkeylen = 0; if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { @@ -116,11 +116,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = CPubKey::COMPRESSED_PUBLIC_KEY_SIZE; + pubkeylen = CPubKey::COMPRESSED_SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; - assert(*privkeylen == CKey::COMPRESSED_PRIVATE_KEY_SIZE); + assert(*privkeylen == CKey::COMPRESSED_SIZE); } else { static const unsigned char begin[] = { 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 @@ -142,11 +142,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = CPubKey::PUBLIC_KEY_SIZE; + pubkeylen = CPubKey::SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; - assert(*privkeylen == CKey::PRIVATE_KEY_SIZE); + assert(*privkeylen == CKey::SIZE); } return 1; } @@ -168,8 +168,8 @@ CPrivKey CKey::GetPrivKey() const { CPrivKey privkey; int ret; size_t privkeylen; - privkey.resize(PRIVATE_KEY_SIZE); - privkeylen = PRIVATE_KEY_SIZE; + privkey.resize(SIZE); + privkeylen = SIZE; ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed); assert(ret); privkey.resize(privkeylen); @@ -179,7 +179,7 @@ CPrivKey CKey::GetPrivKey() const { CPubKey CKey::GetPubKey() const { assert(fValid); secp256k1_pubkey pubkey; - size_t clen = CPubKey::PUBLIC_KEY_SIZE; + size_t clen = CPubKey::SIZE; CPubKey result; int ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, begin()); assert(ret); @@ -271,7 +271,7 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const std::vector> vout(64); if ((nChild >> 31) == 0) { CPubKey pubkey = GetPubKey(); - assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); + assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data()); } else { assert(size() == 32); diff --git a/src/key.h b/src/key.h index 0f695c07b7..3a935d70f1 100644 --- a/src/key.h +++ b/src/key.h @@ -19,7 +19,7 @@ /** * secure_allocator is defined in allocators.h * CPrivKey is a serialized private key, with all parameters included - * (PRIVATE_KEY_SIZE bytes) + * (SIZE bytes) */ typedef std::vector > CPrivKey; @@ -30,15 +30,15 @@ class CKey /** * secp256k1: */ - static const unsigned int PRIVATE_KEY_SIZE = 279; - static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214; + static const unsigned int SIZE = 279; + static const unsigned int COMPRESSED_SIZE = 214; /** * see www.keylength.com * script supports up to 75 for single byte push */ static_assert( - PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE, - "COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE"); + SIZE >= COMPRESSED_SIZE, + "COMPRESSED_SIZE is larger than SIZE"); private: //! Whether this private key is valid. We check for correctness when modifying the key diff --git a/src/psbt.h b/src/psbt.h index c889dad361..99a56b3b3d 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -165,7 +165,7 @@ struct PSBTInput case PSBT_IN_PARTIAL_SIG: { // Make sure that the key is the size of pubkey + 1 - if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) { + if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) { throw std::ios_base::failure("Size of key was not the expected size for the type partial signature pubkey"); } // Read in the pubkey from key diff --git a/src/pubkey.cpp b/src/pubkey.cpp index d38df716bd..10953adc35 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -196,8 +196,8 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector> 31) == 0); - assert(size() == COMPRESSED_PUBLIC_KEY_SIZE); + assert(size() == COMPRESSED_SIZE); unsigned char out[64]; BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild.begin(), out+32, 32); @@ -238,8 +238,8 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) { return false; } - unsigned char pub[COMPRESSED_PUBLIC_KEY_SIZE]; - size_t publen = COMPRESSED_PUBLIC_KEY_SIZE; + unsigned char pub[COMPRESSED_SIZE]; + size_t publen = COMPRESSED_SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED); pubkeyChild.Set(pub, pub + publen); return true; @@ -251,8 +251,8 @@ void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; memcpy(code+9, chaincode.begin(), 32); - assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); - memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); + assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); + memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_SIZE); } void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { diff --git a/src/pubkey.h b/src/pubkey.h index 089324ffda..918aba273f 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -33,8 +33,8 @@ class CPubKey /** * secp256k1: */ - static constexpr unsigned int PUBLIC_KEY_SIZE = 65; - static constexpr unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; + static constexpr unsigned int SIZE = 65; + static constexpr unsigned int COMPRESSED_SIZE = 33; static constexpr unsigned int SIGNATURE_SIZE = 72; static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; /** @@ -42,8 +42,8 @@ class CPubKey * script supports up to 75 for single byte push */ static_assert( - PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE, - "COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE"); + SIZE >= COMPRESSED_SIZE, + "COMPRESSED_SIZE is larger than SIZE"); private: @@ -51,15 +51,15 @@ class CPubKey * Just store the serialized data. * Its length can very cheaply be computed from the first byte. */ - unsigned char vch[PUBLIC_KEY_SIZE]; + unsigned char vch[SIZE]; //! Compute the length of a pubkey with a given first byte. unsigned int static GetLen(unsigned char chHeader) { if (chHeader == 2 || chHeader == 3) - return COMPRESSED_PUBLIC_KEY_SIZE; + return COMPRESSED_SIZE; if (chHeader == 4 || chHeader == 6 || chHeader == 7) - return PUBLIC_KEY_SIZE; + return SIZE; return 0; } @@ -140,7 +140,7 @@ class CPubKey void Unserialize(Stream& s) { unsigned int len = ::ReadCompactSize(s); - if (len <= PUBLIC_KEY_SIZE) { + if (len <= SIZE) { s.read((char*)vch, len); } else { // invalid pubkey, skip available data @@ -179,7 +179,7 @@ class CPubKey //! Check whether this is a compressed public key. bool IsCompressed() const { - return size() == COMPRESSED_PUBLIC_KEY_SIZE; + return size() == COMPRESSED_SIZE; } /** diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 95b25b4911..7f9db59c45 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -61,17 +61,17 @@ static inline void popstack(std::vector& stack) } bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() < CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() < CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: too short return false; } if (vchPubKey[0] == 0x04) { - if (vchPubKey.size() != CPubKey::PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::SIZE) { // Non-canonical public key: invalid length for uncompressed key return false; } } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) { - if (vchPubKey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: invalid length for compressed key return false; } @@ -83,7 +83,7 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { } bool static IsCompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: invalid length for compressed key return false; } diff --git a/src/script/sign.h b/src/script/sign.h index 491fb54c45..ed65397d6b 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -168,7 +168,7 @@ template void DeserializeHDKeypaths(Stream& s, const std::vector& key, std::map& hd_keypaths) { // Make sure that the key is the size of pubkey + 1 - if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) { + if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) { throw std::ios_base::failure("Size of key was not the expected size for the type BIP32 keypath"); } // Read in the pubkey from key diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 31bfd04b0f..eb704ebb19 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -43,12 +43,12 @@ const char* GetTxnOutputType(txnouttype t) static bool MatchPayToPubkey(const CScript& script, valtype& pubkey) { - if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { - pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1); + if (script.size() == CPubKey::SIZE + 2 && script[0] == CPubKey::SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::SIZE + 1); return CPubKey::ValidSize(pubkey); } - if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { - pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1); + if (script.size() == CPubKey::COMPRESSED_SIZE + 2 && script[0] == CPubKey::COMPRESSED_SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_SIZE + 1); return CPubKey::ValidSize(pubkey); } return false; From 0580f86bb48004b797d4cb6273e7ffee0b0a0584 Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Mon, 4 Mar 2019 01:26:31 -0800 Subject: [PATCH 0105/4486] Fixup whitespace --- src/pubkey.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pubkey.h b/src/pubkey.h index 918aba273f..c2900f0b07 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -33,10 +33,10 @@ class CPubKey /** * secp256k1: */ - static constexpr unsigned int SIZE = 65; - static constexpr unsigned int COMPRESSED_SIZE = 33; - static constexpr unsigned int SIGNATURE_SIZE = 72; - static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; + static constexpr unsigned int SIZE = 65; + static constexpr unsigned int COMPRESSED_SIZE = 33; + static constexpr unsigned int SIGNATURE_SIZE = 72; + static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; /** * see www.keylength.com * script supports up to 75 for single byte push From c7ea8d3236e7c1b0c198345cc78a6754338d3724 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Mon, 4 Mar 2019 11:03:50 +0100 Subject: [PATCH 0106/4486] Add sizeof(size_t) assumptions --- src/compat/assumptions.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compat/assumptions.h b/src/compat/assumptions.h index 820c9b93d9..0d39f66dbd 100644 --- a/src/compat/assumptions.h +++ b/src/compat/assumptions.h @@ -40,8 +40,13 @@ static_assert(sizeof(double) == 8, "64-bit double assumed"); static_assert(sizeof(short) == 2, "16-bit short assumed"); static_assert(sizeof(int) == 4, "32-bit int assumed"); +// Assumption: We assume size_t to be 32-bit or 64-bit. +// Example(s): size_t assumed to be at least 32-bit in ecdsa_signature_parse_der_lax(...). +// size_t assumed to be 32-bit or 64-bit in MallocUsage(...). +static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t assumed to be 32-bit or 64-bit"); +static_assert(sizeof(size_t) == sizeof(void*), "Sizes of size_t and void* assumed to be equal"); + // Some important things we are NOT assuming (non-exhaustive list): -// * We are NOT assuming a specific value for sizeof(std::size_t). // * We are NOT assuming a specific value for std::endian::native. // * We are NOT assuming a specific value for std::locale("").name(). // * We are NOT assuming a specific value for std::numeric_limits::is_signed. From fad76e7a49dc66b7b50902ee14a73808780d11bb Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 4 Mar 2019 14:08:54 -0500 Subject: [PATCH 0107/4486] doc: Remove pr release notes file in wrong dir --- doc/release-notes/release-notes-pr12255.md | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 doc/release-notes/release-notes-pr12255.md diff --git a/doc/release-notes/release-notes-pr12255.md b/doc/release-notes/release-notes-pr12255.md deleted file mode 100644 index 5ac8b44283..0000000000 --- a/doc/release-notes/release-notes-pr12255.md +++ /dev/null @@ -1,17 +0,0 @@ -systemd init file -========= - -The systemd init file (`contrib/init/bitcoind.service`) has been changed to use -`/var/lib/bitcoind` as the data directory instead of `~bitcoin/.bitcoin`. This -change makes Bitcoin Core more consistent with other services, and makes the -systemd init config more consistent with existing Upstart and OpenRC configs. - -The configuration, PID, and data directories are now completely managed by -systemd, which will take care of their creation, permissions, etc. See -[`systemd.exec (5)`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RuntimeDirectory=) -for more details. - -When using the provided init files under `contrib/init`, overriding the -`datadir` option in `/etc/bitcoin/bitcoin.conf` will have no effect. This is -because the command line arguments specified in the init files take precedence -over the options specified in `/etc/bitcoin/bitcoin.conf`. From fa58a2e335d417bc660bd9384157e223a2d86af8 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 4 Mar 2019 14:44:48 -0500 Subject: [PATCH 0108/4486] contrib: Bump gitian descriptors for 0.19 --- contrib/gitian-descriptors/gitian-linux.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 2 +- contrib/gitian-descriptors/gitian-win.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index e97072c80a..391c166e56 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-linux-0.18" +name: "bitcoin-core-linux-0.19" enable_cache: true suites: - "bionic" diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 87d8007ccb..46e056dc32 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-osx-0.18" +name: "bitcoin-core-osx-0.19" enable_cache: true suites: - "bionic" diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 31b9c309c7..fa1989f994 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-win-0.18" +name: "bitcoin-core-win-0.19" enable_cache: true suites: - "bionic" From 4d4e4c644826db03317d69a04fea03309c3ebabf Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Mon, 4 Mar 2019 15:57:58 -0500 Subject: [PATCH 0109/4486] Suggested interfaces::Chain cleanups from #15288 Mostly documentation improvements requested in the last review of #15288 before it was merged (https://github.com/bitcoin/bitcoin/pull/15288#pullrequestreview-210241864) --- src/interfaces/README.md | 4 ++-- src/interfaces/chain.cpp | 8 ++++---- src/interfaces/chain.h | 38 ++++++++++++++++++++++++++++++-------- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/interfaces/README.md b/src/interfaces/README.md index 57d41df746..f77d172153 100644 --- a/src/interfaces/README.md +++ b/src/interfaces/README.md @@ -2,9 +2,9 @@ The following interfaces are defined here: -* [`Chain`](chain.h) — used by wallet to access blockchain and mempool state. Added in [#10973](https://github.com/bitcoin/bitcoin/pull/10973). +* [`Chain`](chain.h) — used by wallet to access blockchain and mempool state. Added in [#14437](https://github.com/bitcoin/bitcoin/pull/14437), [#14711](https://github.com/bitcoin/bitcoin/pull/14711), [#15288](https://github.com/bitcoin/bitcoin/pull/15288), and [#10973](https://github.com/bitcoin/bitcoin/pull/10973). -* [`ChainClient`](chain.h) — used by node to start & stop `Chain` clients. Added in [#10973](https://github.com/bitcoin/bitcoin/pull/10973). +* [`ChainClient`](chain.h) — used by node to start & stop `Chain` clients. Added in [#14437](https://github.com/bitcoin/bitcoin/pull/14437). * [`Node`](node.h) — used by GUI to start & stop bitcoin node. Added in [#10244](https://github.com/bitcoin/bitcoin/pull/10244). diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index fb634e73da..2eecea28d0 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -148,7 +148,7 @@ class LockImpl : public Chain::Lock LockAnnotation lock(::cs_main); return CheckFinalTx(tx); } - bool submitToMemoryPool(CTransactionRef tx, CAmount absurd_fee, CValidationState& state) override + bool submitToMemoryPool(const CTransactionRef& tx, CAmount absurd_fee, CValidationState& state) override { LockAnnotation lock(::cs_main); return AcceptToMemoryPool(::mempool, state, tx, nullptr /* missing inputs */, nullptr /* txn replaced */, @@ -207,8 +207,8 @@ class ChainImpl : public Chain bool hasDescendantsInMempool(const uint256& txid) override { LOCK(::mempool.cs); - auto it_mp = ::mempool.mapTx.find(txid); - return it_mp != ::mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1; + auto it = ::mempool.GetIter(txid); + return it && (*it)->GetCountWithDescendants() > 1; } void relayTransaction(const uint256& txid) override { @@ -219,7 +219,7 @@ class ChainImpl : public Chain { ::mempool.GetTransactionAncestry(txid, ancestors, descendants); } - bool checkChainLimits(CTransactionRef tx) override + bool checkChainLimits(const CTransactionRef& tx) override { LockPoints lp; CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp); diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 60f8570e36..037e8e9ff5 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -6,7 +6,6 @@ #define BITCOIN_INTERFACES_CHAIN_H #include // For Optional and nullopt -#include // For RBFTransactionState #include // For CTransactionRef #include @@ -16,9 +15,11 @@ #include class CBlock; +class CFeeRate; class CScheduler; class CValidationState; class uint256; +enum class RBFTransactionState; struct CBlockLocator; struct FeeCalculation; @@ -26,7 +27,27 @@ namespace interfaces { class Wallet; -//! Interface for giving wallet processes access to blockchain state. +//! Interface giving clients (wallet processes, maybe other analysis tools in +//! the future) ability to access to the chain state, receive notifications, +//! estimate fees, and submit transactions. +//! +//! TODO: Current chain methods are too low level, exposing too much of the +//! internal workings of the bitcoin node, and not being very convenient to use. +//! Chain methods should be cleaned up and simplified over time. Examples: +//! +//! * The Chain::lock() method, which lets clients delay chain tip updates +//! should be removed when clients are able to respond to updates +//! asynchronously +//! (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269). +//! +//! * The relayTransactions() and submitToMemoryPool() methods could be replaced +//! with a higher-level broadcastTransaction method +//! (https://github.com/bitcoin/bitcoin/pull/14978#issuecomment-459373984). +//! +//! * The initMessages() and loadWallet() methods which the wallet uses to send +//! notifications to the GUI should go away when GUI and wallet can directly +//! communicate with each other without going through the node +//! (https://github.com/bitcoin/bitcoin/pull/15288#discussion_r253321096). class Chain { public: @@ -114,8 +135,9 @@ class Chain virtual bool checkFinalTx(const CTransaction& tx) = 0; //! Add transaction to memory pool if the transaction fee is below the - //! amount specified by absurd_fee (as a safeguard). */ - virtual bool submitToMemoryPool(CTransactionRef tx, CAmount absurd_fee, CValidationState& state) = 0; + //! amount specified by absurd_fee. Returns false if the transaction + //! could not be added due to the fee or for another reason. + virtual bool submitToMemoryPool(const CTransactionRef& tx, CAmount absurd_fee, CValidationState& state) = 0; }; //! Return Lock interface. Chain is locked when this is called, and @@ -154,8 +176,8 @@ class Chain //! Calculate mempool ancestor and descendant counts for the given transaction. virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0; - //! Check chain limits. - virtual bool checkChainLimits(CTransactionRef tx) = 0; + //! Check if transaction will pass the mempool's chain limits. + virtual bool checkChainLimits(const CTransactionRef& tx) = 0; //! Estimate smart fee. virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc = nullptr) = 0; @@ -163,10 +185,10 @@ class Chain //! Fee estimator max target. virtual unsigned int estimateMaxBlocks() = 0; - //! Pool min fee. + //! Mempool minimum fee. virtual CFeeRate mempoolMinFee() = 0; - //! Get node max tx fee setting (-maxtxfee). + //! Node max tx fee setting (-maxtxfee). //! This could be replaced by a per-wallet max fee, as proposed at //! https://github.com/bitcoin/bitcoin/issues/15355 //! But for the time being, wallets call this to access the node setting. From faebd2ef40bf6c9209110ad4e229e5a207b9c9da Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 18 Feb 2019 16:09:45 -0500 Subject: [PATCH 0110/4486] doc: Move wallet lock annotations to header --- src/wallet/wallet.cpp | 57 +++++++++++++++++++++---------------------- src/wallet/wallet.h | 10 ++++---- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 02f3a265d9..e47f5fa956 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -193,7 +193,7 @@ CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) { assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); assert(!IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)); - AssertLockHeld(cs_wallet); // mapKeyMetadata + AssertLockHeld(cs_wallet); bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets CKey secret; @@ -281,9 +281,9 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); } -bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& secret, const CPubKey &pubkey) +bool CWallet::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& secret, const CPubKey& pubkey) { - AssertLockHeld(cs_wallet); // mapKeyMetadata + AssertLockHeld(cs_wallet); // Make sure we aren't adding private keys to private key disabled wallets assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); @@ -345,16 +345,16 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, } } -void CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta) +void CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata& meta) { - AssertLockHeld(cs_wallet); // mapKeyMetadata + AssertLockHeld(cs_wallet); UpdateTimeFirstKey(meta.nCreateTime); mapKeyMetadata[keyID] = meta; } -void CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta) +void CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata& meta) { - AssertLockHeld(cs_wallet); // m_script_metadata + AssertLockHeld(cs_wallet); UpdateTimeFirstKey(meta.nCreateTime); m_script_metadata[script_id] = meta; } @@ -367,7 +367,7 @@ bool CWallet::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, void CWallet::UpgradeKeyMetadata() { - AssertLockHeld(cs_wallet); // mapKeyMetadata + AssertLockHeld(cs_wallet); if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) { return; } @@ -569,7 +569,7 @@ void CWallet::ChainStateFlushed(const CBlockLocator& loc) void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit) { - LOCK(cs_wallet); // nWalletVersion + LOCK(cs_wallet); if (nWalletVersion >= nVersion) return; @@ -593,7 +593,7 @@ void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool CWallet::SetMaxVersion(int nVersion) { - LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion + LOCK(cs_wallet); // cannot downgrade below current version if (nWalletVersion > nVersion) return false; @@ -877,9 +877,9 @@ DBErrors CWallet::ReorderTransactions() return DBErrors::LOAD_OK; } -int64_t CWallet::IncOrderPosNext(WalletBatch *batch) +int64_t CWallet::IncOrderPosNext(WalletBatch* batch) { - AssertLockHeld(cs_wallet); // nOrderPosNext + AssertLockHeld(cs_wallet); int64_t nRet = nOrderPosNext++; if (batch) { batch->WriteOrderPosNext(nOrderPosNext); @@ -2614,9 +2614,9 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm return res; } -bool CWallet::SignTransaction(CMutableTransaction &tx) +bool CWallet::SignTransaction(CMutableTransaction& tx) { - AssertLockHeld(cs_wallet); // mapWallet + AssertLockHeld(cs_wallet); // sign the new tx int nIn = 0; @@ -3230,8 +3230,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) DBErrors CWallet::ZapSelectTx(std::vector& vHashIn, std::vector& vHashOut) { - AssertLockHeld(cs_wallet); // mapWallet - DBErrors nZapSelectTxRet = WalletBatch(*database,"cr+").ZapSelectTx(vHashIn, vHashOut); + AssertLockHeld(cs_wallet); + DBErrors nZapSelectTxRet = WalletBatch(*database, "cr+").ZapSelectTx(vHashIn, vHashOut); for (uint256 hash : vHashOut) { const auto& it = mapWallet.find(hash); wtxOrdered.erase(it->second.m_it_wtxOrdered); @@ -3257,7 +3257,6 @@ DBErrors CWallet::ZapSelectTx(std::vector& vHashIn, std::vector& vWtx) @@ -3377,7 +3376,7 @@ bool CWallet::NewKeyPool() size_t CWallet::KeypoolCountExternalKeys() { - AssertLockHeld(cs_wallet); // setExternalKeyPool + AssertLockHeld(cs_wallet); return setExternalKeyPool.size() + set_pre_split_keypool.size(); } @@ -3641,7 +3640,7 @@ std::map CWallet::GetAddressBalances(interfaces::Chain: std::set< std::set > CWallet::GetAddressGroupings() { - AssertLockHeld(cs_wallet); // mapWallet + AssertLockHeld(cs_wallet); std::set< std::set > groupings; std::set grouping; @@ -3809,25 +3808,25 @@ void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id) void CWallet::LockCoin(const COutPoint& output) { - AssertLockHeld(cs_wallet); // setLockedCoins + AssertLockHeld(cs_wallet); setLockedCoins.insert(output); } void CWallet::UnlockCoin(const COutPoint& output) { - AssertLockHeld(cs_wallet); // setLockedCoins + AssertLockHeld(cs_wallet); setLockedCoins.erase(output); } void CWallet::UnlockAllCoins() { - AssertLockHeld(cs_wallet); // setLockedCoins + AssertLockHeld(cs_wallet); setLockedCoins.clear(); } bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const { - AssertLockHeld(cs_wallet); // setLockedCoins + AssertLockHeld(cs_wallet); COutPoint outpt(hash, n); return (setLockedCoins.count(outpt) > 0); @@ -3835,7 +3834,7 @@ bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const void CWallet::ListLockedCoins(std::vector& vOutpts) const { - AssertLockHeld(cs_wallet); // setLockedCoins + AssertLockHeld(cs_wallet); for (std::set::iterator it = setLockedCoins.begin(); it != setLockedCoins.end(); it++) { COutPoint outpt = (*it); @@ -3845,8 +3844,8 @@ void CWallet::ListLockedCoins(std::vector& vOutpts) const /** @} */ // end of Actions -void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map &mapKeyBirth) const { - AssertLockHeld(cs_wallet); // mapKeyMetadata +void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map& mapKeyBirth) const { + AssertLockHeld(cs_wallet); mapKeyBirth.clear(); // get birth times for keys with metadata @@ -4125,7 +4124,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, } } - int prev_version = walletInstance->nWalletVersion; + int prev_version = walletInstance->GetVersion(); if (gArgs.GetBoolArg("-upgradewallet", fFirstRun)) { int nMaxVersion = gArgs.GetArg("-upgradewallet", 0); @@ -4150,8 +4149,8 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, LOCK(walletInstance->cs_wallet); // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT - int max_version = walletInstance->nWalletVersion; - if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >=FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) { + int max_version = walletInstance->GetVersion(); + if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) { chain.initError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.")); return nullptr; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 51e3edac34..ea196c8799 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -648,7 +648,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr; //! the current wallet version: clients below this version are not able to load the wallet - int nWalletVersion = FEATURE_BASE; + int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE}; //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded int nWalletMaxVersion GUARDED_BY(cs_wallet) = FEATURE_BASE; @@ -698,11 +698,11 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface CHDChain hdChain; /* HD derive new child key (on internal or external chain) */ - void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void DeriveNewChildKey(WalletBatch& batch, CKeyMetadata& metadata, CKey& secret, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - std::set setInternalKeyPool; + std::set setInternalKeyPool GUARDED_BY(cs_wallet); std::set setExternalKeyPool GUARDED_BY(cs_wallet); - std::set set_pre_split_keypool; + std::set set_pre_split_keypool GUARDED_BY(cs_wallet); int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0; std::map m_pool_key_to_index; std::atomic m_wallet_flags{0}; @@ -1065,7 +1065,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { - AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool + AssertLockHeld(cs_wallet); return setInternalKeyPool.size() + setExternalKeyPool.size(); } From fa2797808ea0f055d1df7977deee80cc63e7b323 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 4 Mar 2019 18:21:51 -0500 Subject: [PATCH 0111/4486] test: Remove python3.4 workaround in feature_dbcrash --- test/functional/feature_dbcrash.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py index 8b06cc7372..62062926a6 100755 --- a/test/functional/feature_dbcrash.py +++ b/test/functional/feature_dbcrash.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2018 The Bitcoin Core developers +# Copyright (c) 2017-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test recovery from a crash during chainstate writing. @@ -28,18 +28,12 @@ import errno import http.client import random -import sys import time from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut, ToHex from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, create_confirmed_utxos, hex_str_to_bytes -HTTP_DISCONNECT_ERRORS = [http.client.CannotSendRequest] -try: - HTTP_DISCONNECT_ERRORS.append(http.client.RemoteDisconnected) -except AttributeError: - pass class ChainstateWriteCrashTest(BitcoinTestFramework): def set_test_params(self): @@ -110,14 +104,7 @@ def submit_block_catch_error(self, node_index, block): try: self.nodes[node_index].submitblock(block) return True - except http.client.BadStatusLine as e: - # Prior to 3.5 BadStatusLine('') was raised for a remote disconnect error. - if sys.version_info[0] == 3 and sys.version_info[1] < 5 and e.line == "''": - self.log.debug("node %d submitblock raised exception: %s", node_index, e) - return False - else: - raise - except tuple(HTTP_DISCONNECT_ERRORS) as e: + except (http.client.CannotSendRequest, http.client.RemoteDisconnected) as e: self.log.debug("node %d submitblock raised exception: %s", node_index, e) return False except OSError as e: From 1111f0718acea42954600a4dbd553ac40aae797f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 4 Mar 2019 18:34:39 -0500 Subject: [PATCH 0112/4486] test: .style.yapf: Set column_limit=160 --- .style.yapf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.style.yapf b/.style.yapf index fe6227baf6..69d8c6aee4 100644 --- a/.style.yapf +++ b/.style.yapf @@ -55,7 +55,7 @@ blank_line_before_nested_class_or_def=False coalesce_brackets=False # The column limit. -column_limit=79 +column_limit=160 # The style for continuation alignment. Possible values are: # From 21be609b4947c955b93dd2be3fbc7624f6e04325 Mon Sep 17 00:00:00 2001 From: Glenn Willen Date: Mon, 4 Mar 2019 17:10:11 -0800 Subject: [PATCH 0113/4486] In lint-format-strings, open files sequentially In lint-format-strings, we use python argparse to read our file arguments. In this mode, argparse opens all the files simultaneously. On OS X, where the default filehandle limit is 128, this causes the lint to fail. Instead, ask argparse for our filename arguments as strings, and open them one at a time using 'with open'. --- test/lint/lint-format-strings.py | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py index f5d4780b6d..187da91ef1 100755 --- a/test/lint/lint-format-strings.py +++ b/test/lint/lint-format-strings.py @@ -262,27 +262,27 @@ def main(): parser.add_argument("--skip-arguments", type=int, help="number of arguments before the format string " "argument (e.g. 1 in the case of fprintf)", default=0) parser.add_argument("function_name", help="function name (e.g. fprintf)", default=None) - parser.add_argument("file", type=argparse.FileType("r", encoding="utf-8"), nargs="*", help="C++ source code file (e.g. foo.cpp)") + parser.add_argument("file", nargs="*", help="C++ source code file (e.g. foo.cpp)") args = parser.parse_args() - exit_code = 0 - for f in args.file: - for function_call_str in parse_function_calls(args.function_name, f.read()): - parts = parse_function_call_and_arguments(args.function_name, function_call_str) - relevant_function_call_str = unescape("".join(parts))[:512] - if (f.name, relevant_function_call_str) in FALSE_POSITIVES: - continue - if len(parts) < 3 + args.skip_arguments: - exit_code = 1 - print("{}: Could not parse function call string \"{}(...)\": {}".format(f.name, args.function_name, relevant_function_call_str)) - continue - argument_count = len(parts) - 3 - args.skip_arguments - format_str = parse_string_content(parts[1 + args.skip_arguments]) - format_specifier_count = count_format_specifiers(format_str) - if format_specifier_count != argument_count: - exit_code = 1 - print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format(f.name, format_specifier_count, argument_count, relevant_function_call_str)) - continue + for filename in args.file: + with open(filename, "r", encoding="utf-8") as f: + for function_call_str in parse_function_calls(args.function_name, f.read()): + parts = parse_function_call_and_arguments(args.function_name, function_call_str) + relevant_function_call_str = unescape("".join(parts))[:512] + if (f.name, relevant_function_call_str) in FALSE_POSITIVES: + continue + if len(parts) < 3 + args.skip_arguments: + exit_code = 1 + print("{}: Could not parse function call string \"{}(...)\": {}".format(f.name, args.function_name, relevant_function_call_str)) + continue + argument_count = len(parts) - 3 - args.skip_arguments + format_str = parse_string_content(parts[1 + args.skip_arguments]) + format_specifier_count = count_format_specifiers(format_str) + if format_specifier_count != argument_count: + exit_code = 1 + print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format(f.name, format_specifier_count, argument_count, relevant_function_call_str)) + continue sys.exit(exit_code) From 82c3b3f8e07f0572327275841333256fa3e679e3 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Mon, 4 Mar 2019 19:52:50 +0100 Subject: [PATCH 0114/4486] Remove sharp edge (uninitialized m_filter_type) when using the compiler-generated constructor for BlockFilter --- src/blockfilter.cpp | 2 ++ src/blockfilter.h | 5 +++-- src/test/blockfilter_tests.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp index bcf24047ff..e15213c552 100644 --- a/src/blockfilter.cpp +++ b/src/blockfilter.cpp @@ -251,6 +251,8 @@ bool BlockFilter::BuildParams(GCSFilter::Params& params) const params.m_P = BASIC_FILTER_P; params.m_M = BASIC_FILTER_M; return true; + case BlockFilterType::INVALID: + return false; } return false; diff --git a/src/blockfilter.h b/src/blockfilter.h index 4d1f51dd60..e5e087ed5a 100644 --- a/src/blockfilter.h +++ b/src/blockfilter.h @@ -83,9 +83,10 @@ class GCSFilter constexpr uint8_t BASIC_FILTER_P = 19; constexpr uint32_t BASIC_FILTER_M = 784931; -enum BlockFilterType : uint8_t +enum class BlockFilterType : uint8_t { BASIC = 0, + INVALID = 255, }; /** @@ -95,7 +96,7 @@ enum BlockFilterType : uint8_t class BlockFilter { private: - BlockFilterType m_filter_type; + BlockFilterType m_filter_type = BlockFilterType::INVALID; uint256 m_block_hash; GCSFilter m_filter; diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp index 625362f446..cd0c36d802 100644 --- a/src/test/blockfilter_tests.cpp +++ b/src/test/blockfilter_tests.cpp @@ -112,6 +112,12 @@ BOOST_AUTO_TEST_CASE(blockfilter_basic_test) BOOST_CHECK_EQUAL(block_filter.GetFilterType(), block_filter2.GetFilterType()); BOOST_CHECK_EQUAL(block_filter.GetBlockHash(), block_filter2.GetBlockHash()); BOOST_CHECK(block_filter.GetEncodedFilter() == block_filter2.GetEncodedFilter()); + + BlockFilter default_ctor_block_filter_1; + BlockFilter default_ctor_block_filter_2; + BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetFilterType(), default_ctor_block_filter_2.GetFilterType()); + BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetBlockHash(), default_ctor_block_filter_2.GetBlockHash()); + BOOST_CHECK(default_ctor_block_filter_1.GetEncodedFilter() == default_ctor_block_filter_2.GetEncodedFilter()); } BOOST_AUTO_TEST_CASE(blockfilters_json_test) From c7a7250302b60b78af39f39ee403d330c0cb7aa0 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Mon, 4 Mar 2019 14:55:44 +0100 Subject: [PATCH 0115/4486] Document assumptions about C++ compiler --- src/compat/assumptions.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/compat/assumptions.h b/src/compat/assumptions.h index 0d39f66dbd..6e7b4d3ded 100644 --- a/src/compat/assumptions.h +++ b/src/compat/assumptions.h @@ -17,6 +17,17 @@ # error "Bitcoin cannot be compiled without assertions." #endif +// Assumption: We assume a C++11 (ISO/IEC 14882:2011) compiler (minimum requirement). +// Example(s): We assume the presence of C++11 features everywhere :-) +// Note: MSVC does not report the expected __cplusplus value due to legacy +// reasons. +#if !defined(_MSC_VER) +// ISO Standard C++11 [cpp.predefined]p1: +// "The name __cplusplus is defined to the value 201103L when compiling a C++ +// translation unit." +static_assert(__cplusplus >= 201103L, "C++11 standard assumed"); +#endif + // Assumption: We assume the floating-point types to fulfill the requirements of // IEC 559 (IEEE 754) standard. // Example(s): Floating-point division by zero in ConnectBlock, CreateTransaction From 91868e6288abf9d133620b585bc6de793a11e0e3 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Sun, 30 Jul 2017 16:00:56 -0400 Subject: [PATCH 0116/4486] Remove use CValidationInterface in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 56 +++++++++++++++++++++++++ src/interfaces/chain.h | 26 ++++++++++++ src/wallet/test/wallet_test_fixture.cpp | 7 +--- src/wallet/test/wallet_test_fixture.h | 1 - src/wallet/wallet.cpp | 28 ++++++------- src/wallet/wallet.h | 14 +++++-- 6 files changed, 107 insertions(+), 25 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 2eecea28d0..8ce718cc50 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include @@ -161,6 +163,55 @@ class LockingStateImpl : public LockImpl, public UniqueLock using UniqueLock::UniqueLock; }; +class NotificationsHandlerImpl : public Handler, CValidationInterface +{ +public: + explicit NotificationsHandlerImpl(Chain& chain, Chain::Notifications& notifications) + : m_chain(chain), m_notifications(¬ifications) + { + RegisterValidationInterface(this); + } + ~NotificationsHandlerImpl() override { disconnect(); } + void disconnect() override + { + if (m_notifications) { + m_notifications = nullptr; + UnregisterValidationInterface(this); + } + } + void TransactionAddedToMempool(const CTransactionRef& tx) override + { + m_notifications->TransactionAddedToMempool(tx); + } + void TransactionRemovedFromMempool(const CTransactionRef& tx) override + { + m_notifications->TransactionRemovedFromMempool(tx); + } + void BlockConnected(const std::shared_ptr& block, + const CBlockIndex* index, + const std::vector& tx_conflicted) override + { + m_notifications->BlockConnected(*block, tx_conflicted); + } + void BlockDisconnected(const std::shared_ptr& block) override + { + m_notifications->BlockDisconnected(*block); + } + void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->ChainStateFlushed(locator); } + void ResendWalletTransactions(int64_t best_block_time, CConnman*) override + { + // `cs_main` is always held when this method is called, so it is safe to + // call `assumeLocked`. This is awkward, and the `assumeLocked` method + // should be able to be removed entirely if `ResendWalletTransactions` + // is replaced by a wallet timer as suggested in + // https://github.com/bitcoin/bitcoin/issues/15619 + auto locked_chain = m_chain.assumeLocked(); + m_notifications->ResendWalletTransactions(*locked_chain, best_block_time); + } + Chain& m_chain; + Chain::Notifications* m_notifications; +}; + class ChainImpl : public Chain { public: @@ -254,6 +305,11 @@ class ChainImpl : public Chain void initWarning(const std::string& message) override { InitWarning(message); } void initError(const std::string& message) override { InitError(message); } void loadWallet(std::unique_ptr wallet) override { ::uiInterface.LoadWallet(wallet); } + std::unique_ptr handleNotifications(Notifications& notifications) override + { + return MakeUnique(*this, notifications); + } + void waitForNotifications() override { SyncWithValidationInterfaceQueue(); } }; } // namespace diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 037e8e9ff5..72862617b3 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -25,6 +25,7 @@ struct FeeCalculation; namespace interfaces { +class Handler; class Wallet; //! Interface giving clients (wallet processes, maybe other analysis tools in @@ -40,6 +41,12 @@ class Wallet; //! asynchronously //! (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269). //! +//! * The isPotentialTip() and waitForNotifications() methods are too low-level +//! and should be replaced with a higher level +//! waitForNotificationsUpTo(block_hash) method that the wallet can call +//! instead +//! (https://github.com/bitcoin/bitcoin/pull/10973#discussion_r266995234). +//! //! * The relayTransactions() and submitToMemoryPool() methods could be replaced //! with a higher-level broadcastTransaction method //! (https://github.com/bitcoin/bitcoin/pull/14978#issuecomment-459373984). @@ -217,6 +224,25 @@ class Chain //! Send wallet load notification to the GUI. virtual void loadWallet(std::unique_ptr wallet) = 0; + + //! Chain notifications. + class Notifications + { + public: + virtual ~Notifications() {} + virtual void TransactionAddedToMempool(const CTransactionRef& tx) {} + virtual void TransactionRemovedFromMempool(const CTransactionRef& ptx) {} + virtual void BlockConnected(const CBlock& block, const std::vector& tx_conflicted) {} + virtual void BlockDisconnected(const CBlock& block) {} + virtual void ChainStateFlushed(const CBlockLocator& locator) {} + virtual void ResendWalletTransactions(Lock& locked_chain, int64_t best_block_time) {} + }; + + //! Register handler for notifications. + virtual std::unique_ptr handleNotifications(Notifications& notifications) = 0; + + //! Wait for pending notifications to be handled. + virtual void waitForNotifications() = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index a5fb1db86c..6a9922b3cd 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -13,12 +13,7 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): { bool fFirstRun; m_wallet.LoadWallet(fFirstRun); - RegisterValidationInterface(&m_wallet); + m_wallet.m_chain_notifications_handler = m_chain->handleNotifications(m_wallet); RegisterWalletRPCCommands(tableRPC); } - -WalletTestingSetup::~WalletTestingSetup() -{ - UnregisterValidationInterface(&m_wallet); -} diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h index e6fe8c9473..edc06a8351 100644 --- a/src/wallet/test/wallet_test_fixture.h +++ b/src/wallet/test/wallet_test_fixture.h @@ -17,7 +17,6 @@ */ struct WalletTestingSetup: public TestingSetup { explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); - ~WalletTestingSetup(); std::unique_ptr m_chain = interfaces::MakeChain(); CWallet m_wallet; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 02f3a265d9..f6acec2d3e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -96,7 +96,7 @@ static void ReleaseWallet(CWallet* wallet) wallet->WalletLogPrintf("Releasing wallet\n"); wallet->BlockUntilSyncedToCurrentChain(); wallet->Flush(); - UnregisterValidationInterface(wallet); + wallet->m_chain_notifications_handler.reset(); delete wallet; // Wallet is now released, notify UnloadWallet, if any. { @@ -1243,7 +1243,8 @@ void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx) { } } -void CWallet::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) { +void CWallet::BlockConnected(const CBlock& block, const std::vector& vtxConflicted) { + const uint256& block_hash = block.GetHash(); auto locked_chain = chain().lock(); LOCK(cs_wallet); // TODO: Temporarily ensure that mempool removals are notified before @@ -1258,19 +1259,19 @@ void CWallet::BlockConnected(const std::shared_ptr& pblock, const SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */); TransactionRemovedFromMempool(ptx); } - for (size_t i = 0; i < pblock->vtx.size(); i++) { - SyncTransaction(pblock->vtx[i], pindex->GetBlockHash(), i); - TransactionRemovedFromMempool(pblock->vtx[i]); + for (size_t i = 0; i < block.vtx.size(); i++) { + SyncTransaction(block.vtx[i], block_hash, i); + TransactionRemovedFromMempool(block.vtx[i]); } - m_last_block_processed = pindex->GetBlockHash(); + m_last_block_processed = block_hash; } -void CWallet::BlockDisconnected(const std::shared_ptr& pblock) { +void CWallet::BlockDisconnected(const CBlock& block) { auto locked_chain = chain().lock(); LOCK(cs_wallet); - for (const CTransactionRef& ptx : pblock->vtx) { + for (const CTransactionRef& ptx : block.vtx) { SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */); } } @@ -1297,7 +1298,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() { // ...otherwise put a callback in the validation interface queue and wait // for the queue to drain enough to execute it (indicating we are caught up // at least with the time we entered this function). - SyncWithValidationInterfaceQueue(); + chain().waitForNotifications(); } @@ -2137,7 +2138,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(interfaces::Chain:: return result; } -void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) +void CWallet::ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime) { // Do this infrequently and randomly to avoid giving away // that these are our transactions. @@ -2155,8 +2156,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman // Rebroadcast unconfirmed txes older than 5 minutes before the last // block was found: - auto locked_chain = chain().assumeLocked(); // Temporary. Removed in upcoming lock cleanup - std::vector relayed = ResendWalletTransactionsBefore(*locked_chain, nBestBlockTime-5*60); + std::vector relayed = ResendWalletTransactionsBefore(locked_chain, nBestBlockTime-5*60); if (!relayed.empty()) WalletLogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size()); } @@ -4385,8 +4385,8 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, chain.loadWallet(interfaces::MakeWallet(walletInstance)); - // Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main. - RegisterValidationInterface(walletInstance.get()); + // Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain. + walletInstance->m_chain_notifications_handler = chain.handleNotifications(*walletInstance); walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 51e3edac34..02f1788ddb 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -637,7 +638,7 @@ class WalletRescanReserver; //forward declarations for ScanForWalletTransactions * A CWallet is an extension of a keystore, which also maintains a set of transactions and balances, * and provides the ability to create new transactions. */ -class CWallet final : public CCryptoKeyStore, public CValidationInterface +class CWallet final : public CCryptoKeyStore, private interfaces::Chain::Notifications { private: std::atomic fAbortRescan{false}; @@ -808,6 +809,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface std::set setLockedCoins GUARDED_BY(cs_wallet); + /** Registered interfaces::Chain::Notifications handler. */ + std::unique_ptr m_chain_notifications_handler; + /** Interface for accessing chain state. */ interfaces::Chain& chain() const { return m_chain; } @@ -920,8 +924,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true); void LoadToWallet(const CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void TransactionAddedToMempool(const CTransactionRef& tx) override; - void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) override; - void BlockDisconnected(const std::shared_ptr& pblock) override; + void BlockConnected(const CBlock& block, const std::vector& vtxConflicted) override; + void BlockDisconnected(const CBlock& block) override; int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update); struct ScanResult { @@ -942,7 +946,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface ScanResult ScanForWalletTransactions(const uint256& first_block, const uint256& last_block, const WalletRescanReserver& reserver, bool fUpdate); void TransactionRemovedFromMempool(const CTransactionRef &ptx) override; void ReacceptWalletTransactions(); - void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override EXCLUSIVE_LOCKS_REQUIRED(cs_main); + void ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime) override; // ResendWalletTransactionsBefore may only be called if fBroadcastTransactions! std::vector ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime); CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE, const int min_depth=0) const; @@ -1220,6 +1224,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface /** Add a KeyOriginInfo to the wallet */ bool AddKeyOrigin(const CPubKey& pubkey, const KeyOriginInfo& info); + + friend struct WalletTestingSetup; }; /** A key allocated from the key pool. */ From 4e4d9e9f85eaf9c3bec48559bd4cad3e8a9333ca Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Mon, 31 Jul 2017 11:46:13 -0400 Subject: [PATCH 0117/4486] Remove use of CRPCTable::appendCommand in wallet code This commit does not change behavior. --- src/interfaces/chain.cpp | 47 ++++++++++++++++++- src/interfaces/chain.h | 5 ++ src/interfaces/wallet.cpp | 3 +- src/rpc/server.cpp | 61 +++++++++++++++---------- src/rpc/server.h | 31 ++++++++++--- src/test/rpc_tests.cpp | 5 +- src/wallet/rpcwallet.cpp | 4 +- src/wallet/rpcwallet.h | 9 +++- src/wallet/test/wallet_test_fixture.cpp | 2 +- src/wallet/test/wallet_test_fixture.h | 1 + 10 files changed, 128 insertions(+), 40 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 8ce718cc50..f04d07d49d 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -15,12 +15,15 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -212,6 +215,45 @@ class NotificationsHandlerImpl : public Handler, CValidationInterface Chain::Notifications* m_notifications; }; +class RpcHandlerImpl : public Handler +{ +public: + RpcHandlerImpl(const CRPCCommand& command) : m_command(command), m_wrapped_command(&command) + { + m_command.actor = [this](const JSONRPCRequest& request, UniValue& result, bool last_handler) { + if (!m_wrapped_command) return false; + try { + return m_wrapped_command->actor(request, result, last_handler); + } catch (const UniValue& e) { + // If this is not the last handler and a wallet not found + // exception was thrown, return false so the next handler can + // try to handle the request. Otherwise, reraise the exception. + if (!last_handler) { + const UniValue& code = e["code"]; + if (code.isNum() && code.get_int() == RPC_WALLET_NOT_FOUND) { + return false; + } + } + throw; + } + }; + ::tableRPC.appendCommand(m_command.name, &m_command); + } + + void disconnect() override final + { + if (m_wrapped_command) { + m_wrapped_command = nullptr; + ::tableRPC.removeCommand(m_command.name, &m_command); + } + } + + ~RpcHandlerImpl() override { disconnect(); } + + CRPCCommand m_command; + const CRPCCommand* m_wrapped_command; +}; + class ChainImpl : public Chain { public: @@ -310,8 +352,11 @@ class ChainImpl : public Chain return MakeUnique(*this, notifications); } void waitForNotifications() override { SyncWithValidationInterfaceQueue(); } + std::unique_ptr handleRpc(const CRPCCommand& command) override + { + return MakeUnique(command); + } }; - } // namespace std::unique_ptr MakeChain() { return MakeUnique(); } diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 72862617b3..0936449e22 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -16,6 +16,7 @@ class CBlock; class CFeeRate; +class CRPCCommand; class CScheduler; class CValidationState; class uint256; @@ -243,6 +244,10 @@ class Chain //! Wait for pending notifications to be handled. virtual void waitForNotifications() = 0; + + //! Register handler for RPC. Command is not copied, so reference + //! needs to remain valid until Handler is disconnected. + virtual std::unique_ptr handleRpc(const CRPCCommand& command) = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 7abbee0912..97eadac6a9 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -514,7 +514,7 @@ class WalletClientImpl : public ChainClient : m_chain(chain), m_wallet_filenames(std::move(wallet_filenames)) { } - void registerRpcs() override { return RegisterWalletRPCCommands(::tableRPC); } + void registerRpcs() override { return RegisterWalletRPCCommands(m_chain, m_rpc_handlers); } bool verify() override { return VerifyWallets(m_chain, m_wallet_filenames); } bool load() override { return LoadWallets(m_chain, m_wallet_filenames); } void start(CScheduler& scheduler) override { return StartWallets(scheduler); } @@ -524,6 +524,7 @@ class WalletClientImpl : public ChainClient Chain& m_chain; std::vector m_wallet_filenames; + std::vector> m_rpc_handlers; }; } // namespace diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index cd90573da0..e803fabcc6 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -30,6 +30,7 @@ static std::string rpcWarmupStatus GUARDED_BY(cs_rpcWarmup) = "RPC server starte static RPCTimerInterface* timerInterface = nullptr; /* Map of name to timer. */ static std::map > deadlineTimers; +static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler); struct RPCCommandExecutionInfo { @@ -173,11 +174,11 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& { std::string strRet; std::string category; - std::set setDone; + std::set setDone; std::vector > vCommands; for (const auto& entry : mapCommands) - vCommands.push_back(make_pair(entry.second->category + entry.first, entry.second)); + vCommands.push_back(make_pair(entry.second.front()->category + entry.first, entry.second.front())); sort(vCommands.begin(), vCommands.end()); JSONRPCRequest jreq(helpreq); @@ -193,9 +194,9 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& jreq.strMethod = strMethod; try { - rpcfn_type pfn = pcmd->actor; - if (setDone.insert(pfn).second) - (*pfn)(jreq); + UniValue unused_result; + if (setDone.insert(pcmd->unique_id).second) + pcmd->actor(jreq, unused_result, true /* last_handler */); } catch (const std::exception& e) { @@ -337,32 +338,32 @@ CRPCTable::CRPCTable() const CRPCCommand *pcmd; pcmd = &vRPCCommands[vcidx]; - mapCommands[pcmd->name] = pcmd; + mapCommands[pcmd->name].push_back(pcmd); } } -const CRPCCommand *CRPCTable::operator[](const std::string &name) const -{ - std::map::const_iterator it = mapCommands.find(name); - if (it == mapCommands.end()) - return nullptr; - return (*it).second; -} - bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd) { if (IsRPCRunning()) return false; - // don't allow overwriting for now - std::map::const_iterator it = mapCommands.find(name); - if (it != mapCommands.end()) - return false; - - mapCommands[name] = pcmd; + mapCommands[name].push_back(pcmd); return true; } +bool CRPCTable::removeCommand(const std::string& name, const CRPCCommand* pcmd) +{ + auto it = mapCommands.find(name); + if (it != mapCommands.end()) { + auto new_end = std::remove(it->second.begin(), it->second.end(), pcmd); + if (it->second.end() != new_end) { + it->second.erase(new_end, it->second.end()); + return true; + } + } + return false; +} + void StartRPC() { LogPrint(BCLog::RPC, "Starting RPC\n"); @@ -543,18 +544,28 @@ UniValue CRPCTable::execute(const JSONRPCRequest &request) const } // Find method - const CRPCCommand *pcmd = tableRPC[request.strMethod]; - if (!pcmd) - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); + auto it = mapCommands.find(request.strMethod); + if (it != mapCommands.end()) { + UniValue result; + for (const auto& command : it->second) { + if (ExecuteCommand(*command, request, result, &command == &it->second.back())) { + return result; + } + } + } + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); +} +static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler) +{ try { RPCCommandExecution execution(request.strMethod); // Execute, convert arguments to array if necessary if (request.params.isObject()) { - return pcmd->actor(transformNamedArguments(request, pcmd->argNames)); + return command.actor(transformNamedArguments(request, command.argNames), result, last_handler); } else { - return pcmd->actor(request); + return command.actor(request, result, last_handler); } } catch (const std::exception& e) diff --git a/src/rpc/server.h b/src/rpc/server.h index 2d62a76f3c..e2a85887ba 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -131,10 +131,31 @@ typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest); class CRPCCommand { public: + //! RPC method handler reading request and assigning result. Should return + //! true if request is fully handled, false if it should be passed on to + //! subsequent handlers. + using Actor = std::function; + + //! Constructor taking Actor callback supporting multiple handlers. + CRPCCommand(std::string category, std::string name, Actor actor, std::vector args, intptr_t unique_id) + : category(std::move(category)), name(std::move(name)), actor(std::move(actor)), argNames(std::move(args)), + unique_id(unique_id) + { + } + + //! Simplified constructor taking plain rpcfn_type function pointer. + CRPCCommand(const char* category, const char* name, rpcfn_type fn, std::initializer_list args) + : CRPCCommand(category, name, + [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn(request); return true; }, + {args.begin(), args.end()}, intptr_t(fn)) + { + } + std::string category; std::string name; - rpcfn_type actor; + Actor actor; std::vector argNames; + intptr_t unique_id; }; /** @@ -143,10 +164,9 @@ class CRPCCommand class CRPCTable { private: - std::map mapCommands; + std::map> mapCommands; public: CRPCTable(); - const CRPCCommand* operator[](const std::string& name) const; std::string help(const std::string& name, const JSONRPCRequest& helpreq) const; /** @@ -169,9 +189,7 @@ class CRPCTable * * 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 + * Commands with different method names but the same unique_id 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 @@ -179,6 +197,7 @@ class CRPCTable * register different names, types, and numbers of parameters. */ bool appendCommand(const std::string& name, const CRPCCommand* pcmd); + bool removeCommand(const std::string& name, const CRPCCommand* pcmd); }; bool IsDeprecatedRPCEnabled(const std::string& method); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index ff48398925..9bb2bf551b 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -31,10 +31,9 @@ UniValue CallRPC(std::string args) request.strMethod = strMethod; request.params = RPCConvertValues(strMethod, vArgs); request.fHelp = false; - BOOST_CHECK(tableRPC[strMethod]); - rpcfn_type method = tableRPC[strMethod]->actor; + if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); try { - UniValue result = (*method)(request); + UniValue result = tableRPC.execute(request); return result; } catch (const UniValue& objError) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 31a3209a49..3a197ec0ef 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4156,8 +4156,8 @@ static const CRPCCommand commands[] = }; // clang-format on -void RegisterWalletRPCCommands(CRPCTable &t) +void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector>& handlers) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - t.appendCommand(commands[vcidx].name, &commands[vcidx]); + handlers.emplace_back(chain.handleRpc(commands[vcidx])); } diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 58053bde59..7cf607ccc7 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -5,7 +5,9 @@ #ifndef BITCOIN_WALLET_RPCWALLET_H #define BITCOIN_WALLET_RPCWALLET_H +#include #include +#include class CRPCTable; class CWallet; @@ -14,7 +16,12 @@ class UniValue; struct PartiallySignedTransaction; class CTransaction; -void RegisterWalletRPCCommands(CRPCTable &t); +namespace interfaces { +class Chain; +class Handler; +} + +void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector>& handlers); /** * Figures out what wallet, if any, to use for a JSONRPCRequest. diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 6a9922b3cd..6a051214a9 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -15,5 +15,5 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): m_wallet.LoadWallet(fFirstRun); m_wallet.m_chain_notifications_handler = m_chain->handleNotifications(m_wallet); - RegisterWalletRPCCommands(tableRPC); + m_chain_client->registerRpcs(); } diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h index edc06a8351..dcfbc55f94 100644 --- a/src/wallet/test/wallet_test_fixture.h +++ b/src/wallet/test/wallet_test_fixture.h @@ -19,6 +19,7 @@ struct WalletTestingSetup: public TestingSetup { explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); std::unique_ptr m_chain = interfaces::MakeChain(); + std::unique_ptr m_chain_client = interfaces::MakeWalletClient(*m_chain, {}); CWallet m_wallet; }; From b1b2b238928e7be044ad62cf1b222464907ece2c Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Tue, 17 Jul 2018 13:04:35 -0400 Subject: [PATCH 0118/4486] Remove use of CCoinsViewMemPool::GetCoin in wallet code This commit does not change behavior. --- src/Makefile.am | 2 ++ src/interfaces/chain.cpp | 2 ++ src/interfaces/chain.h | 6 ++++++ src/node/coin.cpp | 22 +++++++++++++++++++ src/node/coin.h | 22 +++++++++++++++++++ src/rpc/rawtransaction.cpp | 44 ++++++++++++++++++-------------------- 6 files changed, 75 insertions(+), 23 deletions(-) create mode 100644 src/node/coin.cpp create mode 100644 src/node/coin.h diff --git a/src/Makefile.am b/src/Makefile.am index 14db963253..5131c6819a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -154,6 +154,7 @@ BITCOIN_CORE_H = \ netaddress.h \ netbase.h \ netmessagemaker.h \ + node/coin.h \ node/transaction.h \ noui.h \ optional.h \ @@ -262,6 +263,7 @@ libbitcoin_server_a_SOURCES = \ miner.cpp \ net.cpp \ net_processing.cpp \ + node/coin.cpp \ node/transaction.cpp \ noui.cpp \ outputtype.cpp \ diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index f04d07d49d..7913c4473e 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -287,6 +288,7 @@ class ChainImpl : public Chain } return true; } + void findCoins(std::map& coins) override { return FindCoins(coins); } double guessVerificationProgress(const uint256& block_hash) override { LOCK(cs_main); diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 0936449e22..b4db9dda15 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -19,6 +19,7 @@ class CFeeRate; class CRPCCommand; class CScheduler; class CValidationState; +class Coin; class uint256; enum class RBFTransactionState; struct CBlockLocator; @@ -168,6 +169,11 @@ class Chain int64_t* time = nullptr, int64_t* max_time = nullptr) = 0; + //! Look up unspent output information. Returns coins in the mempool and in + //! the current chain UTXO set. Iterates through all the keys in the map and + //! populates the values. + virtual void findCoins(std::map& coins) = 0; + //! Estimate fraction of total transactions verified if blocks up to //! the specified block hash are verified. virtual double guessVerificationProgress(const uint256& block_hash) = 0; diff --git a/src/node/coin.cpp b/src/node/coin.cpp new file mode 100644 index 0000000000..bb98e63f3a --- /dev/null +++ b/src/node/coin.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2019 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 + +#include +#include + +void FindCoins(std::map& coins) +{ + LOCK2(cs_main, ::mempool.cs); + assert(pcoinsTip); + CCoinsViewCache& chain_view = *::pcoinsTip; + CCoinsViewMemPool mempool_view(&chain_view, ::mempool); + for (auto& coin : coins) { + if (!mempool_view.GetCoin(coin.first, coin.second)) { + // Either the coin is not in the CCoinsViewCache or is spent. Clear it. + coin.second.Clear(); + } + } +} diff --git a/src/node/coin.h b/src/node/coin.h new file mode 100644 index 0000000000..eb95b75cfb --- /dev/null +++ b/src/node/coin.h @@ -0,0 +1,22 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_NODE_COIN_H +#define BITCOIN_NODE_COIN_H + +#include + +class COutPoint; +class Coin; + +/** + * Look up unspent output information. Returns coins in the mempool and in the + * current chain UTXO set. Iterates through all the keys in the map and + * populates the values. + * + * @param[in,out] coins map to fill + */ +void FindCoins(std::map& coins); + +#endif // BITCOIN_NODE_COIN_H diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d19afaa8a1..1336740292 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -790,23 +791,20 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) return EncodeHexTx(CTransaction(mergedTx)); } +// TODO(https://github.com/bitcoin/bitcoin/pull/10973#discussion_r267084237): +// This function is called from both wallet and node rpcs +// (signrawtransactionwithwallet and signrawtransactionwithkey). It should be +// moved to a util file so wallet code doesn't need to link against node code. +// Also the dependency on interfaces::Chain should be removed, so +// signrawtransactionwithkey doesn't need access to a Chain instance. UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType) { // Fetch previous transactions (inputs): - CCoinsView viewDummy; - CCoinsViewCache view(&viewDummy); - { - LOCK2(cs_main, mempool.cs); - CCoinsViewCache &viewChain = *pcoinsTip; - CCoinsViewMemPool viewMempool(&viewChain, mempool); - view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view - - for (const CTxIn& txin : mtx.vin) { - view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail. - } - - view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long + std::map coins; + for (const CTxIn& txin : mtx.vin) { + coins[txin.prevout]; // Create empty map entry keyed by prevout. } + chain.findCoins(coins); // Add previous txouts given in the RPC call: if (!prevTxsUnival.isNull()) { @@ -838,10 +836,10 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con CScript scriptPubKey(pkData.begin(), pkData.end()); { - const Coin& coin = view.AccessCoin(out); - if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) { + auto coin = coins.find(out); + if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) { std::string err("Previous output scriptPubKey mismatch:\n"); - err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+ + err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+ ScriptToAsmStr(scriptPubKey); throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err); } @@ -852,7 +850,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount")); } newcoin.nHeight = 1; - view.AddCoin(out, std::move(newcoin), true); + coins[out] = std::move(newcoin); } // if redeemScript and private keys were given, add redeemScript to the keystore so it can be signed @@ -896,15 +894,15 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con // Sign what we can: for (unsigned int i = 0; i < mtx.vin.size(); i++) { CTxIn& txin = mtx.vin[i]; - const Coin& coin = view.AccessCoin(txin.prevout); - if (coin.IsSpent()) { + auto coin = coins.find(txin.prevout); + if (coin == coins.end() || coin->second.IsSpent()) { TxInErrorToJSON(txin, vErrors, "Input not found or already spent"); continue; } - const CScript& prevPubKey = coin.out.scriptPubKey; - const CAmount& amount = coin.out.nValue; + const CScript& prevPubKey = coin->second.out.scriptPubKey; + const CAmount& amount = coin->second.out.nValue; - SignatureData sigdata = DataFromTransaction(mtx, i, coin.out); + SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out); // Only sign SIGHASH_SINGLE if there's a corresponding output: if (!fHashSingle || (i < mtx.vout.size())) { ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata); @@ -914,7 +912,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con // amount must be specified for valid segwit signature if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) { - throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin.out.ToString())); + throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin->second.out.ToString())); } ScriptError serror = SCRIPT_ERR_OK; From 276972cb95ba944a7a4b1858a08d333962261396 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Tue, 5 Mar 2019 11:04:32 -0500 Subject: [PATCH 0119/4486] wallet_bumpfee.py: Make sure coin selection produces change --- test/functional/wallet_bumpfee.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 7d3d9b61e2..3bef70f0a0 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -260,7 +260,9 @@ def test_unconfirmed_not_spendable(rbf_node, rbf_node_address): def test_bumpfee_metadata(rbf_node, dest_address): - rbfid = rbf_node.sendtoaddress(dest_address, Decimal("0.00100000"), "comment value", "to value") + assert(rbf_node.getbalance() < 49) + rbf_node.generatetoaddress(101, rbf_node.getnewaddress()) + rbfid = rbf_node.sendtoaddress(dest_address, 49, "comment value", "to value") bumped_tx = rbf_node.bumpfee(rbfid) bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"]) assert_equal(bumped_wtx["comment"], "comment value") From 2e5d482659371082e34ee3aba42b3c5a301b8168 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 22 Feb 2019 18:06:34 +0000 Subject: [PATCH 0120/4486] tests: Print remaining jobs in test_runner.py This helps finding out which tests fail to finish. --- test/functional/test_runner.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 999cd72108..7f06382552 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -477,6 +477,11 @@ def get_next(self): log_stderr)) if not self.jobs: raise IndexError('pop from empty list') + + # Print remaining running jobs when all jobs have been started. + if not self.test_list: + print("Remaining jobs: [{}]".format(", ".join(j[0] for j in self.jobs))) + dot_count = 0 while True: # Return first proc that finishes From e5efacb941f78645462da1237ed04c75082d3aed Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Thu, 28 Jun 2018 07:50:45 +0900 Subject: [PATCH 0121/4486] test: Refactor vout fetches in rpc_rawtransaction --- test/functional/rpc_rawtransaction.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index fba9e75268..df7c894827 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -285,11 +285,7 @@ def run_test(self): txDetails = self.nodes[0].gettransaction(txId, True) rawTx = self.nodes[0].decoderawtransaction(txDetails['hex']) - vout = False - for outpoint in rawTx['vout']: - if outpoint['value'] == Decimal('2.20000000'): - vout = outpoint - break + vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('2.20000000')) bal = self.nodes[0].getbalance() inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] @@ -330,11 +326,7 @@ def run_test(self): txDetails = self.nodes[0].gettransaction(txId, True) rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex']) - vout = False - for outpoint in rawTx2['vout']: - if outpoint['value'] == Decimal('2.20000000'): - vout = outpoint - break + vout = next(o for o in rawTx2['vout'] if o['value'] == Decimal('2.20000000')) bal = self.nodes[0].getbalance() inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}] From d358466de15ef29c1d2bccb9aebab360d574d1d0 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Wed, 6 Mar 2019 16:47:57 -0500 Subject: [PATCH 0122/4486] Remove remaining wallet accesses to node globals --- src/interfaces/chain.cpp | 9 +++++++++ src/interfaces/chain.h | 17 ++++++++++++++++- src/interfaces/wallet.cpp | 8 +------- src/interfaces/wallet.h | 3 --- src/qt/walletmodeltransaction.cpp | 2 +- src/wallet/feebumper.cpp | 14 ++++++++------ src/wallet/fees.cpp | 9 +++++---- src/wallet/init.cpp | 2 +- src/wallet/rpcdump.cpp | 14 +++++++------- src/wallet/rpcwallet.cpp | 4 ++-- src/wallet/wallet.cpp | 28 ++++++++++++---------------- src/wallet/wallet.h | 2 +- 12 files changed, 63 insertions(+), 49 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 7913c4473e..0c765f2092 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -340,15 +341,23 @@ class ChainImpl : public Chain { return ::mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); } + CFeeRate relayMinFee() override { return ::minRelayTxFee; } + CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; } + CFeeRate relayDustFee() override { return ::dustRelayFee; } CAmount maxTxFee() override { return ::maxTxFee; } bool getPruneMode() override { return ::fPruneMode; } bool p2pEnabled() override { return g_connman != nullptr; } bool isInitialBlockDownload() override { return IsInitialBlockDownload(); } + bool shutdownRequested() override { return ShutdownRequested(); } int64_t getAdjustedTime() override { return GetAdjustedTime(); } void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } void initWarning(const std::string& message) override { InitWarning(message); } void initError(const std::string& message) override { InitError(message); } void loadWallet(std::unique_ptr wallet) override { ::uiInterface.LoadWallet(wallet); } + void showProgress(const std::string& title, int progress, bool resume_possible) override + { + ::uiInterface.ShowProgress(title, progress, resume_possible); + } std::unique_ptr handleNotifications(Notifications& notifications) override { return MakeUnique(*this, notifications); diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index b4db9dda15..a9b05f27fc 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -202,6 +202,15 @@ class Chain //! Mempool minimum fee. virtual CFeeRate mempoolMinFee() = 0; + //! Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings). + virtual CFeeRate relayMinFee() = 0; + + //! Relay incremental fee setting (-incrementalrelayfee), reflecting cost of relay. + virtual CFeeRate relayIncrementalFee() = 0; + + //! Relay dust fee setting (-dustrelayfee), reflecting lowest rate it's economical to spend. + virtual CFeeRate relayDustFee() = 0; + //! Node max tx fee setting (-maxtxfee). //! This could be replaced by a per-wallet max fee, as proposed at //! https://github.com/bitcoin/bitcoin/issues/15355 @@ -214,9 +223,12 @@ class Chain //! Check if p2p enabled. virtual bool p2pEnabled() = 0; - // Check if in IBD. + //! Check if in IBD. virtual bool isInitialBlockDownload() = 0; + //! Check if shutdown requested. + virtual bool shutdownRequested() = 0; + //! Get adjusted time. virtual int64_t getAdjustedTime() = 0; @@ -232,6 +244,9 @@ class Chain //! Send wallet load notification to the GUI. virtual void loadWallet(std::unique_ptr wallet) = 0; + //! Send progress indicator. + virtual void showProgress(const std::string& title, int progress, bool resume_possible) = 0; + //! Chain notifications. class Notifications { diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 97eadac6a9..60173b29ac 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -47,8 +47,6 @@ class PendingWalletTxImpl : public PendingWalletTx const CTransaction& get() override { return *m_tx; } - int64_t getVirtualSize() override { return GetVirtualTransactionSize(*m_tx); } - bool commit(WalletValueMap value_map, WalletOrderForm order_form, std::string& reject_reason) override @@ -99,12 +97,8 @@ WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, co //! Construct wallet tx status struct. WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx) { - LockAnnotation lock(::cs_main); // Temporary, for mapBlockIndex below. Removed in upcoming commit. - WalletTxStatus result; - auto mi = ::mapBlockIndex.find(wtx.hashBlock); - CBlockIndex* block = mi != ::mapBlockIndex.end() ? mi->second : nullptr; - result.block_height = (block ? block->nHeight : std::numeric_limits::max()); + result.block_height = locked_chain.getBlockHeight(wtx.hashBlock).get_value_or(std::numeric_limits::max()); result.blocks_to_maturity = wtx.GetBlocksToMaturity(locked_chain); result.depth_in_main_chain = wtx.GetDepthInMainChain(locked_chain); result.time_received = wtx.nTimeReceived; diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index a931e5fafb..cabc455b1f 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -292,9 +292,6 @@ class PendingWalletTx //! Get transaction data. virtual const CTransaction& get() = 0; - //! Get virtual transaction size. - virtual int64_t getVirtualSize() = 0; - //! Send pending transaction and commit to wallet. virtual bool commit(WalletValueMap value_map, WalletOrderForm order_form, diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index eb3b0baf08..2694d67800 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -29,7 +29,7 @@ std::unique_ptr& WalletModelTransaction::getWtx() unsigned int WalletModelTransaction::getTransactionSize() { - return wtx ? wtx->getVirtualSize() : 0; + return wtx ? GetVirtualTransactionSize(wtx->get()) : 0; } CAmount WalletModelTransaction::getTransactionFee() const diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index a1c3a21d4b..ef7f3be728 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -123,16 +123,17 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin // The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to // future proof against changes to network wide policy for incremental relay // fee that our node may not be aware of. + CFeeRate nodeIncrementalRelayFee = wallet->chain().relayIncrementalFee(); CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE); - if (::incrementalRelayFee > walletIncrementalRelayFee) { - walletIncrementalRelayFee = ::incrementalRelayFee; + if (nodeIncrementalRelayFee > walletIncrementalRelayFee) { + walletIncrementalRelayFee = nodeIncrementalRelayFee; } if (total_fee > 0) { - CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + ::incrementalRelayFee.GetFee(maxNewTxSize); + CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + nodeIncrementalRelayFee.GetFee(maxNewTxSize); if (total_fee < minTotalFee) { errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)", - FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(::incrementalRelayFee.GetFee(maxNewTxSize)))); + FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(nodeIncrementalRelayFee.GetFee(maxNewTxSize)))); return Result::INVALID_PARAMETER; } CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize); @@ -159,9 +160,10 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin } // Check that in all cases the new fee doesn't violate maxTxFee - if (new_fee > maxTxFee) { + const CAmount max_tx_fee = wallet->chain().maxTxFee(); + if (new_fee > max_tx_fee) { errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)", - FormatMoney(new_fee), FormatMoney(maxTxFee))); + FormatMoney(new_fee), FormatMoney(max_tx_fee))); return Result::WALLET_ERROR; } diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index 545adaebc1..560c86a70a 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -22,8 +22,9 @@ CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinC { CAmount fee_needed = GetMinimumFeeRate(wallet, coin_control, feeCalc).GetFee(nTxBytes); // Always obey the maximum - if (fee_needed > maxTxFee) { - fee_needed = maxTxFee; + const CAmount max_tx_fee = wallet.chain().maxTxFee(); + if (fee_needed > max_tx_fee) { + fee_needed = max_tx_fee; if (feeCalc) feeCalc->reason = FeeReason::MAXTXFEE; } return fee_needed; @@ -31,7 +32,7 @@ CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinC CFeeRate GetRequiredFeeRate(const CWallet& wallet) { - return std::max(wallet.m_min_fee, ::minRelayTxFee); + return std::max(wallet.m_min_fee, wallet.chain().relayMinFee()); } CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, FeeCalculation* feeCalc) @@ -96,6 +97,6 @@ CFeeRate GetDiscardRate(const CWallet& wallet) // Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate); // Discard rate must be at least dustRelayFee - discard_rate = std::max(discard_rate, ::dustRelayFee); + discard_rate = std::max(discard_rate, wallet.chain().relayDustFee()); return discard_rate; } diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 7ad343c15f..76a7eaa681 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -153,7 +153,7 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector& wal LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); - uiInterface.InitMessage(_("Verifying wallet(s)...")); + chain.initMessage(_("Verifying wallet(s)...")); // Parameter interaction code should have thrown an error if -salvagewallet // was enabled with more than wallet file, so the wallet_files size check diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 684d900478..6c3b5a49dc 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -595,11 +595,11 @@ UniValue importwallet(const JSONRPCRequest& request) // Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which // we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button. - uiInterface.ShowProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI + pwallet->chain().showProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI std::vector> keys; std::vector> scripts; while (file.good()) { - uiInterface.ShowProgress("", std::max(1, std::min(50, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false); + pwallet->chain().showProgress("", std::max(1, std::min(50, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false); std::string line; std::getline(file, line); if (line.empty() || line[0] == '#') @@ -637,13 +637,13 @@ UniValue importwallet(const JSONRPCRequest& request) file.close(); // We now know whether we are importing private keys, so we can error if private keys are disabled if (keys.size() > 0 && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { - uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI + pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when private keys are disabled"); } double total = (double)(keys.size() + scripts.size()); double progress = 0; for (const auto& key_tuple : keys) { - uiInterface.ShowProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false); + pwallet->chain().showProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false); const CKey& key = std::get<0>(key_tuple); int64_t time = std::get<1>(key_tuple); bool has_label = std::get<2>(key_tuple); @@ -668,7 +668,7 @@ UniValue importwallet(const JSONRPCRequest& request) progress++; } for (const auto& script_pair : scripts) { - uiInterface.ShowProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false); + pwallet->chain().showProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false); const CScript& script = script_pair.first; int64_t time = script_pair.second; CScriptID id(script); @@ -687,10 +687,10 @@ UniValue importwallet(const JSONRPCRequest& request) } progress++; } - uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI + pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI pwallet->UpdateTimeFirstKey(nTimeBegin); } - uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI + pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI RescanWallet(*pwallet, reserver, nTimeBegin, false /* update */); pwallet->MarkDirty(); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3a197ec0ef..fa7604b695 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2367,8 +2367,8 @@ static UniValue settxfee(const JSONRPCRequest& request) CFeeRate tx_fee_rate(nAmount, 1000); if (tx_fee_rate == 0) { // automatic selection - } else if (tx_fee_rate < ::minRelayTxFee) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", ::minRelayTxFee.ToString())); + } else if (tx_fee_rate < pwallet->chain().relayMinFee()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString())); } else if (tx_fee_rate < pwallet->m_min_fee) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than wallet min fee (%s)", pwallet->m_min_fee.ToString())); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f6acec2d3e..7b7ad35f55 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1791,7 +1791,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc progress_end = chain().guessVerificationProgress(stop_block.IsNull() ? tip_hash : stop_block); } double progress_current = progress_begin; - while (block_height && !fAbortRescan && !ShutdownRequested()) { + while (block_height && !fAbortRescan && !chain().shutdownRequested()) { if (*block_height % 100 == 0 && progress_end - progress_begin > 0.0) { ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), std::max(1, std::min(99, (int)((progress_current - progress_begin) / (progress_end - progress_begin) * 100)))); } @@ -1853,7 +1853,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc if (block_height && fAbortRescan) { WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", *block_height, progress_current); result.status = ScanResult::USER_ABORT; - } else if (block_height && ShutdownRequested()) { + } else if (block_height && chain().shutdownRequested()) { WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", *block_height, progress_current); result.status = ScanResult::USER_ABORT; } @@ -2310,7 +2310,6 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth) const { - AssertLockHeld(cs_main); AssertLockHeld(cs_wallet); vCoins.clear(); @@ -2420,7 +2419,6 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< std::map> CWallet::ListCoins(interfaces::Chain::Lock& locked_chain) const { - AssertLockHeld(cs_main); AssertLockHeld(cs_wallet); std::map> result; @@ -2692,13 +2690,13 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC return true; } -static bool IsCurrentForAntiFeeSniping(interfaces::Chain::Lock& locked_chain) +static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain) { - if (IsInitialBlockDownload()) { + if (chain.isInitialBlockDownload()) { return false; } constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60; // in seconds - if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) { + if (locked_chain.getBlockTime(*locked_chain.getHeight()) < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) { return false; } return true; @@ -2708,7 +2706,7 @@ static bool IsCurrentForAntiFeeSniping(interfaces::Chain::Lock& locked_chain) * Return a height-based locktime for new transactions (uses the height of the * current chain tip unless we are not synced with the current chain */ -static uint32_t GetLocktimeForNewTransaction(interfaces::Chain::Lock& locked_chain) +static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain) { uint32_t const height = locked_chain.getHeight().get_value_or(-1); uint32_t locktime; @@ -2732,7 +2730,7 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain::Lock& locked_cha // enough, that fee sniping isn't a problem yet, but by implementing a fix // now we ensure code won't be written that makes assumptions about // nLockTime that preclude a fix later. - if (IsCurrentForAntiFeeSniping(locked_chain)) { + if (IsCurrentForAntiFeeSniping(chain, locked_chain)) { locktime = height; // Secondly occasionally randomly pick a nLockTime even further back, so @@ -2806,7 +2804,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std CMutableTransaction txNew; - txNew.nLockTime = GetLocktimeForNewTransaction(locked_chain); + txNew.nLockTime = GetLocktimeForNewTransaction(chain(), locked_chain); FeeCalculation feeCalc; CAmount nFeeNeeded; @@ -2902,7 +2900,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std // Include the fee cost for outputs. Note this is only used for BnB right now coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION); - if (IsDust(txout, ::dustRelayFee)) + if (IsDust(txout, chain().relayDustFee())) { if (recipient.fSubtractFeeFromAmount && nFeeRet > 0) { @@ -3003,7 +3001,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std // If we made it here and we aren't even able to meet the relay fee on the next pass, give up // because we must be at the maximum allowed fee. - if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes)) + if (nFeeNeeded < chain().relayMinFee().GetFee(nBytes)) { strFailReason = _("Transaction too large for fee policy"); return false; @@ -4281,9 +4279,9 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, _("This is the transaction fee you will pay if you send a transaction.")); } walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000); - if (walletInstance->m_pay_tx_fee < ::minRelayTxFee) { + if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) { chain.initError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), - gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString())); + gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString())); return nullptr; } } @@ -4446,8 +4444,6 @@ int CMerkleTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const if (hashUnset()) return 0; - AssertLockHeld(cs_main); - return locked_chain.getBlockDepth(hashBlock) * (nIndex == -1 ? -1 : 1); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 02f1788ddb..7473172a21 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -506,7 +506,7 @@ class CWalletTx : public CMerkleTx CAmount GetCredit(interfaces::Chain::Lock& locked_chain, const isminefilter& filter) const; CAmount GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true) const; // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct - // annotation "EXCLUSIVE_LOCKS_REQUIRED(cs_main, pwallet->cs_wallet)". The + // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The // annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid // having to resolve the issue of member access into incomplete type CWallet. CAmount GetAvailableCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS; From 32da92bdf6bb55d6d312b0f85797d439cc942db5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 6 Mar 2019 18:22:29 +0100 Subject: [PATCH 0123/4486] gitian: Improve error handling --- contrib/devtools/split-debug.sh.in | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 5 +++-- contrib/gitian-descriptors/gitian-osx-signer.yml | 2 ++ contrib/gitian-descriptors/gitian-osx.yml | 2 ++ contrib/gitian-descriptors/gitian-win-signer.yml | 2 ++ contrib/gitian-descriptors/gitian-win.yml | 2 ++ 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/contrib/devtools/split-debug.sh.in b/contrib/devtools/split-debug.sh.in index deda49cc54..92b72b1446 100644 --- a/contrib/devtools/split-debug.sh.in +++ b/contrib/devtools/split-debug.sh.in @@ -1,5 +1,5 @@ #!/bin/sh - +set -e if [ $# -ne 3 ]; then echo "usage: $0 " fi diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index e97072c80a..2f0231fa93 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -36,6 +36,7 @@ remotes: "dir": "bitcoin" files: [] script: | + set -e -o pipefail WRAP_DIR=$HOME/wrapped HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu" @@ -179,8 +180,8 @@ script: | find . -name "lib*.la" -delete find . -name "lib*.a" -delete rm -rf ${DISTNAME}/lib/pkgconfig - find ${DISTNAME}/bin -type f -executable -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \; - find ${DISTNAME}/lib -type f -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \; + find ${DISTNAME}/bin -type f -executable -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg + find ${DISTNAME}/lib -type f -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg cp ../doc/README.md ${DISTNAME}/ find ${DISTNAME} -not -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz find ${DISTNAME} -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml index 297a136fae..df6cddbf03 100644 --- a/contrib/gitian-descriptors/gitian-osx-signer.yml +++ b/contrib/gitian-descriptors/gitian-osx-signer.yml @@ -12,6 +12,8 @@ remotes: files: - "bitcoin-osx-unsigned.tar.gz" script: | + set -e -o pipefail + WRAP_DIR=$HOME/wrapped mkdir -p ${WRAP_DIR} export PATH=`pwd`:$PATH diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 87d8007ccb..f250909de3 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -33,6 +33,8 @@ remotes: files: - "MacOSX10.11.sdk.tar.gz" script: | + set -e -o pipefail + WRAP_DIR=$HOME/wrapped HOSTS="x86_64-apple-darwin14" CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage" diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml index 045be873e9..08d20177a6 100644 --- a/contrib/gitian-descriptors/gitian-win-signer.yml +++ b/contrib/gitian-descriptors/gitian-win-signer.yml @@ -16,6 +16,8 @@ files: - "osslsigncode-Backports-to-1.7.1.patch" - "bitcoin-win-unsigned.tar.gz" script: | + set -e -o pipefail + BUILD_DIR=`pwd` SIGDIR=${BUILD_DIR}/signature/win UNSIGNED_DIR=${BUILD_DIR}/unsigned diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 31b9c309c7..fedd87fcc8 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -27,6 +27,8 @@ remotes: "dir": "bitcoin" files: [] script: | + set -e -o pipefail + WRAP_DIR=$HOME/wrapped HOSTS="i686-w64-mingw32 x86_64-w64-mingw32" CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests" From fa55104cb8e73c709e90fc5f81c9cb6a8a0713a6 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 6 Mar 2019 12:32:33 -0500 Subject: [PATCH 0124/4486] build: use full version string in setup.exe --- share/setup.nsi.in | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/share/setup.nsi.in b/share/setup.nsi.in index 6542370f97..148cddf02d 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -5,7 +5,6 @@ SetCompressor /SOLID lzma # General Symbol Definitions !define REGKEY "SOFTWARE\$(^Name)" -!define VERSION @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@ !define COMPANY "@PACKAGE_NAME@ project" !define URL @PACKAGE_URL@ @@ -49,7 +48,7 @@ Var StartMenuGroup !insertmacro MUI_LANGUAGE English # Installer attributes -OutFile @abs_top_srcdir@/@PACKAGE_TARNAME@-${VERSION}-win@WINDOWS_BITS@-setup.exe +OutFile @abs_top_srcdir@/@PACKAGE_TARNAME@-@PACKAGE_VERSION@-win@WINDOWS_BITS@-setup.exe !if "@WINDOWS_BITS@" == "64" InstallDir $PROGRAMFILES64\Bitcoin !else @@ -59,12 +58,12 @@ CRCCheck on XPStyle on BrandingText " " ShowInstDetails show -VIProductVersion ${VERSION}.@CLIENT_VERSION_BUILD@ +VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@ VIAddVersionKey ProductName "@PACKAGE_NAME@" -VIAddVersionKey ProductVersion "${VERSION}" +VIAddVersionKey ProductVersion "@PACKAGE_VERSION@" VIAddVersionKey CompanyName "${COMPANY}" VIAddVersionKey CompanyWebsite "${URL}" -VIAddVersionKey FileVersion "${VERSION}" +VIAddVersionKey FileVersion "@PACKAGE_VERSION@" VIAddVersionKey FileDescription "" VIAddVersionKey LegalCopyright "" InstallDirRegKey HKCU "${REGKEY}" Path @@ -98,7 +97,7 @@ Section -post SEC0001 CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe !insertmacro MUI_STARTMENU_WRITE_END WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "@PACKAGE_VERSION@" WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}" WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}" WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe From 2d5cf4c41d86f2bdd1df99edc130ade1d093258f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Mon, 17 Dec 2018 15:30:01 +0000 Subject: [PATCH 0125/4486] rpc: Speedup getrawmempool when verbose=true Co-Authored-By: MarcoFalke --- src/rpc/blockchain.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 1827aec637..2273d92f3f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -474,7 +474,10 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose) const uint256& hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); entryToJSON(pool, info, e); - o.pushKV(hash.ToString(), info); + // Mempool has unique entries so there is no advantage in using + // UniValue::pushKV, which checks if the key already exists in O(N). + // UniValue::__pushKV is used instead which currently is O(1). + o.__pushKV(hash.ToString(), info); } return o; } else { From e377846ff1e718961148e64ff73e891b24f37ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Mon, 25 Feb 2019 15:09:24 +0000 Subject: [PATCH 0126/4486] rest/rpc: Make mempoolinfo atomic --- src/rpc/blockchain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 1827aec637..0eea269375 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1483,6 +1483,8 @@ static UniValue getchaintips(const JSONRPCRequest& request) UniValue MempoolInfoToJSON(const CTxMemPool& pool) { + // Make sure this call is atomic in the pool. + LOCK(pool.cs); UniValue ret(UniValue::VOBJ); ret.pushKV("size", (int64_t)pool.size()); ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize()); From 5bd078876adb4f3f5c2106b163cf0601c3e12b97 Mon Sep 17 00:00:00 2001 From: "Ferdinando M. Ametrano" Date: Wed, 6 Mar 2019 20:19:06 +0100 Subject: [PATCH 0127/4486] doc: correct path in build-windows.md Co-authored-by: fanquake --- doc/build-windows.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/doc/build-windows.md b/doc/build-windows.md index 9641e0d3fd..036c585b44 100644 --- a/doc/build-windows.md +++ b/doc/build-windows.md @@ -71,6 +71,11 @@ If you want to build the windows installer with `make deploy` you need [NSIS](ht sudo apt install nsis +Acquire the source in the usual way: + + git clone https://github.com/bitcoin/bitcoin.git + cd bitcoin + ## Building for 64-bit Windows The first step is to install the mingw-w64 cross-compilation tool chain: @@ -87,11 +92,7 @@ Note that for WSL the Bitcoin Core source path MUST be somewhere in the default example /usr/src/bitcoin, AND not under /mnt/d/. If this is not the case the dependency autoconf scripts will fail. This means you cannot use a directory that is located directly on the host Windows file system to perform the build. -Acquire the source in the usual way: - - git clone https://github.com/bitcoin/bitcoin.git - -Once the source code is ready the build steps are below: +Build using: PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') # strip out problematic Windows %PATH% imported var cd depends @@ -115,11 +116,7 @@ Note that for WSL the Bitcoin Core source path MUST be somewhere in the default example /usr/src/bitcoin, AND not under /mnt/d/. If this is not the case the dependency autoconf scripts will fail. This means you cannot use a directory that located directly on the host Windows file system to perform the build. -Acquire the source in the usual way: - - git clone https://github.com/bitcoin/bitcoin.git - -Then build using: +Build using: PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') # strip out problematic Windows %PATH% imported var cd depends From 6e1aaffa98acd38fe7c86719d22b001402194521 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 9 Mar 2019 16:19:39 +0800 Subject: [PATCH 0128/4486] doc: remove release note fragments Removes all release note fragments from prior to the 0.18.0 branch off. All of these fragments have been merged into the WIP release-notes on the dev wiki. --- doc/release-notes-14021.md | 11 ----------- doc/release-notes-14481.md | 9 --------- doc/release-notes-14491.md | 5 ----- doc/release-notes-14667.md | 4 ---- doc/release-notes-15226.md | 8 -------- doc/release-notes-15393.md | 4 ---- doc/release-notes-15492.md | 11 ----------- 7 files changed, 52 deletions(-) delete mode 100644 doc/release-notes-14021.md delete mode 100644 doc/release-notes-14481.md delete mode 100644 doc/release-notes-14491.md delete mode 100644 doc/release-notes-14667.md delete mode 100644 doc/release-notes-15226.md delete mode 100644 doc/release-notes-15393.md delete mode 100644 doc/release-notes-15492.md diff --git a/doc/release-notes-14021.md b/doc/release-notes-14021.md deleted file mode 100644 index 4797a95bdb..0000000000 --- a/doc/release-notes-14021.md +++ /dev/null @@ -1,11 +0,0 @@ -Miscellaneous RPC Changes -------------------------- -- Descriptors with key origin information imported through `importmulti` will have their key origin information stored in the wallet for use with creating PSBTs. -- If `bip32derivs` of both `walletprocesspsbt` and `walletcreatefundedpsbt` is set to true but the key metadata for a public key has not been updated yet, then that key will have a derivation path as if it were just an independent key (i.e. no derivation path and its master fingerprint is itself) - -Miscellaneous Wallet changes ----------------------------- - -- The key metadata will need to be upgraded the first time that the HD seed is available. -For unencrypted wallets this will occur on wallet loading. -For encrypted wallets this will occur the first time the wallet is unlocked. diff --git a/doc/release-notes-14481.md b/doc/release-notes-14481.md deleted file mode 100644 index ea8fc3c34e..0000000000 --- a/doc/release-notes-14481.md +++ /dev/null @@ -1,9 +0,0 @@ -Low-level RPC changes ----------------------- - -The `listunspent` RPC has been modified so that it also returns `witnessScript`, -the witness script in the case of a P2WSH or P2SH-P2WSH output. - -The `signrawtransactionwithkey` and `signrawtransactionwithwallet` RPCs have been -modified so that they also optionally accept a `witnessScript`, the witness script in the -case of a P2WSH or P2SH-P2WSH output. This is compatible with the change to `listunspent`. diff --git a/doc/release-notes-14491.md b/doc/release-notes-14491.md deleted file mode 100644 index 1cf36e85cf..0000000000 --- a/doc/release-notes-14491.md +++ /dev/null @@ -1,5 +0,0 @@ -Descriptor import support ---------------------- - -The `importmulti` RPC now supports importing of addresses from descriptors. A "desc" parameter can be provided instead of the "scriptPubKey" in a request, as well as an optional range for ranged descriptors to specify the start and end of the range to import. More information about -descriptors can be found [here](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md). diff --git a/doc/release-notes-14667.md b/doc/release-notes-14667.md deleted file mode 100644 index 5cb1d0aee7..0000000000 --- a/doc/release-notes-14667.md +++ /dev/null @@ -1,4 +0,0 @@ -New RPC methods ------------- - -- `deriveaddresses` returns one or more addresses corresponding to an [output descriptor](/doc/descriptors.md). diff --git a/doc/release-notes-15226.md b/doc/release-notes-15226.md deleted file mode 100644 index 3be84db3e9..0000000000 --- a/doc/release-notes-15226.md +++ /dev/null @@ -1,8 +0,0 @@ -Miscellaneous RPC changes ------------- - -- The RPC `createwallet` now has an optional `blank` argument that can be used to create a blank wallet. -Blank wallets do not have any keys or HD seed. -They cannot be opened in software older than 0.18. -Once a blank wallet has a HD seed set (by using `sethdseed`) or private keys, scripts, addresses, and other watch only things have been imported, the wallet is no longer blank and can be opened in 0.17.x. -Encrypting a blank wallet will also set a HD seed for it. diff --git a/doc/release-notes-15393.md b/doc/release-notes-15393.md deleted file mode 100644 index f478dc798d..0000000000 --- a/doc/release-notes-15393.md +++ /dev/null @@ -1,4 +0,0 @@ -Dependencies ------------- - -- The minimum required version of QT has been increased from 5.2 to 5.5.1 (the [depends system](https://github.com/bitcoin/bitcoin/blob/master/depends/README.md) provides 5.9.7) diff --git a/doc/release-notes-15492.md b/doc/release-notes-15492.md deleted file mode 100644 index 1149eb0dbc..0000000000 --- a/doc/release-notes-15492.md +++ /dev/null @@ -1,11 +0,0 @@ -Deprecated or removed RPCs --------------------------- -- The wallet's `generate` RPC method was deprecated in v0.18 and has now - been fully removed. This RPC is only used for - testing, but its implementation reached across multiple subsystems - (wallet and mining), so it has been removed to simplify the - wallet-node interface. Projects that are using `generate` for testing - purposes should transition to using the `generatetoaddress` RPC, which - does not require or use the wallet component. Calling - `generatetoaddress` with an address returned by the `getnewaddress` - RPC gives the same functionality as the old `generate` RPC. From 890396cbd504b4670597d39ecb037e69ffb8bd3e Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 9 Mar 2019 16:15:17 +0800 Subject: [PATCH 0129/4486] cli: replace testnet with chain and return network name as per BIP70. --- doc/release-notes-15566.md | 3 +++ src/bitcoin-cli.cpp | 2 +- test/functional/interface_bitcoin_cli.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 doc/release-notes-15566.md diff --git a/doc/release-notes-15566.md b/doc/release-notes-15566.md new file mode 100644 index 0000000000..49964d7550 --- /dev/null +++ b/doc/release-notes-15566.md @@ -0,0 +1,3 @@ +Miscellaneous CLI Changes +------------------------- +- The `testnet` field in `bitcoin-cli -getinfo` has been renamed to `chain` and now returns the current network name as defined in BIP70 (main, test, regtest). \ No newline at end of file diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index b0e1f67d93..62a53e2308 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -262,7 +262,7 @@ class GetinfoRequestHandler: public BaseRequestHandler result.pushKV("connections", batch[ID_NETWORKINFO]["result"]["connections"]); result.pushKV("proxy", batch[ID_NETWORKINFO]["result"]["networks"][0]["proxy"]); result.pushKV("difficulty", batch[ID_BLOCKCHAININFO]["result"]["difficulty"]); - result.pushKV("testnet", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"].get_str() == "test")); + result.pushKV("chain", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"])); if (!batch[ID_WALLETINFO].isNull()) { result.pushKV("walletversion", batch[ID_WALLETINFO]["result"]["walletversion"]); result.pushKV("balance", batch[ID_WALLETINFO]["result"]["balance"]); diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index f44fc768dc..8640ae95c6 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -65,7 +65,7 @@ def run_test(self): assert_equal(cli_get_info['connections'], network_info['connections']) assert_equal(cli_get_info['proxy'], network_info['networks'][0]['proxy']) assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty']) - assert_equal(cli_get_info['testnet'], blockchain_info['chain'] == "test") + assert_equal(cli_get_info['chain'], blockchain_info['chain']) if self.is_wallet_compiled(): assert_equal(cli_get_info['balance'], wallet_info['balance']) assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest']) From 3f6568d66b42bd151b26df3bd84c64959bbe3fc9 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 9 Mar 2019 15:54:49 +0800 Subject: [PATCH 0130/4486] cli: remove duplicate wallet fields from -getinfo --- src/bitcoin-cli.cpp | 4 ---- test/functional/interface_bitcoin_cli.py | 4 +--- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index b0e1f67d93..306badbb36 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -253,10 +253,6 @@ class GetinfoRequestHandler: public BaseRequestHandler } result.pushKV("version", batch[ID_NETWORKINFO]["result"]["version"]); result.pushKV("protocolversion", batch[ID_NETWORKINFO]["result"]["protocolversion"]); - if (!batch[ID_WALLETINFO].isNull()) { - result.pushKV("walletversion", batch[ID_WALLETINFO]["result"]["walletversion"]); - result.pushKV("balance", batch[ID_WALLETINFO]["result"]["balance"]); - } result.pushKV("blocks", batch[ID_BLOCKCHAININFO]["result"]["blocks"]); result.pushKV("timeoffset", batch[ID_NETWORKINFO]["result"]["timeoffset"]); result.pushKV("connections", batch[ID_NETWORKINFO]["result"]["connections"]); diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index f44fc768dc..c843d25f51 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -57,9 +57,6 @@ def run_test(self): assert_equal(cli_get_info['version'], network_info['version']) assert_equal(cli_get_info['protocolversion'], network_info['protocolversion']) - if self.is_wallet_compiled(): - assert_equal(cli_get_info['walletversion'], wallet_info['walletversion']) - assert_equal(cli_get_info['balance'], wallet_info['balance']) assert_equal(cli_get_info['blocks'], blockchain_info['blocks']) assert_equal(cli_get_info['timeoffset'], network_info['timeoffset']) assert_equal(cli_get_info['connections'], network_info['connections']) @@ -67,6 +64,7 @@ def run_test(self): assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty']) assert_equal(cli_get_info['testnet'], blockchain_info['chain'] == "test") if self.is_wallet_compiled(): + assert_equal(cli_get_info['walletversion'], wallet_info['walletversion']) assert_equal(cli_get_info['balance'], wallet_info['balance']) assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest']) assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize']) From 56f1d28d9b606397c0c746b57243a0f2b971ff8a Mon Sep 17 00:00:00 2001 From: Lenny Maiorani Date: Sun, 10 Mar 2019 11:37:05 -0600 Subject: [PATCH 0131/4486] dead code: Remove dead option in HexStr conversion Problem: - Nothing uses the `fspaces` argument to `HexStr()` besides unit tests. This argument results in extra complexity and a small performance decrease within the function for branch evalulation. Solution: - Remove unused `fspaces` option. --- src/test/util_tests.cpp | 40 ---------------------------------------- src/util/strencodings.h | 12 +++++------- 2 files changed, 5 insertions(+), 47 deletions(-) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index e17ae7103b..e106bdeb65 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -77,80 +77,40 @@ BOOST_AUTO_TEST_CASE(util_HexStr) HexStr(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected)), "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); - BOOST_CHECK_EQUAL( - HexStr(ParseHex_expected, ParseHex_expected + 5, true), - "04 67 8a fd b0"); - BOOST_CHECK_EQUAL( HexStr(ParseHex_expected + sizeof(ParseHex_expected), ParseHex_expected + sizeof(ParseHex_expected)), ""); - BOOST_CHECK_EQUAL( - HexStr(ParseHex_expected + sizeof(ParseHex_expected), - ParseHex_expected + sizeof(ParseHex_expected), true), - ""); - BOOST_CHECK_EQUAL( HexStr(ParseHex_expected, ParseHex_expected), ""); - BOOST_CHECK_EQUAL( - HexStr(ParseHex_expected, ParseHex_expected, true), - ""); - std::vector ParseHex_vec(ParseHex_expected, ParseHex_expected + 5); - BOOST_CHECK_EQUAL( - HexStr(ParseHex_vec, true), - "04 67 8a fd b0"); - BOOST_CHECK_EQUAL( HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend()), "b0fd8a6704" ); - BOOST_CHECK_EQUAL( - HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend(), true), - "b0 fd 8a 67 04" - ); - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator(ParseHex_expected), std::reverse_iterator(ParseHex_expected)), "" ); - BOOST_CHECK_EQUAL( - HexStr(std::reverse_iterator(ParseHex_expected), - std::reverse_iterator(ParseHex_expected), true), - "" - ); - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator(ParseHex_expected + 1), std::reverse_iterator(ParseHex_expected)), "04" ); - BOOST_CHECK_EQUAL( - HexStr(std::reverse_iterator(ParseHex_expected + 1), - std::reverse_iterator(ParseHex_expected), true), - "04" - ); - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator(ParseHex_expected + 5), std::reverse_iterator(ParseHex_expected)), "b0fd8a6704" ); - BOOST_CHECK_EQUAL( - HexStr(std::reverse_iterator(ParseHex_expected + 5), - std::reverse_iterator(ParseHex_expected), true), - "b0 fd 8a 67 04" - ); - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator(ParseHex_expected + 65), std::reverse_iterator(ParseHex_expected)), diff --git a/src/util/strencodings.h b/src/util/strencodings.h index cf77044094..7c4364a082 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -121,28 +122,25 @@ NODISCARD bool ParseUInt64(const std::string& str, uint64_t *out); NODISCARD bool ParseDouble(const std::string& str, double *out); template -std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) +std::string HexStr(const T itbegin, const T itend) { std::string rv; static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - rv.reserve((itend-itbegin)*3); + rv.reserve(std::distance(itbegin, itend) * 2); for(T it = itbegin; it < itend; ++it) { unsigned char val = (unsigned char)(*it); - if(fSpaces && it != itbegin) - rv.push_back(' '); rv.push_back(hexmap[val>>4]); rv.push_back(hexmap[val&15]); } - return rv; } template -inline std::string HexStr(const T& vch, bool fSpaces=false) +inline std::string HexStr(const T& vch) { - return HexStr(vch.begin(), vch.end(), fSpaces); + return HexStr(vch.begin(), vch.end()); } /** From 228e80608d93a6359b9846fd3d05a199fd488ddd Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Mon, 11 Mar 2019 16:03:49 +0000 Subject: [PATCH 0132/4486] Enable TLS in link to chris.beams.io --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 139fe7dc52..82c96efa0c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ Commit messages should be verbose by default consisting of a short subject line paragraph(s), unless the title alone is self-explanatory (like "Corrected typo in init.cpp") in which case a single title line is sufficient. Commit messages should be helpful to people reading your code in the future, so explain the reasoning for -your decisions. Further explanation [here](http://chris.beams.io/posts/git-commit/). +your decisions. Further explanation [here](https://chris.beams.io/posts/git-commit/). If a particular commit references another issue, please add the reference. For example: `refs #1234` or `fixes #4321`. Using the `fixes` or `closes` keywords From 19a0c4af0f329e8f5d1f2eb7a29689d5d0a581a9 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Mon, 11 Mar 2019 13:05:58 -0400 Subject: [PATCH 0133/4486] depends: native_protobuf: avoid system zlib --- depends/packages/native_protobuf.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/packages/native_protobuf.mk b/depends/packages/native_protobuf.mk index ce50b366fa..1de8c37d36 100644 --- a/depends/packages/native_protobuf.mk +++ b/depends/packages/native_protobuf.mk @@ -5,7 +5,7 @@ $(package)_file_name=protobuf-$($(package)_version).tar.bz2 $(package)_sha256_hash=ee445612d544d885ae240ffbcbf9267faa9f593b7b101f21d58beceb92661910 define $(package)_set_vars -$(package)_config_opts=--disable-shared +$(package)_config_opts=--disable-shared --without-zlib endef define $(package)_config_cmds From c9963ae8b1a4d26d19c58e18fde9c85783edb788 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 11 Mar 2019 15:16:24 -0700 Subject: [PATCH 0134/4486] Fix overflow bug in analyzepsbt fee: CAmount instead of int --- src/rpc/rawtransaction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d19afaa8a1..3da7661638 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1981,8 +1981,8 @@ UniValue analyzepsbt(const JSONRPCRequest& request) } if (calc_fee) { // Get the output amount - CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), 0, - [](int a, const CTxOut& b) { + CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0), + [](CAmount a, const CTxOut& b) { return a += b.nValue; } ); From a4d0fd026b74db034dc8a1fa7efbd4f1dba8cdb9 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 8 Mar 2019 12:20:51 +0800 Subject: [PATCH 0135/4486] doc: correct analysepsbt rpc doc --- src/rpc/rawtransaction.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d19afaa8a1..80d8c962d0 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1862,21 +1862,21 @@ UniValue analyzepsbt(const JSONRPCRequest& request) " \"has_utxo\" : true|false (boolean) Whether a UTXO is provided\n" " \"is_final\" : true|false (boolean) Whether the input is finalized\n" " \"missing\" : { (json object, optional) Things that are missing that are required to complete this input\n" - " \"pubkeys\" : [ (array)\n" + " \"pubkeys\" : [ (array, optional)\n" " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing\n" " ]\n" - " \"signatures\" : [ (array)\n" + " \"signatures\" : [ (array, optional)\n" " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose signature is missing\n" " ]\n" - " \"redeemscript\" : \"hash\" (string) Hash160 of the redeemScript that is missing\n" - " \"witnessscript\" : \"hash\" (string) SHA256 of the witnessScript that is missing\n" + " \"redeemscript\" : \"hash\" (string, optional) Hash160 of the redeemScript that is missing\n" + " \"witnessscript\" : \"hash\" (string, optional) SHA256 of the witnessScript that is missing\n" " }\n" - " \"next\" : \"role\" (string) Role of the next person that this input needs to go to\n" + " \"next\" : \"role\" (string, optional) Role of the next person that this input needs to go to\n" " }\n" " ,...\n" " ]\n" - " \"estimated_vsize\" : vsize (numeric) Estimated vsize of the final signed transaction\n" - " \"estimated_feerate\" : feerate (numeric, optional) Estimated feerate of the final signed transaction. Shown only if all UTXO slots in the PSBT have been filled.\n" + " \"estimated_vsize\" : vsize (numeric, optional) Estimated vsize of the final signed transaction\n" + " \"estimated_feerate\" : feerate (numeric, optional) Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled.\n" " \"fee\" : fee (numeric, optional) The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled.\n" " \"next\" : \"role\" (string) Role of the next person that this psbt needs to go to\n" "}\n" From 335931df4a37467299a2ee0ba521ecd5c4e6d39e Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 9 Mar 2019 14:50:44 +0800 Subject: [PATCH 0136/4486] rpc: return a number for estimated_feerate in analyzepsbt --- src/rpc/rawtransaction.cpp | 2 +- test/functional/rpc_psbt.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 80d8c962d0..541171602e 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -2021,7 +2021,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request) result.pushKV("estimated_vsize", (int)size); // Estimate fee rate CFeeRate feerate(fee, size); - result.pushKV("estimated_feerate", feerate.ToString()); + result.pushKV("estimated_feerate", ValueFromAmount(feerate.GetFeePerK())); } result.pushKV("fee", ValueFromAmount(fee)); diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 885e07c4dd..904ddac428 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -355,7 +355,7 @@ def run_test(self): assert analyzed['inputs'][0]['has_utxo'] and not analyzed['inputs'][0]['is_final'] and analyzed['inputs'][0]['next'] == 'signer' and analyzed['next'] == 'signer' and analyzed['inputs'][0]['missing']['signatures'][0] == addrinfo['embedded']['witness_program'] # Check fee and size things - assert analyzed['fee'] == Decimal('0.001') and analyzed['estimated_vsize'] == 134 and analyzed['estimated_feerate'] == '0.00746268 BTC/kB' + assert analyzed['fee'] == Decimal('0.001') and analyzed['estimated_vsize'] == 134 and analyzed['estimated_feerate'] == Decimal('0.00746268') # After signing and finalizing, needs extracting signed = self.nodes[1].walletprocesspsbt(updated)['psbt'] From fae5f874d51c770322fb18cc4050b3f14697de66 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 13 Mar 2019 14:45:53 -0400 Subject: [PATCH 0137/4486] rpc: Document that minconf is an ignored dummy value --- src/wallet/rpcwallet.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 31a3209a49..a35659e371 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -807,9 +807,7 @@ static UniValue sendmany(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) - throw std::runtime_error( - RPCHelpMan{"sendmany", + const RPCHelpMan help{"sendmany", "\nSend multiple times. Amounts are double-precision floating point numbers." + HelpRequiringPassphrase(pwallet) + "\n", { @@ -819,7 +817,7 @@ static UniValue sendmany(const JSONRPCRequest& request) {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"}, }, }, - {"minconf", RPCArg::Type::NUM, /* default */ "1", "Only use the balance confirmed at least this many times."}, + {"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Ignored dummy value"}, {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment"}, {"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array with addresses.\n" " The fee will be equally deducted from the amount of each selected address.\n" @@ -850,7 +848,11 @@ static UniValue sendmany(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"") }, - }.ToString()); + }; + + if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { + throw std::runtime_error(help.ToString()); + } // Make sure the results are valid at least up to the most recent block // the user could have gotten from another RPC command prior to now @@ -867,9 +869,6 @@ static UniValue sendmany(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\""); } UniValue sendTo = request.params[1].get_obj(); - int nMinDepth = 1; - if (!request.params[2].isNull()) - nMinDepth = request.params[2].get_int(); mapValue_t mapValue; if (!request.params[3].isNull() && !request.params[3].get_str().empty()) @@ -897,7 +896,6 @@ static UniValue sendmany(const JSONRPCRequest& request) std::set destinations; std::vector vecSend; - CAmount totalAmount = 0; std::vector keys = sendTo.getKeys(); for (const std::string& name_ : keys) { CTxDestination dest = DecodeDestination(name_); @@ -914,7 +912,6 @@ static UniValue sendmany(const JSONRPCRequest& request) CAmount nAmount = AmountFromValue(sendTo[name_]); if (nAmount <= 0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); - totalAmount += nAmount; bool fSubtractFeeFromAmount = false; for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) { @@ -929,11 +926,6 @@ static UniValue sendmany(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); - // Check funds - if (totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth)) { - throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds"); - } - // Shuffle recipient list std::shuffle(vecSend.begin(), vecSend.end(), FastRandomContext()); From 15c69b158da570f4e1430280c610e94ffdee0e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Mon, 11 Mar 2019 22:57:59 +0000 Subject: [PATCH 0138/4486] wallet: Log and ignore errors in ListWalletDir and IsBerkeleyBtree --- src/wallet/walletutil.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index d779251d56..2d8adf8ba6 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -4,6 +4,7 @@ #include +#include #include fs::path GetWalletDir() @@ -33,7 +34,9 @@ static bool IsBerkeleyBtree(const fs::path& path) // A Berkeley DB Btree file has at least 4K. // This check also prevents opening lock files. boost::system::error_code ec; - if (fs::file_size(path, ec) < 4096) return false; + auto size = fs::file_size(path, ec); + if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string()); + if (size < 4096) return false; fsbridge::ifstream file(path, std::ios::binary); if (!file.is_open()) return false; @@ -54,8 +57,14 @@ std::vector ListWalletDir() const fs::path wallet_dir = GetWalletDir(); const size_t offset = wallet_dir.string().size() + 1; std::vector paths; + boost::system::error_code ec; + + for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) { + if (ec) { + LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string()); + continue; + } - for (auto it = fs::recursive_directory_iterator(wallet_dir); it != fs::recursive_directory_iterator(); ++it) { // Get wallet path relative to walletdir by removing walletdir from the wallet path. // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60. const fs::path path = it->path().string().substr(offset); From 7abd2e697c0f8e93245e09ac853bae05d0b48bee Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Thu, 14 Feb 2019 17:07:29 +0900 Subject: [PATCH 0139/4486] wallet/rpc: add maxfeerate parameter to testmempoolaccept --- src/rpc/client.cpp | 1 + src/rpc/rawtransaction.cpp | 26 ++++++++++++++++++++------ test/functional/feature_cltv.py | 2 +- test/functional/feature_dersig.py | 2 +- test/functional/rpc_rawtransaction.py | 12 +++++++++--- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c19160d325..4144a17bc3 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -95,6 +95,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendrawtransaction", 1, "maxfeerate" }, { "testmempoolaccept", 0, "rawtxs" }, { "testmempoolaccept", 1, "allowhighfees" }, + { "testmempoolaccept", 1, "maxfeerate" }, { "combinerawtransaction", 0, "txs" }, { "fundrawtransaction", 1, "options" }, { "fundrawtransaction", 2, "iswitness" }, diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index fedc30dc35..27fb53654f 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1108,7 +1108,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""}, }, }, - {"allowhighfees", RPCArg::Type::BOOL, /* default */ "false", "Allow high fees"}, + {"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(maxTxFee), "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kB\n"}, }, RPCResult{ "[ (array) The result of the mempool acceptance test for each raw transaction in the input array.\n" @@ -1133,7 +1133,11 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) }.ToString()); } - RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VBOOL}); + RPCTypeCheck(request.params, { + UniValue::VARR, + UniValueType(), // NUM or BOOL, checked later + }); + if (request.params[0].get_array().size() != 1) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now"); } @@ -1145,9 +1149,19 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) CTransactionRef tx(MakeTransactionRef(std::move(mtx))); const uint256& tx_hash = tx->GetHash(); - CAmount max_raw_tx_fee = ::maxTxFee; - if (!request.params[1].isNull() && request.params[1].get_bool()) { - max_raw_tx_fee = 0; + CAmount max_raw_tx_fee = maxTxFee; + // TODO: temporary migration code for old clients. Remove in v0.20 + if (request.params[1].isBool()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0."); + } else if (request.params[1].isNum()) { + size_t weight = GetTransactionWeight(*tx); + CFeeRate fr(AmountFromValue(request.params[1])); + // the +3/4 part rounds the value up, and is the same formula used when + // calculating the fee for a transaction + // (see GetVirtualTransactionSize) + max_raw_tx_fee = fr.GetFee((weight+3)/4); + } else if (!request.params[1].isNull()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "second argument (maxfeerate) must be numeric"); } UniValue result(UniValue::VARR); @@ -2068,7 +2082,7 @@ static const CRPCCommand commands[] = { "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} }, { "hidden", "signrawtransaction", &signrawtransaction, {"hexstring","prevtxs","privkeys","sighashtype"} }, { "rawtransactions", "signrawtransactionwithkey", &signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} }, - { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees"} }, + { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees|maxfeerate"} }, { "rawtransactions", "decodepsbt", &decodepsbt, {"psbt"} }, { "rawtransactions", "combinepsbt", &combinepsbt, {"txs"} }, { "rawtransactions", "finalizepsbt", &finalizepsbt, {"psbt", "extract"} }, diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index 070242c1df..b16eafccca 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -113,7 +113,7 @@ def run_test(self): # rejected from the mempool for exactly that reason. assert_equal( [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Negative locktime)'}], - self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], allowhighfees=True) + self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0) ) # Now we verify that a block with this transaction is also invalid. diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 4ddfd80b07..7480e5c5ba 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -102,7 +102,7 @@ def run_test(self): # rejected from the mempool for exactly that reason. assert_equal( [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Non-canonical DER signature)'}], - self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], allowhighfees=True) + self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0) ) # Now we verify that a block with this transaction is also invalid. diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index a5a5633359..8c82b0ae4d 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -426,7 +426,7 @@ def run_test(self): decrawtx = self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['version'], 0x7fffffff) - self.log.info('sendrawtransaction with maxfeerate') + self.log.info('sendrawtransaction/testmempoolaccept with maxfeerate') txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) rawTx = self.nodes[0].getrawtransaction(txId, True) @@ -439,9 +439,15 @@ def run_test(self): rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx) assert_equal(rawTxSigned['complete'], True) # 1000 sat fee, ~200 b transaction, fee rate should land around 5 sat/b = 0.00005000 BTC/kB - # Thus, below call should fail + # Thus, testmempoolaccept should reject + testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']], 0.00001000)[0] + assert_equal(testres['allowed'], False) + assert_equal(testres['reject-reason'], '256: absurdly-high-fee') + # and sendrawtransaction should throw assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex'], 0.00001000) - # And below call should succeed + # And below calls should both succeed + testres = self.nodes[2].testmempoolaccept(rawtxs=[rawTxSigned['hex']], maxfeerate=0.00007000)[0] + assert_equal(testres['allowed'], True) self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex'], maxfeerate=0.00007000) From 6c0a6f73e3672bbec31b63d5046d591599aa21a8 Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Wed, 27 Jun 2018 17:21:07 +0900 Subject: [PATCH 0140/4486] wallet/rpc: add maxfeerate parameter to sendrawtransaction --- src/rpc/client.cpp | 1 + src/rpc/rawtransaction.cpp | 30 +++++++-- src/validation.cpp | 20 ++++++ test/functional/feature_fee_estimation.py | 4 +- test/functional/feature_nulldummy.py | 14 ++-- test/functional/feature_rbf.py | 76 +++++++++++----------- test/functional/feature_segwit.py | 4 +- test/functional/mempool_accept.py | 16 ++--- test/functional/rpc_createmultisig.py | 2 +- test/functional/rpc_rawtransaction.py | 19 ++++++ test/functional/test_framework/util.py | 4 +- test/functional/wallet_basic.py | 4 +- test/functional/wallet_listtransactions.py | 2 +- 13 files changed, 126 insertions(+), 70 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index a266580b3d..c19160d325 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -92,6 +92,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "signrawtransactionwithkey", 2, "prevtxs" }, { "signrawtransactionwithwallet", 1, "prevtxs" }, { "sendrawtransaction", 1, "allowhighfees" }, + { "sendrawtransaction", 1, "maxfeerate" }, { "testmempoolaccept", 0, "rawtxs" }, { "testmempoolaccept", 1, "allowhighfees" }, { "combinerawtransaction", 0, "txs" }, diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d19afaa8a1..fedc30dc35 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -28,6 +28,7 @@ #include