008eb35f95
The IDE include checker got to the point where it is actually useful and this removes a lot of unneeded includes. Naturally, especially for headers like util.h, this may mean we need to re-add includes in consuming cpp files that bloats the diff a bit.
201 lines
7.3 KiB
C++
201 lines
7.3 KiB
C++
/*
|
|
* This file is part of the Flowee project
|
|
* Copyright (C) 2011-2015 The Bitcoin Core developers
|
|
* Copyright (C) 2022 Tom Zander <tom@flowee.org>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "base58_tests.h"
|
|
#include <encodings_legacy.h>
|
|
|
|
#include <primitives/PrivateKey.h>
|
|
#include <primitives/script.h>
|
|
#include <uint256.h>
|
|
#include <util.h>
|
|
#include <chainparams.h>
|
|
#include <utilstrencodings.h>
|
|
|
|
// Visitor to check address type
|
|
class TestAddrTypeVisitor : public boost::static_visitor<bool>
|
|
{
|
|
private:
|
|
std::string exp_addrType;
|
|
public:
|
|
TestAddrTypeVisitor(const std::string &exp_addrType) : exp_addrType(exp_addrType) { }
|
|
bool operator()(const KeyId &id) const
|
|
{
|
|
return (exp_addrType == "pubkey");
|
|
}
|
|
bool operator()(const CScriptID &id) const
|
|
{
|
|
return (exp_addrType == "script");
|
|
}
|
|
bool operator()(const CNoDestination &no) const
|
|
{
|
|
return (exp_addrType == "none");
|
|
}
|
|
};
|
|
|
|
void Base58Tests::base58KeysValidParse()
|
|
{
|
|
QFile in(":/base58_keys_valid.json");
|
|
QVERIFY(in.open(QIODevice::ReadOnly));
|
|
auto testDoc = QJsonDocument::fromJson(in.readAll());
|
|
QVERIFY(testDoc.isArray());
|
|
auto tests = testDoc.array();
|
|
|
|
CBitcoinSecret secret;
|
|
CBitcoinAddress addr;
|
|
SelectParams(CBaseChainParams::MAIN);
|
|
for (auto row = tests.begin(); row != tests.end(); ++row) {
|
|
auto test = row->toArray();
|
|
if (test.size() < 3) { // Allow for extra stuff (useful for comments)
|
|
QFAIL("Bad test");
|
|
continue;
|
|
}
|
|
std::string exp_base58string = test[0].toString().toStdString();
|
|
auto exp_payload = ParseHex(test[1].toString().toStdString());
|
|
auto metadata = test[2].toObject();
|
|
bool isPrivkey = metadata.value("isPrivkey").toBool();
|
|
bool isTestnet = metadata.value("isTestnet").toBool();
|
|
if (isTestnet)
|
|
SelectParams(CBaseChainParams::TESTNET);
|
|
else
|
|
SelectParams(CBaseChainParams::MAIN);
|
|
if (isPrivkey) {
|
|
PrivateKey key;
|
|
|
|
bool isCompressed = metadata.value("isCompressed").toBool();
|
|
// Must be valid private key
|
|
// Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
|
|
QVERIFY2(secret.SetString(exp_base58string), "!SetString");
|
|
QVERIFY2(secret.IsValid(), "!IsValid");
|
|
PrivateKey privkey = secret.GetKey();
|
|
QVERIFY2(privkey.isCompressed() == isCompressed, "compressed mismatch");
|
|
QVERIFY2(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch");
|
|
|
|
// Private key must be invalid public key
|
|
addr.SetString(exp_base58string);
|
|
QVERIFY2(!addr.IsValid(), "IsValid privkey as pubkey");
|
|
}
|
|
else {
|
|
std::string exp_addrType = metadata.value("addrType").toString().toStdString(); // "script" or "pubkey"
|
|
// Must be valid public key
|
|
QVERIFY2(addr.SetString(exp_base58string), "SetString");
|
|
QVERIFY2(addr.IsValid(), "!IsValid");
|
|
QVERIFY2(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch");
|
|
CTxDestination dest = addr.Get();
|
|
QVERIFY2(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch");
|
|
|
|
// Public key must be invalid private key
|
|
secret.SetString(exp_base58string);
|
|
QVERIFY2(!secret.IsValid(), "IsValid pubkey as privkey");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Goal: check that generated keys match test vectors
|
|
void Base58Tests::base58KeysValidGen()
|
|
{
|
|
QFile in(":/base58_keys_valid.json");
|
|
QVERIFY(in.open(QIODevice::ReadOnly));
|
|
auto testDoc = QJsonDocument::fromJson(in.readAll());
|
|
QVERIFY(testDoc.isArray());
|
|
auto tests = testDoc.array();
|
|
|
|
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
|
auto test = tests[idx].toArray();
|
|
if (test.size() < 3) { // Allow for extra stuff (useful for comments)
|
|
QFAIL("Bad test");
|
|
continue;
|
|
}
|
|
std::string exp_base58string = test[0].toString().toStdString();
|
|
auto exp_payload = ParseHex(test[1].toString().toStdString());
|
|
auto metadata = test[2].toObject();
|
|
|
|
bool isPrivkey = metadata.value("isPrivkey").toBool();
|
|
bool isTestnet = metadata.value("isTestnet").toBool();
|
|
if (isTestnet)
|
|
SelectParams(CBaseChainParams::TESTNET);
|
|
else
|
|
SelectParams(CBaseChainParams::MAIN);
|
|
if (isPrivkey) {
|
|
bool isCompressed = metadata.value("isCompressed").toBool();
|
|
PrivateKey key;
|
|
key.set(exp_payload.begin(), exp_payload.end(), isCompressed);
|
|
QVERIFY(key.isValid());
|
|
CBitcoinSecret secret;
|
|
secret.SetKey(key);
|
|
QVERIFY2(secret.ToString() == exp_base58string, "result mismatch");
|
|
}
|
|
else {
|
|
std::string exp_addrType = metadata.value("addrType").toString().toStdString(); // "script" or "pubkey"
|
|
CTxDestination dest;
|
|
if(exp_addrType == "pubkey") {
|
|
dest = KeyId(uint160(exp_payload));
|
|
}
|
|
else if(exp_addrType == "script") {
|
|
dest = CScriptID(uint160(exp_payload));
|
|
}
|
|
else if(exp_addrType == "none") {
|
|
dest = CNoDestination();
|
|
}
|
|
else {
|
|
QFAIL("Bad addrtype");
|
|
continue;
|
|
}
|
|
CBitcoinAddress addrOut;
|
|
QVERIFY2(addrOut.Set(dest), "encode dest");
|
|
QVERIFY2(addrOut.ToString() == exp_base58string, "mismatch");
|
|
}
|
|
}
|
|
|
|
// Visiting a CNoDestination must fail
|
|
CBitcoinAddress dummyAddr;
|
|
CTxDestination nodest = CNoDestination();
|
|
QVERIFY(!dummyAddr.Set(nodest));
|
|
|
|
SelectParams(CBaseChainParams::MAIN);
|
|
}
|
|
|
|
// Goal: check that base58 parsing code is robust against a variety of corrupted data
|
|
void Base58Tests::base58KeysInvalid()
|
|
{
|
|
QFile in(":/base58_keys_invalid.json");
|
|
QVERIFY(in.open(QIODevice::ReadOnly));
|
|
auto testDoc = QJsonDocument::fromJson(in.readAll());
|
|
QVERIFY(testDoc.isArray());
|
|
auto tests = testDoc.array();
|
|
CBitcoinSecret secret;
|
|
CBitcoinAddress addr;
|
|
|
|
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
|
auto test = tests[idx].toArray();
|
|
if (test.size() < 1) { // Allow for extra stuff (useful for comments)
|
|
QFAIL("Bad test");
|
|
continue;
|
|
}
|
|
std::string exp_base58string = test[0].toString().toStdString();
|
|
|
|
// must be invalid as public and as private key
|
|
addr.SetString(exp_base58string);
|
|
QVERIFY2(!addr.IsValid(), "IsValid pubkey");
|
|
secret.SetString(exp_base58string);
|
|
QVERIFY2(!secret.IsValid(), "IsValid privkey");
|
|
}
|
|
}
|
|
|
|
|