Files
thehub/testing/utils/TestHDWallets.cpp
T

117 lines
5.2 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
auto mPubKeyTestnet = HDMasterPubkey::fromXPub(mkey.toXPubString(hardDerivPath, HDMasterKey::Testnet));
QVERIFY(mPubKeyTestnet.isValid());
QCOMPARE(mPubKeyTestnet.chain(), HDMasterPubkey::Testnet);
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";
}