b5b493542b
The unit tests testing base58 encoding were using univalue JSON parsing, since we deprecatd univalue to be a hub-private lib this has now been ported to Qts JSON parser. Which also makes the clunky cmake hack nice to replace with the QRC files concept. As I was in there anyway, the base58 methods being global scope C-style methods has now been fixed by putting them in a namespace.
122 lines
5.3 KiB
C++
122 lines
5.3 KiB
C++
/*
|
|
* This file is part of the Flowee project
|
|
* Copyright (C) 2021 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 "TestHDWallets.h"
|
|
#include <Logger.h>
|
|
|
|
#include <apputils/Mnemonic.h>
|
|
#include <utils/HDMasterKey.h>
|
|
#include <utils/HDMasterPubkey.h>
|
|
#include <cashaddr.h>
|
|
|
|
TestHDWallets::TestHDWallets()
|
|
{
|
|
ECC_Start(); // neded for crypto module, deriving pubkeys for instance.
|
|
}
|
|
|
|
TestHDWallets::~TestHDWallets()
|
|
{
|
|
ECC_Stop();
|
|
}
|
|
|
|
void TestHDWallets::hdwallet()
|
|
{
|
|
QFETCH(QString, mnemonic);
|
|
QFETCH(QString, masterPrivKey);
|
|
QFETCH(QString, derivation);
|
|
QFETCH(QString, bitcoinAddress);
|
|
|
|
HDMasterKey mkey = HDMasterKey::fromMnemonic(mnemonic.toStdString());
|
|
QVERIFY(mkey.isValid());
|
|
QCOMPARE(QString::fromStdString(mkey.privToString()), masterPrivKey);
|
|
auto derivedKey = mkey.derive(derivation.toStdString());
|
|
QVERIFY(derivedKey.isValid());
|
|
auto id = derivedKey.getPubKey().getKeyId();
|
|
auto address = CashAddress::encodeCashAddr("bitcoincash",
|
|
{ CashAddress::PUBKEY_TYPE,
|
|
std::vector<uint8_t>(id.begin(), id.end())});
|
|
QCOMPARE(QString::fromStdString(address), bitcoinAddress);
|
|
|
|
const auto derivationPathOrig = HDMasterKey::deriveFromString(derivation.toStdString());
|
|
auto iter = derivationPathOrig.begin();
|
|
for (size_t index = 0; index < derivationPathOrig.size(); ++index) {
|
|
if ((derivationPathOrig[index] & HDMasterKey::Hardened) == 0)
|
|
break;
|
|
++iter;
|
|
}
|
|
// Split into the hardened part and the rest.
|
|
std::vector<uint32_t> hardDerivPath(derivationPathOrig.begin(), iter);
|
|
|
|
// See if the HDMasterPubkey also comes to the same conclusion using the xpub
|
|
try {
|
|
auto mPubKeyTestnet = HDMasterPubkey::fromXPub(mkey.toXPubString(hardDerivPath, HDMasterKey::Testnet));
|
|
QVERIFY(mPubKeyTestnet.isValid());
|
|
QCOMPARE(mPubKeyTestnet.chain(), HDMasterPubkey::Testnet);
|
|
} catch (std::exception &e) {
|
|
QFAIL(e.what());
|
|
}
|
|
|
|
const auto xpub = mkey.toXPubString(hardDerivPath, HDMasterKey::MainChain);
|
|
auto mPubKey = HDMasterPubkey::fromXPub(xpub);
|
|
QVERIFY(mPubKey.isValid());
|
|
QCOMPARE(mPubKey.chain(), HDMasterPubkey::MainChain);
|
|
QCOMPARE(mPubKey.toString(), xpub);
|
|
|
|
auto derivedPubKey = mPubKey.derive(derivation.toStdString());
|
|
QVERIFY(derivedPubKey.isValid());
|
|
id = derivedPubKey.getKeyId();
|
|
address = CashAddress::encodeCashAddr("bitcoincash",
|
|
{ CashAddress::PUBKEY_TYPE,
|
|
std::vector<uint8_t>(id.begin(), id.end())});
|
|
QCOMPARE(QString::fromStdString(address), bitcoinAddress);
|
|
|
|
// merthod 3, use the static method: HDMasterPubkey::fromHDMaster()
|
|
auto mPubKey2 = HDMasterPubkey::fromHDMaster(mkey, derivation.toStdString());
|
|
QVERIFY(mPubKey2.isValid());
|
|
QCOMPARE(mPubKey2.chain(), HDMasterPubkey::MainChain);
|
|
QCOMPARE(mPubKey2.toString(), xpub);
|
|
|
|
derivedPubKey = mPubKey2.derive(derivation.toStdString());
|
|
QVERIFY(derivedPubKey.isValid());
|
|
id = derivedPubKey.getKeyId();
|
|
address = CashAddress::encodeCashAddr("bitcoincash",
|
|
{ CashAddress::PUBKEY_TYPE,
|
|
std::vector<uint8_t>(id.begin(), id.end())});
|
|
QCOMPARE(QString::fromStdString(address), bitcoinAddress);
|
|
}
|
|
|
|
void TestHDWallets::hdwallet_data()
|
|
{
|
|
QTest::addColumn<QString>("mnemonic"); // n-words of seed phrase.
|
|
QTest::addColumn<QString>("masterPrivKey");
|
|
QTest::addColumn<QString>("derivation");
|
|
QTest::addColumn<QString>("bitcoinAddress");
|
|
|
|
QTest::newRow("small-zero")
|
|
<< "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
|
<< "xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu"
|
|
<< "m/0'/0'/0" << "bitcoincash:qp8aaqjvjrujq3fk2hdwcy98pur8hsd2c5rvshznat";
|
|
QTest::newRow("south")
|
|
<< "south monkey fire corn link estate burger lucky bronze pet chapter lamp"
|
|
<< "xprv9s21ZrQH143K4TATPFMZLvCbsFigZdnRDvD2E9dftwgLWUcEWDmRJFi7MuKRSCUd3cFgcyzpvEfAupd3AhK5JJ8RGxDtnYH8vXjYNn1kTmR"
|
|
<< "m/44'/145'/0'/0/0" << "bitcoincash:qrg0jddykyfeal70xduvyeathd3ulhm7hv22m3t7na";
|
|
QTest::newRow("south 2")
|
|
<< "south monkey fire corn link estate burger lucky bronze pet chapter lamp"
|
|
<< "xprv9s21ZrQH143K4TATPFMZLvCbsFigZdnRDvD2E9dftwgLWUcEWDmRJFi7MuKRSCUd3cFgcyzpvEfAupd3AhK5JJ8RGxDtnYH8vXjYNn1kTmR"
|
|
<< "m/44'/145'/0'/0/10" << "bitcoincash:qpk93uwjdpw6aezz0sy0vpv3my4sm0ths55ydxed2n";
|
|
}
|