# Tevador 14 word Monero seed
add_subdirectory(contrib/monero-seed)
+# Polyseed 16 word mnemonic seeds
+find_path(POLYSEED_INCLUDE_DIR polyseed.h)
+message(STATUS "POLYSEED PATH ${POLYSEED_INCLUDE_DIR}")
+
+find_library(POLYSEED_LIBRARY polyseed)
+message(STATUS "POLYSEED LIBARY ${POLYSEED_LIBRARY}")
+
# libzip
find_package(zlib CONFIG)
find_path(LIBZIP_INCLUDE_DIRS zip.h)
./configure --enable-static --disable-shared --without-imagemagick --with-gtk=no --with-python=no --enable-doc=no && \
make -j$THREADS && \
make install && \
+ rm -rf $(pwd)
+
+# polyseed: Required for Feather
+RUN git clone https://github.com/tevador/polyseed.git && \
+ cd polyseed && \
+ git reset --hard 4945d8239d6b26dc12723ca2aaa9f8110ceff5af && \
+ mkdir build && \
+ cd build && \
+ cmake .. && \
+ make && \
+ make install && \
+ rm /usr/local/lib/libpolyseed.so* && \
rm -rf $(pwd)
\ No newline at end of file
"qrcode/*.cpp"
"dialog/*.h"
"dialog/*.cpp"
+ "polyseed/*.h"
+ "polyseed/*.cpp"
+ "polyseed/*.c"
"qrcode_scanner/QrCodeUtils.cpp"
"qrcode_scanner/QrCodeUtils.h"
)
${ZLIB_INCLUDE_DIRS}
${LIBZIP_INCLUDE_DIRS}
${ZBAR_INCLUDE_DIR}
+ ${POLYSEED_INCLUDE_DIR}
)
if(WITH_SCANNER)
${ZLIB_LIBRARIES}
${LIBZIP_LIBRARIES}
${ZBAR_LIBRARIES}
+ ${POLYSEED_LIBRARY}
SingleApplication::SingleApplication
)
}
Wallet *wallet = nullptr;
- if (seed.type == Seed::Type::TEVADOR) {
+ if (seed.type == Seed::Type::POLYSEED || seed.type == Seed::Type::TEVADOR) {
wallet = m_walletManager->createDeterministicWalletFromSpendKey(path, password, seed.language, constants::networkType, seed.spendKey, seed.restoreHeight, constants::kdfRounds, seedOffset);
wallet->setCacheAttribute("feather.seed", seed.mnemonic.join(" "));
wallet->setCacheAttribute("feather.seedoffset", seedOffset);
}
- if (seed.type == Seed::Type::MONERO) {
+ else if (seed.type == Seed::Type::MONERO) {
wallet = m_walletManager->recoveryWallet(path, password, seed.mnemonic.join(" "), seedOffset, constants::networkType, seed.restoreHeight, constants::kdfRounds);
}
--- /dev/null
+/*
+ * Copyright 2005,2007,2009 Colin Percival
+ * Copyright 2021 tevador <tevador@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#include <sodium/crypto_auth_hmacsha256.h>
+#include <sodium/utils.h>
+
+static inline void
+store32_be(uint8_t dst[4], uint32_t w)
+{
+ dst[3] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[0] = (uint8_t) w;
+}
+
+void
+crypto_pbkdf2_sha256(const uint8_t* passwd, size_t passwdlen,
+ const uint8_t* salt, size_t saltlen, uint64_t c,
+ uint8_t* buf, size_t dkLen)
+{
+ crypto_auth_hmacsha256_state Phctx, PShctx, hctx;
+ size_t i;
+ uint8_t ivec[4];
+ uint8_t U[32];
+ uint8_t T[32];
+ uint64_t j;
+ int k;
+ size_t clen;
+
+ crypto_auth_hmacsha256_init(&Phctx, passwd, passwdlen);
+ PShctx = Phctx;
+ crypto_auth_hmacsha256_update(&PShctx, salt, saltlen);
+
+ for (i = 0; i * 32 < dkLen; i++) {
+ store32_be(ivec, (uint32_t)(i + 1));
+ hctx = PShctx;
+ crypto_auth_hmacsha256_update(&hctx, ivec, 4);
+ crypto_auth_hmacsha256_final(&hctx, U);
+
+ memcpy(T, U, 32);
+ for (j = 2; j <= c; j++) {
+ hctx = Phctx;
+ crypto_auth_hmacsha256_update(&hctx, U, 32);
+ crypto_auth_hmacsha256_final(&hctx, U);
+
+ for (k = 0; k < 32; k++) {
+ T[k] ^= U[k];
+ }
+ }
+
+ clen = dkLen - i * 32;
+ if (clen > 32) {
+ clen = 32;
+ }
+ memcpy(&buf[i * 32], T, clen);
+ }
+ sodium_memzero((void*)&Phctx, sizeof Phctx);
+ sodium_memzero((void*)&PShctx, sizeof PShctx);
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2021 tevador <tevador@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef PBKDF2_H
+#define PBKDF2_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+crypto_pbkdf2_sha256(const uint8_t* passwd, size_t passwdlen,
+ const uint8_t* salt, size_t saltlen, uint64_t c,
+ uint8_t* buf, size_t dkLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2021 tevador <tevador@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "polyseed.h"
+#include "pbkdf2.h"
+
+#include <sodium/core.h>
+#include <sodium/utils.h>
+#include <sodium/randombytes.h>
+#include <boost/locale.hpp>
+
+#include <cstdint>
+#include <cstring>
+#include <algorithm>
+#include <array>
+
+namespace polyseed {
+
+ static std::locale locale;
+
+ static size_t utf8_nfc(const char* str, polyseed_str norm) {
+ auto s = boost::locale::normalize(str, boost::locale::norm_type::norm_nfc, locale);
+ size_t size = std::min(s.size(), (size_t)POLYSEED_STR_SIZE - 1);
+ s.copy(norm, size);
+ norm[size] = '\0';
+ sodium_memzero(&s[0], s.size());
+ return size;
+ }
+
+ static size_t utf8_nfkd(const char* str, polyseed_str norm) {
+ auto s = boost::locale::normalize(str, boost::locale::norm_type::norm_nfkd, locale);
+ size_t size = std::min(s.size(), (size_t)POLYSEED_STR_SIZE - 1);
+ s.copy(norm, size);
+ norm[size] = '\0';
+ sodium_memzero(&s[0], s.size());
+ return size;
+ }
+
+ struct dependency {
+ dependency();
+ std::vector<language> languages;
+ };
+
+ static dependency deps;
+
+ dependency::dependency() {
+ if (sodium_init() == -1) {
+ throw std::runtime_error("sodium_init failed");
+ }
+
+ boost::locale::generator gen;
+ gen.locale_cache_enabled(true);
+ locale = gen("");
+
+ polyseed_dependency pd;
+ pd.randbytes = &randombytes_buf;
+ pd.pbkdf2_sha256 = &crypto_pbkdf2_sha256;
+ pd.memzero = &sodium_memzero;
+ pd.u8_nfc = &utf8_nfc;
+ pd.u8_nfkd = &utf8_nfkd;
+ pd.time = nullptr;
+ pd.alloc = nullptr;
+ pd.free = nullptr;
+
+ polyseed_inject(&pd);
+
+ for (int i = 0; i < polyseed_get_num_langs(); ++i) {
+ languages.push_back(language(polyseed_get_lang(i)));
+ }
+ }
+
+ static language invalid_lang;
+
+ const std::vector<language>& get_langs() {
+ return deps.languages;
+ }
+
+ const language& get_lang_by_name(const std::string& name) {
+ for (auto& lang : deps.languages) {
+ if (name == lang.name_en()) {
+ return lang;
+ }
+ if (name == lang.name()) {
+ return lang;
+ }
+ }
+ return invalid_lang;
+ }
+
+ inline void data::check_init() const {
+ if (valid()) {
+ throw std::runtime_error("already initialized");
+ }
+ }
+
+ static std::array<const char*, 7> error_desc = {
+ "Success",
+ "Wrong number of words in the phrase",
+ "Unknown language or unsupported words",
+ "Checksum mismatch",
+ "Unsupported seed features",
+ "Invalid seed format",
+ "Memory allocation failure",
+ };
+
+ static error get_error(polyseed_status status) {
+ if (status > 0 && status < sizeof(error_desc) / sizeof(const char*)) {
+ return error(error_desc[(int)status], status);
+ }
+ return error("Unknown error", status);
+ }
+
+ void data::create(feature_type features) {
+ check_init();
+ auto status = polyseed_create(features, &m_data);
+ if (status != POLYSEED_OK) {
+ throw get_error(status);
+ }
+ }
+
+ void data::load(polyseed_storage storage) {
+ check_init();
+ auto status = polyseed_load(storage, &m_data);
+ if (status != POLYSEED_OK) {
+ throw get_error(status);
+ }
+ }
+
+ language data::decode(const char* phrase) {
+ check_init();
+ const polyseed_lang* lang;
+ auto status = polyseed_decode(phrase, m_coin, &lang, &m_data);
+ if (status != POLYSEED_OK) {
+ throw get_error(status);
+ }
+ return language(lang);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2021 tevador <tevador@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <polyseed.h>
+#include <vector>
+#include <stdexcept>
+#include <string>
+
+namespace polyseed {
+
+ class data;
+
+ class language {
+ public:
+ language() : m_lang(nullptr) {}
+ language(const language&) = default;
+ language(const polyseed_lang* lang) : m_lang(lang) {}
+ const char* name() const {
+ return polyseed_get_lang_name(m_lang);
+ }
+ const char* name_en() const {
+ return polyseed_get_lang_name_en(m_lang);
+ }
+ bool valid() const {
+ return m_lang != nullptr;
+ }
+ private:
+ const polyseed_lang* m_lang;
+
+ friend class data;
+ };
+
+ const std::vector<language>& get_langs();
+ const language& get_lang_by_name(const std::string& name);
+
+ class error : public std::runtime_error {
+ public:
+ error(const char* msg, polyseed_status status)
+ : std::runtime_error(msg), m_status(status)
+ {
+ }
+ polyseed_status status() const {
+ return m_status;
+ }
+ private:
+ polyseed_status m_status;
+ };
+
+ using feature_type = unsigned int;
+
+ inline int enable_features(feature_type features) {
+ return polyseed_enable_features(features);
+ }
+
+ class data {
+ public:
+ data(const data&) = delete;
+ data(polyseed_coin coin) : m_data(nullptr), m_coin(coin) {}
+ ~data() {
+ polyseed_free(m_data);
+ }
+
+ void create(feature_type features);
+
+ void load(polyseed_storage storage);
+
+ language decode(const char* phrase);
+
+ template<class str_type>
+ void encode(const language& lang, str_type& str) const {
+ check_valid();
+ if (!lang.valid()) {
+ throw std::runtime_error("invalid language");
+ }
+ str.resize(POLYSEED_STR_SIZE);
+ auto size = polyseed_encode(m_data, lang.m_lang, m_coin, &str[0]);
+ str.resize(size);
+ }
+
+ void save(polyseed_storage storage) const {
+ check_valid();
+ polyseed_store(m_data, storage);
+ }
+
+ void crypt(const char* password) {
+ check_valid();
+ polyseed_crypt(m_data, password);
+ }
+
+ void keygen(void* ptr, size_t key_size) const {
+ check_valid();
+ polyseed_keygen(m_data, m_coin, key_size, (uint8_t*)ptr);
+ }
+
+ bool valid() const {
+ return m_data != nullptr;
+ }
+
+ bool encrypted() const {
+ check_valid();
+ return polyseed_is_encrypted(m_data);
+ }
+
+ uint64_t birthday() const {
+ check_valid();
+ return polyseed_get_birthday(m_data);
+ }
+
+ bool has_feature(feature_type feature) const {
+ check_valid();
+ return polyseed_get_feature(m_data, feature) != 0;
+ }
+ private:
+ void check_valid() const {
+ if (m_data == nullptr) {
+ throw std::runtime_error("invalid object");
+ }
+ }
+ void check_init() const;
+
+ polyseed_data* m_data;
+ polyseed_coin m_coin;
+ };
+}
\ No newline at end of file
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-FileCopyrightText: 2020-2022 The Monero Project
+#include <iomanip>
#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) {
+ // We only support the creation of Polyseeds
+ if (this->type != Type::POLYSEED) {
this->errorString = "Unsupported seed type";
return;
}
this->time = std::time(nullptr);
try {
- monero_seed seed(this->time, constants::coinName);
+ polyseed::data seed(POLYSEED_MONERO);
+ seed.create(0);
- std::stringstream buffer;
- buffer << seed;
- this->mnemonic = QString::fromStdString(buffer.str()).split(" ");
+ uint8_t key[32];
+ seed.keygen(&key, sizeof(key));
- buffer.str(std::string());
- buffer << seed.key();
- this->spendKey = QString::fromStdString(buffer.str());
+ std::stringstream keyStream;
+ for (unsigned char i : key) {
+ keyStream << std::hex << std::setfill('0') << std::setw(2) << (int)i;
+ }
+
+ std::string phrase;
+ seed.encode(polyseed::get_lang_by_name("English"), phrase);
+
+ this->mnemonic = QString::fromStdString(phrase).split(" ");
+ this->spendKey = QString::fromStdString(keyStream.str());
}
catch (const std::exception &e) {
this->errorString = QString::fromStdString(e.what());
}
if (this->type == Type::POLYSEED) {
- this->errorString = "Unsupported seed type";
- return;
+ try {
+ polyseed::data seed(POLYSEED_MONERO);
+ auto lang = seed.decode(this->mnemonic.join(" ").toStdString().c_str());
+
+ uint8_t key[32];
+ seed.keygen(&key, sizeof(key));
+
+ std::stringstream keyStream;
+ for (unsigned char i : key) {
+ keyStream << std::hex << std::setfill('0') << std::setw(2) << (int)i;
+ }
+ this->spendKey = QString::fromStdString(keyStream.str());
+
+ this->time = seed.birthday();
+ this->setRestoreHeight();
+ }
+ catch (const std::exception &e) {
+ this->errorString = e.what();
+ return;
+ }
}
if (this->type == Type::TEVADOR) {
#include "constants.h"
#include "libwalletqt/Wallet.h"
#include "monero_seed/monero_seed.hpp"
+#include "polyseed/polyseed.h"
#include "utils/AppData.h"
#include <QString>
// (illegible word with a known location). This can be tested by replacing a word with xxxx
bip39English << "xxxx";
+ m_polyseed.length = 16;
+ m_polyseed.setWords(bip39English);
+
m_tevador.length = 14;
m_tevador.setWords(bip39English);
}
void PageWalletRestoreSeed::onSeedTypeToggled() {
+ if (ui->radio16->isChecked()) {
+ m_mode = &m_polyseed;
+ m_fields->seedType = Seed::Type::POLYSEED;
+ ui->seedEdit->setPlaceholderText("Enter 16 word seed..");
+ ui->group_seedLanguage->hide();
+ }
if (ui->radio14->isChecked()) {
m_mode = &m_tevador;
m_fields->seedType = Seed::Type::TEVADOR;
}
}
- Seed _seed = Seed(m_mode->length == 14 ? Seed::Type::TEVADOR : Seed::Type::MONERO, seedSplit, constants::networkType);
+ Seed _seed = Seed(m_fields->seedType, seedSplit, constants::networkType);
if (!_seed.errorString.isEmpty()) {
QMessageBox::warning(this, "Invalid seed", QString("Invalid seed:\n\n%1").arg(_seed.errorString));
Ui::PageWalletRestoreSeed *ui;
WizardFields *m_fields;
+ seedType m_polyseed;
seedType m_tevador;
seedType m_legacy;
<property name="text">
<string>14 word mnemonic seed</string>
</property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">seedBtnGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radio16">
+ <property name="text">
+ <string>16 word mnemonic seed (Polyseed)</string>
+ </property>
<property name="checked">
<bool>true</bool>
</property>
QPixmap warningIcon = QPixmap(":/assets/images/warning.png");
ui->warningIcon->setPixmap(warningIcon.scaledToWidth(32, Qt::SmoothTransformation));
+ QPixmap infoIcon = QPixmap(":/assets/images/info2.svg");
+ ui->newSeedWarningIcon->setPixmap(infoIcon.scaledToWidth(32, Qt::SmoothTransformation));
+
QPixmap pixmap = QPixmap(":/assets/images/seed.png");
ui->seedIcon->setPixmap(pixmap.scaledToWidth(32, Qt::SmoothTransformation));
- ui->seedWord2->setHelpText("In addition to the private spend key, Tevador's 14 word seed scheme also encodes the "
- "restore date, cryptocurrency type, and reserves a few bits for future use. "
- "The second word is static because the reserved bits remain the same for each seed generation.");
-
connect(ui->btnRoulette, &QPushButton::clicked, [=]{
this->seedRoulette(0);
});
void PageWalletSeed::generateSeed() {
QString mnemonic;
- do {
- m_seed = Seed(Seed::Type::TEVADOR);
- mnemonic = m_seed.mnemonic.join(" ");
- m_restoreHeight = m_seed.restoreHeight;
- } while (mnemonic.split(" ").length() != 14); // https://github.com/tevador/monero-seed/issues/2
+
+ m_seed = Seed(Seed::Type::POLYSEED);
+ mnemonic = m_seed.mnemonic.join(" ");
+ m_restoreHeight = m_seed.restoreHeight;
this->displaySeed(mnemonic);
ui->seedWord12->setText(seedSplit[11]);
ui->seedWord13->setText(seedSplit[12]);
ui->seedWord14->setText(seedSplit[13]);
+ ui->seedWord15->setText(seedSplit[14]);
+ ui->seedWord16->setText(seedSplit[15]);
}
int PageWalletSeed::nextId() const {
<rect>
<x>0</x>
<y>0</y>
- <width>877</width>
- <height>625</height>
+ <width>654</width>
+ <height>594</height>
</rect>
</property>
<property name="windowTitle">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
- <string>Store your 14-word wallet seed in a safe location.</string>
+ <string><html><head/><body><p>Store your <span style=" font-weight:600;">16-word</span> seed in a safe location.</p></body></html></string>
</property>
<property name="wordWrap">
<bool>true</bool>
</layout>
</widget>
</item>
+ <item>
+ <widget class="QFrame" name="frame_18">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_20">
+ <item>
+ <widget class="QLabel" name="newSeedWarningIcon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>icon</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>5</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_9">
+ <item>
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string><html><head/><body><p>Feather recently switched to a new seed scheme called <span style=" font-weight:600;">Polyseed</span>.</p></body></html></string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>Please take note that mnemonic seeds now consist of 16 words instead of 14.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>For more information visit: docs.featherwallet.org/guides/seed-scheme</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item>
<widget class="QFrame" name="frame_invalidSeed">
<property name="frameShape">
</widget>
</item>
<item>
- <widget class="QFrame" name="frame_13">
+ <widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_11">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_27">
+ <widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>4.</string>
+ <string>5.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord4">
+ <widget class="QLabel" name="seedWord5">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
- <widget class="QFrame" name="frame_11">
+ <widget class="QFrame" name="frame_5">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_9">
+ <layout class="QHBoxLayout" name="horizontalLayout_15">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_19">
+ <widget class="QLabel" name="label_29">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>7.</string>
+ <string>9.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord7">
+ <widget class="QLabel" name="seedWord9">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
- <widget class="QFrame" name="frame_8">
+ <widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <layout class="QHBoxLayout" name="horizontalLayout_16">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_13">
+ <widget class="QLabel" name="label_31">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>10.</string>
+ <string>13.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord10">
+ <widget class="QLabel" name="seedWord13">
<property name="text">
<string>TextLabel</string>
</property>
</layout>
</widget>
</item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
<item>
- <widget class="QFrame" name="frame_4">
+ <widget class="QFrame" name="frame_6">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_16">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_31">
+ <widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>13.</string>
+ <string>2.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord13">
+ <widget class="QLabel" name="seedWord2">
<property name="text">
<string>TextLabel</string>
</property>
</layout>
</widget>
</item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_4">
<item>
- <widget class="QFrame" name="frame_6">
+ <widget class="QFrame" name="frame_7">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_9">
+ <widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>2.</string>
+ <string>6.</string>
</property>
</widget>
</item>
<item>
- <widget class="HelpLabel" name="seedWord2">
+ <widget class="QLabel" name="seedWord6">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
- <widget class="QFrame" name="frame_3">
+ <widget class="QFrame" name="frame_8">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_7">
+ <widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>5.</string>
+ <string>10.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord5">
+ <widget class="QLabel" name="seedWord10">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
- <widget class="QFrame" name="frame_14">
+ <widget class="QFrame" name="frame_9">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_13">
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_25">
+ <widget class="QLabel" name="label_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>8.</string>
+ <string>14.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord8">
+ <widget class="QLabel" name="seedWord14">
<property name="text">
<string>TextLabel</string>
</property>
</layout>
</widget>
</item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
<item>
- <widget class="QFrame" name="frame_12">
+ <widget class="QFrame" name="frame_10">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_10">
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_21">
+ <widget class="QLabel" name="label_17">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>11.</string>
+ <string>3.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord11">
+ <widget class="QLabel" name="seedWord3">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
- <widget class="QFrame" name="frame_9">
+ <widget class="QFrame" name="frame_11">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_15">
+ <widget class="QLabel" name="label_19">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>14.</string>
+ <string>7.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord14">
+ <widget class="QLabel" name="seedWord7">
<property name="text">
<string>TextLabel</string>
</property>
</layout>
</widget>
</item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_5">
<item>
- <widget class="QFrame" name="frame_10">
+ <widget class="QFrame" name="frame_12">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_17">
+ <widget class="QLabel" name="label_21">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>3.</string>
+ <string>11.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord3">
+ <widget class="QLabel" name="seedWord11">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
- <widget class="QFrame" name="frame_7">
+ <widget class="QFrame" name="frame_16">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <layout class="QHBoxLayout" name="horizontalLayout_18">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_11">
+ <widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>6.</string>
+ <string>15.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord6">
+ <widget class="QLabel" name="seedWord15">
<property name="text">
<string>TextLabel</string>
</property>
</layout>
</widget>
</item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_8">
<item>
- <widget class="QFrame" name="frame_5">
+ <widget class="QFrame" name="frame_13">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_15">
+ <layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="topMargin">
<number>7</number>
</property>
<number>7</number>
</property>
<item>
- <widget class="QLabel" name="label_29">
+ <widget class="QLabel" name="label_27">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
</sizepolicy>
</property>
<property name="text">
- <string>9.</string>
+ <string>4.</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="seedWord9">
+ <widget class="QLabel" name="seedWord4">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="frame_14">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_13">
+ <property name="topMargin">
+ <number>7</number>
+ </property>
+ <property name="bottomMargin">
+ <number>7</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_25">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>8.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="seedWord8">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string/>
+ <widget class="QFrame" name="frame_17">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
</property>
+ <layout class="QHBoxLayout" name="horizontalLayout_19">
+ <property name="topMargin">
+ <number>7</number>
+ </property>
+ <property name="bottomMargin">
+ <number>7</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>16.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="seedWord16">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
- <customwidgets>
- <customwidget>
- <class>HelpLabel</class>
- <extends>QLabel</extends>
- <header>components.h</header>
- </customwidget>
- </customwidgets>
<resources/>
<connections/>
</ui>