750447e345 Merge bitcoin/bitcoin#20586: Fix Windows build with --enable-werror (W. J. van der Laan)
368a6ef512 Merge bitcoin-core/gui#390: Add SubFeeFromAmount to options (Hennadii Stepanov)
7df9788c85 Merge bitcoin-core/gui#381: refactor: Make BitcoinCore class reusable (W. J. van der Laan)
40a8b925db Merge bitcoin/bitcoin#22688: contrib: use `keys.openpgp.org` to retrieve builder keys (fanquake)
62b5358a9c Merge #11909: contrib: Replace developer keys with list of pgp fingerprints (Wladimir J. van der Laan)
1ff42b40e3 Merge bitcoin/bitcoin#21500: wallet, rpc: add an option to list private descriptors (Samuel Dobson)
5a803ae765 Merge bitcoin/bitcoin#22378: test: remove confusing `MAX_BLOCK_BASE_SIZE` (MarcoFalke)
42a0cf0709 Merge bitcoin/bitcoin#21562: [net processing] Various tidying up of PeerManagerImpl ctor (MarcoFalke)
e3c69da4f2 Merge bitcoin/bitcoin#22232: refactor: Pass interpreter flags as uint32_t instead of signed int (MarcoFalke)

Pull request description:

  ## What was done?
  Regular batch of backports from Bitcoin v23

  ## How Has This Been Tested?
  Run unit and functional tests

  ## Breaking Changes
  N/A

  ## Checklist:
  - [x] I have performed a self-review of my own code
  - [ ] I have commented my code, particularly in hard-to-understand areas
  - [ ] I have added or updated relevant unit/integration/functional/e2e tests
  - [ ] I have made corresponding changes to the documentation
  - [x] I have assigned this pull request to a milestone

ACKs for top commit:
  UdjinM6:
    utACK 750447e345
  PastaPastaPasta:
    utACK 750447e345

Tree-SHA512: 46e0de22798937b6b0a228ea9ca39b465cd9e8b822f973f23af80fccb1fe2d733716930d3f3843aaf41a58225aa98e18cd5d5e361245f64e146ff1be118f91ca
This commit is contained in:
pasta 2024-10-25 10:12:52 -05:00
commit a0ab06f5c0
No known key found for this signature in database
GPG Key ID: E2F3D7916E722D38
30 changed files with 306 additions and 171 deletions

View File

@ -25,7 +25,7 @@ test/lint/lint-all.sh
if [ "$CIRRUS_REPO_FULL_NAME" = "dashpay/dash" ] && [ -n "$CIRRUS_CRON" ]; then
git log --merges --before="2 days ago" -1 --format='%H' > ./contrib/verify-commits/trusted-sha512-root-commit
${CI_RETRY_EXE} gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys $(<contrib/verify-commits/trusted-keys) &&
${CI_RETRY_EXE} gpg --keyserver hkps://keys.openpgp.org --recv-keys $(<contrib/verify-commits/trusted-keys) &&
./contrib/verify-commits/verify-commits.py --clean-merge=2;
fi

View File

@ -15,7 +15,3 @@ export RUN_SECURITY_TESTS="false"
export GOAL="deploy"
export BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --disable-miner --without-boost-process"
export DIRECT_WINE_EXEC_TESTS=true
# Compiler for MinGW-w64 causes false -Wreturn-type warning.
# See https://sourceforge.net/p/mingw-w64/bugs/306/
export NO_WERROR=1

View File

@ -459,7 +459,13 @@ if test "x$enable_werror" = "xyes"; then
AX_CHECK_COMPILE_FLAG([-Werror=range-loop-analysis],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=range-loop-analysis"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=unused-variable],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=unused-variable"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=date-time],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=date-time"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=return-type],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=return-type"],,[[$CXXFLAG_WERROR]])
dnl -Wreturn-type is broken in GCC for MinGW-w64.
dnl https://sourceforge.net/p/mingw-w64/bugs/306/
AX_CHECK_COMPILE_FLAG([-Werror=return-type], [ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=return-type"], [], [$CXXFLAG_WERROR],
[AC_LANG_SOURCE([[#include <cassert>
int f(){ assert(false); }]])])
AX_CHECK_COMPILE_FLAG([-Werror=conditional-uninitialized],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=conditional-uninitialized"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=sign-compare],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=sign-compare"],,[[$CXXFLAG_WERROR]])
dnl -Wsuggest-override is broken with GCC before 9.2

View File

@ -1,15 +1,26 @@
PGP keys
========
## PGP keys of builders and Developers
This folder contains the public keys of developers and active contributors.
The file `keys.txt` contains fingerprints of the public keys of builders and
active developers.
The keys are mainly used to sign git commits or the build results of builds.
You can import the keys into gpg as follows. Also, make sure to fetch the
latest version from the key server to see if any key was revoked in the
meantime.
The most recent version of each pgp key can be found on most pgp key servers.
Fetch the latest version from the key server to see if any key was revoked in
the meantime.
To fetch the latest version of all pgp keys in your gpg homedir,
```sh
gpg --import ./*.pgp
gpg --refresh-keys
```
To fetch keys of builders and active developers, feed the list of fingerprints
of the primary keys into gpg:
```sh
while read fingerprint keyholder_name; do gpg --keyserver hkps://keys.openpgp.org --recv-keys ${fingerprint}; done < ./keys.txt
```
Add your key to the list if you provided Guix attestations for two major or
minor releases of Dash Core.

View File

@ -40,7 +40,7 @@ Import trusted keys
In order to check the commit signatures, you must add the trusted PGP keys to your machine. [GnuPG](https://gnupg.org/) may be used to import the trusted keys by running the following command:
```sh
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys $(<contrib/verify-commits/trusted-keys)
gpg --keyserver hkps://keys.openpgp.org --recv-keys $(<contrib/verify-commits/trusted-keys)
```
Key expiry/revocation

View File

@ -58,6 +58,7 @@ QT_MOC_CPP = \
qt/moc_editaddressdialog.cpp \
qt/moc_governancelist.cpp \
qt/moc_guiutil.cpp \
qt/moc_initexecutor.cpp \
qt/moc_intro.cpp \
qt/moc_macdockiconhandler.cpp \
qt/moc_macnotificationhandler.cpp \
@ -133,6 +134,7 @@ BITCOIN_QT_H = \
qt/governancelist.h \
qt/guiconstants.h \
qt/guiutil.h \
qt/initexecutor.h \
qt/intro.h \
qt/macdockiconhandler.h \
qt/macnotificationhandler.h \
@ -222,6 +224,7 @@ BITCOIN_QT_BASE_CPP = \
qt/clientmodel.cpp \
qt/csvmodelwriter.cpp \
qt/guiutil.cpp \
qt/initexecutor.cpp \
qt/intro.cpp \
qt/modaloverlay.cpp \
qt/networkstyle.cpp \

View File

@ -49,7 +49,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma
* Count total signature operations for a transaction.
* @param[in] tx Transaction for which we are counting sigops
* @param[in] inputs Map of previous transactions that have outputs we're spending
* @param[out] flags Script verification flags
* @param[in] flags Script verification flags
* @return Total signature operation count for a tx
*/
unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags);

View File

@ -1620,6 +1620,7 @@ void PeerManagerImpl::FinalizeNode(const CNode& node) {
assert(m_num_preferred_download_peers == 0);
assert(m_peers_downloading_from == 0);
assert(m_outbound_peers_with_protect_from_disconnect == 0);
assert(m_orphanage.Size() == 0);
}
} // cs_main

View File

@ -8,21 +8,34 @@
#endif
#include <qt/bitcoin.h>
#include <qt/bitcoingui.h>
#include <chainparams.h>
#include <fs.h>
#include <init.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <net.h>
#include <node/context.h>
#include <node/ui_interface.h>
#include <noui.h>
#include <qt/bitcoingui.h>
#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/initexecutor.h>
#include <qt/intro.h>
#include <net.h>
#include <qt/networkstyle.h>
#include <qt/optionsmodel.h>
#include <qt/splashscreen.h>
#include <qt/utilitydialog.h>
#include <qt/winshutdownmonitor.h>
#include <stacktraces.h>
#include <uint256.h>
#include <util/string.h>
#include <util/system.h>
#include <util/threadnames.h>
#include <util/translation.h>
#include <validation.h>
#ifdef ENABLE_WALLET
#include <qt/paymentserver.h>
@ -30,19 +43,6 @@
#include <qt/walletmodel.h>
#endif // ENABLE_WALLET
#include <init.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <node/context.h>
#include <node/ui_interface.h>
#include <noui.h>
#include <stacktraces.h>
#include <uint256.h>
#include <util/system.h>
#include <util/threadnames.h>
#include <util/translation.h>
#include <validation.h>
#include <boost/signals2/connection.hpp>
#include <memory>
@ -52,7 +52,6 @@
#include <QLibraryInfo>
#include <QLocale>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QThread>
#include <QTimer>
@ -208,72 +207,11 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
}
}
BitcoinCore::BitcoinCore(interfaces::Node& node) :
QObject(), m_node(node)
{
}
void BitcoinCore::handleRunawayException(const std::exception_ptr e)
{
PrintExceptionContinue(e, "Runaway exception");
Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings().translated));
}
void BitcoinCore::initialize()
{
try
{
util::ThreadRename("qt-init");
qDebug() << __func__ << ": Running initialization in thread";
interfaces::BlockAndHeaderTipInfo tip_info;
bool rv = m_node.appInitMain(&tip_info);
Q_EMIT initializeResult(rv, tip_info);
} catch (...) {
handleRunawayException(std::current_exception());
}
}
void BitcoinCore::restart(QStringList args)
{
static bool executing_restart{false};
if(!executing_restart) { // Only restart 1x, no matter how often a user clicks on a restart-button
executing_restart = true;
try
{
qDebug() << __func__ << ": Running Restart in thread";
m_node.appPrepareShutdown();
qDebug() << __func__ << ": Shutdown finished";
Q_EMIT shutdownResult();
CExplicitNetCleanup::callCleanup();
QProcess::startDetached(QApplication::applicationFilePath(), args);
qDebug() << __func__ << ": Restart initiated...";
QApplication::quit();
} catch (...) {
handleRunawayException(std::current_exception());
}
}
}
void BitcoinCore::shutdown()
{
try
{
qDebug() << __func__ << ": Running Shutdown in thread";
m_node.appShutdown();
qDebug() << __func__ << ": Shutdown finished";
Q_EMIT shutdownResult();
} catch (...) {
handleRunawayException(std::current_exception());
}
}
static int qt_argc = 1;
static const char* qt_argv = "dash-qt";
BitcoinApplication::BitcoinApplication():
QApplication(qt_argc, const_cast<char **>(&qt_argv)),
coreThread(nullptr),
optionsModel(nullptr),
clientModel(nullptr),
window(nullptr),
@ -287,13 +225,7 @@ BitcoinApplication::BitcoinApplication():
BitcoinApplication::~BitcoinApplication()
{
if(coreThread)
{
qDebug() << __func__ << ": Stopping thread";
coreThread->quit();
coreThread->wait();
qDebug() << __func__ << ": Stopped thread";
}
m_executor.reset();
delete window;
window = nullptr;
@ -350,23 +282,16 @@ bool BitcoinApplication::baseInitialize()
void BitcoinApplication::startThread()
{
if(coreThread)
return;
coreThread = new QThread(this);
BitcoinCore *executor = new BitcoinCore(node());
executor->moveToThread(coreThread);
assert(!m_executor);
m_executor.emplace(node());
/* communication to and from thread */
connect(executor, &BitcoinCore::initializeResult, this, &BitcoinApplication::initializeResult);
connect(executor, &BitcoinCore::shutdownResult, this, &BitcoinApplication::shutdownResult);
connect(executor, &BitcoinCore::runawayException, this, &BitcoinApplication::handleRunawayException);
connect(this, &BitcoinApplication::requestedInitialize, executor, &BitcoinCore::initialize);
connect(this, &BitcoinApplication::requestedShutdown, executor, &BitcoinCore::shutdown);
connect(window, &BitcoinGUI::requestedRestart, executor, &BitcoinCore::restart);
/* make sure executor object is deleted in its own thread */
connect(coreThread, &QThread::finished, executor, &QObject::deleteLater);
coreThread->start();
connect(&m_executor.value(), &InitExecutor::initializeResult, this, &BitcoinApplication::initializeResult);
connect(&m_executor.value(), &InitExecutor::shutdownResult, this, &BitcoinApplication::shutdownResult);
connect(&m_executor.value(), &InitExecutor::runawayException, this, &BitcoinApplication::handleRunawayException);
connect(this, &BitcoinApplication::requestedInitialize, &m_executor.value(), &InitExecutor::initialize);
connect(this, &BitcoinApplication::requestedShutdown, &m_executor.value(), &InitExecutor::shutdown);
connect(window, &BitcoinGUI::requestedRestart, &m_executor.value(), &InitExecutor::restart);
}
void BitcoinApplication::parameterSetup()
@ -399,7 +324,6 @@ void BitcoinApplication::requestShutdown()
shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window));
qDebug() << __func__ << ": Requesting shutdown";
startThread();
window->hide();
// Must disconnect node signals otherwise current thread can deadlock since
// no event loop is running.

View File

@ -9,11 +9,14 @@
#include <config/bitcoin-config.h>
#endif
#include <QApplication>
#include <interfaces/node.h>
#include <qt/initexecutor.h>
#include <assert.h>
#include <memory>
#include <optional>
#include <interfaces/node.h>
#include <QApplication>
class BitcoinGUI;
class ClientModel;
@ -25,32 +28,6 @@ class WalletController;
class WalletModel;
/** Class encapsulating Bitcoin Core startup and shutdown.
* Allows running startup and shutdown in a different thread from the UI thread.
*/
class BitcoinCore: public QObject
{
Q_OBJECT
public:
explicit BitcoinCore(interfaces::Node& node);
public Q_SLOTS:
void initialize();
void shutdown();
void restart(QStringList args);
Q_SIGNALS:
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
void shutdownResult();
void runawayException(const QString &message);
private:
/// Pass fatal exception message to UI thread
void handleRunawayException(const std::exception_ptr e);
interfaces::Node& m_node;
};
/** Main Bitcoin application object */
class BitcoinApplication: public QApplication
{
@ -113,7 +90,7 @@ protected:
bool event(QEvent* e) override;
private:
QThread *coreThread;
std::optional<InitExecutor> m_executor;
OptionsModel *optionsModel;
ClientModel *clientModel;
BitcoinGUI *window;

View File

@ -315,6 +315,16 @@
</widget>
<widget class="QWidget" name="pageWallet">
<layout class="QVBoxLayout" name="verticalLayout_Wallet">
<item>
<widget class="QCheckBox" name="subFeeFromAmount">
<property name="toolTip">
<string extracomment="Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.">Whether to set subtract fee from amount as default or not.</string>
</property>
<property name="text">
<string extracomment="An Options window setting to set subtracting the fee from a sending amount as default.">Subtract &amp;fee from amount by default</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>

85
src/qt/initexecutor.cpp Normal file
View File

@ -0,0 +1,85 @@
// Copyright (c) 2014-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.
#include <qt/initexecutor.h>
#include <interfaces/node.h>
#include <util/system.h>
#include <util/threadnames.h>
#include <exception>
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QProcess>
#include <QString>
#include <QThread>
InitExecutor::InitExecutor(interfaces::Node& node)
: QObject(), m_node(node)
{
this->moveToThread(&m_thread);
m_thread.start();
}
InitExecutor::~InitExecutor()
{
qDebug() << __func__ << ": Stopping thread";
m_thread.quit();
m_thread.wait();
qDebug() << __func__ << ": Stopped thread";
}
void InitExecutor::handleRunawayException(const std::exception_ptr e)
{
PrintExceptionContinue(e, "Runaway exception");
Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings().translated));
}
void InitExecutor::initialize()
{
try {
util::ThreadRename("qt-init");
qDebug() << __func__ << ": Running initialization in thread";
interfaces::BlockAndHeaderTipInfo tip_info;
bool rv = m_node.appInitMain(&tip_info);
Q_EMIT initializeResult(rv, tip_info);
} catch (...) {
handleRunawayException(std::current_exception());
}
}
void InitExecutor::restart(QStringList args)
{
static bool executing_restart{false};
if(!executing_restart) { // Only restart 1x, no matter how often a user clicks on a restart-button
executing_restart = true;
try {
qDebug() << __func__ << ": Running Restart in thread";
m_node.appPrepareShutdown();
qDebug() << __func__ << ": Shutdown finished";
Q_EMIT shutdownResult();
CExplicitNetCleanup::callCleanup();
QProcess::startDetached(QApplication::applicationFilePath(), args);
qDebug() << __func__ << ": Restart initiated...";
QApplication::quit();
} catch (...) {
handleRunawayException(std::current_exception());
}
}
}
void InitExecutor::shutdown()
{
try {
qDebug() << __func__ << ": Running Shutdown in thread";
m_node.appShutdown();
qDebug() << __func__ << ": Shutdown finished";
Q_EMIT shutdownResult();
} catch (...) {
handleRunawayException(std::current_exception());
}
}

47
src/qt/initexecutor.h Normal file
View File

@ -0,0 +1,47 @@
// Copyright (c) 2014-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.
#ifndef BITCOIN_QT_INITEXECUTOR_H
#define BITCOIN_QT_INITEXECUTOR_H
#include <interfaces/node.h>
#include <exception>
#include <QObject>
#include <QThread>
QT_BEGIN_NAMESPACE
class QString;
QT_END_NAMESPACE
/** Class encapsulating Bitcoin Core startup and shutdown.
* Allows running startup and shutdown in a different thread from the UI thread.
*/
class InitExecutor : public QObject
{
Q_OBJECT
public:
explicit InitExecutor(interfaces::Node& node);
~InitExecutor();
public Q_SLOTS:
void initialize();
void shutdown();
void restart(QStringList args);
Q_SIGNALS:
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
void shutdownResult();
void runawayException(const QString& message);
private:
/// Pass fatal exception message to UI thread
void handleRunawayException(const std::exception_ptr e);
interfaces::Node& m_node;
QThread m_thread;
};
#endif // BITCOIN_QT_INITEXECUTOR_H

View File

@ -325,6 +325,7 @@ void OptionsDialog::setMapper()
/* Wallet */
mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures);
mapper->addMapping(ui->subFeeFromAmount, OptionsModel::SubFeeFromAmount);
mapper->addMapping(ui->keepChangeAddress, OptionsModel::KeepChangeAddress);
mapper->addMapping(ui->showMasternodesTab, OptionsModel::ShowMasternodesTab);
mapper->addMapping(ui->showGovernanceTab, OptionsModel::ShowGovernanceTab);

View File

@ -222,6 +222,11 @@ void OptionsModel::Init(bool resetSettings)
if (!gArgs.SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool()))
addOverriddenOption("-spendzeroconfchange");
if (!settings.contains("SubFeeFromAmount")) {
settings.setValue("SubFeeFromAmount", false);
}
m_sub_fee_from_amount = settings.value("SubFeeFromAmount", false).toBool();
// CoinJoin
if (!settings.contains("nCoinJoinSessions"))
settings.setValue("nCoinJoinSessions", DEFAULT_COINJOIN_SESSIONS);
@ -458,6 +463,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
#ifdef ENABLE_WALLET
case SpendZeroConfChange:
return settings.value("bSpendZeroConfChange");
case SubFeeFromAmount:
return m_sub_fee_from_amount;
case ShowMasternodesTab:
return settings.value("fShowMasternodesTab");
case ShowGovernanceTab:
@ -633,6 +640,10 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
setRestartRequired(true);
}
break;
case SubFeeFromAmount:
m_sub_fee_from_amount = value.toBool();
settings.setValue("SubFeeFromAmount", m_sub_fee_from_amount);
break;
case ShowGovernanceTab:
if (settings.value("fShowGovernanceTab") != value) {
settings.setValue("fShowGovernanceTab", value);

View File

@ -67,6 +67,7 @@ public:
FontWeightBold, // int
Language, // QString
CoinControlFeatures, // bool
SubFeeFromAmount, // bool
KeepChangeAddress, // bool
ThreadsScriptVerif, // int
Prune, // bool
@ -105,6 +106,7 @@ public:
int getDisplayUnit() const { return nDisplayUnit; }
QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; }
bool getCoinControlFeatures() const { return fCoinControlFeatures; }
bool getSubFeeFromAmount() const { return m_sub_fee_from_amount; }
bool getKeepChangeAddress() const { return fKeepChangeAddress; }
bool getShowAdvancedCJUI() { return fShowAdvancedCJUI; }
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
@ -132,6 +134,7 @@ private:
int nDisplayUnit;
QString strThirdPartyTxUrls;
bool fCoinControlFeatures;
bool m_sub_fee_from_amount;
bool fKeepChangeAddress;
bool fShowAdvancedCJUI;
/* settings that were overridden by command-line */

View File

@ -103,7 +103,9 @@ void SendCoinsEntry::clear()
ui->payTo->clear();
ui->addAsLabel->clear();
ui->payAmount->clear();
ui->checkboxSubtractFeeFromAmount->setCheckState(Qt::Unchecked);
if (model && model->getOptionsModel()) {
ui->checkboxSubtractFeeFromAmount->setChecked(model->getOptionsModel()->getSubFeeFromAmount());
}
ui->messageTextLabel->clear();
ui->messageTextLabel->hide();
ui->messageLabel->hide();

View File

@ -9,6 +9,7 @@
#include <interfaces/node.h>
#include <qt/bitcoin.h>
#include <qt/initexecutor.h>
#include <qt/test/apptests.h>
#include <qt/test/rpcnestedtests.h>
#include <qt/test/uritests.h>

View File

@ -17,7 +17,7 @@ class WinShutdownMonitor : public QAbstractNativeEventFilter
{
public:
/** Implements QAbstractNativeEventFilter interface for processing Windows messages */
bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult);
bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) override;
/** Register the reason for blocking shutdown on Windows to allow clean client exit */
static void registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId);

View File

@ -164,6 +164,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "importmulti", 0, "requests" },
{ "importmulti", 1, "options" },
{ "importdescriptors", 0, "requests" },
{ "listdescriptors", 0, "private" },
{ "verifychain", 0, "checklevel" },
{ "verifychain", 1, "nblocks" },
{ "getblockstats", 0, "hash_or_height" },

View File

@ -50,6 +50,13 @@ public:
* (ie orphans that may have found their final missing parent, and so should be reconsidered for the mempool) */
void AddChildrenToWorkSet(const CTransaction& tx, std::set<uint256>& orphan_work_set) const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
/** Return how many entries exist in the orphange */
size_t Size() LOCKS_EXCLUDED(::g_cs_orphans)
{
LOCK(::g_cs_orphans);
return m_orphans.size();
}
protected:
struct OrphanTx {
CTransactionRef tx;

View File

@ -1941,8 +1941,10 @@ RPCHelpMan listdescriptors()
{
return RPCHelpMan{
"listdescriptors",
"\nList descriptors imported into a descriptor-enabled wallet.",
{},
"\nList descriptors imported into a descriptor-enabled wallet.\n",
{
{"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private descriptors."}
},
RPCResult{RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
{RPCResult::Type::ARR, "descriptors", "Array of descriptor objects",
@ -1962,6 +1964,7 @@ RPCHelpMan listdescriptors()
}},
RPCExamples{
HelpExampleCli("listdescriptors", "") + HelpExampleRpc("listdescriptors", "")
+ HelpExampleCli("listdescriptors", "true") + HelpExampleRpc("listdescriptors", "true")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
@ -1972,6 +1975,11 @@ RPCHelpMan listdescriptors()
throw JSONRPCError(RPC_WALLET_ERROR, "listdescriptors is not available for non-descriptor wallets");
}
const bool priv = !request.params[0].isNull() && request.params[0].get_bool();
if (priv) {
EnsureWalletIsUnlocked(*wallet);
}
LOCK(wallet->cs_wallet);
UniValue descriptors(UniValue::VARR);
@ -1985,8 +1993,9 @@ RPCHelpMan listdescriptors()
LOCK(desc_spk_man->cs_desc_man);
const auto& wallet_descriptor = desc_spk_man->GetWalletDescriptor();
std::string descriptor;
if (!desc_spk_man->GetDescriptorString(descriptor)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Can't get normalized descriptor string.");
if (!desc_spk_man->GetDescriptorString(descriptor, priv)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Can't get descriptor string.");
}
spk.pushKV("desc", descriptor);
spk.pushKV("timestamp", wallet_descriptor.creation_time);

View File

@ -4009,7 +4009,7 @@ RPCHelpMan getaddressinfo()
DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(pwallet->GetScriptPubKeyMan(scriptPubKey));
if (desc_spk_man) {
std::string desc_str;
if (desc_spk_man->GetDescriptorString(desc_str)) {
if (desc_spk_man->GetDescriptorString(desc_str, /* priv */ false)) {
ret.pushKV("parent_desc", desc_str);
}
}

View File

@ -2403,13 +2403,20 @@ const std::vector<CScript> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
return script_pub_keys;
}
bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out) const
bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out, const bool priv) const
{
LOCK(cs_desc_man);
FlatSigningProvider provider;
provider.keys = GetKeys();
if (priv) {
// For the private version, always return the master key to avoid
// exposing child private keys. The risk implications of exposing child
// private keys together with the parent xpub may be non-obvious for users.
return m_wallet_descriptor.descriptor->ToPrivateString(provider, out);
}
return m_wallet_descriptor.descriptor->ToNormalizedString(provider, out, &m_wallet_descriptor.cache);
}

View File

@ -600,7 +600,7 @@ public:
const WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
const std::vector<CScript> GetScriptPubKeys() const;
bool GetDescriptorString(std::string& out) const;
bool GetDescriptorString(std::string& out, const bool priv) const;
void UpgradeDescriptorCache();
};

View File

@ -329,24 +329,24 @@ class FullBlockTest(BitcoinTestFramework):
self.move_tip(15)
b23 = self.next_block(23, spend=out[6])
tx = CTransaction()
script_length = MAX_BLOCK_SIZE - len(b23.serialize()) - 69
script_length = MAX_BLOCK_SIZE - b23.get_weight() - 69
script_output = CScript([b'\x00' * script_length])
tx.vout.append(CTxOut(0, script_output))
tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 0)))
b23 = self.update_block(23, [tx])
# Make sure the math above worked out to produce a max-sized block
assert_equal(len(b23.serialize()), MAX_BLOCK_SIZE)
assert_equal(b23.get_weight(), MAX_BLOCK_SIZE)
self.send_blocks([b23], True)
self.save_spendable_output()
self.log.info("Reject a block of size MAX_BLOCK_SIZE + 1")
self.move_tip(15)
b24 = self.next_block(24, spend=out[6])
script_length = MAX_BLOCK_SIZE - len(b24.serialize()) - 69
script_length = MAX_BLOCK_SIZE - b24.get_weight() - 69
script_output = CScript([b'\x00' * (script_length + 1)])
tx.vout = [CTxOut(0, script_output)]
b24 = self.update_block(24, [tx])
assert_equal(len(b24.serialize()), MAX_BLOCK_SIZE + 1)
assert_equal(b24.get_weight(), MAX_BLOCK_SIZE + 1)
self.send_blocks([b24], success=False, reject_reason='bad-blk-length', reconnect=True)
b25 = self.next_block(25, spend=out[7])
@ -500,13 +500,13 @@ class FullBlockTest(BitcoinTestFramework):
# Until block is full, add tx's with 1 satoshi to p2sh_script, the rest to OP_TRUE
tx_new = None
tx_last = tx
total_size = len(b39.serialize())
while(total_size < MAX_BLOCK_SIZE):
total_weight = b39.get_weight()
while total_weight < MAX_BLOCK_SIZE:
tx_new = self.create_tx(tx_last, 1, 1, p2sh_script)
tx_new.vout.append(CTxOut(tx_last.vout[1].nValue - 1, CScript([OP_TRUE])))
tx_new.rehash()
total_size += len(tx_new.serialize())
if total_size >= MAX_BLOCK_SIZE:
total_weight += tx_new.get_weight()
if total_weight >= MAX_BLOCK_SIZE:
break
b39.vtx.append(tx_new) # add tx to block
tx_last = tx_new
@ -517,7 +517,7 @@ class FullBlockTest(BitcoinTestFramework):
# Make sure we didn't accidentally make too big a block. Note that the
# size of the block has non-determinism due to the ECDSA signature in
# the first transaction.
while (len(b39.serialize()) >= MAX_BLOCK_SIZE):
while b39.get_weight() >= MAX_BLOCK_SIZE:
del b39.vtx[-1]
b39 = self.update_block(39, [])
@ -938,7 +938,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.vout.append(CTxOut(0, script_output))
tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0)))
b64a = self.update_block("64a", [tx])
assert_equal(len(b64a.serialize()), MAX_BLOCK_SIZE + 8)
assert_equal(b64a.get_weight(), MAX_BLOCK_SIZE + 8)
self.send_blocks([b64a], success=False, reject_reason='non-canonical ReadCompactSize()')
# dashd doesn't disconnect us for sending a bloated block, but if we subsequently
@ -952,7 +952,7 @@ class FullBlockTest(BitcoinTestFramework):
b64 = CBlock(b64a)
b64.vtx = copy.deepcopy(b64a.vtx)
assert_equal(b64.hash, b64a.hash)
assert_equal(len(b64.serialize()), MAX_BLOCK_SIZE)
assert_equal(b64.get_weight(), MAX_BLOCK_SIZE)
self.blocks[64] = b64
b64 = self.update_block(64, [])
self.send_blocks([b64], True)
@ -1290,12 +1290,12 @@ class FullBlockTest(BitcoinTestFramework):
for i in range(89, LARGE_REORG_SIZE + 89):
b = self.next_block(i, spend)
tx = CTransaction()
script_length = MAX_BLOCK_SIZE - len(b.serialize()) - 69
script_length = MAX_BLOCK_SIZE - b.get_weight() - 69
script_output = CScript([b'\x00' * script_length])
tx.vout.append(CTxOut(0, script_output))
tx.vin.append(CTxIn(COutPoint(b.vtx[1].sha256, 0)))
b = self.update_block(i, [tx])
assert_equal(len(b.serialize()), MAX_BLOCK_SIZE)
assert_equal(b.get_weight(), MAX_BLOCK_SIZE)
blocks.append(b)
self.save_spendable_output()
spend = self.get_spendable_output()

View File

@ -55,8 +55,8 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[start_range:end_range], end_range - start_range, (i+1)*base_fee)
# Make sure that the size of each group of transactions exceeds
# MAX_BLOCK_SIZE -- otherwise the test needs to be revised to create
# more transactions.
# MAX_BLOCK_SIZE -- otherwise the test needs to be revised to
# create more transactions.
mempool = self.nodes[0].getrawmempool(True)
sizes = [0, 0, 0]
for i in range(3):

View File

@ -133,7 +133,7 @@ class P2PPermissionsTests(BitcoinTestFramework):
tx.vout[0].nValue += 1
txid = tx.rehash()
# Send the transaction twice. The first time, it'll be rejected by ATMP because it conflicts
# with a mempool transaction. The second time, it'll be in the recentRejects filter.
# with a mempool transaction. The second time, it'll be in the m_recent_rejects filter.
p2p_rebroadcast_wallet.send_txs_and_test(
[tx],
self.nodes[1],

View File

@ -546,6 +546,7 @@ class CTransaction:
def get_vsize(self):
return len(self.serialize())
# it's just a helper that return vsize to reduce conflicts during backporting
def get_weight(self):
return self.get_vsize()
@ -681,6 +682,10 @@ class CBlock(CBlockHeader):
self.nNonce += 1
self.rehash()
# it's just a helper that return vsize to reduce conflicts during backporting
def get_weight(self):
return len(self.serialize())
def __repr__(self):
return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)" \
% (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot,

View File

@ -72,11 +72,39 @@ class ListDescriptorsTest(BitcoinTestFramework):
],
}
assert_equal(expected, wallet.listdescriptors())
assert_equal(expected, wallet.listdescriptors(False))
self.log.info('Test list private descriptors')
expected_private = {
'wallet_name': 'w2',
'descriptors': [
{'desc': descsum_create('pkh(' + xprv + hardened_path + '/0/*)'),
'timestamp': 1296688602,
'active': False,
'range': [0, 0],
'next': 0},
],
}
assert_equal(expected_private, wallet.listdescriptors(True))
self.log.info("Test listdescriptors with encrypted wallet")
wallet.encryptwallet("pass")
assert_equal(expected, wallet.listdescriptors())
self.log.info('Test list private descriptors with encrypted wallet')
assert_raises_rpc_error(-13, 'Please enter the wallet passphrase with walletpassphrase first.', wallet.listdescriptors, True)
wallet.walletpassphrase(passphrase="pass", timeout=1000000)
assert_equal(expected_private, wallet.listdescriptors(True))
self.log.info('Test list private descriptors with watch-only wallet')
node.createwallet(wallet_name='watch-only', descriptors=True, disable_private_keys=True)
watch_only_wallet = node.get_wallet_rpc('watch-only')
watch_only_wallet.importdescriptors([{
'desc': descsum_create('pkh(' + xpub_acc + ')'),
'timestamp': 1296688602,
}])
assert_raises_rpc_error(-4, 'Can\'t get descriptor string', watch_only_wallet.listdescriptors, True)
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')