feather/src/utils/Seed.cpp

106 lines
3.4 KiB
C++
Raw Normal View History

2022-02-25 15:29:33 +00:00
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-FileCopyrightText: 2020-2022 The Monero Project
#include "Seed.h"
Seed::Seed(Type type, NetworkType::Type networkType, QString language)
: type(type), networkType(networkType), language(std::move(language))
{
// We only support the creation of Tevador-style seeds for now.
if (this->type != Type::TEVADOR) {
this->errorString = "Unsupported seed type";
return;
}
// We only support the creation of English language seeds for now.
if (this->language != "English") {
this->errorString = "Unsupported seed language";
return;
}
this->time = std::time(nullptr);
try {
monero_seed seed(this->time, constants::coinName);
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());
}
catch (const std::exception &e) {
this->errorString = QString::fromStdString(e.what());
return;
}
// Basic check against seed library implementation issues
if (m_insecureSeeds.contains(this->spendKey)) {
this->errorString = "Insecure spendkey";
return;
}
this->setRestoreHeight();
}
Seed::Seed(Type type, QStringList mnemonic, NetworkType::Type networkType)
: type(type), mnemonic(std::move(mnemonic)), networkType(networkType)
{
if (m_seedLength[this->type] != this->mnemonic.length()) {
this->errorString = "Invalid seed length";
return;
}
if (this->type == Type::POLYSEED) {
this->errorString = "Unsupported seed type";
return;
}
if (this->type == Type::TEVADOR) {
try {
monero_seed seed(this->mnemonic.join(" ").toStdString(), constants::coinName);
this->time = seed.date();
this->setRestoreHeight();
std::stringstream buffer;
buffer << seed.key();
this->spendKey = QString::fromStdString(buffer.str());
// Tevador style seeds have built-in error correction
// Any word can be replaced with 'xxxx' to recover the original word
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;
}
}
}
void Seed::setRestoreHeight(int height) {
auto now = std::time(nullptr);
auto nowClearance = 3600 * 24;
auto currentBlockHeight = appData()->restoreHeights[this->networkType]->dateToHeight(now - nowClearance);
if (height >= currentBlockHeight + nowClearance) {
qWarning() << "unrealistic restore height detected, setting to current blockheight instead: " << currentBlockHeight;
this->restoreHeight = currentBlockHeight;
} else {
this->restoreHeight = height;
}
}
void Seed::setRestoreHeight() {
// Ignore the embedded restore date, new wallets should sync from the current block height.
this->restoreHeight = appData()->restoreHeights[networkType]->dateToHeight(this->time);
}
Seed::Seed() = default;