mirror of
				https://git.wownero.com/wowlet/wowlet.git
				synced 2024-08-15 01:03:14 +00:00 
			
		
		
		
	FeatherSeed: allow erasure
This commit is contained in:
		
							parent
							
								
									a736f5f5c6
								
							
						
					
					
						commit
						aa3d674242
					
				
					 10 changed files with 231 additions and 192 deletions
				
			
		| 
						 | 
				
			
			@ -533,12 +533,21 @@ void AppContext::createWallet(FeatherSeed seed, const QString &path, const QStri
 | 
			
		|||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(seed.mnemonicSeed.isEmpty()) {
 | 
			
		||||
    if(seed.mnemonic.isEmpty()) {
 | 
			
		||||
        emit walletCreatedError("Mnemonic seed error. Failed to write wallet.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this->currentWallet = seed.writeWallet(this->walletManager, this->networkType, path, password, this->kdfRounds);
 | 
			
		||||
    Wallet *wallet = nullptr;
 | 
			
		||||
    if (seed.seedType == SeedType::TEVADOR) {
 | 
			
		||||
        wallet = this->walletManager->createDeterministicWalletFromSpendKey(path, password, seed.language, this->networkType, seed.spendKey, seed.restoreHeight, this->kdfRounds);
 | 
			
		||||
        wallet->setCacheAttribute("feather.seed", seed.mnemonic.join(" "));
 | 
			
		||||
    }
 | 
			
		||||
    if (seed.seedType == SeedType::MONERO) {
 | 
			
		||||
        wallet = this->walletManager->recoveryWallet(path, password, seed.mnemonic.join(" "), "", this->networkType, seed.restoreHeight, this->kdfRounds);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this->currentWallet = wallet;
 | 
			
		||||
    if(this->currentWallet == nullptr) {
 | 
			
		||||
        emit walletCreatedError("Failed to write wallet");
 | 
			
		||||
        return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,9 +17,10 @@
 | 
			
		|||
#include "utils/xmrig.h"
 | 
			
		||||
#include "utils/wsclient.h"
 | 
			
		||||
#include "utils/txfiathistory.h"
 | 
			
		||||
#include "utils/FeatherSeed.h"
 | 
			
		||||
#include "widgets/RedditPost.h"
 | 
			
		||||
#include "widgets/CCSEntry.h"
 | 
			
		||||
#include "utils/seeds.h"
 | 
			
		||||
#include "utils/RestoreHeightLookup.h"
 | 
			
		||||
#include "utils/nodes.h"
 | 
			
		||||
 | 
			
		||||
#include "libwalletqt/WalletManager.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
#include <QStandardItemModel>
 | 
			
		||||
#include <QAbstractButton>
 | 
			
		||||
 | 
			
		||||
#include "utils/seeds.h"
 | 
			
		||||
#include "utils/RestoreHeightLookup.h"
 | 
			
		||||
#include "appcontext.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										114
									
								
								src/utils/FeatherSeed.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/utils/FeatherSeed.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,114 @@
 | 
			
		|||
#ifndef FEATHER_FEATHERSEED_H
 | 
			
		||||
#define FEATHER_FEATHERSEED_H
 | 
			
		||||
 | 
			
		||||
#include "libwalletqt/WalletManager.h"
 | 
			
		||||
#include "libwalletqt/Wallet.h"
 | 
			
		||||
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include "RestoreHeightLookup.h"
 | 
			
		||||
 | 
			
		||||
enum SeedType {
 | 
			
		||||
    MONERO = 0, // 25 word seeds
 | 
			
		||||
    TEVADOR     // 14 word seeds
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct FeatherSeed {
 | 
			
		||||
    QString coin;
 | 
			
		||||
    QString language;
 | 
			
		||||
    SeedType seedType;
 | 
			
		||||
 | 
			
		||||
    QStringList mnemonic;
 | 
			
		||||
    QString spendKey;
 | 
			
		||||
    QString correction;
 | 
			
		||||
 | 
			
		||||
    time_t time;
 | 
			
		||||
    int restoreHeight = 0;
 | 
			
		||||
    RestoreHeightLookup *lookup = nullptr;
 | 
			
		||||
 | 
			
		||||
    QString errorString;
 | 
			
		||||
 | 
			
		||||
    explicit FeatherSeed(RestoreHeightLookup *lookup,
 | 
			
		||||
                          const QString &coin = "monero",
 | 
			
		||||
                          const QString &language = "English",
 | 
			
		||||
                          const QStringList &mnemonic = {})
 | 
			
		||||
            : lookup(lookup), coin(coin), language(language), mnemonic(mnemonic)
 | 
			
		||||
    {
 | 
			
		||||
        // Generate a new mnemonic if none was given
 | 
			
		||||
        if (mnemonic.length() == 0) {
 | 
			
		||||
            this->time = std::time(nullptr);
 | 
			
		||||
            monero_seed seed(this->time, coin.toStdString());
 | 
			
		||||
 | 
			
		||||
            std::stringstream buffer;
 | 
			
		||||
            buffer << seed;
 | 
			
		||||
            this->mnemonic = QString::fromStdString(buffer.str()).split(" ");
 | 
			
		||||
 | 
			
		||||
            buffer.str(std::string());
 | 
			
		||||
            buffer << seed.key();
 | 
			
		||||
            this->spendKey = QString::fromStdString(buffer.str());
 | 
			
		||||
 | 
			
		||||
            this->setRestoreHeight();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mnemonic.length() == 25) {
 | 
			
		||||
            this->seedType = SeedType::MONERO;
 | 
			
		||||
        }
 | 
			
		||||
        else if (mnemonic.length() == 14) {
 | 
			
		||||
            this->seedType = SeedType::TEVADOR;
 | 
			
		||||
        } else {
 | 
			
		||||
            this->errorString = "Mnemonic seed does not match known type";
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (seedType == SeedType::TEVADOR) {
 | 
			
		||||
            try {
 | 
			
		||||
                monero_seed seed(mnemonic.join(" ").toStdString(), coin.toStdString());
 | 
			
		||||
 | 
			
		||||
                this->time = seed.date();
 | 
			
		||||
                this->setRestoreHeight();
 | 
			
		||||
 | 
			
		||||
                std::stringstream buffer;
 | 
			
		||||
                buffer << seed.key();
 | 
			
		||||
                this->spendKey = QString::fromStdString(buffer.str());
 | 
			
		||||
 | 
			
		||||
                this->correction = QString::fromStdString(seed.correction());
 | 
			
		||||
                if (!this->correction.isEmpty()) {
 | 
			
		||||
                    buffer.str(std::string());
 | 
			
		||||
                    buffer << seed;
 | 
			
		||||
                    int index = this->mnemonic.indexOf("xxxx");
 | 
			
		||||
                    this->mnemonic.replace(index, this->correction);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (const std::exception &e) {
 | 
			
		||||
                this->errorString = e.what();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int setRestoreHeight() {
 | 
			
		||||
        if (this->lookup == nullptr)
 | 
			
		||||
            return 1;
 | 
			
		||||
 | 
			
		||||
        if (this->time == 0)
 | 
			
		||||
            return 1;
 | 
			
		||||
 | 
			
		||||
        this->restoreHeight = this->lookup->dateToRestoreHeight(this->time);
 | 
			
		||||
        return this->restoreHeight;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int setRestoreHeight(int height) {
 | 
			
		||||
        auto now = std::time(nullptr);
 | 
			
		||||
        auto nowClearance = 3600 * 24;
 | 
			
		||||
        auto currentBlockHeight = this->lookup->dateToRestoreHeight(now - nowClearance);
 | 
			
		||||
        if (height >= currentBlockHeight + nowClearance) {
 | 
			
		||||
            qCritical() << "unrealistic restore height detected, setting to current blockheight instead: " << currentBlockHeight;
 | 
			
		||||
            this->restoreHeight = currentBlockHeight;
 | 
			
		||||
        } else {
 | 
			
		||||
            this->restoreHeight = height;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this->restoreHeight;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_FEATHERSEED_H
 | 
			
		||||
							
								
								
									
										76
									
								
								src/utils/RestoreHeightLookup.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/utils/RestoreHeightLookup.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020-2021, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_RESTOREHEIGHTLOOKUP_H
 | 
			
		||||
#define FEATHER_RESTOREHEIGHTLOOKUP_H
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
 | 
			
		||||
#include <monero_seed/monero_seed.hpp>
 | 
			
		||||
 | 
			
		||||
#include "networktype.h"
 | 
			
		||||
#include "utils/utils.h"
 | 
			
		||||
 | 
			
		||||
struct RestoreHeightLookup {
 | 
			
		||||
    NetworkType::Type type;
 | 
			
		||||
    QMap<int, int> data;
 | 
			
		||||
    explicit RestoreHeightLookup(NetworkType::Type type) : type(type) {}
 | 
			
		||||
 | 
			
		||||
    int dateToRestoreHeight(int date) {
 | 
			
		||||
        // restore height based on a given timestamp using a lookup
 | 
			
		||||
        // table. If it cannot find the date in the lookup table, it
 | 
			
		||||
        // will calculate the blockheight based off the last known
 | 
			
		||||
        // date: ((now - lastKnownDate) / blockTime) - clearance
 | 
			
		||||
 | 
			
		||||
        if(this->type == NetworkType::TESTNET) return 1;
 | 
			
		||||
        int blockTime = 120;
 | 
			
		||||
        int blocksPerDay = 86400 / blockTime;
 | 
			
		||||
        int blockCalcClearance = blocksPerDay * 5;
 | 
			
		||||
        QList<int> values = this->data.keys();
 | 
			
		||||
        if(date <= values.at(0))
 | 
			
		||||
            return this->data[values.at(0)];
 | 
			
		||||
        for(int i = 0; i != values.count(); i++) {
 | 
			
		||||
            if(values[i] > date) {
 | 
			
		||||
                return i - 1 < 0 ? this->data[values[i]] : this->data[values[i-1]] - blockCalcClearance;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // lookup failed, calculate blockheight from last known checkpoint
 | 
			
		||||
        int lastBlockHeightTime = values.at(values.count() - 1);
 | 
			
		||||
        int lastBlockHeight = this->data[lastBlockHeightTime];
 | 
			
		||||
        int deltaTime = date - lastBlockHeightTime;
 | 
			
		||||
        int deltaBlocks = deltaTime / blockTime;
 | 
			
		||||
        int blockHeight = (lastBlockHeight + deltaBlocks) - blockCalcClearance;
 | 
			
		||||
        qDebug() << "Calculated blockheight: " << blockHeight << " from epoch " << date;
 | 
			
		||||
        return blockHeight;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int restoreHeightToDate(int height) {
 | 
			
		||||
        // @TODO: most likely inefficient, refactor
 | 
			
		||||
        QMap<int, int>::iterator i;
 | 
			
		||||
        int timestamp = 0;
 | 
			
		||||
        for (i = this->data.begin(); i != this->data.end(); ++i) {
 | 
			
		||||
            int ts = i.key();
 | 
			
		||||
            if (i.value() > height)
 | 
			
		||||
                return timestamp;
 | 
			
		||||
            timestamp = ts;
 | 
			
		||||
        }
 | 
			
		||||
        return timestamp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static RestoreHeightLookup *fromFile(const QString &fn, NetworkType::Type type) {
 | 
			
		||||
        // initialize this class using a lookup table, e.g `:/assets/restore_heights_monero_mainnet.txt`/
 | 
			
		||||
        auto rtn = new RestoreHeightLookup(type);
 | 
			
		||||
        auto data = Utils::barrayToString(Utils::fileOpen(fn));
 | 
			
		||||
        QMap<int, int> _data;
 | 
			
		||||
        for(const auto &line: data.split('\n')) {
 | 
			
		||||
            if(line.trimmed().isEmpty()) continue;
 | 
			
		||||
            auto spl = line.trimmed().split(':');
 | 
			
		||||
            rtn->data[spl.at(0).toUInt()] = spl.at(1).toUInt();
 | 
			
		||||
        }
 | 
			
		||||
        return rtn;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_RESTOREHEIGHTLOOKUP_H
 | 
			
		||||
| 
						 | 
				
			
			@ -1,168 +0,0 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020-2021, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_SEEDS_H
 | 
			
		||||
#define FEATHER_SEEDS_H
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
#include <monero_seed/monero_seed.hpp>
 | 
			
		||||
 | 
			
		||||
#include "networktype.h"
 | 
			
		||||
#include "libwalletqt/WalletManager.h"
 | 
			
		||||
#include "libwalletqt/Wallet.h"
 | 
			
		||||
#include "utils/utils.h"
 | 
			
		||||
 | 
			
		||||
struct RestoreHeightLookup {
 | 
			
		||||
    NetworkType::Type type;
 | 
			
		||||
    QMap<int, int> data;
 | 
			
		||||
    explicit RestoreHeightLookup(NetworkType::Type type) : type(type) {}
 | 
			
		||||
 | 
			
		||||
    int dateToRestoreHeight(int date) {
 | 
			
		||||
        // restore height based on a given timestamp using a lookup
 | 
			
		||||
        // table. If it cannot find the date in the lookup table, it
 | 
			
		||||
        // will calculate the blockheight based off the last known
 | 
			
		||||
        // date: ((now - lastKnownDate) / blockTime) - clearance
 | 
			
		||||
 | 
			
		||||
        if(this->type == NetworkType::TESTNET) return 1;
 | 
			
		||||
        int blockTime = 120;
 | 
			
		||||
        int blocksPerDay = 86400 / blockTime;
 | 
			
		||||
        int blockCalcClearance = blocksPerDay * 5;
 | 
			
		||||
        QList<int> values = this->data.keys();
 | 
			
		||||
        if(date <= values.at(0))
 | 
			
		||||
            return this->data[values.at(0)];
 | 
			
		||||
        for(int i = 0; i != values.count(); i++) {
 | 
			
		||||
            if(values[i] > date) {
 | 
			
		||||
                return i - 1 < 0 ? this->data[values[i]] : this->data[values[i-1]] - blockCalcClearance;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // lookup failed, calculate blockheight from last known checkpoint
 | 
			
		||||
        int lastBlockHeightTime = values.at(values.count() - 1);
 | 
			
		||||
        int lastBlockHeight = this->data[lastBlockHeightTime];
 | 
			
		||||
        int deltaTime = date - lastBlockHeightTime;
 | 
			
		||||
        int deltaBlocks = deltaTime / blockTime;
 | 
			
		||||
        int blockHeight = (lastBlockHeight + deltaBlocks) - blockCalcClearance;
 | 
			
		||||
        qDebug() << "Calculated blockheight: " << blockHeight << " from epoch " << date;
 | 
			
		||||
        return blockHeight;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int restoreHeightToDate(int height) {
 | 
			
		||||
        // @TODO: most likely inefficient, refactor
 | 
			
		||||
        QMap<int, int>::iterator i;
 | 
			
		||||
        int timestamp = 0;
 | 
			
		||||
        for (i = this->data.begin(); i != this->data.end(); ++i) {
 | 
			
		||||
            int ts = i.key();
 | 
			
		||||
            if (i.value() > height)
 | 
			
		||||
                return timestamp;
 | 
			
		||||
            timestamp = ts;
 | 
			
		||||
        }
 | 
			
		||||
        return timestamp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static RestoreHeightLookup *fromFile(const QString &fn, NetworkType::Type type) {
 | 
			
		||||
        // initialize this class using a lookup table, e.g `:/assets/restore_heights_monero_mainnet.txt`/
 | 
			
		||||
        auto rtn = new RestoreHeightLookup(type);
 | 
			
		||||
        auto data = Utils::barrayToString(Utils::fileOpen(fn));
 | 
			
		||||
        QMap<int, int> _data;
 | 
			
		||||
        for(const auto &line: data.split('\n')) {
 | 
			
		||||
            if(line.trimmed().isEmpty()) continue;
 | 
			
		||||
            auto spl = line.trimmed().split(':');
 | 
			
		||||
            rtn->data[spl.at(0).toUInt()] = spl.at(1).toUInt();
 | 
			
		||||
        }
 | 
			
		||||
        return rtn;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct FeatherSeed {
 | 
			
		||||
    QString mnemonicSeed;
 | 
			
		||||
    QString spendKey;
 | 
			
		||||
    time_t time = 0;
 | 
			
		||||
    int restoreHeight = 0;
 | 
			
		||||
    RestoreHeightLookup *lookup = nullptr;
 | 
			
		||||
    QString language;
 | 
			
		||||
    std::string coinName;
 | 
			
		||||
    explicit FeatherSeed(RestoreHeightLookup *lookup, const std::string &coinName = "monero", const QString &language = "English") : lookup(lookup), coinName(coinName), language(language) {}
 | 
			
		||||
 | 
			
		||||
    static FeatherSeed fromSeed(RestoreHeightLookup *lookup,
 | 
			
		||||
                                const std::string &coinName,
 | 
			
		||||
                                const QString &seedLanguage,
 | 
			
		||||
                                const std::string &mnemonicSeed) {
 | 
			
		||||
 | 
			
		||||
        auto rtn = FeatherSeed(lookup, coinName, seedLanguage);
 | 
			
		||||
        rtn.lookup = lookup;
 | 
			
		||||
        rtn.mnemonicSeed = QString::fromStdString(mnemonicSeed);
 | 
			
		||||
 | 
			
		||||
        if(QString::fromStdString(mnemonicSeed).split(" ").count() == 14) {
 | 
			
		||||
            monero_seed seed(mnemonicSeed, coinName);
 | 
			
		||||
            std::stringstream buffer;
 | 
			
		||||
            buffer << seed.key();
 | 
			
		||||
            rtn.time = seed.date();
 | 
			
		||||
            rtn.setRestoreHeight();
 | 
			
		||||
            rtn.spendKey = QString::fromStdString(buffer.str());
 | 
			
		||||
        }
 | 
			
		||||
        return rtn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static FeatherSeed generate(RestoreHeightLookup *lookup, const std::string &coinName, const QString &language) {
 | 
			
		||||
        auto rtn = FeatherSeed(lookup, coinName, language);
 | 
			
		||||
        time_t _time = std::time(nullptr);
 | 
			
		||||
        monero_seed seed(_time, coinName);
 | 
			
		||||
 | 
			
		||||
        std::stringstream buffer;
 | 
			
		||||
        buffer << seed;
 | 
			
		||||
        rtn.mnemonicSeed = QString::fromStdString(buffer.str());
 | 
			
		||||
        buffer.str(std::string());
 | 
			
		||||
        buffer << seed.key();
 | 
			
		||||
        rtn.spendKey = QString::fromStdString(buffer.str());
 | 
			
		||||
        rtn.time = _time;
 | 
			
		||||
        rtn.setRestoreHeight();
 | 
			
		||||
        return rtn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Wallet *writeWallet(WalletManager *manager, NetworkType::Type type, const QString &path, const QString &password, quint64 kdfRounds) {
 | 
			
		||||
        // writes both 14/25 word mnemonic seeds.
 | 
			
		||||
        Wallet *wallet = nullptr;
 | 
			
		||||
        if(this->lookup == nullptr) return wallet;
 | 
			
		||||
        if(this->mnemonicSeed.split(" ").count() == 14) {
 | 
			
		||||
            if(this->spendKey.isEmpty()) {
 | 
			
		||||
                auto _seed = FeatherSeed::fromSeed(this->lookup, this->coinName, this->language, this->mnemonicSeed.toStdString());
 | 
			
		||||
                _seed.setRestoreHeight();
 | 
			
		||||
                this->time = _seed.time;
 | 
			
		||||
                this->restoreHeight = _seed.restoreHeight;
 | 
			
		||||
                this->spendKey = _seed.spendKey;
 | 
			
		||||
            }
 | 
			
		||||
            wallet = manager->createDeterministicWalletFromSpendKey(path, password, this->language, type, this->spendKey, this->restoreHeight, kdfRounds);
 | 
			
		||||
            wallet->setCacheAttribute("feather.seed", this->mnemonicSeed);
 | 
			
		||||
        } else {
 | 
			
		||||
            wallet = manager->recoveryWallet(path, password, this->mnemonicSeed, "", type, this->restoreHeight, kdfRounds);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        wallet->setPassword(password);
 | 
			
		||||
        return wallet;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int setRestoreHeight() {
 | 
			
		||||
        if(this->lookup == nullptr) return 1;
 | 
			
		||||
        if(this->time == 0) return 1;
 | 
			
		||||
        this->restoreHeight = this->lookup->dateToRestoreHeight(this->time);
 | 
			
		||||
        return this->restoreHeight;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int setRestoreHeight(int height) {
 | 
			
		||||
        auto now = std::time(nullptr);
 | 
			
		||||
        auto nowClearance = 3600 * 24;
 | 
			
		||||
        auto currentBlockHeight = this->lookup->dateToRestoreHeight(now - nowClearance);
 | 
			
		||||
        if(height >= currentBlockHeight + nowClearance) {
 | 
			
		||||
            qCritical() << "unrealistic restore height detected, setting to current blockheight instead: " << currentBlockHeight;
 | 
			
		||||
            this->restoreHeight = currentBlockHeight;
 | 
			
		||||
        } else
 | 
			
		||||
            this->restoreHeight = height;
 | 
			
		||||
 | 
			
		||||
        return this->restoreHeight;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_SEEDS_H
 | 
			
		||||
| 
						 | 
				
			
			@ -34,8 +34,8 @@ CreateWalletSeedPage::CreateWalletSeedPage(AppContext *ctx, QWidget *parent) :
 | 
			
		|||
void CreateWalletSeedPage::seedRoulette(int count) {
 | 
			
		||||
    count += 1;
 | 
			
		||||
    if(count > m_rouletteSpin) return;
 | 
			
		||||
    auto seed = FeatherSeed::generate(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage);
 | 
			
		||||
    m_mnemonic = seed.mnemonicSeed;
 | 
			
		||||
    FeatherSeed seed = FeatherSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName, m_ctx->seedLanguage);
 | 
			
		||||
    m_mnemonic = seed.mnemonic.join(" ");
 | 
			
		||||
    m_restoreHeight = seed.restoreHeight;
 | 
			
		||||
 | 
			
		||||
    this->displaySeed(m_mnemonic);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,8 +7,10 @@
 | 
			
		|||
 | 
			
		||||
#include <QLineEdit>
 | 
			
		||||
#include <QPlainTextEdit>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
#include <monero_seed/wordlist.hpp>  // tevador 14 word
 | 
			
		||||
#include "utils/FeatherSeed.h"
 | 
			
		||||
 | 
			
		||||
RestorePage::RestorePage(AppContext *ctx, QWidget *parent) :
 | 
			
		||||
        QWizardPage(parent),
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +31,10 @@ RestorePage::RestorePage(AppContext *ctx, QWidget *parent) :
 | 
			
		|||
    for(int i = 0; i != 2048; i++)
 | 
			
		||||
        m_words14 << QString::fromStdString(wordlist::english.get_word(i));
 | 
			
		||||
 | 
			
		||||
    // Restore has limited error correction capability, namely it can correct a single erasure
 | 
			
		||||
    // (illegible word with a known location). This can be tested by replacing a word with xxxx
 | 
			
		||||
    m_words14 << "xxxx";
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    m_completer14Model = new QStringListModel(m_words14, m_completer14);
 | 
			
		||||
    m_completer14 = new QCompleter(this);
 | 
			
		||||
| 
						 | 
				
			
			@ -127,13 +133,6 @@ bool RestorePage::validatePage() {
 | 
			
		|||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto _seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage, seed.toStdString());
 | 
			
		||||
        restoreHeight = _seed.restoreHeight;
 | 
			
		||||
 | 
			
		||||
        this->setField("restoreHeight", restoreHeight);
 | 
			
		||||
        this->setField("mnemonicRestoredSeed", seed);
 | 
			
		||||
        return true;
 | 
			
		||||
    } else if(m_mode == 25) {
 | 
			
		||||
        if(seedSplit.length() != 25) {
 | 
			
		||||
            ui->label_errorString->show();
 | 
			
		||||
| 
						 | 
				
			
			@ -150,15 +149,22 @@ bool RestorePage::validatePage() {
 | 
			
		|||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto _seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage, seed.toStdString());
 | 
			
		||||
        _seed.setRestoreHeight(restoreHeight);
 | 
			
		||||
        this->setField("restoreHeight", restoreHeight);
 | 
			
		||||
        this->setField("mnemonicSeed", seed);
 | 
			
		||||
        this->setField("mnemonicRestoredSeed", seed);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ui->seedEdit->setStyleSheet(errStyle);
 | 
			
		||||
    return false;
 | 
			
		||||
    auto _seed = FeatherSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName, m_ctx->seedLanguage, seedSplit);
 | 
			
		||||
    if (!_seed.errorString.isEmpty()) {
 | 
			
		||||
        QMessageBox::warning(this, "Invalid seed", QString("Invalid seed:\n\n%1").arg(_seed.errorString));
 | 
			
		||||
        ui->seedEdit->setStyleSheet(errStyle);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (!_seed.correction.isEmpty()) {
 | 
			
		||||
        QMessageBox::information(this, "Corrected erasure", QString("xxxx -> %1").arg(_seed.correction));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    restoreHeight = _seed.restoreHeight;
 | 
			
		||||
 | 
			
		||||
    this->setField("restoreHeight", restoreHeight);
 | 
			
		||||
    this->setField("mnemonicSeed", seed);
 | 
			
		||||
    this->setField("mnemonicRestoredSeed", seed);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,7 +80,8 @@ void WalletWizard::createWallet() {
 | 
			
		|||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage, mnemonicSeed.toStdString());
 | 
			
		||||
    auto seed = FeatherSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName, m_ctx->seedLanguage, mnemonicSeed.split(" "));
 | 
			
		||||
 | 
			
		||||
    if(restoreHeight > 0)
 | 
			
		||||
        seed.setRestoreHeight(restoreHeight);
 | 
			
		||||
    m_ctx->createWallet(seed, walletPath, walletPasswd);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@
 | 
			
		|||
#include <QRadioButton>
 | 
			
		||||
 | 
			
		||||
#include "appcontext.h"
 | 
			
		||||
#include "utils/seeds.h"
 | 
			
		||||
#include "utils/RestoreHeightLookup.h"
 | 
			
		||||
#include "utils/config.h"
 | 
			
		||||
 | 
			
		||||
class WalletWizard : public QWizard
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue