diff --git a/src/cashaddr.h b/src/cashaddr.h --- a/src/cashaddr.h +++ b/src/cashaddr.h @@ -22,6 +22,4 @@ */ std::pair<std::string, std::vector<uint8_t>> Decode(const std::string &str); -std::vector<uint8_t> EncodingCharset(); - } // namespace cashaddr diff --git a/src/cashaddr.cpp b/src/cashaddr.cpp --- a/src/cashaddr.cpp +++ b/src/cashaddr.cpp @@ -292,9 +292,4 @@ return {prefix, data(values.begin(), values.end() - 8)}; } -std::vector<uint8_t> EncodingCharset() { - const size_t size = 32; - return std::vector<uint8_t>(CHARSET, CHARSET + size); -} - } // namespace cashaddr diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp --- a/src/qt/bitcoinaddressvalidator.cpp +++ b/src/qt/bitcoinaddressvalidator.cpp @@ -16,41 +16,6 @@ - All upper-case letters except for 'I' and 'O' - All lower-case letters except for 'l' */ -static bool ValidLegacyInput(const QString &input) { - // Alphanumeric and not a 'forbidden' character - for (QChar ch : input) { - if (!(((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z')) && - ch != 'l' && ch != 'I' && ch != '0' && ch != 'O')) - return false; - } - return true; -} - -static bool ValidCashaddrInput(const QString &prefix, const QString &input) { - - std::vector<uint8_t> charset = cashaddr::EncodingCharset(); - - // Input may be incomplete. We're checking if it so far looks good. - - for (int i = 0; i < input.size(); ++i) { - char ch = std::tolower(input[i].toLatin1()); - - // Does the input have the right prefix? - if (i < prefix.size()) { - if (ch != prefix[i].toLatin1()) { - return false; - } - continue; - } - - // Payload, must use cashaddr charset. - if (std::find(begin(charset), end(charset), ch) == end(charset)) { - return false; - } - } - return true; -} BitcoinAddressEntryValidator::BitcoinAddressEntryValidator( const std::string &cashaddrprefix, QObject *parent) : QValidator(parent), cashaddrprefix(cashaddrprefix) {} @@ -60,7 +25,9 @@ Q_UNUSED(pos); // Empty address is "intermediate" input - if (input.isEmpty()) return QValidator::Intermediate; + if (input.isEmpty()) { + return QValidator::Intermediate; + } // Correction for (int idx = 0; idx < input.size();) { @@ -80,20 +47,33 @@ } // Remove whitespace - if (ch.isSpace()) removeChar = true; + if (ch.isSpace()) { + removeChar = true; + } // To next character - if (removeChar) + if (removeChar) { input.remove(idx, 1); - else + } else { ++idx; + } } // Validation - const QString cashPrefix = QString::fromStdString(cashaddrprefix) + ":"; - return (ValidLegacyInput(input) || ValidCashaddrInput(cashPrefix, input)) - ? QValidator::Acceptable - : QValidator::Invalid; + QValidator::State state = QValidator::Acceptable; + for (int idx = 0; idx < input.size(); ++idx) { + int ch = input.at(idx).unicode(); + + if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || (ch == ':')) { + // Alphanumeric and not a 'forbidden' character + // We also include ':' for cashaddr. + } else { + return QValidator::Invalid; + } + } + + return state; } BitcoinAddressCheckValidator::BitcoinAddressCheckValidator(QObject *parent) @@ -102,6 +82,7 @@ QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &pos) const { Q_UNUSED(pos); + // Validate the passed Bitcoin address if (IsValidDestinationString(input.toStdString())) { return QValidator::Acceptable; diff --git a/src/qt/test/bitcoinaddressvalidatortests.cpp b/src/qt/test/bitcoinaddressvalidatortests.cpp --- a/src/qt/test/bitcoinaddressvalidatortests.cpp +++ b/src/qt/test/bitcoinaddressvalidatortests.cpp @@ -14,23 +14,40 @@ int unused = 0; QString in; - // invalid base58 because of I, invalid cashaddr + // Empty string is intermediate. + in = ""; + QVERIFY(v.validate(in, unused) == QValidator::Intermediate); + + // invalid base58 because of I, invalid cashaddr, currently considered valid + // anyway. in = "BIIC"; - QVERIFY(QValidator::Invalid == v.validate(in, unused)); + QVERIFY(v.validate(in, unused) == QValidator::Acceptable); - // invalid base58, invalid cashaddr + // invalid base58, invalid cashaddr, currently considered valid anyway. in = "BITCOINCASHH"; - QVERIFY(QValidator::Invalid == v.validate(in, unused)); + QVERIFY(v.validate(in, unused) == QValidator::Acceptable); // invalid base58 because of I, but could be a cashaddr prefix in = "BITC"; - QVERIFY(QValidator::Acceptable == v.validate(in, unused)); + QVERIFY(v.validate(in, unused) == QValidator::Acceptable); // invalid base58, valid cashaddr in = "BITCOINCASH:QP"; - QVERIFY(QValidator::Acceptable == v.validate(in, unused)); + QVERIFY(v.validate(in, unused) == QValidator::Acceptable); + + // invalid base58, valid cashaddr, lower case + in = "bitcoincash:qp"; + QVERIFY(v.validate(in, unused) == QValidator::Acceptable); + + // invalid base58, valid cashaddr, mixed case + in = "bItCoInCaSh:Qp"; + QVERIFY(v.validate(in, unused) == QValidator::Acceptable); // valid base58, invalid cash in = "BBBBBBBBBBBBBB"; - QVERIFY(QValidator::Acceptable == v.validate(in, unused)); + QVERIFY(v.validate(in, unused) == QValidator::Acceptable); + + // Only alphanumeric chars are accepted. + in = "%"; + QVERIFY(v.validate(in, unused) == QValidator::Invalid); }