diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -7,6 +7,7 @@ TEST_QT_MOC_CPP = \ qt/test/moc_compattests.cpp \ + qt/test/moc_guiutiltests.cpp \ qt/test/moc_rpcnestedtests.cpp \ qt/test/moc_uritests.cpp @@ -16,6 +17,7 @@ TEST_QT_H = \ qt/test/compattests.h \ + qt/test/guiutiltests.h \ qt/test/rpcnestedtests.h \ qt/test/uritests.h \ qt/test/paymentrequestdata.h \ @@ -26,6 +28,7 @@ qt_test_test_bitcoin_qt_SOURCES = \ qt/test/compattests.cpp \ + qt/test/guiutiltests.cpp \ qt/test/rpcnestedtests.cpp \ qt/test/test_main.cpp \ qt/test/uritests.cpp \ diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -20,6 +20,8 @@ class QValidatedLineEdit; class SendCoinsRecipient; +class CChainParams; +class Config; QT_BEGIN_NAMESPACE class QAbstractItemView; @@ -42,6 +44,9 @@ // Return a monospace font QFont fixedPitchFont(); +// Generate an invalid, but convincing address. +std::string DummyAddress(const CChainParams ¶ms, const Config &cfg); + // Set up widgets for address and amounts void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent); void setupAmountWidget(QLineEdit *widget, QWidget *parent); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -6,9 +6,11 @@ #include "bitcoinaddressvalidator.h" #include "bitcoinunits.h" +#include "dstencode.h" #include "qvalidatedlineedit.h" #include "walletmodel.h" +#include "config.h" #include "dstencode.h" #include "init.h" #include "policy/policy.h" @@ -17,6 +19,7 @@ #include "script/script.h" #include "script/standard.h" #include "util.h" +#include "utilstrencodings.h" #ifdef WIN32 #ifdef _WIN32_WINNT @@ -112,29 +115,31 @@ #endif } -// Just some dummy data to generate an convincing random-looking (but -// consistent) address -static const uint8_t dummydata[] = { - 0xeb, 0x15, 0x23, 0x1d, 0xfc, 0xeb, 0x60, 0x92, 0x58, 0x86, 0xb6, 0x7d, - 0x06, 0x52, 0x99, 0x92, 0x59, 0x15, 0xae, 0xb1, 0x72, 0xc0, 0x66, 0x47}; - -// Generate a dummy address with invalid CRC, starting with the network prefix. -static std::string DummyAddress(const CChainParams ¶ms) { - std::vector sourcedata = - params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); - sourcedata.insert(sourcedata.end(), dummydata, - dummydata + sizeof(dummydata)); - for (int i = 0; i < 256; ++i) { // Try every trailing byte - std::string s = EncodeBase58(sourcedata.data(), - sourcedata.data() + sourcedata.size()); - if (!IsValidDestinationString(s)) { - return s; - } - sourcedata[sourcedata.size() - 1] += 1; +static std::string MakeAddrInvalid(std::string addr) { + if (addr.size() < 2) { + return ""; + } + + // Checksum is at the end of the address. Swapping chars to make it invalid. + std::swap(addr[addr.size() - 1], addr[addr.size() - 2]); + if (!IsValidDestinationString(addr)) { + return addr; } return ""; } +std::string DummyAddress(const CChainParams ¶ms, const Config &cfg) { + + // Just some dummy data to generate an convincing random-looking (but + // consistent) address + static const std::vector dummydata = { + 0xeb, 0x15, 0x23, 0x1d, 0xfc, 0xeb, 0x60, 0x92, 0x58, 0x86, + 0xb6, 0x7d, 0x06, 0x52, 0x99, 0x92, 0x59, 0x15, 0xae, 0xb1}; + + const CTxDestination dstKey = CKeyID(uint160(dummydata)); + return MakeAddrInvalid(EncodeDestination(dstKey, params, cfg)); +} + void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) { parent->setFocusProxy(widget); @@ -142,9 +147,9 @@ #if QT_VERSION >= 0x040700 // We don't want translators to use own addresses in translations // and this is the only place, where this address is supplied. - widget->setPlaceholderText( - QObject::tr("Enter a Bitcoin address (e.g. %1)") - .arg(QString::fromStdString(DummyAddress(Params())))); + widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)") + .arg(QString::fromStdString(DummyAddress( + Params(), GlobalConfig())))); #endif widget->setValidator(new BitcoinAddressEntryValidator(parent)); widget->setCheckValidator(new BitcoinAddressCheckValidator(parent)); diff --git a/src/qt/test/guiutiltests.h b/src/qt/test/guiutiltests.h new file mode 100644 --- /dev/null +++ b/src/qt/test/guiutiltests.h @@ -0,0 +1,18 @@ +// Copyright (c) 2017 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_TEST_GUIUTILTESTS_H +#define BITCOIN_QT_TEST_GUIUTILTESTS_H + +#include +#include + +class GUIUtilTests : public QObject { + Q_OBJECT + +private Q_SLOTS: + void dummyAddressTest(); +}; + +#endif // BITCOIN_QT_TEST_GUIUTILTESTS_H diff --git a/src/qt/test/guiutiltests.cpp b/src/qt/test/guiutiltests.cpp new file mode 100644 --- /dev/null +++ b/src/qt/test/guiutiltests.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "guiutiltests.h" +#include "chainparams.h" +#include "config.h" +#include "dstencode.h" +#include "guiutil.h" + +namespace { + +class UtilCfgDummy : public DummyConfig { +public: + UtilCfgDummy() : useCashAddr(false) {} + void SetCashAddrEncoding(bool b) override { useCashAddr = b; } + bool UseCashAddrEncoding() const override { return useCashAddr; } + +private: + bool useCashAddr; +}; + +} // anon ns + +void GUIUtilTests::dummyAddressTest() { + CChainParams ¶ms = Params(CBaseChainParams::MAIN); + UtilCfgDummy cfg; + std::string dummyaddr; + + cfg.SetCashAddrEncoding(false); + dummyaddr = GUIUtil::DummyAddress(params, cfg); + QVERIFY(!IsValidDestinationString(dummyaddr, params)); + QVERIFY(!dummyaddr.empty()); + + cfg.SetCashAddrEncoding(true); + dummyaddr = GUIUtil::DummyAddress(params, cfg); + QVERIFY(!IsValidDestinationString(dummyaddr, params)); + QVERIFY(!dummyaddr.empty()); +} diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -8,6 +8,7 @@ #include "chainparams.h" #include "compattests.h" +#include "guiutiltests.h" #include "key.h" #include "rpcnestedtests.h" #include "uritests.h" @@ -60,6 +61,8 @@ if (QTest::qExec(&test3) != 0) fInvalid = true; CompatTests test4; if (QTest::qExec(&test4) != 0) fInvalid = true; + GUIUtilTests test5; + if (QTest::qExec(&test5) != 0) fInvalid = true; ECC_Stop(); return fInvalid;