diff options
64 files changed, 451 insertions, 210 deletions
diff --git a/configure.ac b/configure.ac index 239fe13e41..c4ad5fae59 100644 --- a/configure.ac +++ b/configure.ac @@ -863,7 +863,7 @@ if test x$use_hardening != xno; then dnl -fcf-protection used with Clang 7 causes ld to emit warnings: dnl ld: error: ... <corrupt x86 feature size: 0x8> - dnl Use CHECK_LINK_FLAG & --fatal-warnings to ensure we wont use the flag in this case. + dnl Use CHECK_LINK_FLAG & --fatal-warnings to ensure we won't use the flag in this case. AX_CHECK_LINK_FLAG([-fcf-protection=full],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fcf-protection=full"],, [[$LDFLAG_WERROR]]) dnl stack-clash-protection does not work properly when building for Windows. @@ -1269,7 +1269,7 @@ if test "x$enable_fuzz" = "xyes"; then [[-fsanitize=$use_sanitizers]], [AC_MSG_RESULT([no])], [AC_MSG_RESULT([yes]) - CPPFLAGS="$CPPFLAGS -DPROVIDE_MAIN_FUNCTION"], + CPPFLAGS="$CPPFLAGS -DPROVIDE_FUZZ_MAIN_FUNCTION"], [], [AC_LANG_PROGRAM([[ #include <cstdint> @@ -1293,7 +1293,7 @@ else QT_TEST_INCLUDES=SUPPRESS_WARNINGS($QT_TEST_INCLUDES) fi - CPPFLAGS="$CPPFLAGS -DPROVIDE_MAIN_FUNCTION" + CPPFLAGS="$CPPFLAGS -DPROVIDE_FUZZ_MAIN_FUNCTION" fi if test x$enable_wallet != xno; then @@ -1902,9 +1902,9 @@ if test "x$enable_wallet" != "xno"; then echo " with sqlite = $use_sqlite" echo " with bdb = $use_bdb" fi -echo " with gui / qt = $bitcoin_enable_qt" +echo " with gui / qt = $bitcoin_enable_qt" if test x$bitcoin_enable_qt != xno; then - echo " with qr = $use_qr" + echo " with qr = $use_qr" fi echo " with zmq = $use_zmq" if test x$enable_fuzz == xno; then diff --git a/contrib/guix/README.md b/contrib/guix/README.md index e218ba89a0..e3573b6fe3 100644 --- a/contrib/guix/README.md +++ b/contrib/guix/README.md @@ -118,6 +118,13 @@ find output/ -type f -print0 | sort -z | xargs -r0 sha256sum depends tree. Setting this to the same directory across multiple builds of the depends tree can eliminate unnecessary building of packages. +* _**SDK_PATH**_ + + Set the path where _extracted_ SDKs can be found. This is passed through to + the depends tree. Note that this is should be set to the _parent_ directory of + the actual SDK (e.g. SDK_PATH=$HOME/Downloads/macOS-SDKs instead of + $HOME/Downloads/macOS-SDKs/Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers). + * _**MAX_JOBS**_ Override the maximum number of jobs to run simultaneously, you might want to diff --git a/contrib/guix/guix-build.sh b/contrib/guix/guix-build.sh index 7af132b240..333e18d4ed 100755 --- a/contrib/guix/guix-build.sh +++ b/contrib/guix/guix-build.sh @@ -196,10 +196,11 @@ and untracked files and directories will be wiped, allowing you to start anew. EOF } -# Create SOURCES_PATH and BASE_CACHE if they are non-empty so that we can map -# them into the container +# Create SOURCES_PATH, BASE_CACHE, and SDK_PATH if they are non-empty so that we +# can map them into the container [ -z "$SOURCES_PATH" ] || mkdir -p "$SOURCES_PATH" [ -z "$BASE_CACHE" ] || mkdir -p "$BASE_CACHE" +[ -z "$SDK_PATH" ] || mkdir -p "$SDK_PATH" # Deterministically build Bitcoin Core # shellcheck disable=SC2153 @@ -302,6 +303,7 @@ EOF --expose="$(git rev-parse --git-common-dir)" \ ${SOURCES_PATH:+--share="$SOURCES_PATH"} \ ${BASE_CACHE:+--share="$BASE_CACHE"} \ + ${SDK_PATH:+--share="$SDK_PATH"} \ --max-jobs="$MAX_JOBS" \ --keep-failed \ ${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} \ @@ -312,6 +314,7 @@ EOF ${V:+V=1} \ ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \ ${BASE_CACHE:+BASE_CACHE="$BASE_CACHE"} \ + ${SDK_PATH:+SDK_PATH="$SDK_PATH"} \ DISTSRC="$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")" \ OUTDIR=/outdir \ bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh" diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index 72588c54a7..1e5463aa9d 100644 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -3,6 +3,16 @@ export LC_ALL=C set -e -o pipefail export TZ=UTC +# Althought Guix _does_ set umask when building its own packages (in our case, +# this is all packages in manifest.scm), it does not set it for `guix +# environment`. It does make sense for at least `guix environment --container` +# to set umask, so if that change gets merged upstream and we bump the +# time-machine to a commit which includes the aforementioned change, we can +# remove this line. +# +# This line should be placed before any commands which creates files. +umask 0022 + if [ -n "$V" ]; then # Print both unexpanded (-v) and expanded (-x) forms of commands as they are # read from this file. @@ -174,6 +184,7 @@ make -C depends --jobs="$MAX_JOBS" HOST="$HOST" \ ${V:+V=1} \ ${SOURCES_PATH+SOURCES_PATH="$SOURCES_PATH"} \ ${BASE_CACHE+BASE_CACHE="$BASE_CACHE"} \ + ${SDK_PATH+SDK_PATH="$SDK_PATH"} \ i686_linux_CC=i686-linux-gnu-gcc \ i686_linux_CXX=i686-linux-gnu-g++ \ i686_linux_AR=i686-linux-gnu-ar \ diff --git a/doc/external-signer.md b/doc/external-signer.md index 053752ee2f..c91ea9bab7 100644 --- a/doc/external-signer.md +++ b/doc/external-signer.md @@ -168,4 +168,4 @@ It then imports descriptors for all support address types, in a BIP44/49/84 comp The `displayaddress` RPC reuses some code from `getaddressinfo` on the provided address and obtains the inferred descriptor. It then calls `<cmd> --fingerprint=00000000 displayaddress --desc=<descriptor>`. -`sendtoaddress` and `sendmany` check `inputs->bip32_derivs` to see if any inputs have the same `master_fingerprint` as the signer. If so, it calls `<cmd> --fingerprint=00000000 signtransaction <psbt>`. It waits for the device to return a (partially) signed psbt, tries to finalize it and broadcasts the transation. +`sendtoaddress` and `sendmany` check `inputs->bip32_derivs` to see if any inputs have the same `master_fingerprint` as the signer. If so, it calls `<cmd> --fingerprint=00000000 signtransaction <psbt>`. It waits for the device to return a (partially) signed psbt, tries to finalize it and broadcasts the transaction. diff --git a/src/Makefile.am b/src/Makefile.am index 8a9ef49a34..eae226b1d4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -231,6 +231,7 @@ BITCOIN_CORE_H = \ util/bip32.h \ util/bytevectorhash.h \ util/check.h \ + util/epochguard.h \ util/error.h \ util/fees.h \ util/getuniquepath.h \ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index ccc0a6828c..6677c9e3b5 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -88,6 +88,8 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center()); } + setContextMenuPolicy(Qt::PreventContextMenu); + #ifdef ENABLE_WALLET enableWallet = WalletModel::isWalletEnabled(); #endif // ENABLE_WALLET @@ -544,7 +546,6 @@ void BitcoinGUI::createToolBars() { QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); appToolBar = toolbar; - toolbar->setContextMenuPolicy(Qt::PreventContextMenu); toolbar->setMovable(false); toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); toolbar->addAction(overviewAction); diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index 9e828ce0a6..e45cafe48a 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -1079,7 +1079,7 @@ <item row="1" column="0"> <widget class="QLabel" name="peerConnectionTypeLabel"> <property name="toolTip"> - <string>The direction and type of peer connection: %1</string> + <string>The direction and type of peer connection: %1</string> </property> <property name="text"> <string>Direction/Type</string> @@ -1342,13 +1342,65 @@ </widget> </item> <item row="12" column="0"> + <widget class="QLabel" name="peerLastBlockLabel"> + <property name="toolTip"> + <string>Elapsed time since a novel block passing initial validity checks was received from this peer.</string> + </property> + <property name="text"> + <string>Last Block</string> + </property> + </widget> + </item> + <item row="12" column="1"> + <widget class="QLabel" name="peerLastBlock"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="13" column="0"> + <widget class="QLabel" name="peerLastTxLabel"> + <property name="toolTip"> + <string>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</string> + </property> + <property name="text"> + <string>Last Tx</string> + </property> + </widget> + </item> + <item row="13" column="1"> + <widget class="QLabel" name="peerLastTx"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="14" column="0"> <widget class="QLabel" name="label_15"> <property name="text"> <string>Last Send</string> </property> </widget> </item> - <item row="12" column="1"> + <item row="14" column="1"> <widget class="QLabel" name="peerLastSend"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1364,14 +1416,14 @@ </property> </widget> </item> - <item row="13" column="0"> + <item row="15" column="0"> <widget class="QLabel" name="label_19"> <property name="text"> <string>Last Receive</string> </property> </widget> </item> - <item row="13" column="1"> + <item row="15" column="1"> <widget class="QLabel" name="peerLastRecv"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1387,14 +1439,14 @@ </property> </widget> </item> - <item row="14" column="0"> + <item row="16" column="0"> <widget class="QLabel" name="label_18"> <property name="text"> <string>Sent</string> </property> </widget> </item> - <item row="14" column="1"> + <item row="16" column="1"> <widget class="QLabel" name="peerBytesSent"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1410,14 +1462,14 @@ </property> </widget> </item> - <item row="15" column="0"> + <item row="17" column="0"> <widget class="QLabel" name="label_20"> <property name="text"> <string>Received</string> </property> </widget> </item> - <item row="15" column="1"> + <item row="17" column="1"> <widget class="QLabel" name="peerBytesRecv"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1433,14 +1485,14 @@ </property> </widget> </item> - <item row="16" column="0"> + <item row="18" column="0"> <widget class="QLabel" name="label_26"> <property name="text"> <string>Ping Time</string> </property> </widget> </item> - <item row="16" column="1"> + <item row="18" column="1"> <widget class="QLabel" name="peerPingTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1456,7 +1508,7 @@ </property> </widget> </item> - <item row="17" column="0"> + <item row="19" column="0"> <widget class="QLabel" name="peerPingWaitLabel"> <property name="toolTip"> <string>The duration of a currently outstanding ping.</string> @@ -1466,7 +1518,7 @@ </property> </widget> </item> - <item row="17" column="1"> + <item row="19" column="1"> <widget class="QLabel" name="peerPingWait"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1482,14 +1534,14 @@ </property> </widget> </item> - <item row="18" column="0"> + <item row="20" column="0"> <widget class="QLabel" name="peerMinPingLabel"> <property name="text"> <string>Min Ping</string> </property> </widget> </item> - <item row="18" column="1"> + <item row="20" column="1"> <widget class="QLabel" name="peerMinPing"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1505,14 +1557,14 @@ </property> </widget> </item> - <item row="19" column="0"> + <item row="21" column="0"> <widget class="QLabel" name="label_timeoffset"> <property name="text"> <string>Time Offset</string> </property> </widget> </item> - <item row="19" column="1"> + <item row="21" column="1"> <widget class="QLabel" name="timeoffset"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1528,7 +1580,7 @@ </property> </widget> </item> - <item row="20" column="0"> + <item row="22" column="0"> <widget class="QLabel" name="peerMappedASLabel"> <property name="toolTip"> <string>The mapped Autonomous System used for diversifying peer selection.</string> @@ -1538,7 +1590,7 @@ </property> </widget> </item> - <item row="20" column="1"> + <item row="22" column="1"> <widget class="QLabel" name="peerMappedAS"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1554,7 +1606,7 @@ </property> </widget> </item> - <item row="21" column="0"> + <item row="23" column="0"> <spacer name="verticalSpacer_3"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 62adaa4e9f..0da12c84fd 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -45,9 +45,9 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWid // context menu actions QAction *copyURIAction = new QAction(tr("Copy URI"), this); QAction* copyAddressAction = new QAction(tr("Copy address"), this); - QAction *copyLabelAction = new QAction(tr("Copy label"), this); - QAction *copyMessageAction = new QAction(tr("Copy message"), this); - QAction *copyAmountAction = new QAction(tr("Copy amount"), this); + copyLabelAction = new QAction(tr("Copy label"), this); + copyMessageAction = new QAction(tr("Copy message"), this); + copyAmountAction = new QAction(tr("Copy amount"), this); // context menu contextMenu = new QMenu(this); @@ -269,9 +269,18 @@ void ReceiveCoinsDialog::copyColumnToClipboard(int column) // context menu void ReceiveCoinsDialog::showMenu(const QPoint &point) { - if (!selectedRow().isValid()) { + const QModelIndex sel = selectedRow(); + if (!sel.isValid()) { return; } + + // disable context menu actions when appropriate + const RecentRequestsTableModel* const submodel = model->getRecentRequestsTableModel(); + const RecentRequestEntry& req = submodel->entry(sel.row()); + copyLabelAction->setDisabled(req.recipient.label.isEmpty()); + copyMessageAction->setDisabled(req.recipient.message.isEmpty()); + copyAmountAction->setDisabled(req.recipient.amount == 0); + contextMenu->exec(QCursor::pos()); } diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index f12cd8ce0c..fbbccc5a33 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -53,6 +53,9 @@ private: Ui::ReceiveCoinsDialog *ui; WalletModel *model; QMenu *contextMenu; + QAction* copyLabelAction; + QAction* copyMessageAction; + QAction* copyAmountAction; const PlatformStyle *platformStyle; QModelIndex selectedRow(); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 4a4b557acc..5acf8b1cf0 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1120,11 +1120,14 @@ void RPCConsole::updateDetailWidget() if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings == "" ? "From" : "/From"); if (bip152_hb_settings == "") bip152_hb_settings = "No"; ui->peerHighBandwidth->setText(bip152_hb_settings); - ui->peerLastSend->setText(stats->nodeStats.nLastSend ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastSend) : tr("never")); - ui->peerLastRecv->setText(stats->nodeStats.nLastRecv ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastRecv) : tr("never")); + const int64_t time_now{GetSystemTimeInSeconds()}; + ui->peerConnTime->setText(GUIUtil::formatDurationStr(time_now - stats->nodeStats.nTimeConnected)); + ui->peerLastBlock->setText(TimeDurationField(time_now, stats->nodeStats.nLastBlockTime)); + ui->peerLastTx->setText(TimeDurationField(time_now, stats->nodeStats.nLastTXTime)); + ui->peerLastSend->setText(TimeDurationField(time_now, stats->nodeStats.nLastSend)); + ui->peerLastRecv->setText(TimeDurationField(time_now, stats->nodeStats.nLastRecv)); ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes)); ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes)); - ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nTimeConnected)); ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_ping_usec)); ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_usec)); ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset)); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 5f308dc36d..27d4c42eb4 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -168,6 +168,11 @@ private: /** Update UI with latest network info from model. */ void updateNetworkState(); + /** Helper for the output of a time duration field. Inputs are UNIX epoch times. */ + QString TimeDurationField(uint64_t time_now, uint64_t time_at_event) const { + return time_at_event ? GUIUtil::formatDurationStr(time_now - time_at_event) : tr("Never"); + } + private Q_SLOTS: void updateAlerts(const QString& warnings); }; diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index b568f41158..e1ec7b6ed0 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -172,6 +172,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this); QAction *copyTxHexAction = new QAction(tr("Copy raw transaction"), this); QAction *copyTxPlainText = new QAction(tr("Copy full transaction details"), this); + QAction *editLabelAction = new QAction(tr("Edit address label"), this); QAction *showDetailsAction = new QAction(tr("Show transaction details"), this); contextMenu = new QMenu(this); @@ -186,6 +187,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa contextMenu->addSeparator(); contextMenu->addAction(bumpFeeAction); contextMenu->addAction(abandonAction); + contextMenu->addAction(editLabelAction); connect(dateWidget, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &TransactionView::chooseDate); connect(typeWidget, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &TransactionView::chooseType); @@ -206,6 +208,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa connect(copyTxIDAction, &QAction::triggered, this, &TransactionView::copyTxID); connect(copyTxHexAction, &QAction::triggered, this, &TransactionView::copyTxHex); connect(copyTxPlainText, &QAction::triggered, this, &TransactionView::copyTxPlainText); + connect(editLabelAction, &QAction::triggered, this, &TransactionView::editLabel); connect(showDetailsAction, &QAction::triggered, this, &TransactionView::showDetails); // Double-clicking on a transaction on the transaction history page shows details connect(this, &TransactionView::doubleClicked, this, &TransactionView::showDetails); @@ -474,6 +477,52 @@ void TransactionView::copyTxPlainText() GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::TxPlainTextRole); } +void TransactionView::editLabel() +{ + if(!transactionView->selectionModel() ||!model) + return; + QModelIndexList selection = transactionView->selectionModel()->selectedRows(); + if(!selection.isEmpty()) + { + AddressTableModel *addressBook = model->getAddressTableModel(); + if(!addressBook) + return; + QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString(); + if(address.isEmpty()) + { + // If this transaction has no associated address, exit + return; + } + // Is address in address book? Address book can miss address when a transaction is + // sent from outside the UI. + int idx = addressBook->lookupAddress(address); + if(idx != -1) + { + // Edit sending / receiving address + QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex()); + // Determine type of address, launch appropriate editor dialog type + QString type = modelIdx.data(AddressTableModel::TypeRole).toString(); + + EditAddressDialog dlg( + type == AddressTableModel::Receive + ? EditAddressDialog::EditReceivingAddress + : EditAddressDialog::EditSendingAddress, this); + dlg.setModel(addressBook); + dlg.loadRow(idx); + dlg.exec(); + } + else + { + // Add sending address + EditAddressDialog dlg(EditAddressDialog::NewSendingAddress, + this); + dlg.setModel(addressBook); + dlg.setAddress(address); + dlg.exec(); + } + } +} + void TransactionView::showDetails() { if(!transactionView->selectionModel()) diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index cd40813461..35ada4aa7a 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -90,6 +90,7 @@ private Q_SLOTS: void dateRangeChanged(); void showDetails(); void copyAddress(); + void editLabel(); void copyLabel(); void copyAmount(); void copyTxID(); diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp index 1ea6b3d01d..b55f1c72b1 100644 --- a/src/test/fuzz/addrman.cpp +++ b/src/test/fuzz/addrman.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp index 9ecd172e19..dbc0b5ab81 100644 --- a/src/test/fuzz/autofile.cpp +++ b/src/test/fuzz/autofile.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp index e0715f3e29..124439559e 100644 --- a/src/test/fuzz/banman.cpp +++ b/src/test/fuzz/banman.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,7 +26,7 @@ int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept void initialize_banman() { - static const auto testing_setup = MakeFuzzingContext<>(); + static const auto testing_setup = MakeNoLogFileContext<>(); } FUZZ_TARGET_INIT(banman, initialize_banman) diff --git a/src/test/fuzz/bloom_filter.cpp b/src/test/fuzz/bloom_filter.cpp index d43c182644..c5bb8744a4 100644 --- a/src/test/fuzz/bloom_filter.cpp +++ b/src/test/fuzz/bloom_filter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp index 3a1b2dbbe7..ffe38f10fc 100644 --- a/src/test/fuzz/buffered_file.cpp +++ b/src/test/fuzz/buffered_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 8ece94d771..19486365f6 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -36,7 +36,7 @@ bool operator==(const Coin& a, const Coin& b) void initialize_coins_view() { - static const auto testing_setup = MakeFuzzingContext<const TestingSetup>(); + static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); } FUZZ_TARGET_INIT(coins_view, initialize_coins_view) diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index 71b4b00116..3fb8d8ca06 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -17,7 +17,7 @@ void initialize_connman() { - static const auto testing_setup = MakeFuzzingContext<>(); + static const auto testing_setup = MakeNoLogFileContext<>(); } FUZZ_TARGET_INIT(connman, initialize_connman) diff --git a/src/test/fuzz/crypto.cpp b/src/test/fuzz/crypto.cpp index 17ac48fca7..eeeac18968 100644 --- a/src/test/fuzz/crypto.cpp +++ b/src/test/fuzz/crypto.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/crypto_chacha20.cpp b/src/test/fuzz/crypto_chacha20.cpp index bb8dd4594f..8adfa92420 100644 --- a/src/test/fuzz/crypto_chacha20.cpp +++ b/src/test/fuzz/crypto_chacha20.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp index 0e1c44cded..bb4ef22158 100644 --- a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp +++ b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/data_stream.cpp b/src/test/fuzz/data_stream.cpp index f3b6e6af04..d6ef0c6691 100644 --- a/src/test/fuzz/data_stream.cpp +++ b/src/test/fuzz/data_stream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,7 +13,7 @@ void initialize_data_stream_addr_man() { - static const auto testing_setup = MakeFuzzingContext<>(); + static const auto testing_setup = MakeNoLogFileContext<>(); } FUZZ_TARGET_INIT(data_stream_addr_man, initialize_data_stream_addr_man) diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index ba5f0c1a75..64c6e49615 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2020 The Bitcoin Core developers +// Copyright (c) 2009-2021 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/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index edb270d437..1fab46ff13 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2020 The Bitcoin Core developers +// Copyright (c) 2009-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -44,7 +44,7 @@ void initialize() std::get<1>(it->second)(); } -#if defined(PROVIDE_MAIN_FUNCTION) +#if defined(PROVIDE_FUZZ_MAIN_FUNCTION) static bool read_stdin(std::vector<uint8_t>& data) { uint8_t buffer[1024]; @@ -71,7 +71,7 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) return 0; } -#if defined(PROVIDE_MAIN_FUNCTION) +#if defined(PROVIDE_FUZZ_MAIN_FUNCTION) int main(int argc, char** argv) { initialize(); diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h index 4abc52c15a..2bad77bdc1 100644 --- a/src/test/fuzz/fuzz.h +++ b/src/test/fuzz/fuzz.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2020 The Bitcoin Core developers +// Copyright (c) 2009-2021 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/src/test/fuzz/kitchen_sink.cpp b/src/test/fuzz/kitchen_sink.cpp index fa4024fc38..908e9a1c83 100644 --- a/src/test/fuzz/kitchen_sink.cpp +++ b/src/test/fuzz/kitchen_sink.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/load_external_block_file.cpp b/src/test/fuzz/load_external_block_file.cpp index 95597bf082..dbd0c76d42 100644 --- a/src/test/fuzz/load_external_block_file.cpp +++ b/src/test/fuzz/load_external_block_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,7 @@ void initialize_load_external_block_file() { - static const auto testing_setup = MakeFuzzingContext<const TestingSetup>(); + static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); } FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file) diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp index 23e0baa564..1eefd4c521 100644 --- a/src/test/fuzz/merkleblock.cpp +++ b/src/test/fuzz/merkleblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/muhash.cpp b/src/test/fuzz/muhash.cpp index 2d761cef15..4ea9511870 100644 --- a/src/test/fuzz/muhash.cpp +++ b/src/test/fuzz/muhash.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index 21dca4eb05..b056f46f2e 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,7 +22,7 @@ void initialize_net() { - static const auto testing_setup = MakeFuzzingContext<>(CBaseChainParams::MAIN); + static const auto testing_setup = MakeNoLogFileContext<>(CBaseChainParams::MAIN); } FUZZ_TARGET_INIT(net, initialize_net) diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp index a42080eb66..f9d8129ca9 100644 --- a/src/test/fuzz/netaddress.cpp +++ b/src/test/fuzz/netaddress.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp index fff893fb3f..311550f041 100644 --- a/src/test/fuzz/policy_estimator.cpp +++ b/src/test/fuzz/policy_estimator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -16,7 +16,7 @@ void initialize_policy_estimator() { - static const auto testing_setup = MakeFuzzingContext<>(); + static const auto testing_setup = MakeNoLogFileContext<>(); } FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator) diff --git a/src/test/fuzz/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp index 73242870a0..c24ad3d49a 100644 --- a/src/test/fuzz/policy_estimator_io.cpp +++ b/src/test/fuzz/policy_estimator_io.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,7 +12,7 @@ void initialize_policy_estimator_io() { - static const auto testing_setup = MakeFuzzingContext<>(); + static const auto testing_setup = MakeNoLogFileContext<>(); } FUZZ_TARGET_INIT(policy_estimator_io, initialize_policy_estimator_io) diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp index c4348495bf..53726ca893 100644 --- a/src/test/fuzz/pow.cpp +++ b/src/test/fuzz/pow.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index 442e32d4ca..e3571e15b7 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -56,7 +56,7 @@ void initialize_process_message() { Assert(GetNumMsgTypes() == getAllNetMessageTypes().size()); // If this fails, add or remove the message type below - static const auto testing_setup = MakeFuzzingContext<const TestingSetup>(); + static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); g_setup = testing_setup.get(); for (int i = 0; i < 2 * COINBASE_MATURITY; i++) { MineBlock(g_setup->m_node, CScript() << OP_TRUE); diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index ef45196671..f62a0c64ed 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -23,7 +23,7 @@ const TestingSetup* g_setup; void initialize_process_messages() { - static const auto testing_setup = MakeFuzzingContext<const TestingSetup>(); + static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); g_setup = testing_setup.get(); for (int i = 0; i < 2 * COINBASE_MATURITY; i++) { MineBlock(g_setup->m_node, CScript() << OP_TRUE); diff --git a/src/test/fuzz/rolling_bloom_filter.cpp b/src/test/fuzz/rolling_bloom_filter.cpp index 2a08b45aa3..07059cce76 100644 --- a/src/test/fuzz/rolling_bloom_filter.cpp +++ b/src/test/fuzz/rolling_bloom_filter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp index 7fadf36f98..193862e847 100644 --- a/src/test/fuzz/script.cpp +++ b/src/test/fuzz/script.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020 The Bitcoin Core developers +// Copyright (c) 2019-2021 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/src/test/fuzz/script_assets_test_minimizer.cpp b/src/test/fuzz/script_assets_test_minimizer.cpp index 8d9a939dab..5f07acbcc7 100644 --- a/src/test/fuzz/script_assets_test_minimizer.cpp +++ b/src/test/fuzz/script_assets_test_minimizer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/script_ops.cpp b/src/test/fuzz/script_ops.cpp index bdbfe817ff..eb1c808a88 100644 --- a/src/test/fuzz/script_ops.cpp +++ b/src/test/fuzz/script_ops.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/scriptnum_ops.cpp b/src/test/fuzz/scriptnum_ops.cpp index bc4867839c..62ed50d13f 100644 --- a/src/test/fuzz/scriptnum_ops.cpp +++ b/src/test/fuzz/scriptnum_ops.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/signet.cpp b/src/test/fuzz/signet.cpp index 83effec064..0d1999731f 100644 --- a/src/test/fuzz/signet.cpp +++ b/src/test/fuzz/signet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -17,7 +17,7 @@ void initialize_signet() { - static const auto testing_setup = MakeFuzzingContext<>(CBaseChainParams::SIGNET); + static const auto testing_setup = MakeNoLogFileContext<>(CBaseChainParams::SIGNET); } FUZZ_TARGET_INIT(signet, initialize_signet) diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp index ec8a3b23db..93b4948a2f 100644 --- a/src/test/fuzz/string.cpp +++ b/src/test/fuzz/string.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/strprintf.cpp b/src/test/fuzz/strprintf.cpp index b66a7abfb3..2c92b159a5 100644 --- a/src/test/fuzz/strprintf.cpp +++ b/src/test/fuzz/strprintf.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/system.cpp b/src/test/fuzz/system.cpp index 3621702e45..d9571209fa 100644 --- a/src/test/fuzz/system.cpp +++ b/src/test/fuzz/system.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Bitcoin Core developers +// Copyright (c) 2020-2021 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/src/test/fuzz/util.h b/src/test/fuzz/util.h index 7a2dcfe84a..f3bc3c78ab 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2020 The Bitcoin Core developers +// Copyright (c) 2009-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -325,7 +325,7 @@ inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, co void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, bool init_version) noexcept; template <class T = const BasicTestingSetup> -std::unique_ptr<T> MakeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST, const std::vector<const char*>& extra_args = {}) +std::unique_ptr<T> MakeNoLogFileContext(const std::string& chain_name = CBaseChainParams::REGTEST, const std::vector<const char*>& extra_args = {}) { // Prepend default arguments for fuzzing const std::vector<const char*> arguments = Cat( diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index d1770f750f..8f1d99b199 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -63,7 +63,7 @@ static std::map<std::string, unsigned int> mapFlagNames = { unsigned int ParseScriptFlags(std::string strFlags) { - if (strFlags.empty() | strFlags == "NONE") return 0; + if (strFlags.empty() || strFlags == "NONE") return 0; unsigned int flags = 0; std::vector<std::string> words; boost::algorithm::split(words, strFlags, boost::algorithm::is_any_of(",")); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 899835019a..48424a75d0 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -23,7 +23,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFe int64_t _nTime, unsigned int _entryHeight, bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp) : tx(_tx), nFee(_nFee), nTxWeight(GetTransactionWeight(*tx)), nUsageSize(RecursiveDynamicUsage(tx)), nTime(_nTime), entryHeight(_entryHeight), - spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp), m_epoch(0) + spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp) { nCountWithDescendants = 1; nSizeWithDescendants = GetTxSize(); @@ -132,7 +132,7 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashes // include them, and update their CTxMemPoolEntry::m_parents to include this tx. // we cache the in-mempool children to avoid duplicate updates { - const auto epoch = GetFreshEpoch(); + WITH_FRESH_EPOCH(m_epoch); for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) { const uint256 &childHash = iter->second->GetHash(); txiter childIter = mapTx.find(childHash); @@ -1119,22 +1119,3 @@ void CTxMemPool::SetIsLoaded(bool loaded) LOCK(cs); m_is_loaded = loaded; } - - -CTxMemPool::EpochGuard CTxMemPool::GetFreshEpoch() const -{ - return EpochGuard(*this); -} -CTxMemPool::EpochGuard::EpochGuard(const CTxMemPool& in) : pool(in) -{ - assert(!pool.m_has_epoch_guard); - ++pool.m_epoch; - pool.m_has_epoch_guard = true; -} - -CTxMemPool::EpochGuard::~EpochGuard() -{ - // prevents stale results being used - ++pool.m_epoch; - pool.m_has_epoch_guard = false; -} diff --git a/src/txmempool.h b/src/txmempool.h index b8de326737..143048b205 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -21,6 +21,7 @@ #include <primitives/transaction.h> #include <random.h> #include <sync.h> +#include <util/epochguard.h> #include <util/hasher.h> #include <boost/multi_index_container.hpp> @@ -64,6 +65,7 @@ struct CompareIteratorByHash { return a->GetTx().GetHash() < b->GetTx().GetHash(); } }; + /** \class CTxMemPoolEntry * * CTxMemPoolEntry stores data about the corresponding transaction, as well @@ -156,7 +158,7 @@ public: Children& GetMemPoolChildren() const { return m_children; } mutable size_t vTxHashesIdx; //!< Index in mempool's vTxHashes - mutable uint64_t m_epoch; //!< epoch when last touched, useful for graph algorithms + mutable Epoch::Marker m_epoch_marker; //!< epoch when last touched, useful for graph algorithms }; // Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index. @@ -486,8 +488,7 @@ private: mutable int64_t lastRollingFeeUpdate; mutable bool blockSinceLastRollingFeeBump; mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially - mutable uint64_t m_epoch{0}; - mutable bool m_has_epoch_guard{false}; + mutable Epoch m_epoch GUARDED_BY(cs); // In-memory counter for external mempool tracking purposes. // This number is incremented once every time a transaction @@ -666,7 +667,7 @@ public: * for). Note: vHashesToUpdate should be the set of transactions from the * disconnected block that have been accepted back into the mempool. */ - void UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); + void UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main) LOCKS_EXCLUDED(m_epoch); /** Try to calculate all in-mempool ancestors of entry. * (these are all calculated including the tx itself) @@ -827,52 +828,22 @@ private: */ void removeUnchecked(txiter entry, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs); public: - /** EpochGuard: RAII-style guard for using epoch-based graph traversal algorithms. - * When walking ancestors or descendants, we generally want to avoid - * visiting the same transactions twice. Some traversal algorithms use - * std::set (or setEntries) to deduplicate the transaction we visit. - * However, use of std::set is algorithmically undesirable because it both - * adds an asymptotic factor of O(log n) to traverals cost and triggers O(n) - * more dynamic memory allocations. - * In many algorithms we can replace std::set with an internal mempool - * counter to track the time (or, "epoch") that we began a traversal, and - * check + update a per-transaction epoch for each transaction we look at to - * determine if that transaction has not yet been visited during the current - * traversal's epoch. - * Algorithms using std::set can be replaced on a one by one basis. - * Both techniques are not fundamentally incompatible across the codebase. - * Generally speaking, however, the remaining use of std::set for mempool - * traversal should be viewed as a TODO for replacement with an epoch based - * traversal, rather than a preference for std::set over epochs in that - * algorithm. - */ - class EpochGuard { - const CTxMemPool& pool; - public: - explicit EpochGuard(const CTxMemPool& in); - ~EpochGuard(); - }; - // N.B. GetFreshEpoch modifies mutable state via the EpochGuard construction - // (and later destruction) - EpochGuard GetFreshEpoch() const EXCLUSIVE_LOCKS_REQUIRED(cs); - /** visited marks a CTxMemPoolEntry as having been traversed - * during the lifetime of the most recently created EpochGuard + * during the lifetime of the most recently created Epoch::Guard * and returns false if we are the first visitor, true otherwise. * - * An EpochGuard must be held when visited is called or an assert will be + * An Epoch::Guard must be held when visited is called or an assert will be * triggered. * */ - bool visited(txiter it) const EXCLUSIVE_LOCKS_REQUIRED(cs) { - assert(m_has_epoch_guard); - bool ret = it->m_epoch >= m_epoch; - it->m_epoch = std::max(it->m_epoch, m_epoch); - return ret; + bool visited(const txiter it) const EXCLUSIVE_LOCKS_REQUIRED(cs, m_epoch) + { + return m_epoch.visited(it->m_epoch_marker); } - bool visited(Optional<txiter> it) const EXCLUSIVE_LOCKS_REQUIRED(cs) { - assert(m_has_epoch_guard); + bool visited(Optional<txiter> it) const EXCLUSIVE_LOCKS_REQUIRED(cs, m_epoch) + { + assert(m_epoch.guarded()); // verify guard even when it==nullopt return !it || visited(*it); } }; diff --git a/src/util/epochguard.h b/src/util/epochguard.h new file mode 100644 index 0000000000..1570ec4eb4 --- /dev/null +++ b/src/util/epochguard.h @@ -0,0 +1,91 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2020 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_UTIL_EPOCHGUARD_H +#define BITCOIN_UTIL_EPOCHGUARD_H + +#include <threadsafety.h> + +#include <cassert> + +/** Epoch: RAII-style guard for using epoch-based graph traversal algorithms. + * When walking ancestors or descendants, we generally want to avoid + * visiting the same transactions twice. Some traversal algorithms use + * std::set (or setEntries) to deduplicate the transaction we visit. + * However, use of std::set is algorithmically undesirable because it both + * adds an asymptotic factor of O(log n) to traversals cost and triggers O(n) + * more dynamic memory allocations. + * In many algorithms we can replace std::set with an internal mempool + * counter to track the time (or, "epoch") that we began a traversal, and + * check + update a per-transaction epoch for each transaction we look at to + * determine if that transaction has not yet been visited during the current + * traversal's epoch. + * Algorithms using std::set can be replaced on a one by one basis. + * Both techniques are not fundamentally incompatible across the codebase. + * Generally speaking, however, the remaining use of std::set for mempool + * traversal should be viewed as a TODO for replacement with an epoch based + * traversal, rather than a preference for std::set over epochs in that + * algorithm. + */ + +class LOCKABLE Epoch +{ +private: + uint64_t m_raw_epoch = 0; + bool m_guarded = false; + +public: + Epoch() = default; + Epoch(const Epoch&) = delete; + Epoch& operator=(const Epoch&) = delete; + + bool guarded() const { return m_guarded; } + + class Marker + { + private: + uint64_t m_marker = 0; + + // only allow modification via Epoch member functions + friend class Epoch; + Marker& operator=(const Marker&) = delete; + }; + + class SCOPED_LOCKABLE Guard + { + private: + Epoch& m_epoch; + + public: + explicit Guard(Epoch& epoch) EXCLUSIVE_LOCK_FUNCTION(epoch) : m_epoch(epoch) + { + assert(!m_epoch.m_guarded); + ++m_epoch.m_raw_epoch; + m_epoch.m_guarded = true; + } + ~Guard() UNLOCK_FUNCTION() + { + assert(m_epoch.m_guarded); + ++m_epoch.m_raw_epoch; // ensure clear separation between epochs + m_epoch.m_guarded = false; + } + }; + + bool visited(Marker& marker) const EXCLUSIVE_LOCKS_REQUIRED(*this) + { + assert(m_guarded); + if (marker.m_marker < m_raw_epoch) { + // marker is from a previous epoch, so this is its first visit + marker.m_marker = m_raw_epoch; + return false; + } else { + return true; + } + } +}; + +#define WITH_FRESH_EPOCH(epoch) const Epoch::Guard PASTE2(epoch_guard_, __COUNTER__)(epoch) + +#endif // BITCOIN_UTIL_EPOCHGUARD_H diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index fc530ee286..f3e24384df 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -62,7 +62,7 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const CURRENCY_UNIT, FormatMoney(CFeeRate{DEFAULT_PAY_TX_FEE}.GetFeePerK())), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-rescan", "Rescan the block chain for missing wallet transactions on startup", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); #ifdef ENABLE_EXTERNAL_SIGNER - argsman.AddArg("-signer=<cmd>", "External signing tool, see docs/external-signer.md", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); + argsman.AddArg("-signer=<cmd>", "External signing tool, see doc/external-signer.md", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); #endif argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 99803a91d2..a2872f10ae 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1775,6 +1775,8 @@ RPCHelpMan listdescriptors() throw JSONRPCError(RPC_WALLET_ERROR, "listdescriptors is not available for non-descriptor wallets"); } + EnsureWalletIsUnlocked(wallet.get()); + LOCK(wallet->cs_wallet); UniValue response(UniValue::VARR); @@ -1787,7 +1789,11 @@ RPCHelpMan listdescriptors() UniValue spk(UniValue::VOBJ); LOCK(desc_spk_man->cs_desc_man); const auto& wallet_descriptor = desc_spk_man->GetWalletDescriptor(); - spk.pushKV("desc", wallet_descriptor.descriptor->ToString()); + std::string descriptor; + if (!desc_spk_man->GetDescriptorString(descriptor, false)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Can't get normalized descriptor string."); + } + spk.pushKV("desc", descriptor); spk.pushKV("timestamp", wallet_descriptor.creation_time); const bool active = active_spk_mans.count(desc_spk_man) != 0; spk.pushKV("active", active); diff --git a/test/functional/feature_blockfilterindex_prune.py b/test/functional/feature_blockfilterindex_prune.py index 455073ef9c..d13d191b20 100755 --- a/test/functional/feature_blockfilterindex_prune.py +++ b/test/functional/feature_blockfilterindex_prune.py @@ -5,49 +5,60 @@ """Test blockfilterindex in conjunction with prune.""" from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - assert_raises_rpc_error, + assert_equal, assert_greater_than, + assert_raises_rpc_error, ) class FeatureBlockfilterindexPruneTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 2 - self.extra_args = [["-fastprune", "-prune=1"], ["-fastprune", "-prune=1", "-blockfilterindex=1"]] + self.num_nodes = 1 + self.extra_args = [["-fastprune", "-prune=1", "-blockfilterindex=1"]] + + def sync_index(self, height): + expected = {'basic block filter index': {'synced': True, 'best_block_height': height}} + self.wait_until(lambda: self.nodes[0].getindexinfo() == expected) def run_test(self): - # test basic pruning compatibility & filter access of pruned blocks self.log.info("check if we can access a blockfilter when pruning is enabled but no blocks are actually pruned") - assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0 + self.sync_index(height=200) + assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getbestblockhash())['filter']), 0) # Mine two batches of blocks to avoid hitting NODE_NETWORK_LIMITED_MIN_BLOCKS disconnection - self.nodes[1].generate(250) + self.nodes[0].generate(250) self.sync_all() - self.nodes[1].generate(250) + self.nodes[0].generate(250) self.sync_all() + self.sync_index(height=700) + self.log.info("prune some blocks") - pruneheight = self.nodes[1].pruneblockchain(400) - assert pruneheight != 0 + pruneheight = self.nodes[0].pruneblockchain(400) + assert_equal(pruneheight, 250) + self.log.info("check if we can access the tips blockfilter when we have pruned some blocks") - assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0 + assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getbestblockhash())['filter']), 0) + self.log.info("check if we can access the blockfilter of a pruned block") - assert len(self.nodes[1].getblockfilter(self.nodes[1].getblockhash(2))['filter']) > 0 + assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getblockhash(2))['filter']), 0) + self.log.info("start node without blockfilterindex") - self.stop_node(1) - self.start_node(1, extra_args=self.extra_args[0]) + self.restart_node(0, extra_args=["-fastprune", "-prune=1"]) + self.log.info("make sure accessing the blockfilters throws an error") - assert_raises_rpc_error(-1, "Index is not enabled for filtertype basic", self.nodes[1].getblockfilter, self.nodes[1].getblockhash(2)) - self.nodes[1].generate(1000) + assert_raises_rpc_error(-1, "Index is not enabled for filtertype basic", self.nodes[0].getblockfilter, self.nodes[0].getblockhash(2)) + self.nodes[0].generate(1000) + self.log.info("prune below the blockfilterindexes best block while blockfilters are disabled") - pruneheight_new = self.nodes[1].pruneblockchain(1000) + pruneheight_new = self.nodes[0].pruneblockchain(1000) assert_greater_than(pruneheight_new, pruneheight) - self.stop_node(1) + self.stop_node(0) + self.log.info("make sure we get an init error when starting the node again with block filters") - with self.nodes[1].assert_debug_log(["basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"]): - self.nodes[1].assert_start_raises_init_error(extra_args=self.extra_args[1]) + with self.nodes[0].assert_debug_log(["basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"]): + self.nodes[0].assert_start_raises_init_error(extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"]) + self.log.info("make sure the node starts again with the -reindex arg") - reindex_args = self.extra_args[1] - reindex_args.append("-reindex") - self.start_node(1, extra_args=reindex_args) + self.start_node(0, extra_args = ["-fastprune", "-prune=1", "-blockfilterindex", "-reindex"]) if __name__ == '__main__': diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 573760a8cb..a0bcd9f12a 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -19,7 +19,7 @@ class ConfArgsTest(BitcoinTestFramework): self.wallet_names = [] def test_config_file_parser(self): - # Assume node is stopped + self.stop_node(0) inc_conf_file_path = os.path.join(self.nodes[0].datadir, 'include.conf') with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf: @@ -89,11 +89,12 @@ class ConfArgsTest(BitcoinTestFramework): ) def test_log_buffer(self): + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['Warning: parsed potentially confusing double-negative -connect=0\n']): self.start_node(0, extra_args=['-noconnect=0']) - self.stop_node(0) def test_args_log(self): + self.stop_node(0) self.log.info('Test config args logging') with self.nodes[0].assert_debug_log( expected_msgs=[ @@ -120,37 +121,41 @@ class ConfArgsTest(BitcoinTestFramework): '-rpcuser=secret-rpcuser', '-torpassword=secret-torpassword', ]) - self.stop_node(0) def test_networkactive(self): self.log.info('Test -networkactive option') + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']): self.start_node(0) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']): self.start_node(0, extra_args=['-networkactive']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']): self.start_node(0, extra_args=['-networkactive=1']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']): self.start_node(0, extra_args=['-networkactive=0']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']): self.start_node(0, extra_args=['-nonetworkactive']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']): self.start_node(0, extra_args=['-nonetworkactive=1']) - self.stop_node(0) def test_seed_peers(self): self.log.info('Test seed peers') default_data_dir = self.nodes[0].datadir + # Only regtest has no fixed seeds. To avoid connections to random + # nodes, regtest is the only network where it is safe to enable + # -fixedseeds in tests + util.assert_equal(self.nodes[0].getblockchaininfo()['chain'],'regtest') + self.stop_node(0) # No peers.dat exists and -dnsseed=1 # We expect the node will use DNS Seeds, but Regtest mode has 0 DNS seeds @@ -159,10 +164,12 @@ class ConfArgsTest(BitcoinTestFramework): start = int(time.time()) with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", - "0 addresses found from DNS seeds"]): - self.start_node(0, extra_args=['-dnsseed=1 -mocktime={}'.format(start)]) + "0 addresses found from DNS seeds", + ]): + self.start_node(0, extra_args=['-dnsseed=1', '-fixedseeds=1', f'-mocktime={start}']) with self.nodes[0].assert_debug_log(expected_msgs=[ - "Adding fixed seeds as 60 seconds have passed and addrman is empty"]): + "Adding fixed seeds as 60 seconds have passed and addrman is empty", + ]): self.nodes[0].setmocktime(start + 65) self.stop_node(0) @@ -173,8 +180,9 @@ class ConfArgsTest(BitcoinTestFramework): with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", "DNS seeding disabled", - "Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n"]): - self.start_node(0, extra_args=['-dnsseed=0']) + "Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n", + ]): + self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1']) assert time.time() - start < 60 self.stop_node(0) @@ -185,7 +193,8 @@ class ConfArgsTest(BitcoinTestFramework): with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", "DNS seeding disabled", - "Fixed seeds are disabled"]): + "Fixed seeds are disabled", + ]): self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=0']) assert time.time() - start < 60 self.stop_node(0) @@ -196,17 +205,15 @@ class ConfArgsTest(BitcoinTestFramework): start = int(time.time()) with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", - "DNS seeding disabled"]): - self.start_node(0, extra_args=['-dnsseed=0', '-addnode=fakenodeaddr -mocktime={}'.format(start)]) + "DNS seeding disabled", + ]): + self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1', '-addnode=fakenodeaddr', f'-mocktime={start}']) with self.nodes[0].assert_debug_log(expected_msgs=[ - "Adding fixed seeds as 60 seconds have passed and addrman is empty"]): + "Adding fixed seeds as 60 seconds have passed and addrman is empty", + ]): self.nodes[0].setmocktime(start + 65) - self.stop_node(0) - def run_test(self): - self.stop_node(0) - self.test_log_buffer() self.test_args_log() self.test_seed_peers() diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index a6afbad0fc..e090030205 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -23,6 +23,7 @@ import http.client import os import subprocess +from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE from test_framework.blocktools import ( create_block, create_coinbase, @@ -71,11 +72,10 @@ class BlockchainTest(BitcoinTestFramework): 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) + self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2WSH_OP_TRUE) assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200) def _test_getblockchaininfo(self): @@ -227,7 +227,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res['transactions'], 200) assert_equal(res['height'], 200) assert_equal(res['txouts'], 200) - assert_equal(res['bogosize'], 15000), + assert_equal(res['bogosize'], 16800), assert_equal(res['bestblock'], node.getblockhash(200)) size = res['disk_size'] assert size > 6400 @@ -332,12 +332,12 @@ class BlockchainTest(BitcoinTestFramework): def _test_stopatheight(self): assert_equal(self.nodes[0].getblockcount(), 200) - self.nodes[0].generatetoaddress(6, self.nodes[0].get_deterministic_priv_key().address) + self.nodes[0].generatetoaddress(6, ADDRESS_BCRT1_P2WSH_OP_TRUE) assert_equal(self.nodes[0].getblockcount(), 206) self.log.debug('Node should not stop at this height') assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3)) try: - self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address) + self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2WSH_OP_TRUE) except (ConnectionError, http.client.BadStatusLine): pass # The node already shut down before response self.log.debug('Node should stop at this height...') @@ -387,8 +387,7 @@ class BlockchainTest(BitcoinTestFramework): node = self.nodes[0] miniwallet = MiniWallet(node) - miniwallet.generate(5) - node.generate(100) + miniwallet.scan_blocks(num=5) fee_per_byte = Decimal('0.00000010') fee_per_kb = 1000 * fee_per_byte diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index f7eaaa548f..02eb10b5a4 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -19,6 +19,7 @@ import tempfile import time from typing import List +from .address import ADDRESS_BCRT1_P2WSH_OP_TRUE from .authproxy import JSONRPCException from . import coverage from .p2p import NetworkThread @@ -732,16 +733,17 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): # Set a time in the past, so that blocks don't end up in the future cache_node.setmocktime(cache_node.getblockheader(cache_node.getbestblockhash())['time']) - # Create a 199-block-long chain; each of the 4 first nodes + # Create a 199-block-long chain; each of the 3 first nodes # gets 25 mature blocks and 25 immature. - # The 4th node gets only 24 immature blocks so that the very last + # The 4th address gets 25 mature and 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(). + gen_addresses = [k.address for k in TestNode.PRIV_KEYS] + [ADDRESS_BCRT1_P2WSH_OP_TRUE] for i in range(8): cache_node.generatetoaddress( nblocks=25 if i != 7 else 24, - address=TestNode.PRIV_KEYS[i % 4].address, + address=gen_addresses[i % 4], ) assert_equal(cache_node.getblockchaininfo()["blocks"], 199) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 123c48852c..d335d4ea79 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -368,6 +368,7 @@ def write_config(config_path, *, n, chain, extra_config=""): f.write("keypool=1\n") f.write("discover=0\n") f.write("dnsseed=0\n") + f.write("fixedseeds=0\n") f.write("listenonion=0\n") f.write("printtoconsole=0\n") f.write("upnp=0\n") diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py index edd7792608..38fbf3c1a6 100644 --- a/test/functional/test_framework/wallet.py +++ b/test/functional/test_framework/wallet.py @@ -32,6 +32,15 @@ class MiniWallet: self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE self._scriptPubKey = hex_str_to_bytes(self._test_node.validateaddress(self._address)['scriptPubKey']) + def scan_blocks(self, *, start=1, num): + """Scan the blocks for self._address outputs and add them to self._utxos""" + for i in range(start, start + num): + block = self._test_node.getblock(blockhash=self._test_node.getblockhash(i), verbosity=2) + for tx in block['tx']: + for out in tx['vout']: + if out['scriptPubKey']['hex'] == self._scriptPubKey.hex(): + self._utxos.append({'txid': tx['txid'], 'vout': out['n'], 'value': out['value']}) + def generate(self, num_blocks): """Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list""" blocks = self._test_node.generatetoaddress(num_blocks, self._address) diff --git a/test/functional/wallet_listdescriptors.py b/test/functional/wallet_listdescriptors.py index 9f8c341bc7..8d02949ff4 100755 --- a/test/functional/wallet_listdescriptors.py +++ b/test/functional/wallet_listdescriptors.py @@ -50,6 +50,22 @@ class ListDescriptorsTest(BitcoinTestFramework): assert item['range'] == [0, 0] assert item['timestamp'] is not None + self.log.info('Test descriptors with hardened derivations are listed in importable form.') + xprv = 'tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg' + xpub_acc = 'tpubDCMVLhErorrAGfApiJSJzEKwqeaf2z3NrkVMxgYQjZLzMjXMBeRw2muGNYbvaekAE8rUFLftyEar4LdrG2wXyyTJQZ26zptmeTEjPTaATts' + hardened_path = '/84\'/1\'/0\'' + wallet = node.get_wallet_rpc('w2') + wallet.importdescriptors([{ + 'desc': descsum_create('wpkh(' + xprv + hardened_path + '/0/*)'), + 'timestamp': 1296688602, + }]) + expected = {'desc': descsum_create('wpkh([80002067' + hardened_path + ']' + xpub_acc + '/0/*)'), + 'timestamp': 1296688602, + 'active': False, + 'range': [0, 0], + 'next': 0} + assert_equal([expected], wallet.listdescriptors()) + self.log.info('Test non-active non-range combo descriptor') node.createwallet(wallet_name='w4', blank=True, descriptors=True) wallet = node.get_wallet_rpc('w4') diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index 893a2d9617..6fc1d13c53 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -11,9 +11,10 @@ from test_framework.util import ( ) from test_framework.messages import CTransaction, COIN + class TxnMallTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 4 + self.num_nodes = 3 self.supports_cli = False def skip_test_if_missing_module(self): @@ -38,9 +39,8 @@ class TxnMallTest(BitcoinTestFramework): # All nodes should start with 1,250 BTC: starting_balance = 1250 - for i in range(4): + for i in range(3): assert_equal(self.nodes[i].getbalance(), starting_balance) - self.nodes[i].getnewaddress() # bug workaround, coins generated assigned to first getnewaddress! self.nodes[0].settxfee(.001) @@ -139,5 +139,6 @@ class TxnMallTest(BitcoinTestFramework): expected -= 50 assert_equal(self.nodes[0].getbalance(), expected) + if __name__ == '__main__': TxnMallTest().main() diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index c7f7a8546a..0cb7328948 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -11,9 +11,10 @@ from test_framework.util import ( find_output, ) + class TxnMallTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 4 + self.num_nodes = 3 self.supports_cli = False def skip_test_if_missing_module(self): @@ -39,9 +40,8 @@ class TxnMallTest(BitcoinTestFramework): for n in self.nodes: assert n.getblockchaininfo()["initialblockdownload"] == False - for i in range(4): + for i in range(3): assert_equal(self.nodes[i].getbalance(), starting_balance) - self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! # Assign coins to foo and bar addresses: node0_address_foo = self.nodes[0].getnewaddress() @@ -136,5 +136,6 @@ class TxnMallTest(BitcoinTestFramework): # Node1's balance should be its initial balance (1250 for 25 block rewards) plus the doublespend: assert_equal(self.nodes[1].getbalance(), 1250 + 1240) + if __name__ == '__main__': TxnMallTest().main() |