Files
blackcoin-more/src/qt/bitcoinaddressvalidator.cpp
lateminer 323a6750c2 Add CashAddr Address Format
Ported from Bitcoin Unlimited, Bitcoin ABC
2018-01-14 22:32:08 +03:00

126 lines
3.6 KiB
C++

// Copyright (c) 2011-2014 The Bitcoin Core developers
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
// 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 "bitcoinaddressvalidator.h"
#include "cashaddr.h"
#include "dstencode.h"
/* Base58 characters are:
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
This is:
- All numbers except for '0'
- 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)
{
}
QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &pos) const
{
Q_UNUSED(pos);
// Empty address is "intermediate" input
if (input.isEmpty())
return QValidator::Intermediate;
// Correction
for (int idx = 0; idx < input.size();)
{
bool removeChar = false;
QChar ch = input.at(idx);
// Corrections made are very conservative on purpose, to avoid
// users unexpectedly getting away with typos that would normally
// be detected, and thus sending to the wrong address.
switch(ch.unicode())
{
// Qt categorizes these as "Other_Format" not "Separator_Space"
case 0x200B: // ZERO WIDTH SPACE
case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
removeChar = true;
break;
default:
break;
}
// Remove whitespace
if (ch.isSpace())
removeChar = true;
// To next character
if (removeChar)
input.remove(idx, 1);
else
++idx;
}
// Validation
const QString cashPrefix = QString::fromStdString(cashaddrprefix) + ":";
return (ValidLegacyInput(input) || ValidCashaddrInput(cashPrefix, input)) ? QValidator::Acceptable :
QValidator::Invalid;
}
BitcoinAddressCheckValidator::BitcoinAddressCheckValidator(QObject *parent) :
QValidator(parent)
{
}
QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &pos) const
{
Q_UNUSED(pos);
// Validate the passed Bitcoin address
if (IsValidDestinationString(input.toStdString()))
{
return QValidator::Acceptable;
}
return QValidator::Invalid;
}