From 16b2591e77c19221e37b19f486a18ed40f86f339 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Wed, 7 Aug 2019 14:50:48 +0300 Subject: [PATCH 01/11] merge bitcoin#16570: Make descriptor tests deterministic --- src/test/descriptor_tests.cpp | 68 +++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index 7427f37390..96f85b6422 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -40,32 +40,46 @@ bool EqualDescriptor(std::string a, std::string b) return a == b; } -std::string MaybeUseHInsteadOfApostrophy(std::string ret) +std::string UseHInsteadOfApostrophe(const std::string& desc) { - if (InsecureRandBool()) { - while (true) { - auto it = ret.find("'"); - if (it != std::string::npos) { - ret[it] = 'h'; - if (ret.size() > 9 && ret[ret.size() - 9] == '#') ret = ret.substr(0, ret.size() - 9); // Changing apostrophe to h breaks the checksum - } else { - break; - } - } + std::string ret = desc; + while (true) { + auto it = ret.find('\''); + if (it == std::string::npos) break; + ret[it] = 'h'; + } + + // GetDescriptorChecksum returns "" if the checksum exists but is bad. + // Switching apostrophes with 'h' breaks the checksum if it exists - recalculate it and replace the broken one. + if (GetDescriptorChecksum(ret) == "") { + ret = ret.substr(0, desc.size() - 9); + ret += std::string("#") + GetDescriptorChecksum(ret); } return ret; } const std::set> ONLY_EMPTY{{}}; -void Check(const std::string& prv, const std::string& pub, int flags, const std::vector>& scripts, const std::set>& paths = ONLY_EMPTY) +void DoCheck(const std::string& prv, const std::string& pub, int flags, const std::vector>& scripts, const std::set>& paths = ONLY_EMPTY, + bool replace_apostrophe_with_h_in_prv=false, bool replace_apostrophe_with_h_in_pub=false) { FlatSigningProvider keys_priv, keys_pub; std::set> left_paths = paths; + std::unique_ptr parse_priv; + std::unique_ptr parse_pub; // Check that parsing succeeds. - std::unique_ptr parse_priv = Parse(MaybeUseHInsteadOfApostrophy(prv), keys_priv); - std::unique_ptr parse_pub = Parse(MaybeUseHInsteadOfApostrophy(pub), keys_pub); + if (replace_apostrophe_with_h_in_prv) { + parse_priv = Parse(UseHInsteadOfApostrophe(prv), keys_priv); + } else { + parse_priv = Parse(prv, keys_priv); + } + if (replace_apostrophe_with_h_in_pub) { + parse_pub = Parse(UseHInsteadOfApostrophe(pub), keys_pub); + } else { + parse_pub = Parse(pub, keys_pub); + } + BOOST_CHECK(parse_priv); BOOST_CHECK(parse_pub); @@ -164,6 +178,32 @@ void Check(const std::string& prv, const std::string& pub, int flags, const std: BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv); } +void Check(const std::string& prv, const std::string& pub, int flags, const std::vector>& scripts, const std::set>& paths = ONLY_EMPTY) +{ + bool found_apostrophes_in_prv = false; + bool found_apostrophes_in_pub = false; + + // Do not replace apostrophes with 'h' in prv and pub + DoCheck(prv, pub, flags, scripts, paths); + + // Replace apostrophes with 'h' in prv but not in pub, if apostrophes are found in prv + if (prv.find('\'') != std::string::npos) { + found_apostrophes_in_prv = true; + DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */false); + } + + // Replace apostrophes with 'h' in pub but not in prv, if apostrophes are found in pub + if (pub.find('\'') != std::string::npos) { + found_apostrophes_in_pub = true; + DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */false, /*replace_apostrophe_with_h_in_pub = */true); + } + + // Replace apostrophes with 'h' both in prv and in pub, if apostrophes are found in both + if (found_apostrophes_in_prv && found_apostrophes_in_pub) { + DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */true); + } +} + } BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup) From d4a1decb73f3d887b12ed345220a3fddd204665a Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 5 Dec 2021 18:45:22 +0530 Subject: [PATCH 02/11] merge bitcoin#16701: Replace functions deprecated in Qt 5.13 --- src/qt/bitcoinamountfield.cpp | 2 +- src/qt/bitcoingui.cpp | 8 ++++---- src/qt/guiutil.cpp | 12 ++++++++++-- src/qt/guiutil.h | 8 ++++++++ src/qt/optionsdialog.cpp | 2 +- src/qt/rpcconsole.cpp | 4 ++-- src/qt/splashscreen.cpp | 16 ++++++++-------- 7 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 58fe832452..eb0578afe6 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -117,7 +117,7 @@ public: ensurePolished(); const QFontMetrics fm(fontMetrics()); int h = 0; - int w = fm.width(BitcoinUnits::format(BitcoinUnits::DASH, BitcoinUnits::maxMoney(), false, BitcoinUnits::separatorAlways)); + int w = GUIUtil::TextWidth(fm, BitcoinUnits::format(BitcoinUnits::DASH, BitcoinUnits::maxMoney(), false, BitcoinUnits::separatorAlways)); w += 2; // cursor blinking space w += GUIUtil::dashThemeActive() ? 24 : 0; // counteract padding from css return QSize(w, h); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 14c7c86c9c..ceeed5e1b6 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -54,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -89,7 +89,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const NetworkStyle* networkStyle, QSettings settings; if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) { // Restore failed (perhaps missing setting), center the window - move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center()); + move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center()); } #ifdef ENABLE_WALLET @@ -1324,7 +1324,7 @@ void BitcoinGUI::updateWidth() continue; } QFontMetrics fm(button->font()); - nWidthWidestButton = std::max(nWidthWidestButton, fm.width(button->text())); + nWidthWidestButton = std::max(nWidthWidestButton, GUIUtil::TextWidth(fm, button->text())); ++nButtonsVisible; } // Add 30 per button as padding and use minimum 980 which is the minimum required to show all tab's contents @@ -1990,7 +1990,7 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl() : const QFontMetrics fm(GUIUtil::getFontNormal()); for (const BitcoinUnits::Unit unit : units) { - max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit))); + max_width = qMax(max_width, GUIUtil::TextWidth(fm, BitcoinUnits::name(unit))); } setMinimumSize(max_width, 0); setAlignment(Qt::AlignRight | Qt::AlignVCenter); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 0aa06dd1ab..d541e10783 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include @@ -1832,7 +1831,7 @@ qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal m while(font_size >= minPointSize) { font.setPointSizeF(font_size); QFontMetrics fm(font); - if (fm.width(text) < width) { + if (TextWidth(fm, text) < width) { break; } font_size -= 0.5; @@ -1872,4 +1871,13 @@ void PolishProgressDialog(QProgressDialog* dialog) #endif } +int TextWidth(const QFontMetrics& fm, const QString& text) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) + return fm.horizontalAdvance(text); +#else + return fm.width(text); +#endif +} + } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index dd6b4a9d89..425fe7791d 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -467,6 +467,14 @@ namespace GUIUtil // Fix known bugs in QProgressDialog class. void PolishProgressDialog(QProgressDialog* dialog); + + /** + * Returns the distance in pixels appropriate for drawing a subsequent character after text. + * + * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 13.0. + * In Qt 5.11 the QFontMetrics::horizontalAdvance() was introduced. + */ + int TextWidth(const QFontMetrics& fm, const QString& text); } // namespace GUIUtil #endif // BITCOIN_QT_GUIUTIL_H diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 6f8f4c1a79..ad8cca2fd5 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -497,7 +497,7 @@ void OptionsDialog::updateWidth() continue; } QFontMetrics fm(button->font()); - nWidthWidestButton = std::max(nWidthWidestButton, fm.width(button->text())); + nWidthWidestButton = std::max(nWidthWidestButton, GUIUtil::TextWidth(fm, button->text())); ++nButtonsVisible; } // Add 10 per button as padding and use minimum 585 which is what we used in css before diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 63f87b743f..54195c2ee1 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -31,12 +31,12 @@ #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -466,7 +466,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, QWidget* parent, Qt::WindowFlags QSettings settings; if (!restoreGeometry(settings.value("RPCConsoleWindowGeometry").toByteArray())) { // Restore failed (perhaps missing setting), center the window - move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center()); + move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center()); } QChar nonbreaking_hyphen(8209); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 64610f88d4..2e1a479d5a 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -9,22 +9,22 @@ #include -#include -#include #include #include #include #include #include +#include +#include #include #include #include #include #include -#include #include +#include SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const NetworkStyle *networkStyle) : @@ -89,7 +89,7 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw fontBold.setPointSize(50 * fontFactor); pixPaint.setFont(fontBold); QFontMetrics fm = pixPaint.fontMetrics(); - int titleTextWidth = fm.width(titleText); + int titleTextWidth = GUIUtil::TextWidth(fm, titleText); if (titleTextWidth > width * 0.8) { fontFactor = 0.75; } @@ -97,14 +97,14 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw fontBold.setPointSize(50 * fontFactor); pixPaint.setFont(fontBold); fm = pixPaint.fontMetrics(); - titleTextWidth = fm.width(titleText); + titleTextWidth = GUIUtil::TextWidth(fm, titleText); int titleTextHeight = fm.height(); pixPaint.drawText((width / 2) - (titleTextWidth / 2), titleTextHeight + paddingTop, titleText); fontNormal.setPointSize(16 * fontFactor); pixPaint.setFont(fontNormal); fm = pixPaint.fontMetrics(); - int versionTextWidth = fm.width(versionText); + int versionTextWidth = GUIUtil::TextWidth(fm, versionText); pixPaint.drawText((width / 2) - (versionTextWidth / 2), titleTextHeight + paddingTop + titleVersionVSpace, versionText); // draw additional text if special network @@ -112,7 +112,7 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw fontBold.setPointSize(10 * fontFactor); pixPaint.setFont(fontBold); fm = pixPaint.fontMetrics(); - int titleAddTextWidth = fm.width(titleAddText); + int titleAddTextWidth = GUIUtil::TextWidth(fm, titleAddText); // Draw the badge background with the network-specific color QRect badgeRect = QRect(width - titleAddTextWidth - 20, 5, width, fm.height() + 10); QColor badgeColor = networkStyle->getBadgeColor(); @@ -128,7 +128,7 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw QRect r(QPoint(), QSize(width, height)); resize(r.size()); setFixedSize(r.size()); - move(QApplication::desktop()->screenGeometry().center() - r.center()); + move(QGuiApplication::primaryScreen()->geometry().center() - r.center()); subscribeToCoreSignals(); installEventFilter(this); From 4c85471e6d4de5027d8b3f0fe1538874793d9b09 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Thu, 29 Aug 2019 19:13:19 +0300 Subject: [PATCH 03/11] merge bitcoin#16758: Replace QFontMetrics::width() with TextWidth() --- src/qt/guiutil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index d541e10783..8597073c13 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1863,7 +1863,7 @@ void PolishProgressDialog(QProgressDialog* dialog) { #ifdef Q_OS_MAC // Workaround for macOS-only Qt bug; see: QTBUG-65750, QTBUG-70357. - const int margin = dialog->fontMetrics().width("X"); + const int margin = TextWidth(dialog->fontMetrics(), ("X")); dialog->resize(dialog->width() + 2 * margin, dialog->height()); dialog->show(); #else From d7281c82efb179ee9a6e3b78906c622cebd2567e Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 7 Nov 2021 00:44:18 +0530 Subject: [PATCH 04/11] merge bitcoin#16826: Do additional character escaping for wallet names and address labels --- src/qt/bitcoingui.cpp | 2 ++ src/qt/walletcontroller.cpp | 3 ++- src/qt/walletview.cpp | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index ceeed5e1b6..fba897e92b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -489,6 +489,8 @@ void BitcoinGUI::createActions() for (const std::pair& i : m_wallet_controller->listWalletDir()) { const std::string& path = i.first; QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path); + // Menu items remove single &. Single & are shown when && is in the string, but only the first occurrence. So replace only the first & with && + name.replace(name.indexOf(QChar('&')), 1, QString("&&")); QAction* action = m_open_wallet_menu->addAction(name); if (i.second) { diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index 1cd10add04..d82bfe1651 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include #include @@ -70,7 +71,7 @@ void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent) { QMessageBox box(parent); box.setWindowTitle(tr("Close wallet")); - box.setText(tr("Are you sure you wish to close wallet %1?").arg(wallet_model->getDisplayName())); + box.setText(tr("Are you sure you wish to close wallet %1?").arg(GUIUtil::HtmlEscape(wallet_model->getDisplayName()))); box.setInformativeText(tr("Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.")); box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel); box.setDefaultButton(QMessageBox::Yes); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 2ae9074689..f096403930 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -229,9 +229,9 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong(); QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString(); QString address = ttm->data(index, TransactionTableModel::AddressRole).toString(); - QString label = ttm->data(index, TransactionTableModel::LabelRole).toString(); + QString label = GUIUtil::HtmlEscape(ttm->data(index, TransactionTableModel::LabelRole).toString()); - Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, walletModel->getWalletName()); + Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, GUIUtil::HtmlEscape(walletModel->getWalletName())); } void WalletView::gotoGovernancePage() From fc6e35060d5e8792a83c4fabb7cd82c283e46fce Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 12 Dec 2021 18:57:02 +0530 Subject: [PATCH 05/11] merge bitcoin#16796: Fix segfault in CreateWalletFromFile --- src/init.cpp | 2 +- src/wallet/load.h | 4 +-- src/wallet/wallet.cpp | 2 +- .../data/wallets/high_minversion/.walletlock | 0 .../data/wallets/high_minversion/db.log | 0 .../data/wallets/high_minversion/wallet.dat | Bin 0 -> 16384 bytes test/functional/test_framework/util.py | 8 ++++-- test/functional/wallet_multiwallet.py | 25 ++++++++++++++++++ 8 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 test/functional/data/wallets/high_minversion/.walletlock create mode 100644 test/functional/data/wallets/high_minversion/db.log create mode 100644 test/functional/data/wallets/high_minversion/wallet.dat diff --git a/src/init.cpp b/src/init.cpp index 06a1459e46..c9bc43907d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1469,7 +1469,7 @@ bool AppInitParameterInteraction() if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) { return InitError(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", ""))); } - // High fee check is done afterward in WalletParameterInteraction() + // High fee check is done afterward in CWallet::CreateWalletFromFile() ::minRelayTxFee = CFeeRate(n); } else if (incrementalRelayFee > ::minRelayTxFee) { // Allow only setting incrementalRelayFee to control both diff --git a/src/wallet/load.h b/src/wallet/load.h index 9bb6f2166e..7420d81b16 100644 --- a/src/wallet/load.h +++ b/src/wallet/load.h @@ -16,8 +16,8 @@ class Chain; } // namespace interfaces //! Responsible for reading and validating the -wallet arguments and verifying the wallet database. -//! This function will perform salvage on the wallet if requested, as long as only one wallet is -//! being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet). +// This function will perform salvage on the wallet if requested, as long as only one wallet is +// being loaded (WalletInit::ParameterInteraction() forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet). bool VerifyWallets(interfaces::Chain& chain, const std::vector& wallet_files); //! Load wallet databases. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 30f1f38031..7d1851c62f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4885,7 +4885,7 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags) { - const std::string& walletFile = WalletDataFilePath(location.GetPath()).string(); + const std::string walletFile = WalletDataFilePath(location.GetPath()).string(); // needed to restore wallet transaction meta data after -zapwallettxes std::vector vWtx; diff --git a/test/functional/data/wallets/high_minversion/.walletlock b/test/functional/data/wallets/high_minversion/.walletlock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/functional/data/wallets/high_minversion/db.log b/test/functional/data/wallets/high_minversion/db.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/functional/data/wallets/high_minversion/wallet.dat b/test/functional/data/wallets/high_minversion/wallet.dat new file mode 100644 index 0000000000000000000000000000000000000000..99ab8092631c4a7da2236f46e7250e6c265d3b49 GIT binary patch literal 16384 zcmeI&u}i~16vy#*(Nvobr|srq5Cm}%aT7sManxA^wXso3+Z0;yZ*XvNbaQYl2re#y zgMuJV;w&ysI#h6Q^e#1}N(Z+(d=HL$?Ir2;v;BAx5m9E^5lp+1w#AT{aUs%YKX(k@ z)DOp=OquoMDYw#CO0{>L@5(o8^33)o1p){lfB*srAbE+|5k#500IagfB*srAblYQd{CSHZSTHY z|3B&JC;!Md#b5IO@An3h`&kh{009ILKmY**5I_I{1Q0-=Hv%^Qcjk3Z3a0=6tRMA< ze$x$os&DkAKGX&CJ^%v&1Q0*~0R#|0009ILKmY**x(kepx_@y*rN*M=;gQVR-C1^P z@pb)b;(B#D0iov->tW Date: Sun, 12 Dec 2021 16:36:13 +0530 Subject: [PATCH 06/11] merge bitcoin#16850: servicesnames field in getpeerinfo and getnetworkinfo --- test/functional/rpc_net.py | 36 ++++++++++++++++++++-- test/functional/test_framework/messages.py | 2 +- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py index 6075ef0867..97050708c0 100755 --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -18,7 +18,29 @@ from test_framework.util import ( wait_until, ) from test_framework.mininode import P2PInterface -from test_framework.messages import CAddress, msg_addr, NODE_NETWORK +from test_framework.messages import ( + CAddress, + msg_addr, + NODE_NETWORK, + NODE_GETUTXO,NODE_BLOOM, + NODE_NETWORK_LIMITED, +) + +def assert_net_servicesnames(servicesflag, servicenames): + """Utility that checks if all flags are correctly decoded in + `getpeerinfo` and `getnetworkinfo`. + + :param servicesflag: The services as an integer. + :param servicesnames: The list of decoded services names, as strings. + """ + if servicesflag & NODE_NETWORK: + assert "NETWORK" in servicenames + if servicesflag & NODE_GETUTXO: + assert "GETUTXO" in servicenames + if servicesflag & NODE_BLOOM: + assert "BLOOM" in servicenames + if servicesflag & NODE_NETWORK_LIMITED: + assert "NETWORK_LIMITED" in servicenames class NetTest(BitcoinTestFramework): def set_test_params(self): @@ -38,7 +60,7 @@ class NetTest(BitcoinTestFramework): self._test_connection_count() self._test_getnettotals() - self._test_getnetworkinginfo() + self._test_getnetworkinfo() self._test_getaddednodeinfo() self._test_getpeerinfo() self._test_getnodeaddresses() @@ -77,7 +99,7 @@ class NetTest(BitcoinTestFramework): assert_greater_than_or_equal(after['bytesrecv_per_msg'].get('pong', 0), before['bytesrecv_per_msg'].get('pong', 0) + 32) assert_greater_than_or_equal(after['bytessent_per_msg'].get('ping', 0), before['bytessent_per_msg'].get('ping', 0) + 32) - def _test_getnetworkinginfo(self): + def _test_getnetworkinfo(self): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) @@ -92,6 +114,11 @@ class NetTest(BitcoinTestFramework): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) + # check the `servicesnames` field + network_info = [node.getnetworkinfo() for node in self.nodes] + for info in network_info: + assert_net_servicesnames(int(info["localservices"]), info["localservicesnames"]) + def _test_getaddednodeinfo(self): assert_equal(self.nodes[0].getaddednodeinfo(), []) # add a node (node2) to node0 @@ -110,6 +137,9 @@ class NetTest(BitcoinTestFramework): # the address bound to on one side will be the source address for the other node assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr']) assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr']) + # check the `servicesnames` field + for info in peer_info: + assert_net_servicesnames(int(info[0]["services"]), info[0]["servicesnames"]) def _test_getnodeaddresses(self): self.nodes[0].add_p2p_connection(P2PInterface()) diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 69717604cc..4876eb3fda 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -44,7 +44,7 @@ COIN = 100000000 # 1 btc in satoshis BIP125_SEQUENCE_NUMBER = 0xfffffffd # Sequence number that is BIP 125 opt-in and BIP 68-opt-out NODE_NETWORK = (1 << 0) -# NODE_GETUTXO = (1 << 1) +NODE_GETUTXO = (1 << 1) NODE_BLOOM = (1 << 2) NODE_COMPACT_FILTERS = (1 << 6) NODE_NETWORK_LIMITED = (1 << 10) From 45e09d4bb0e17a9b3c672a1e0f43020a7c08b2af Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 7 Nov 2021 00:33:41 +0530 Subject: [PATCH 07/11] merge bitcoin#16865: add some unit tests for merkle.cpp --- src/test/merkle_tests.cpp | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index c03400cb8f..bc6670f4cb 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -249,4 +249,82 @@ BOOST_AUTO_TEST_CASE(merkle_test) } } + +BOOST_AUTO_TEST_CASE(merkle_test_empty_block) +{ + bool mutated = false; + CBlock block; + uint256 root = BlockMerkleRoot(block, &mutated); + + BOOST_CHECK_EQUAL(root.IsNull(), true); + BOOST_CHECK_EQUAL(mutated, false); +} + +BOOST_AUTO_TEST_CASE(merkle_test_oneTx_block) +{ + bool mutated = false; + CBlock block; + + block.vtx.resize(1); + CMutableTransaction mtx; + mtx.nLockTime = 0; + block.vtx[0] = MakeTransactionRef(std::move(mtx)); + uint256 root = BlockMerkleRoot(block, &mutated); + BOOST_CHECK_EQUAL(root, block.vtx[0]->GetHash()); + BOOST_CHECK_EQUAL(mutated, false); +} + +BOOST_AUTO_TEST_CASE(merkle_test_OddTxWithRepeatedLastTx_block) +{ + bool mutated; + CBlock block, blockWithRepeatedLastTx; + + block.vtx.resize(3); + + for (std::size_t pos = 0; pos < block.vtx.size(); pos++) { + CMutableTransaction mtx; + mtx.nLockTime = pos; + block.vtx[pos] = MakeTransactionRef(std::move(mtx)); + } + + blockWithRepeatedLastTx = block; + blockWithRepeatedLastTx.vtx.push_back(blockWithRepeatedLastTx.vtx.back()); + + uint256 rootofBlock = BlockMerkleRoot(block, &mutated); + BOOST_CHECK_EQUAL(mutated, false); + + uint256 rootofBlockWithRepeatedLastTx = BlockMerkleRoot(blockWithRepeatedLastTx, &mutated); + BOOST_CHECK_EQUAL(rootofBlock, rootofBlockWithRepeatedLastTx); + BOOST_CHECK_EQUAL(mutated, true); +} + +BOOST_AUTO_TEST_CASE(merkle_test_LeftSubtreeRightSubtree) +{ + CBlock block, leftSubtreeBlock, rightSubtreeBlock; + + block.vtx.resize(4); + std::size_t pos; + for (pos = 0; pos < block.vtx.size(); pos++) { + CMutableTransaction mtx; + mtx.nLockTime = pos; + block.vtx[pos] = MakeTransactionRef(std::move(mtx)); + } + + for (pos = 0; pos < block.vtx.size() / 2; pos++) + leftSubtreeBlock.vtx.push_back(block.vtx[pos]); + + for (pos = block.vtx.size() / 2; pos < block.vtx.size(); pos++) + rightSubtreeBlock.vtx.push_back(block.vtx[pos]); + + uint256 root = BlockMerkleRoot(block); + uint256 rootOfLeftSubtree = BlockMerkleRoot(leftSubtreeBlock); + uint256 rootOfRightSubtree = BlockMerkleRoot(rightSubtreeBlock); + std::vector leftRight; + leftRight.push_back(rootOfLeftSubtree); + leftRight.push_back(rootOfRightSubtree); + uint256 rootOfLR = ComputeMerkleRoot(leftRight); + + BOOST_CHECK_EQUAL(root, rootOfLR); +} + BOOST_AUTO_TEST_SUITE_END() From ac4dc7f4a6d73e835c35d57c3c82e55afe92d348 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 12 Dec 2021 20:32:48 +0530 Subject: [PATCH 08/11] merge bitcoin#16713: Ignore old versionbit activations to avoid 'unknown softforks' warning --- src/chainparams.cpp | 4 ++++ src/consensus/params.h | 3 +++ src/validation.cpp | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index b589144fb5..46e791f477 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -152,6 +152,7 @@ public: consensus.DIP0003EnforcementHeight = 1047200; consensus.DIP0003EnforcementHash = uint256S("000000000000002d1734087b4c5afc3133e4e1c3e1a89218f62bcd9bb3d17f81"); consensus.DIP0008Height = 1088640; // 00000000000000112e41e4b3afda8b233b8cc07c532d2eac5de097b68358c43e + consensus.MinBIP9WarningHeight = consensus.DIP0008Height + consensus.nMinerConfirmationWindow; consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes @@ -370,6 +371,7 @@ public: consensus.DIP0003EnforcementHeight = 7300; consensus.DIP0003EnforcementHash = uint256S("00000055ebc0e974ba3a3fb785c5ad4365a39637d4df168169ee80d313612f8f"); consensus.DIP0008Height = 78800; // 000000000e9329d964d80e7dab2e704b43b6bd2b91fea1e9315d38932e55fb55 + consensus.MinBIP9WarningHeight = consensus.DIP0008Height + consensus.nMinerConfirmationWindow; consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes @@ -561,6 +563,7 @@ public: consensus.DIP0003EnforcementHeight = 2; // DIP0003 activated immediately on devnet consensus.DIP0003EnforcementHash = uint256(); consensus.DIP0008Height = 2; // DIP0008 activated immediately on devnet + consensus.MinBIP9WarningHeight = consensus.DIP0008Height + consensus.nMinerConfirmationWindow; consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes @@ -795,6 +798,7 @@ public: consensus.DIP0003EnforcementHeight = 500; consensus.DIP0003EnforcementHash = uint256(); consensus.DIP0008Height = 432; + consensus.MinBIP9WarningHeight = 0; consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes diff --git a/src/consensus/params.h b/src/consensus/params.h index 4f66dc9fd3..51d8cac106 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -85,6 +85,9 @@ struct Params { uint256 DIP0003EnforcementHash; /** Block height at which DIP0008 becomes active */ int DIP0008Height; + /** Don't warn about unknown BIP 9 activations below this height. + * This prevents us from warning about the CSV and DIP activations. */ + int MinBIP9WarningHeight; /** * Minimum blocks including miner confirmation of the total of nMinerConfirmationWindow blocks in a retargeting period, * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. diff --git a/src/validation.cpp b/src/validation.cpp index 021323b17d..4db43b8744 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1894,7 +1894,8 @@ public: bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { - return ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && + return pindex->nHeight >= params.MinBIP9WarningHeight && + ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && ((pindex->nVersion >> bit) & 1) != 0 && ((ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0; } From adc3f0478c593795c6a81a094185ba4c40711e38 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 29 Sep 2019 21:49:35 +0300 Subject: [PATCH 09/11] merge bitcoin#16984: Make thread names shorter --- src/util/threadnames.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp index 11f68e2c19..1baee81905 100644 --- a/src/util/threadnames.cpp +++ b/src/util/threadnames.cpp @@ -57,7 +57,7 @@ static void SetInternalName(std::string name) { } void util::ThreadRename(std::string&& name) { - SetThreadName(("dash-" + name).c_str()); + SetThreadName(("d-" + name).c_str()); SetInternalName(std::move(name)); } From 4486659768c1225eb06fda59317137635745aa86 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 7 Nov 2021 00:42:55 +0530 Subject: [PATCH 10/11] merge bitcoin#15928: Move QRImageWidget to its own file-pair --- src/Makefile.qt.include | 3 + src/qt/forms/receiverequestdialog.ui | 2 +- src/qt/guiconstants.h | 6 -- src/qt/qrdialog.cpp | 1 + src/qt/qrimagewidget.cpp | 152 +++++++++++++++++++++++++++ src/qt/qrimagewidget.h | 45 ++++++++ src/qt/receiverequestdialog.cpp | 127 +--------------------- src/qt/receiverequestdialog.h | 30 ------ 8 files changed, 205 insertions(+), 161 deletions(-) create mode 100644 src/qt/qrimagewidget.cpp create mode 100644 src/qt/qrimagewidget.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index cb0ab527a4..d086381865 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -84,6 +84,7 @@ QT_MOC_CPP = \ qt/moc_peertablemodel.cpp \ qt/moc_paymentserver.cpp \ qt/moc_qrdialog.cpp \ + qt/moc_qrimagewidget.cpp \ qt/moc_qvalidatedlineedit.cpp \ qt/moc_qvaluecombobox.cpp \ qt/moc_receivecoinsdialog.cpp \ @@ -167,6 +168,7 @@ BITCOIN_QT_H = \ qt/paymentserver.h \ qt/peertablemodel.h \ qt/qrdialog.h \ + qt/qrimagewidget.h \ qt/qvalidatedlineedit.h \ qt/qvaluecombobox.h \ qt/receivecoinsdialog.h \ @@ -266,6 +268,7 @@ BITCOIN_QT_WALLET_CPP = \ qt/overviewpage.cpp \ qt/paymentserver.cpp \ qt/qrdialog.cpp \ + qt/qrimagewidget.cpp \ qt/receivecoinsdialog.cpp \ qt/receiverequestdialog.cpp \ qt/recentrequeststablemodel.cpp \ diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui index dbe966b241..9f896ee3b1 100644 --- a/src/qt/forms/receiverequestdialog.ui +++ b/src/qt/forms/receiverequestdialog.ui @@ -127,7 +127,7 @@ QRImageWidget QLabel -
qt/receiverequestdialog.h
+
qt/qrimagewidget.h
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index b2ca24ae8d..03f314937b 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -32,12 +32,6 @@ static const bool DEFAULT_SPLASHSCREEN = true; */ static const int TOOLTIP_WRAP_THRESHOLD = 80; -/* Maximum allowed URI length */ -static const int MAX_URI_LENGTH = 255; - -/* QRCodeDialog -- size of exported QR Code image */ -#define QR_IMAGE_SIZE 300 - /* Number of frames in spinner animation */ #define SPINNER_FRAMES 90 diff --git a/src/qt/qrdialog.cpp b/src/qt/qrdialog.cpp index d70ca30c68..6fc8b45d87 100644 --- a/src/qt/qrdialog.cpp +++ b/src/qt/qrdialog.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp new file mode 100644 index 0000000000..2ad72c0256 --- /dev/null +++ b/src/qt/qrimagewidget.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2011-2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_CONFIG_H) +#include /* for USE_QRCODE */ +#endif + +#ifdef USE_QRCODE +#include +#endif + +QRImageWidget::QRImageWidget(QWidget *parent): + QLabel(parent), contextMenu(nullptr) +{ + contextMenu = new QMenu(this); + QAction *saveImageAction = new QAction(tr("&Save Image..."), this); + connect(saveImageAction, &QAction::triggered, this, &QRImageWidget::saveImage); + contextMenu->addAction(saveImageAction); + QAction *copyImageAction = new QAction(tr("&Copy Image"), this); + connect(copyImageAction, &QAction::triggered, this, &QRImageWidget::copyImage); + contextMenu->addAction(copyImageAction); +} + +bool QRImageWidget::setQR(const QString& data, const QString& text) +{ +#ifdef USE_QRCODE + setText(""); + if (data.isEmpty()) return false; + + // limit length + if (data.length() > MAX_URI_LENGTH) { + setText(tr("Resulting URI too long, try to reduce the text for label / message.")); + return false; + } + + QRcode *code = QRcode_encodeString(data.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1); + + if (!code) { + setText(tr("Error encoding URI into QR Code.")); + return false; + } + + QImage qrImage = QImage(code->width + 6, code->width + 6, QImage::Format_RGB32); + qrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET)); + unsigned char *p = code->data; + for (int y = 0; y < code->width; y++) + { + for (int x = 0; x < code->width; x++) + { + qrImage.setPixel(x + 3, y + 3, ((*p & 1) ? GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL).rgb() : GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET).rgb())); + p++; + } + } + QRcode_free(code); + + // Create the image with respect to the device pixel ratio + int qrAddrImageWidth = QR_IMAGE_SIZE; + int qrAddrImageHeight = QR_IMAGE_SIZE + 20; + qreal scale = qApp->devicePixelRatio(); + QImage qrAddrImage = QImage(qrAddrImageWidth * scale, qrAddrImageHeight * scale, QImage::Format_RGB32); + qrAddrImage.setDevicePixelRatio(scale); + QPainter painter(&qrAddrImage); + + // Fill the whole image with border color + qrAddrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BORDER_WIDGET)); + + // Create a 2px/2px smaller rect and fill it with background color to keep the 1px border with the border color + QRect paddedRect = QRect(1, 1, qrAddrImageWidth - 2, qrAddrImageHeight - 2); + painter.fillRect(paddedRect, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET)); + painter.drawImage(2, 2, qrImage.scaled(QR_IMAGE_SIZE - 4, QR_IMAGE_SIZE - 4)); + + // calculate ideal font size + QFont font = GUIUtil::getFontNormal(); + qreal font_size = GUIUtil::calculateIdealFontSize((paddedRect.width() - 20), text, font); + font.setPointSizeF(font_size); + + // paint the address + painter.setFont(font); + painter.setPen(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL)); + paddedRect.setHeight(QR_IMAGE_SIZE + 3); + painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, text); + painter.end(); + + setPixmap(QPixmap::fromImage(qrAddrImage)); + + return true; +#else + setText(tr("QR code support not available.")); + return false; +#endif +} + +QImage QRImageWidget::exportImage() +{ + if(!pixmap()) + return QImage(); + return pixmap()->toImage(); +} + +void QRImageWidget::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton && pixmap()) + { + event->accept(); + QMimeData *mimeData = new QMimeData; + mimeData->setImageData(exportImage()); + + QDrag *drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->exec(); + } else { + QLabel::mousePressEvent(event); + } +} + +void QRImageWidget::saveImage() +{ + if(!pixmap()) + return; + QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr); + if (!fn.isEmpty()) + { + exportImage().save(fn); + } +} + +void QRImageWidget::copyImage() +{ + if(!pixmap()) + return; + QApplication::clipboard()->setImage(exportImage()); +} + +void QRImageWidget::contextMenuEvent(QContextMenuEvent *event) +{ + if(!pixmap()) + return; + contextMenu->exec(event->globalPos()); +} diff --git a/src/qt/qrimagewidget.h b/src/qt/qrimagewidget.h new file mode 100644 index 0000000000..1a5c904707 --- /dev/null +++ b/src/qt/qrimagewidget.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011-2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_QRIMAGEWIDGET_H +#define BITCOIN_QT_QRIMAGEWIDGET_H + +#include +#include + +/* Maximum allowed URI length */ +static const int MAX_URI_LENGTH = 255; + +/* Size of exported QR Code image */ +static const int QR_IMAGE_SIZE = 300; + +QT_BEGIN_NAMESPACE +class QMenu; +QT_END_NAMESPACE + +/* Label widget for QR code. This image can be dragged, dropped, copied and saved + * to disk. + */ +class QRImageWidget : public QLabel +{ + Q_OBJECT + +public: + explicit QRImageWidget(QWidget *parent = nullptr); + bool setQR(const QString& data, const QString& text = ""); + QImage exportImage(); + +public Q_SLOTS: + void saveImage(); + void copyImage(); + +protected: + virtual void mousePressEvent(QMouseEvent *event) override; + virtual void contextMenuEvent(QContextMenuEvent *event) override; + +private: + QMenu *contextMenu; +}; + +#endif // BITCOIN_QT_QRIMAGEWIDGET_H diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index a516380e41..46ef6689ec 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -6,85 +6,17 @@ #include #include -#include #include #include +#include #include -#include -#include -#include -#include #include #if defined(HAVE_CONFIG_H) #include /* for USE_QRCODE */ #endif -#ifdef USE_QRCODE -#include -#endif - -QRImageWidget::QRImageWidget(QWidget *parent): - QLabel(parent), contextMenu(nullptr) -{ - contextMenu = new QMenu(this); - QAction *saveImageAction = new QAction(tr("&Save Image..."), this); - connect(saveImageAction, &QAction::triggered, this, &QRImageWidget::saveImage); - contextMenu->addAction(saveImageAction); - QAction *copyImageAction = new QAction(tr("&Copy Image"), this); - connect(copyImageAction, &QAction::triggered, this, &QRImageWidget::copyImage); - contextMenu->addAction(copyImageAction); -} - -QImage QRImageWidget::exportImage() -{ - if(!pixmap()) - return QImage(); - return pixmap()->toImage(); -} - -void QRImageWidget::mousePressEvent(QMouseEvent *event) -{ - if(event->button() == Qt::LeftButton && pixmap()) - { - event->accept(); - QMimeData *mimeData = new QMimeData; - mimeData->setImageData(exportImage()); - - QDrag *drag = new QDrag(this); - drag->setMimeData(mimeData); - drag->exec(); - } else { - QLabel::mousePressEvent(event); - } -} - -void QRImageWidget::saveImage() -{ - if(!pixmap()) - return; - QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr); - if (!fn.isEmpty()) - { - exportImage().save(fn); - } -} - -void QRImageWidget::copyImage() -{ - if(!pixmap()) - return; - QApplication::clipboard()->setImage(exportImage()); -} - -void QRImageWidget::contextMenuEvent(QContextMenuEvent *event) -{ - if(!pixmap()) - return; - contextMenu->exec(event->globalPos()); -} - ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ReceiveRequestDialog), @@ -153,62 +85,9 @@ void ReceiveRequestDialog::update() } ui->outUri->setText(html); -#ifdef USE_QRCODE - ui->lblQRCode->setText(""); - if(!uri.isEmpty()) - { - // limit URI length - if (uri.length() > MAX_URI_LENGTH) - { - ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message.")); - } else { - QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1); - if (!code) - { - ui->lblQRCode->setText(tr("Error encoding URI into QR Code.")); - return; - } - QImage qrImage = QImage(code->width + 6, code->width + 6, QImage::Format_RGB32); - qrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET)); - unsigned char *p = code->data; - for (int y = 0; y < code->width; y++) - { - for (int x = 0; x < code->width; x++) - { - qrImage.setPixel(x + 3, y + 3, ((*p & 1) ? GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL).rgb() : GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET).rgb())); - p++; - } - } - QRcode_free(code); - // Create the image with respect to the device pixel ratio - int qrAddrImageWidth = QR_IMAGE_SIZE; - int qrAddrImageHeight = QR_IMAGE_SIZE + 20; - qreal scale = qApp->devicePixelRatio(); - QImage qrAddrImage = QImage(qrAddrImageWidth * scale, qrAddrImageHeight * scale, QImage::Format_RGB32); - qrAddrImage.setDevicePixelRatio(scale); - QPainter painter(&qrAddrImage); - // Fill the whole image with border color - qrAddrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BORDER_WIDGET)); - // Create a 2px/2px smaller rect and fill it with background color to keep the 1px border with the border color - QRect paddedRect = QRect(1, 1, qrAddrImageWidth - 2, qrAddrImageHeight - 2); - painter.fillRect(paddedRect, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET)); - painter.drawImage(2, 2, qrImage.scaled(QR_IMAGE_SIZE - 4, QR_IMAGE_SIZE - 4)); - // calculate ideal font size - QFont font = GUIUtil::getFontNormal(); - qreal font_size = GUIUtil::calculateIdealFontSize((paddedRect.width() - 20), info.address, font); - font.setPointSizeF(font_size); - // paint the address - painter.setFont(font); - painter.setPen(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL)); - paddedRect.setHeight(QR_IMAGE_SIZE + 3); - painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, info.address); - painter.end(); - - ui->lblQRCode->setPixmap(QPixmap::fromImage(qrAddrImage)); - ui->btnSaveAs->setEnabled(true); - } + if (ui->lblQRCode->setQR(uri, info.address)) { + ui->btnSaveAs->setEnabled(true); } -#endif } void ReceiveRequestDialog::on_btnCopyURI_clicked() diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 45bbeafbea..c7195d7596 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -8,41 +8,11 @@ #include #include -#include -#include -#include namespace Ui { class ReceiveRequestDialog; } -QT_BEGIN_NAMESPACE -class QMenu; -QT_END_NAMESPACE - -/* Label widget for QR code. This image can be dragged, dropped, copied and saved - * to disk. - */ -class QRImageWidget : public QLabel -{ - Q_OBJECT - -public: - explicit QRImageWidget(QWidget *parent = nullptr); - QImage exportImage(); - -public Q_SLOTS: - void saveImage(); - void copyImage(); - -protected: - virtual void mousePressEvent(QMouseEvent *event) override; - virtual void contextMenuEvent(QContextMenuEvent *event) override; - -private: - QMenu *contextMenu; -}; - class ReceiveRequestDialog : public QDialog { Q_OBJECT From 6718789ada076e4aee4cb1bdf59461264cb0e2bf Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 12 Dec 2021 20:18:21 +0530 Subject: [PATCH 11/11] merge bitcoin#17449: fix uninitialized variable nMinerConfirmationWindow --- src/chainparams.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 46e791f477..55a9307120 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -152,7 +152,7 @@ public: consensus.DIP0003EnforcementHeight = 1047200; consensus.DIP0003EnforcementHash = uint256S("000000000000002d1734087b4c5afc3133e4e1c3e1a89218f62bcd9bb3d17f81"); consensus.DIP0008Height = 1088640; // 00000000000000112e41e4b3afda8b233b8cc07c532d2eac5de097b68358c43e - consensus.MinBIP9WarningHeight = consensus.DIP0008Height + consensus.nMinerConfirmationWindow; + consensus.MinBIP9WarningHeight = 1090656; // dip8 activation height + miner confirmation window consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes @@ -371,7 +371,7 @@ public: consensus.DIP0003EnforcementHeight = 7300; consensus.DIP0003EnforcementHash = uint256S("00000055ebc0e974ba3a3fb785c5ad4365a39637d4df168169ee80d313612f8f"); consensus.DIP0008Height = 78800; // 000000000e9329d964d80e7dab2e704b43b6bd2b91fea1e9315d38932e55fb55 - consensus.MinBIP9WarningHeight = consensus.DIP0008Height + consensus.nMinerConfirmationWindow; + consensus.MinBIP9WarningHeight = 80816; // dip8 activation height + miner confirmation window consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes @@ -563,7 +563,7 @@ public: consensus.DIP0003EnforcementHeight = 2; // DIP0003 activated immediately on devnet consensus.DIP0003EnforcementHash = uint256(); consensus.DIP0008Height = 2; // DIP0008 activated immediately on devnet - consensus.MinBIP9WarningHeight = consensus.DIP0008Height + consensus.nMinerConfirmationWindow; + consensus.MinBIP9WarningHeight = 2018; // dip8 activation height + miner confirmation window consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes