Merge branch 'oranjuice'

This commit is contained in:
Riccardo Spagni 2014-10-05 12:44:31 +02:00
commit a04ca4b966
No known key found for this signature in database
GPG key ID: 55432DF31CCD4FCD
16 changed files with 9243 additions and 3464 deletions

View file

@ -41,6 +41,7 @@ file(GLOB_RECURSE SIMPLEWALLET simplewallet/*)
file(GLOB_RECURSE CONN_TOOL connectivity_tool/*)
file(GLOB_RECURSE WALLET wallet/*)
file(GLOB_RECURSE MINER miner/*)
file(GLOB MNEMONICS mnemonics/*)
source_group(common FILES ${COMMON})
source_group(crypto FILES ${CRYPTO})
@ -53,10 +54,12 @@ source_group(simplewallet FILES ${SIMPLEWALLET})
source_group(connectivity-tool FILES ${CONN_TOOL})
source_group(wallet FILES ${WALLET})
source_group(simpleminer FILES ${MINER})
source_group(mnemonics FILES ${MNEMONICS})
add_library(common ${COMMON})
add_library(crypto ${CRYPTO})
add_library(cryptonote_core ${CRYPTONOTE_CORE})
add_library(mnemonics ${MNEMONICS})
add_executable(daemon ${DAEMON} ${P2P} ${CRYPTONOTE_PROTOCOL})
add_executable(connectivity_tool ${CONN_TOOL})
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})
add_library(rpc ${RPC})
add_library(wallet ${WALLET})
target_link_libraries(wallet mnemonics)
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(rpc version)
add_dependencies(simplewallet version)

View file

@ -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

View 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);
}
}
}

View 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

1692
src/mnemonics/english.h Normal file

File diff suppressed because it is too large Load diff

1692
src/mnemonics/japanese.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,131 @@
// 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 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;
}
/*!
* \brief Returns the number of unique starting characters to be used for matching.
* \return Number of unique starting characters.
*/
std::string get_trim_length() const
{
return trim_length;
}
};
}
#endif

1692
src/mnemonics/old_english.h Normal file

File diff suppressed because it is too large Load diff

1690
src/mnemonics/portuguese.h Normal file

File diff suppressed because it is too large Load diff

62
src/mnemonics/singleton.h Normal file
View 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;
}
};
}

1692
src/mnemonics/spanish.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,12 @@
//
// 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 <iostream>
#include <sstream>
@ -46,7 +52,8 @@
#include "wallet/wallet_rpc_server.h"
#include "version.h"
#include "crypto/crypto.h" // for crypto::secret_key definition
#include "crypto/electrum-words.h"
#include "mnemonics/electrum-words.h"
#include <stdexcept>
#if defined(WIN32)
#include <crtdbg.h>
@ -204,7 +211,7 @@ bool simple_wallet::seed(const std::vector<std::string> &args/* = std::vector<st
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;
}
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
std::string old_language;
// check for recover flag. if present, require electrum word list (only recovery option for now).
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";
return false;
fail_msg_writer() << "electrum-style word list failed verification";
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");
}
else
@ -430,8 +439,49 @@ bool simple_wallet::try_connect_to_daemon()
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;
@ -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
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 = "";
@ -473,7 +541,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
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;
}
success_msg_writer() << "**********************************************************************";

View file

@ -28,6 +28,11 @@
//
// 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
#include <memory>
@ -41,12 +46,15 @@
#include "password_container.h"
#include "crypto/crypto.h" // for definition of crypto::secret_key
/*!
* \namespace cryptonote
* \brief Holds cryptonote related classes and helpers.
*/
namespace cryptonote
{
/************************************************************************/
/* */
/************************************************************************/
/*!
* \brief Manages wallet operations. This is the most abstracted wallet class.
*/
class simple_wallet : public tools::i_wallet2_callback
{
public:
@ -66,7 +74,8 @@ namespace cryptonote
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 close_wallet();
@ -93,6 +102,15 @@ namespace cryptonote
bool try_connect_to_daemon();
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 ---------------------
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);

View file

@ -46,7 +46,7 @@ using namespace epee;
#include "crypto/crypto.h"
#include "serialization/binary_utils.h"
#include "cryptonote_protocol/blobdatatype.h"
#include "crypto/electrum-words.h"
#include "mnemonics/electrum-words.h"
#include "common/dns_utils.h"
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)
{
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;
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;
}
/*!
* \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)
{

View file

@ -152,7 +152,10 @@ namespace tools
void callback(i_wallet2_callback* callback) { m_callback = callback; }
bool get_seed(std::string& electrum_words);
/*!
* \brief Sets the seed language
*/
void set_seed_language(const std::string &language);
void refresh();
void refresh(uint64_t start_height, size_t & blocks_fetched);
void refresh(uint64_t start_height, size_t & blocks_fetched, bool& received_money);
@ -236,6 +239,7 @@ namespace tools
i_wallet2_callback* m_callback;
bool m_testnet;
std::string seed_language;
};
}
BOOST_CLASS_VERSION(tools::wallet2, 7)