fixed conflict in CMakeLists
This commit is contained in:
commit
434095d1f7
@ -41,6 +41,7 @@ file(GLOB_RECURSE SIMPLEWALLET simplewallet/*)
|
|||||||
file(GLOB_RECURSE CONN_TOOL connectivity_tool/*)
|
file(GLOB_RECURSE CONN_TOOL connectivity_tool/*)
|
||||||
file(GLOB_RECURSE WALLET wallet/*)
|
file(GLOB_RECURSE WALLET wallet/*)
|
||||||
file(GLOB_RECURSE MINER miner/*)
|
file(GLOB_RECURSE MINER miner/*)
|
||||||
|
file(GLOB MNEMONICS mnemonics/*)
|
||||||
|
|
||||||
source_group(common FILES ${COMMON})
|
source_group(common FILES ${COMMON})
|
||||||
source_group(crypto FILES ${CRYPTO})
|
source_group(crypto FILES ${CRYPTO})
|
||||||
@ -53,10 +54,12 @@ source_group(simplewallet FILES ${SIMPLEWALLET})
|
|||||||
source_group(connectivity-tool FILES ${CONN_TOOL})
|
source_group(connectivity-tool FILES ${CONN_TOOL})
|
||||||
source_group(wallet FILES ${WALLET})
|
source_group(wallet FILES ${WALLET})
|
||||||
source_group(simpleminer FILES ${MINER})
|
source_group(simpleminer FILES ${MINER})
|
||||||
|
source_group(mnemonics FILES ${MNEMONICS})
|
||||||
|
|
||||||
add_library(common ${COMMON})
|
add_library(common ${COMMON})
|
||||||
add_library(crypto ${CRYPTO})
|
add_library(crypto ${CRYPTO})
|
||||||
add_library(cryptonote_core ${CRYPTONOTE_CORE})
|
add_library(cryptonote_core ${CRYPTONOTE_CORE})
|
||||||
|
add_library(mnemonics ${MNEMONICS})
|
||||||
add_executable(daemon ${DAEMON} ${P2P} ${CRYPTONOTE_PROTOCOL})
|
add_executable(daemon ${DAEMON} ${P2P} ${CRYPTONOTE_PROTOCOL})
|
||||||
add_executable(connectivity_tool ${CONN_TOOL})
|
add_executable(connectivity_tool ${CONN_TOOL})
|
||||||
add_executable(simpleminer ${MINER})
|
add_executable(simpleminer ${MINER})
|
||||||
@ -65,8 +68,9 @@ target_link_libraries(connectivity_tool cryptonote_core crypto common ${UNBOUND_
|
|||||||
target_link_libraries(simpleminer cryptonote_core crypto common ${UNBOUND_LIBRARIES} ${Boost_LIBRARIES})
|
target_link_libraries(simpleminer cryptonote_core crypto common ${UNBOUND_LIBRARIES} ${Boost_LIBRARIES})
|
||||||
add_library(rpc ${RPC})
|
add_library(rpc ${RPC})
|
||||||
add_library(wallet ${WALLET})
|
add_library(wallet ${WALLET})
|
||||||
|
target_link_libraries(wallet mnemonics)
|
||||||
add_executable(simplewallet ${SIMPLEWALLET} )
|
add_executable(simplewallet ${SIMPLEWALLET} )
|
||||||
target_link_libraries(simplewallet wallet rpc cryptonote_core crypto common ${UNBOUND_LIBRARIES} ${UPNP_LIBRARIES} ${Boost_LIBRARIES})
|
target_link_libraries(simplewallet wallet rpc cryptonote_core crypto common mnemonics ${UNBOUND_LIBRARIES} ${UPNP_LIBRARIES} ${Boost_LIBRARIES})
|
||||||
add_dependencies(daemon version)
|
add_dependencies(daemon version)
|
||||||
add_dependencies(rpc version)
|
add_dependencies(rpc version)
|
||||||
add_dependencies(simplewallet version)
|
add_dependencies(simplewallet version)
|
||||||
|
@ -1,138 +0,0 @@
|
|||||||
// Copyright (c) 2014, The Monero Project
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
// used to endorse or promote products derived from this software without specific
|
|
||||||
// prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file and its header file are for translating Electrum-style word lists
|
|
||||||
* into their equivalent byte representations for cross-compatibility with
|
|
||||||
* that method of "backing up" one's wallet keys.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <cassert>
|
|
||||||
#include <map>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <vector>
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#include "crypto/crypto.h" // for declaration of crypto::secret_key
|
|
||||||
|
|
||||||
#include "crypto/electrum-words.h"
|
|
||||||
|
|
||||||
namespace crypto
|
|
||||||
{
|
|
||||||
namespace ElectrumWords
|
|
||||||
{
|
|
||||||
|
|
||||||
/* convert words to bytes, 3 words -> 4 bytes
|
|
||||||
* returns:
|
|
||||||
* false if not a multiple of 3 words, or if a words is not in the
|
|
||||||
* words list
|
|
||||||
*
|
|
||||||
* true otherwise
|
|
||||||
*/
|
|
||||||
bool words_to_bytes(const std::string& words, crypto::secret_key& dst)
|
|
||||||
{
|
|
||||||
int n = NUMWORDS; // hardcoded because this is what electrum uses
|
|
||||||
|
|
||||||
std::vector<std::string> wlist;
|
|
||||||
|
|
||||||
boost::split(wlist, words, boost::is_any_of(" "));
|
|
||||||
|
|
||||||
// error on non-compliant word list
|
|
||||||
if (wlist.size() != 12 && wlist.size() != 24) return false;
|
|
||||||
|
|
||||||
for (unsigned int i=0; i < wlist.size() / 3; i++)
|
|
||||||
{
|
|
||||||
uint32_t val;
|
|
||||||
uint32_t w1, w2, w3;
|
|
||||||
|
|
||||||
// verify all three words exist in the word list
|
|
||||||
if (wordsMap.count(wlist[i*3]) == 0 ||
|
|
||||||
wordsMap.count(wlist[i*3 + 1]) == 0 ||
|
|
||||||
wordsMap.count(wlist[i*3 + 2]) == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
w1 = wordsMap.at(wlist[i*3]);
|
|
||||||
w2 = wordsMap.at(wlist[i*3 + 1]);
|
|
||||||
w3 = wordsMap.at(wlist[i*3 + 2]);
|
|
||||||
|
|
||||||
val = w1 + n * (((n - w1) + w2) % n) + n * n * (((n - w2) + w3) % n);
|
|
||||||
|
|
||||||
if (!(val % n == w1)) return false;
|
|
||||||
|
|
||||||
memcpy(dst.data + i * 4, &val, 4); // copy 4 bytes to position
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string wlist_copy = words;
|
|
||||||
if (wlist.size() == 12)
|
|
||||||
{
|
|
||||||
memcpy(dst.data, dst.data + 16, 16); // if electrum 12-word seed, duplicate
|
|
||||||
wlist_copy += ' ';
|
|
||||||
wlist_copy += words;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert bytes to words, 4 bytes-> 3 words
|
|
||||||
* returns:
|
|
||||||
* false if wrong number of bytes (shouldn't be possible)
|
|
||||||
* true otherwise
|
|
||||||
*/
|
|
||||||
bool bytes_to_words(const crypto::secret_key& src, std::string& words)
|
|
||||||
{
|
|
||||||
int n = NUMWORDS; // hardcoded because this is what electrum uses
|
|
||||||
|
|
||||||
if (sizeof(src.data) % 4 != 0) return false;
|
|
||||||
|
|
||||||
// 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
|
|
||||||
for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
|
|
||||||
{
|
|
||||||
uint32_t w1, w2, w3;
|
|
||||||
|
|
||||||
uint32_t val;
|
|
||||||
|
|
||||||
memcpy(&val, (src.data) + (i * 4), 4);
|
|
||||||
|
|
||||||
w1 = val % n;
|
|
||||||
w2 = ((val / n) + w1) % n;
|
|
||||||
w3 = (((val / n) / n) + w2) % n;
|
|
||||||
|
|
||||||
words += wordsArray[w1];
|
|
||||||
words += ' ';
|
|
||||||
words += wordsArray[w2];
|
|
||||||
words += ' ';
|
|
||||||
words += wordsArray[w3];
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ElectrumWords
|
|
||||||
|
|
||||||
} // namespace crypto
|
|
File diff suppressed because it is too large
Load Diff
375
src/mnemonics/electrum-words.cpp
Normal file
375
src/mnemonics/electrum-words.cpp
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
// Copyright (c) 2014, The Monero Project
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file electrum-words.cpp
|
||||||
|
*
|
||||||
|
* \brief Mnemonic seed generation and wallet restoration from them.
|
||||||
|
*
|
||||||
|
* This file and its header file are for translating Electrum-style word lists
|
||||||
|
* into their equivalent byte representations for cross-compatibility with
|
||||||
|
* that method of "backing up" one's wallet keys.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cassert>
|
||||||
|
#include <map>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include "crypto/crypto.h" // for declaration of crypto::secret_key
|
||||||
|
#include <fstream>
|
||||||
|
#include "mnemonics/electrum-words.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/crc.hpp>
|
||||||
|
#include <boost/algorithm/string/join.hpp>
|
||||||
|
|
||||||
|
#include "english.h"
|
||||||
|
#include "spanish.h"
|
||||||
|
#include "portuguese.h"
|
||||||
|
#include "japanese.h"
|
||||||
|
#include "old_english.h"
|
||||||
|
#include "language_base.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const int seed_length = 24;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Finds the word list that contains the seed words and puts the indices
|
||||||
|
* where matches occured in matched_indices.
|
||||||
|
* \param seed List of words to match.
|
||||||
|
* \param has_checksum If word list passed checksum test, we need to only do a prefix check.
|
||||||
|
* \param matched_indices The indices where the seed words were found are added to this.
|
||||||
|
* \return true if all the words were present in some language false if not.
|
||||||
|
*/
|
||||||
|
bool find_seed_language(const std::vector<std::string> &seed,
|
||||||
|
bool has_checksum, std::vector<uint32_t> &matched_indices, uint32_t &word_list_length,
|
||||||
|
std::string &language_name)
|
||||||
|
{
|
||||||
|
// If there's a new language added, add an instance of it here.
|
||||||
|
std::vector<Language::Base*> language_instances({
|
||||||
|
Language::Singleton<Language::English>::instance(),
|
||||||
|
Language::Singleton<Language::Spanish>::instance(),
|
||||||
|
Language::Singleton<Language::Portuguese>::instance(),
|
||||||
|
Language::Singleton<Language::Japanese>::instance(),
|
||||||
|
Language::Singleton<Language::OldEnglish>::instance()
|
||||||
|
});
|
||||||
|
// To hold trimmed seed words in case of a checksum being present.
|
||||||
|
std::vector<std::string> trimmed_seed;
|
||||||
|
if (has_checksum)
|
||||||
|
{
|
||||||
|
// If it had a checksum, we'll just compare the unique prefix
|
||||||
|
// So we create a list of trimmed seed words
|
||||||
|
for (std::vector<std::string>::const_iterator it = seed.begin(); it != seed.end(); it++)
|
||||||
|
{
|
||||||
|
trimmed_seed.push_back(it->length() > Language::unique_prefix_length ?
|
||||||
|
it->substr(0, Language::unique_prefix_length) : *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through all the languages and find a match
|
||||||
|
for (std::vector<Language::Base*>::iterator it1 = language_instances.begin();
|
||||||
|
it1 != language_instances.end(); it1++)
|
||||||
|
{
|
||||||
|
const std::unordered_map<std::string, uint32_t> &word_map = (*it1)->get_word_map();
|
||||||
|
const std::unordered_map<std::string, uint32_t> &trimmed_word_map = (*it1)->get_trimmed_word_map();
|
||||||
|
// To iterate through seed words
|
||||||
|
std::vector<std::string>::const_iterator it2;
|
||||||
|
// To iterate through trimmed seed words
|
||||||
|
std::vector<std::string>::iterator it3;
|
||||||
|
bool full_match = true;
|
||||||
|
|
||||||
|
// Iterate through all the words and see if they're all present
|
||||||
|
for (it2 = seed.begin(), it3 = trimmed_seed.begin();
|
||||||
|
it2 != seed.end(); it2++, it3++)
|
||||||
|
{
|
||||||
|
if (has_checksum)
|
||||||
|
{
|
||||||
|
// Use the trimmed words and map
|
||||||
|
if (trimmed_word_map.count(*it3) == 0)
|
||||||
|
{
|
||||||
|
full_match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
matched_indices.push_back(trimmed_word_map.at(*it3));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (word_map.count(*it2) == 0)
|
||||||
|
{
|
||||||
|
full_match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
matched_indices.push_back(word_map.at(*it2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (full_match)
|
||||||
|
{
|
||||||
|
word_list_length = (*it1)->get_word_list().size();
|
||||||
|
language_name = (*it1)->get_language_name();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Some didn't match. Clear the index array.
|
||||||
|
matched_indices.clear();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Creates a checksum index in the word list array on the list of words.
|
||||||
|
* \param word_list Vector of words
|
||||||
|
* \return Checksum index
|
||||||
|
*/
|
||||||
|
uint32_t create_checksum_index(const std::vector<std::string> &word_list)
|
||||||
|
{
|
||||||
|
std::string trimmed_words = "";
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator it = word_list.begin(); it != word_list.end(); it++)
|
||||||
|
{
|
||||||
|
if (it->length() > 4)
|
||||||
|
{
|
||||||
|
trimmed_words += it->substr(0, Language::unique_prefix_length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trimmed_words += *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boost::crc_32_type result;
|
||||||
|
result.process_bytes(trimmed_words.data(), trimmed_words.length());
|
||||||
|
return result.checksum() % seed_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Does the checksum test on the seed passed.
|
||||||
|
* \param seed Vector of seed words
|
||||||
|
* \return True if the test passed false if not.
|
||||||
|
*/
|
||||||
|
bool checksum_test(std::vector<std::string> seed)
|
||||||
|
{
|
||||||
|
// The last word is the checksum.
|
||||||
|
std::string last_word = seed.back();
|
||||||
|
seed.pop_back();
|
||||||
|
|
||||||
|
std::string checksum = seed[create_checksum_index(seed)];
|
||||||
|
|
||||||
|
std::string trimmed_checksum = checksum.length() > 4 ? checksum.substr(0, Language::unique_prefix_length) :
|
||||||
|
checksum;
|
||||||
|
std::string trimmed_last_word = checksum.length() > 4 ? last_word.substr(0, Language::unique_prefix_length) :
|
||||||
|
last_word;
|
||||||
|
return trimmed_checksum == trimmed_last_word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace crypto
|
||||||
|
*
|
||||||
|
* \brief crypto namespace.
|
||||||
|
*/
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* \namespace crypto::ElectrumWords
|
||||||
|
*
|
||||||
|
* \brief Mnemonic seed word generation and wallet restoration helper functions.
|
||||||
|
*/
|
||||||
|
namespace ElectrumWords
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* \brief Converts seed words to bytes (secret key).
|
||||||
|
* \param words String containing the words separated by spaces.
|
||||||
|
* \param dst To put the secret key restored from the words.
|
||||||
|
* \param language_name Language of the seed as found gets written here.
|
||||||
|
* \return false if not a multiple of 3 words, or if word is not in the words list
|
||||||
|
*/
|
||||||
|
bool words_to_bytes(const std::string& words, crypto::secret_key& dst,
|
||||||
|
std::string &language_name)
|
||||||
|
{
|
||||||
|
std::vector<std::string> seed;
|
||||||
|
|
||||||
|
boost::split(seed, words, boost::is_any_of(" "));
|
||||||
|
|
||||||
|
// error on non-compliant word list
|
||||||
|
if (seed.size() != seed_length/2 && seed.size() != seed_length &&
|
||||||
|
seed.size() != seed_length + 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is seed with a checksum.
|
||||||
|
bool has_checksum = seed.size() == (seed_length + 1);
|
||||||
|
if (has_checksum)
|
||||||
|
{
|
||||||
|
if (!checksum_test(seed))
|
||||||
|
{
|
||||||
|
// Checksum fail
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
seed.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> matched_indices;
|
||||||
|
uint32_t word_list_length = 0;
|
||||||
|
if (!find_seed_language(seed, has_checksum, matched_indices, word_list_length, language_name))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i=0; i < seed.size() / 3; i++)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
uint32_t w1, w2, w3;
|
||||||
|
w1 = matched_indices[i*3];
|
||||||
|
w2 = matched_indices[i*3 + 1];
|
||||||
|
w3 = matched_indices[i*3 + 2];
|
||||||
|
|
||||||
|
val = w1 + word_list_length * (((word_list_length - w1) + w2) % word_list_length) +
|
||||||
|
word_list_length * word_list_length * (((word_list_length - w2) + w3) % word_list_length);
|
||||||
|
|
||||||
|
if (!(val % word_list_length == w1)) return false;
|
||||||
|
|
||||||
|
memcpy(dst.data + i * 4, &val, 4); // copy 4 bytes to position
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string wlist_copy = words;
|
||||||
|
if (seed.size() == seed_length/2)
|
||||||
|
{
|
||||||
|
memcpy(dst.data, dst.data + 16, 16); // if electrum 12-word seed, duplicate
|
||||||
|
wlist_copy += ' ';
|
||||||
|
wlist_copy += words;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Converts bytes (secret key) to seed words.
|
||||||
|
* \param src Secret key
|
||||||
|
* \param words Space delimited concatenated words get written here.
|
||||||
|
* \param language_name Seed language name
|
||||||
|
* \return true if successful false if not. Unsuccessful if wrong key size.
|
||||||
|
*/
|
||||||
|
bool bytes_to_words(const crypto::secret_key& src, std::string& words,
|
||||||
|
const std::string &language_name)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (sizeof(src.data) % 4 != 0 || sizeof(src.data) == 0) return false;
|
||||||
|
|
||||||
|
Language::Base *language;
|
||||||
|
if (language_name == "English")
|
||||||
|
{
|
||||||
|
language = Language::Singleton<Language::English>::instance();
|
||||||
|
}
|
||||||
|
else if (language_name == "Spanish")
|
||||||
|
{
|
||||||
|
language = Language::Singleton<Language::Spanish>::instance();
|
||||||
|
}
|
||||||
|
else if (language_name == "Portuguese")
|
||||||
|
{
|
||||||
|
language = Language::Singleton<Language::Portuguese>::instance();
|
||||||
|
}
|
||||||
|
else if (language_name == "Japanese")
|
||||||
|
{
|
||||||
|
language = Language::Singleton<Language::Japanese>::instance();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const std::vector<std::string> &word_list = language->get_word_list();
|
||||||
|
// To store the words for random access to add the checksum word later.
|
||||||
|
std::vector<std::string> words_store;
|
||||||
|
|
||||||
|
uint32_t word_list_length = word_list.size();
|
||||||
|
// 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
|
||||||
|
for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
|
||||||
|
{
|
||||||
|
uint32_t w1, w2, w3;
|
||||||
|
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
memcpy(&val, (src.data) + (i * 4), 4);
|
||||||
|
|
||||||
|
w1 = val % word_list_length;
|
||||||
|
w2 = ((val / word_list_length) + w1) % word_list_length;
|
||||||
|
w3 = (((val / word_list_length) / word_list_length) + w2) % word_list_length;
|
||||||
|
|
||||||
|
words += word_list[w1];
|
||||||
|
words += ' ';
|
||||||
|
words += word_list[w2];
|
||||||
|
words += ' ';
|
||||||
|
words += word_list[w3];
|
||||||
|
|
||||||
|
words_store.push_back(word_list[w1]);
|
||||||
|
words_store.push_back(word_list[w2]);
|
||||||
|
words_store.push_back(word_list[w3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
words.pop_back();
|
||||||
|
words += (' ' + words_store[create_checksum_index(words_store)]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets a list of seed languages that are supported.
|
||||||
|
* \param languages The vector is set to the list of languages.
|
||||||
|
*/
|
||||||
|
void get_language_list(std::vector<std::string> &languages)
|
||||||
|
{
|
||||||
|
std::vector<Language::Base*> language_instances({
|
||||||
|
Language::Singleton<Language::English>::instance(),
|
||||||
|
Language::Singleton<Language::Spanish>::instance(),
|
||||||
|
Language::Singleton<Language::Portuguese>::instance(),
|
||||||
|
Language::Singleton<Language::Japanese>::instance()
|
||||||
|
});
|
||||||
|
for (std::vector<Language::Base*>::iterator it = language_instances.begin();
|
||||||
|
it != language_instances.end(); it++)
|
||||||
|
{
|
||||||
|
languages.push_back((*it)->get_language_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tells if the seed passed is an old style seed or not.
|
||||||
|
* \param seed The seed to check (a space delimited concatenated word list)
|
||||||
|
* \return true if the seed passed is a old style seed false if not.
|
||||||
|
*/
|
||||||
|
bool get_is_old_style_seed(const std::string &seed)
|
||||||
|
{
|
||||||
|
std::vector<std::string> word_list;
|
||||||
|
boost::split(word_list, seed, boost::is_any_of(" "));
|
||||||
|
return word_list.size() != (seed_length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
98
src/mnemonics/electrum-words.h
Normal file
98
src/mnemonics/electrum-words.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// Copyright (c) 2014, The Monero Project
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file electrum-words.h
|
||||||
|
*
|
||||||
|
* \brief Mnemonic seed generation and wallet restoration from them.
|
||||||
|
*
|
||||||
|
* This file and its cpp file are for translating Electrum-style word lists
|
||||||
|
* into their equivalent byte representations for cross-compatibility with
|
||||||
|
* that method of "backing up" one's wallet keys.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELECTRUM_WORDS_H
|
||||||
|
#define ELECTRUM_WORDS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include "crypto/crypto.h" // for declaration of crypto::secret_key
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace crypto
|
||||||
|
*
|
||||||
|
* \brief crypto namespace.
|
||||||
|
*/
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* \namespace crypto::ElectrumWords
|
||||||
|
*
|
||||||
|
* \brief Mnemonic seed word generation and wallet restoration helper functions.
|
||||||
|
*/
|
||||||
|
namespace ElectrumWords
|
||||||
|
{
|
||||||
|
|
||||||
|
const std::string old_language_name = "OldEnglish";
|
||||||
|
/*!
|
||||||
|
* \brief Converts seed words to bytes (secret key).
|
||||||
|
* \param words String containing the words separated by spaces.
|
||||||
|
* \param dst To put the secret key restored from the words.
|
||||||
|
* \param language_name Language of the seed as found gets written here.
|
||||||
|
* \return false if not a multiple of 3 words, or if word is not in the words list
|
||||||
|
*/
|
||||||
|
bool words_to_bytes(const std::string& words, crypto::secret_key& dst,
|
||||||
|
std::string &language_name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Converts bytes (secret key) to seed words.
|
||||||
|
* \param src Secret key
|
||||||
|
* \param words Space delimited concatenated words get written here.
|
||||||
|
* \param language_name Seed language name
|
||||||
|
* \return true if successful false if not. Unsuccessful if wrong key size.
|
||||||
|
*/
|
||||||
|
bool bytes_to_words(const crypto::secret_key& src, std::string& words,
|
||||||
|
const std::string &language_name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets a list of seed languages that are supported.
|
||||||
|
* \param languages A vector is set to the list of languages.
|
||||||
|
*/
|
||||||
|
void get_language_list(std::vector<std::string> &languages);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tells if the seed passed is an old style seed or not.
|
||||||
|
* \param seed The seed to check (a space delimited concatenated word list)
|
||||||
|
* \return true if the seed passed is a old style seed false if not.
|
||||||
|
*/
|
||||||
|
bool get_is_old_style_seed(const std::string &seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1691
src/mnemonics/english.h
Normal file
1691
src/mnemonics/english.h
Normal file
File diff suppressed because it is too large
Load Diff
1691
src/mnemonics/japanese.h
Normal file
1691
src/mnemonics/japanese.h
Normal file
File diff suppressed because it is too large
Load Diff
95
src/mnemonics/language_base.h
Normal file
95
src/mnemonics/language_base.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*!
|
||||||
|
* \file language_base.h
|
||||||
|
*
|
||||||
|
* \brief Language Base class for Polymorphism.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LANGUAGE_BASE_H
|
||||||
|
#define LANGUAGE_BASE_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace Language
|
||||||
|
* \brief Mnemonic language related namespace.
|
||||||
|
*/
|
||||||
|
namespace Language
|
||||||
|
{
|
||||||
|
const int unique_prefix_length = 4; /*!< Length of the prefix of all words guaranteed to be unique */
|
||||||
|
/*!
|
||||||
|
* \class Base
|
||||||
|
* \brief A base language class which all languages have to inherit from for
|
||||||
|
* Polymorphism.
|
||||||
|
*/
|
||||||
|
class Base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<std::string> *word_list; /*!< A pointer to the array of words */
|
||||||
|
std::unordered_map<std::string, uint32_t> *word_map; /*!< hash table to find word's index */
|
||||||
|
std::unordered_map<std::string, uint32_t> *trimmed_word_map; /*!< hash table to find word's trimmed index */
|
||||||
|
std::string language_name; /*!< Name of language */
|
||||||
|
/*!
|
||||||
|
* \brief Populates the word maps after the list is ready.
|
||||||
|
*/
|
||||||
|
void populate_maps()
|
||||||
|
{
|
||||||
|
int ii;
|
||||||
|
std::vector<std::string>::iterator it;
|
||||||
|
for (it = word_list->begin(), ii = 0; it != word_list->end(); it++, ii++)
|
||||||
|
{
|
||||||
|
(*word_map)[*it] = ii;
|
||||||
|
if (it->length() > unique_prefix_length)
|
||||||
|
{
|
||||||
|
(*trimmed_word_map)[it->substr(0, unique_prefix_length)] = ii;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*trimmed_word_map)[*it] = ii;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
Base()
|
||||||
|
{
|
||||||
|
word_list = new std::vector<std::string>;
|
||||||
|
word_map = new std::unordered_map<std::string, uint32_t>;
|
||||||
|
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
* \brief Returns a pointer to the word list.
|
||||||
|
* \return A pointer to the word list.
|
||||||
|
*/
|
||||||
|
const std::vector<std::string>& get_word_list() const
|
||||||
|
{
|
||||||
|
return *word_list;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
* \brief Returns a pointer to the word map.
|
||||||
|
* \return A pointer to the word map.
|
||||||
|
*/
|
||||||
|
const std::unordered_map<std::string, uint32_t>& get_word_map() const
|
||||||
|
{
|
||||||
|
return *word_map;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
* \brief Returns a pointer to the trimmed word map.
|
||||||
|
* \return A pointer to the trimmed word map.
|
||||||
|
*/
|
||||||
|
const std::unordered_map<std::string, uint32_t>& get_trimmed_word_map() const
|
||||||
|
{
|
||||||
|
return *trimmed_word_map;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
* \brief Returns the name of the language.
|
||||||
|
* \return Name of the language.
|
||||||
|
*/
|
||||||
|
std::string get_language_name() const
|
||||||
|
{
|
||||||
|
return language_name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1691
src/mnemonics/old_english.h
Normal file
1691
src/mnemonics/old_english.h
Normal file
File diff suppressed because it is too large
Load Diff
1690
src/mnemonics/portuguese.h
Normal file
1690
src/mnemonics/portuguese.h
Normal file
File diff suppressed because it is too large
Load Diff
62
src/mnemonics/singleton.h
Normal file
62
src/mnemonics/singleton.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) 2014, The Monero Project
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file singleton.h
|
||||||
|
*
|
||||||
|
* \brief A singleton helper class based on template.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace Language
|
||||||
|
* \brief Mnemonic language related namespace.
|
||||||
|
*/
|
||||||
|
namespace Language
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* \class Singleton
|
||||||
|
*
|
||||||
|
* \brief Single helper class.
|
||||||
|
*
|
||||||
|
* Do Language::Singleton<YourClass>::instance() to create a singleton instance
|
||||||
|
* of `YourClass`.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
class Singleton
|
||||||
|
{
|
||||||
|
Singleton() {}
|
||||||
|
Singleton(Singleton &s) {}
|
||||||
|
Singleton& operator=(const Singleton&) {}
|
||||||
|
public:
|
||||||
|
static T* instance()
|
||||||
|
{
|
||||||
|
static T* obj = new T;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
1691
src/mnemonics/spanish.h
Normal file
1691
src/mnemonics/spanish.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,12 @@
|
|||||||
//
|
//
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file simplewallet.cpp
|
||||||
|
*
|
||||||
|
* \brief Source file that defines simple_wallet class.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -46,7 +52,8 @@
|
|||||||
#include "wallet/wallet_rpc_server.h"
|
#include "wallet/wallet_rpc_server.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "crypto/crypto.h" // for crypto::secret_key definition
|
#include "crypto/crypto.h" // for crypto::secret_key definition
|
||||||
#include "crypto/electrum-words.h"
|
#include "mnemonics/electrum-words.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
@ -204,7 +211,7 @@ bool simple_wallet::seed(const std::vector<std::string> &args/* = std::vector<st
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
success_msg_writer(true) << "\nPLEASE NOTE: the following 24 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control.\n";
|
success_msg_writer(true) << "\nPLEASE NOTE: the following 25 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control.\n";
|
||||||
std::cout << electrum_words << std::endl;
|
std::cout << electrum_words << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -361,6 +368,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||||||
{
|
{
|
||||||
if (m_wallet_file.empty()) m_wallet_file = m_generate_new; // alias for simplicity later
|
if (m_wallet_file.empty()) m_wallet_file = m_generate_new; // alias for simplicity later
|
||||||
|
|
||||||
|
std::string old_language;
|
||||||
// check for recover flag. if present, require electrum word list (only recovery option for now).
|
// check for recover flag. if present, require electrum word list (only recovery option for now).
|
||||||
if (m_restore_deterministic_wallet)
|
if (m_restore_deterministic_wallet)
|
||||||
{
|
{
|
||||||
@ -380,13 +388,14 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key))
|
if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key, old_language))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << "electrum-style word list failed verification";
|
fail_msg_writer() << "electrum-style word list failed verification";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic, testnet);
|
bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet,
|
||||||
|
m_non_deterministic, testnet, old_language);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "account creation failed");
|
CHECK_AND_ASSERT_MES(r, false, "account creation failed");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -430,8 +439,49 @@ bool simple_wallet::try_connect_to_daemon()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the word seed language from the user.
|
||||||
|
*
|
||||||
|
* User is asked to choose from a list of supported languages.
|
||||||
|
*
|
||||||
|
* \return The chosen language.
|
||||||
|
*/
|
||||||
|
std::string simple_wallet::get_mnemonic_language()
|
||||||
|
{
|
||||||
|
std::vector<std::string> language_list;
|
||||||
|
std::string language_choice;
|
||||||
|
int language_number = -1;
|
||||||
|
crypto::ElectrumWords::get_language_list(language_list);
|
||||||
|
std::cout << "List of available languages for your wallet's seed:" << std::endl;
|
||||||
|
int ii;
|
||||||
|
std::vector<std::string>::iterator it;
|
||||||
|
for (it = language_list.begin(), ii = 0; it != language_list.end(); it++, ii++)
|
||||||
|
{
|
||||||
|
std::cout << ii << " : " << *it << std::endl;
|
||||||
|
}
|
||||||
|
while (language_number < 0)
|
||||||
|
{
|
||||||
|
language_choice = command_line::input_line("Enter the number corresponding to the language of your choice: ");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
language_number = std::stoi(language_choice);
|
||||||
|
if (!((language_number >= 0) && (static_cast<unsigned int>(language_number) < language_list.size())))
|
||||||
|
{
|
||||||
|
language_number = -1;
|
||||||
|
fail_msg_writer() << "Invalid language choice passed. Please try again.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << "Invalid language choice passed. Please try again.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return language_list[language_number];
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key, bool recover, bool two_random, bool testnet)
|
bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key,
|
||||||
|
bool recover, bool two_random, bool testnet, const std::string &old_language)
|
||||||
{
|
{
|
||||||
m_wallet_file = wallet_file;
|
m_wallet_file = wallet_file;
|
||||||
|
|
||||||
@ -456,7 +506,25 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
|||||||
|
|
||||||
// convert rng value to electrum-style word list
|
// convert rng value to electrum-style word list
|
||||||
std::string electrum_words;
|
std::string electrum_words;
|
||||||
crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words);
|
|
||||||
|
bool was_deprecated_wallet = (old_language == crypto::ElectrumWords::old_language_name) ||
|
||||||
|
crypto::ElectrumWords::get_is_old_style_seed(m_electrum_seed);
|
||||||
|
|
||||||
|
std::string mnemonic_language = old_language;
|
||||||
|
// Ask for seed language if it is not a wallet restore or if it was a deprecated wallet
|
||||||
|
// that was earlier used before this restore.
|
||||||
|
if (!m_restore_deterministic_wallet || was_deprecated_wallet)
|
||||||
|
{
|
||||||
|
if (was_deprecated_wallet)
|
||||||
|
{
|
||||||
|
// The user had used an older version of the wallet with old style mnemonics.
|
||||||
|
message_writer(epee::log_space::console_color_green, false) << "\nYou had been using " <<
|
||||||
|
"a deprecated version of the wallet. Please use the new seed that we provide.\n";
|
||||||
|
}
|
||||||
|
mnemonic_language = get_mnemonic_language();
|
||||||
|
}
|
||||||
|
crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words, mnemonic_language);
|
||||||
|
m_wallet->set_seed_language(mnemonic_language);
|
||||||
|
|
||||||
std::string print_electrum = "";
|
std::string print_electrum = "";
|
||||||
|
|
||||||
@ -473,7 +541,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
|||||||
|
|
||||||
if (!two_random)
|
if (!two_random)
|
||||||
{
|
{
|
||||||
success_msg_writer(true) << "\nPLEASE NOTE: the following 24 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control.\n";
|
success_msg_writer(true) << "\nPLEASE NOTE: the following 25 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control.\n";
|
||||||
std::cout << electrum_words << std::endl;
|
std::cout << electrum_words << std::endl;
|
||||||
}
|
}
|
||||||
success_msg_writer() << "**********************************************************************";
|
success_msg_writer() << "**********************************************************************";
|
||||||
|
@ -28,6 +28,11 @@
|
|||||||
//
|
//
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file simplewallet.h
|
||||||
|
*
|
||||||
|
* \brief Header file that declares simple_wallet class.
|
||||||
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -41,12 +46,15 @@
|
|||||||
#include "password_container.h"
|
#include "password_container.h"
|
||||||
#include "crypto/crypto.h" // for definition of crypto::secret_key
|
#include "crypto/crypto.h" // for definition of crypto::secret_key
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace cryptonote
|
||||||
|
* \brief Holds cryptonote related classes and helpers.
|
||||||
|
*/
|
||||||
namespace cryptonote
|
namespace cryptonote
|
||||||
{
|
{
|
||||||
/************************************************************************/
|
/*!
|
||||||
/* */
|
* \brief Manages wallet operations. This is the most abstracted wallet class.
|
||||||
/************************************************************************/
|
*/
|
||||||
class simple_wallet : public tools::i_wallet2_callback
|
class simple_wallet : public tools::i_wallet2_callback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -66,7 +74,8 @@ namespace cryptonote
|
|||||||
|
|
||||||
bool run_console_handler();
|
bool run_console_handler();
|
||||||
|
|
||||||
bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false, bool testnet = false);
|
bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key,
|
||||||
|
bool recover, bool two_random, bool testnet, const std::string &old_language);
|
||||||
bool open_wallet(const std::string &wallet_file, const std::string& password, bool testnet);
|
bool open_wallet(const std::string &wallet_file, const std::string& password, bool testnet);
|
||||||
bool close_wallet();
|
bool close_wallet();
|
||||||
|
|
||||||
@ -93,6 +102,15 @@ namespace cryptonote
|
|||||||
bool try_connect_to_daemon();
|
bool try_connect_to_daemon();
|
||||||
bool ask_wallet_create_if_needed();
|
bool ask_wallet_create_if_needed();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the word seed language from the user.
|
||||||
|
*
|
||||||
|
* User is asked to choose from a list of supported languages.
|
||||||
|
*
|
||||||
|
* \return The chosen language.
|
||||||
|
*/
|
||||||
|
std::string get_mnemonic_language();
|
||||||
|
|
||||||
//----------------- i_wallet2_callback ---------------------
|
//----------------- i_wallet2_callback ---------------------
|
||||||
virtual void on_new_block(uint64_t height, const cryptonote::block& block);
|
virtual void on_new_block(uint64_t height, const cryptonote::block& block);
|
||||||
virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, size_t out_index);
|
virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, size_t out_index);
|
||||||
|
@ -46,7 +46,7 @@ using namespace epee;
|
|||||||
#include "crypto/crypto.h"
|
#include "crypto/crypto.h"
|
||||||
#include "serialization/binary_utils.h"
|
#include "serialization/binary_utils.h"
|
||||||
#include "cryptonote_protocol/blobdatatype.h"
|
#include "cryptonote_protocol/blobdatatype.h"
|
||||||
#include "crypto/electrum-words.h"
|
#include "mnemonics/electrum-words.h"
|
||||||
#include "common/dns_utils.h"
|
#include "common/dns_utils.h"
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -88,7 +88,7 @@ void wallet2::init(const std::string& daemon_address, uint64_t upper_transaction
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::get_seed(std::string& electrum_words)
|
bool wallet2::get_seed(std::string& electrum_words)
|
||||||
{
|
{
|
||||||
crypto::ElectrumWords::bytes_to_words(get_account().get_keys().m_spend_secret_key, electrum_words);
|
crypto::ElectrumWords::bytes_to_words(get_account().get_keys().m_spend_secret_key, electrum_words, seed_language);
|
||||||
|
|
||||||
crypto::secret_key second;
|
crypto::secret_key second;
|
||||||
keccak((uint8_t *)&get_account().get_keys().m_spend_secret_key, sizeof(crypto::secret_key), (uint8_t *)&second, sizeof(crypto::secret_key));
|
keccak((uint8_t *)&get_account().get_keys().m_spend_secret_key, sizeof(crypto::secret_key), (uint8_t *)&second, sizeof(crypto::secret_key));
|
||||||
@ -97,6 +97,13 @@ bool wallet2::get_seed(std::string& electrum_words)
|
|||||||
|
|
||||||
return memcmp(second.data,get_account().get_keys().m_view_secret_key.data, sizeof(crypto::secret_key)) == 0;
|
return memcmp(second.data,get_account().get_keys().m_view_secret_key.data, sizeof(crypto::secret_key)) == 0;
|
||||||
}
|
}
|
||||||
|
/*!
|
||||||
|
* \brief Sets the seed language
|
||||||
|
*/
|
||||||
|
void wallet2::set_seed_language(const std::string &language)
|
||||||
|
{
|
||||||
|
seed_language = language;
|
||||||
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_t height)
|
void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_t height)
|
||||||
{
|
{
|
||||||
|
@ -152,7 +152,10 @@ namespace tools
|
|||||||
void callback(i_wallet2_callback* callback) { m_callback = callback; }
|
void callback(i_wallet2_callback* callback) { m_callback = callback; }
|
||||||
|
|
||||||
bool get_seed(std::string& electrum_words);
|
bool get_seed(std::string& electrum_words);
|
||||||
|
/*!
|
||||||
|
* \brief Sets the seed language
|
||||||
|
*/
|
||||||
|
void set_seed_language(const std::string &language);
|
||||||
void refresh();
|
void refresh();
|
||||||
void refresh(uint64_t start_height, size_t & blocks_fetched);
|
void refresh(uint64_t start_height, size_t & blocks_fetched);
|
||||||
void refresh(uint64_t start_height, size_t & blocks_fetched, bool& received_money);
|
void refresh(uint64_t start_height, size_t & blocks_fetched, bool& received_money);
|
||||||
@ -236,6 +239,7 @@ namespace tools
|
|||||||
|
|
||||||
i_wallet2_callback* m_callback;
|
i_wallet2_callback* m_callback;
|
||||||
bool m_testnet;
|
bool m_testnet;
|
||||||
|
std::string seed_language;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
BOOST_CLASS_VERSION(tools::wallet2, 7)
|
BOOST_CLASS_VERSION(tools::wallet2, 7)
|
||||||
|
Loading…
Reference in New Issue
Block a user