diff options
-rw-r--r-- | src/mnemonics/dutch.h | 11 | ||||
-rw-r--r-- | src/mnemonics/english.h | 11 | ||||
-rw-r--r-- | src/mnemonics/french.h | 11 | ||||
-rw-r--r-- | src/mnemonics/german.h | 11 | ||||
-rw-r--r-- | src/mnemonics/italian.h | 11 | ||||
-rw-r--r-- | src/mnemonics/japanese.h | 11 | ||||
-rw-r--r-- | src/mnemonics/language_base.h | 61 | ||||
-rw-r--r-- | src/mnemonics/old_english.h | 13 | ||||
-rw-r--r-- | src/mnemonics/portuguese.h | 11 | ||||
-rw-r--r-- | src/mnemonics/russian.h | 11 | ||||
-rw-r--r-- | src/mnemonics/spanish.h | 13 | ||||
-rw-r--r-- | tests/unit_tests/mnemonics.cpp | 31 |
12 files changed, 102 insertions, 104 deletions
diff --git a/src/mnemonics/dutch.h b/src/mnemonics/dutch.h index d0a972e59..0d7a637e6 100644 --- a/src/mnemonics/dutch.h +++ b/src/mnemonics/dutch.h @@ -49,9 +49,7 @@ namespace Language class Dutch: public Base
{
public:
- Dutch()
- {
- word_list = new std::vector<std::string>({
+ Dutch(): Base("Dutch", std::vector<std::string>({
"aalglad",
"aalscholver",
"aambeeld",
@@ -1678,11 +1676,8 @@ namespace Language "zwiep",
"zwijmel",
"zworen"
- });
- unique_prefix_length = 4;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "Dutch";
+ }), 4)
+ {
populate_maps();
}
};
diff --git a/src/mnemonics/english.h b/src/mnemonics/english.h index 703c7780c..e6cfa8951 100644 --- a/src/mnemonics/english.h +++ b/src/mnemonics/english.h @@ -49,9 +49,7 @@ namespace Language class English: public Base
{
public:
- English()
- {
- word_list = new std::vector<std::string>({
+ English(): Base("English", std::vector<std::string>({
"abbey",
"abducts",
"ability",
@@ -1678,11 +1676,8 @@ namespace Language "zombie",
"zones",
"zoom"
- });
- unique_prefix_length = 3;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "English";
+ }), 3)
+ {
populate_maps();
}
};
diff --git a/src/mnemonics/french.h b/src/mnemonics/french.h index 2f6eb7e8a..6cf44a197 100644 --- a/src/mnemonics/french.h +++ b/src/mnemonics/french.h @@ -49,9 +49,7 @@ namespace Language class French: public Base { public: - French() - { - word_list = new std::vector<std::string>({ + French(): Base("French", std::vector<std::string>({ "abandon", "abattre", "aboi", @@ -1678,11 +1676,8 @@ namespace Language "zinc", "zone", "zoom" - }); - unique_prefix_length = 4; - word_map = new std::unordered_map<std::string, uint32_t>; - trimmed_word_map = new std::unordered_map<std::string, uint32_t>; - language_name = "French"; + }), 4) + { populate_maps(); } }; diff --git a/src/mnemonics/german.h b/src/mnemonics/german.h index a9614e4a9..1a1e6b467 100644 --- a/src/mnemonics/german.h +++ b/src/mnemonics/german.h @@ -51,9 +51,7 @@ namespace Language class German: public Base
{
public:
- German()
- {
- word_list = new std::vector<std::string>({
+ German(): Base("German", std::vector<std::string>({
"Abakus",
"Abart",
"abbilden",
@@ -1680,11 +1678,8 @@ namespace Language "Zündung",
"Zweck",
"Zyklop"
- });
- unique_prefix_length = 4;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "German";
+ }), 4) + { populate_maps();
}
};
diff --git a/src/mnemonics/italian.h b/src/mnemonics/italian.h index 24ed67442..28cee9d9a 100644 --- a/src/mnemonics/italian.h +++ b/src/mnemonics/italian.h @@ -51,9 +51,7 @@ namespace Language class Italian: public Base
{
public:
- Italian()
- {
- word_list = new std::vector<std::string>({
+ Italian(): Base("Italian", std::vector<std::string>({
"abbinare",
"abbonato",
"abisso",
@@ -1680,11 +1678,8 @@ namespace Language "zolfo",
"zombie",
"zucchero"
- });
- unique_prefix_length = 4;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "Italian";
+ }), 4) + { populate_maps();
}
};
diff --git a/src/mnemonics/japanese.h b/src/mnemonics/japanese.h index b437ae2af..09d05d132 100644 --- a/src/mnemonics/japanese.h +++ b/src/mnemonics/japanese.h @@ -51,9 +51,7 @@ namespace Language class Japanese: public Base
{
public:
- Japanese()
- {
- word_list = new std::vector<std::string>({
+ Japanese(): Base("Japanese", std::vector<std::string>({
"あいこくしん",
"あいさつ",
"あいだ",
@@ -1680,11 +1678,8 @@ namespace Language "ひさん",
"びじゅつかん",
"ひしょ"
- });
- unique_prefix_length = 3;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "Japanese";
+ }), 3)
+ {
populate_maps();
}
};
diff --git a/src/mnemonics/language_base.h b/src/mnemonics/language_base.h index 5ad4211d4..8f0a7a9d3 100644 --- a/src/mnemonics/language_base.h +++ b/src/mnemonics/language_base.h @@ -38,6 +38,7 @@ #include <vector>
#include <unordered_map>
#include <string>
+#include "misc_log_ex.h"
/*!
* \namespace Language
@@ -73,44 +74,62 @@ namespace Language 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 */
+ enum {
+ ALLOW_SHORT_WORDS = 1<<0,
+ ALLOW_DUPLICATE_PREFIXES = 1<<1,
+ };
+ const 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 */
uint32_t unique_prefix_length; /*!< Number of unique starting characters to trim the wordlist to when matching */
/*!
* \brief Populates the word maps after the list is ready.
*/
- void populate_maps()
+ void populate_maps(uint32_t flags = 0)
{
int ii;
- std::vector<std::string>::iterator it;
- for (it = word_list->begin(), ii = 0; it != word_list->end(); it++, ii++)
+ std::vector<std::string>::const_iterator it;
+ if (word_list.size () != 1626)
+ throw std::runtime_error("Wrong word list length for " + language_name);
+ for (it = word_list.begin(), ii = 0; it != word_list.end(); it++, ii++)
{
- (*word_map)[*it] = ii;
+ word_map[*it] = ii;
+ if ((*it).size() < unique_prefix_length)
+ {
+ if (flags & ALLOW_SHORT_WORDS)
+ MWARNING(language_name << " word '" << *it << "' is shorter than its prefix length, " << unique_prefix_length);
+ else
+ throw std::runtime_error("Too short word in " + language_name + " word list: " + *it);
+ }
+ std::string trimmed;
if (it->length() > unique_prefix_length)
{
- (*trimmed_word_map)[utf8prefix(*it, unique_prefix_length)] = ii;
+ trimmed = utf8prefix(*it, unique_prefix_length);
}
else
{
- (*trimmed_word_map)[*it] = ii;
+ trimmed = *it;
+ }
+ if (trimmed_word_map.find(trimmed) != trimmed_word_map.end())
+ {
+ if (flags & ALLOW_DUPLICATE_PREFIXES)
+ MWARNING("Duplicate prefix in " << language_name << " word list: " << trimmed);
+ else
+ throw std::runtime_error("Duplicate prefix in " + language_name + " word list: " + trimmed);
}
+ trimmed_word_map[trimmed] = ii;
}
}
public:
- Base()
+ Base(const char *language_name, const std::vector<std::string> &words, uint32_t prefix_length):
+ word_list(words),
+ unique_prefix_length(prefix_length),
+ language_name(language_name)
{
- 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>;
- unique_prefix_length = 4;
}
virtual ~Base()
{
- delete word_list;
- delete word_map;
- delete trimmed_word_map;
}
/*!
* \brief Returns a pointer to the word list.
@@ -118,7 +137,7 @@ namespace Language */
const std::vector<std::string>& get_word_list() const
{
- return *word_list;
+ return word_list;
}
/*!
* \brief Returns a pointer to the word map.
@@ -126,7 +145,7 @@ namespace Language */
const std::unordered_map<std::string, uint32_t>& get_word_map() const
{
- return *word_map;
+ return word_map;
}
/*!
* \brief Returns a pointer to the trimmed word map.
@@ -134,13 +153,13 @@ namespace Language */
const std::unordered_map<std::string, uint32_t>& get_trimmed_word_map() const
{
- return *trimmed_word_map;
+ return trimmed_word_map;
}
/*!
* \brief Returns the name of the language.
* \return Name of the language.
*/
- std::string get_language_name() const
+ const std::string &get_language_name() const
{
return language_name;
}
diff --git a/src/mnemonics/old_english.h b/src/mnemonics/old_english.h index 690e46616..21ac95de3 100644 --- a/src/mnemonics/old_english.h +++ b/src/mnemonics/old_english.h @@ -51,9 +51,7 @@ namespace Language class OldEnglish: public Base
{
public:
- OldEnglish()
- {
- word_list = new std::vector<std::string>({
+ OldEnglish(): Base("OldEnglish", std::vector<std::string>({
"like",
"just",
"love",
@@ -1680,12 +1678,9 @@ namespace Language "unseen",
"weapon",
"weary"
- });
- unique_prefix_length = 4;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "OldEnglish";
- populate_maps();
+ }), 4)
+ {
+ populate_maps(ALLOW_DUPLICATE_PREFIXES | ALLOW_SHORT_WORDS);
}
};
}
diff --git a/src/mnemonics/portuguese.h b/src/mnemonics/portuguese.h index 91e2145b8..09d7132f5 100644 --- a/src/mnemonics/portuguese.h +++ b/src/mnemonics/portuguese.h @@ -49,9 +49,7 @@ namespace Language class Portuguese: public Base
{
public:
- Portuguese()
- {
- word_list = new std::vector<std::string>({
+ Portuguese(): Base("Portuguese", std::vector<std::string>({
"abaular",
"abdominal",
"abeto",
@@ -1678,11 +1676,8 @@ namespace Language "zeloso",
"zenite",
"zumbi"
- });
- unique_prefix_length = 4;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "Portuguese";
+ }), 4)
+ {
populate_maps();
}
};
diff --git a/src/mnemonics/russian.h b/src/mnemonics/russian.h index 981f40d98..b3db4aa4c 100644 --- a/src/mnemonics/russian.h +++ b/src/mnemonics/russian.h @@ -51,9 +51,7 @@ namespace Language class Russian: public Base
{
public:
- Russian()
- {
- word_list = new std::vector<std::string>({
+ Russian(): Base("Russian", std::vector<std::string>({
"абажур",
"абзац",
"абонент",
@@ -1680,11 +1678,8 @@ namespace Language "яхта",
"ячейка",
"ящик"
- });
- unique_prefix_length = 4;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "Russian";
+ }), 4) + { populate_maps();
}
};
diff --git a/src/mnemonics/spanish.h b/src/mnemonics/spanish.h index ec3a8991d..4b386a968 100644 --- a/src/mnemonics/spanish.h +++ b/src/mnemonics/spanish.h @@ -51,9 +51,7 @@ namespace Language class Spanish: public Base
{
public:
- Spanish()
- {
- word_list = new std::vector<std::string>({
+ Spanish(): Base("Spanish", std::vector<std::string>({
"ábaco",
"abdomen",
"abeja",
@@ -1680,12 +1678,9 @@ namespace Language "risa",
"ritmo",
"rito"
- });
- unique_prefix_length = 4;
- word_map = new std::unordered_map<std::string, uint32_t>;
- trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
- language_name = "Spanish";
- populate_maps();
+ }), 4) + { + populate_maps(ALLOW_SHORT_WORDS);
}
};
}
diff --git a/tests/unit_tests/mnemonics.cpp b/tests/unit_tests/mnemonics.cpp index c0026a00d..94e226247 100644 --- a/tests/unit_tests/mnemonics.cpp +++ b/tests/unit_tests/mnemonics.cpp @@ -38,6 +38,11 @@ #include "mnemonics/spanish.h" #include "mnemonics/portuguese.h" #include "mnemonics/japanese.h" +#include "mnemonics/german.h" +#include "mnemonics/italian.h" +#include "mnemonics/russian.h" +#include "mnemonics/french.h" +#include "mnemonics/dutch.h" #include "mnemonics/old_english.h" #include "mnemonics/language_base.h" #include "mnemonics/singleton.h" @@ -133,6 +138,19 @@ namespace } } +TEST(mnemonics, consistency) +{ + try { + std::vector<std::string> language_list; + crypto::ElectrumWords::get_language_list(language_list); + } + catch(const std::exception &e) + { + std::cout << "Error initializing mnemonics: " << e.what() << std::endl; + ASSERT_TRUE(false); + } +} + TEST(mnemonics, all_languages) { srand(time(NULL)); @@ -141,11 +159,22 @@ TEST(mnemonics, all_languages) Language::Singleton<Language::Spanish>::instance(), Language::Singleton<Language::Portuguese>::instance(), Language::Singleton<Language::Japanese>::instance(), + Language::Singleton<Language::German>::instance(), + Language::Singleton<Language::Italian>::instance(), + Language::Singleton<Language::Russian>::instance(), + Language::Singleton<Language::French>::instance(), + Language::Singleton<Language::Dutch>::instance(), }); for (std::vector<Language::Base*>::iterator it = languages.begin(); it != languages.end(); it++) { - test_language(*(*it)); + try { + test_language(*(*it)); + } + catch (const std::exception &e) { + std::cout << "Error testing " << (*it)->get_language_name() << " language: " << e.what() << std::endl; + ASSERT_TRUE(false); + } } } |