fix multiple hash error

This commit is contained in:
Dario 2020-03-09 12:37:06 +01:00
parent 72f493c561
commit a94f4a1abe
3 changed files with 84 additions and 7 deletions

View File

@ -3,6 +3,7 @@
#include "mnemonic.h"
#include <memory>
#include <cstring>
#include <assert.h>
#include "../dependencies/tinf/src/tinf.h"
#include "DRRandom.h"
@ -51,6 +52,11 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original
//printf("c[Mnemonic::%s] uncompressing success\n", __FUNCTION__);
// fill words in array and hashList
//FILE* f = fopen("uncompressed_buffer", "a");
//fwrite(uncompressed_buffer, sizeof(char), original_size, f);
//fclose(f);
unsigned short cursor = 0;
u32 word_begin = 0, word_end = 0;
@ -58,7 +64,7 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original
if (cursor >= 2048) {
return -3;
}
if (uncompressed_buffer[i] == ',') {
if (uncompressed_buffer[i] == ',' || i == original_size - 1) {
word_end = i;
u32 word_size = word_end - word_begin;
@ -67,12 +73,16 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original
//printf("%s\n", uncompressed_buffer);
continue;
}
if (uncompressed_buffer[i] != ',') {
//printf("last char: %c\n", uncompressed_buffer[i]);
word_size++;
}
// + 1 for null terminating
mWords[cursor] = (char*)malloc(word_size + 1);
// fill hash list for fast reverse lookup
memset(mWords[cursor], 0, word_size + 1);
if (word_begin + word_size >= original_size) {
if (word_begin + word_size > original_size) {
printf("c[Mnemonic::%s] word goes out of array bounds\n", __FUNCTION__);
free(uncompressed_buffer);
return -4;
@ -80,12 +90,39 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original
memcpy(mWords[cursor], &uncompressed_buffer[word_begin], word_size);
//char bu[256]; memset(bu, 0, 256);
//memcpy(bu, &uncompressed_buffer[word_begin - 1], 10);
//memcpy(bu, &uncompressed_buffer[word_begin - 1], 15);
//printf("word (%d): %s\n", cursor, bu);
DHASH word_hash = DRMakeStringHash(mWords[cursor]);
//mWordHashIndices.addByHash(word_hash, (void*)cursor);
mWordHashIndices.insert(WordHashEntry(word_hash, cursor));
auto result = mWordHashIndices.insert(WordHashEntry(word_hash, cursor));
if (!result.second) {
// handle hash collision
auto it_collide = mHashCollisionWords.find(word_hash);
if (it_collide == mHashCollisionWords.end()) {
std::map<std::string, unsigned short> collidedWordsMap;
collidedWordsMap.insert(HashCollideWordEntry(mWords[result.first->second], result.first->second));
auto result2 = mHashCollisionWords.insert(std::pair<DHASH, std::map<std::string, unsigned short>>(word_hash, collidedWordsMap));
if (!result2.second) {
free(uncompressed_buffer);
printf("c[Mnemonc::%s] error inserting hash collided word map\n", __FUNCTION__);
return -6;
}
it_collide = result2.first;
}
assert(it_collide != mHashCollisionWords.end());
auto result3 = it_collide->second.insert(HashCollideWordEntry(mWords[cursor], cursor));
if (!result3.second) {
free(uncompressed_buffer);
printf("c[Mnemonc::%s] error inserting hash collided word entry\n", __FUNCTION__);
return -7;
}
//printf("c[Mnemonic::%s] error inserting word, hash collision?\n", __FUNCTION__);
//printf("current word: %s\n", mWords[cursor]);
//printf("existing word: %s\n", mWords[result.first->second]);
}
word_begin = i + 1;
cursor++;
@ -93,6 +130,12 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original
}
//printf("c[Mnemonic::%s] before freeing uncompressed buffer \n", __FUNCTION__);
free(uncompressed_buffer);
// remove hash colliding entrys from regular map
for (auto it_collide = mHashCollisionWords.begin(); it_collide != mHashCollisionWords.end(); it_collide++) {
mWordHashIndices.erase(it_collide->first);
}
return 0;
}
//printf("c[Mnemonic::%s] before freeing buffer \n", __FUNCTION__);
@ -100,6 +143,31 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original
return -5;
}
short Mnemonic::getWordIndex(const char* word) const
{
DHASH word_hash = DRMakeStringHash(word);
auto it = mWordHashIndices.find(word_hash);
if (it != mWordHashIndices.end()) {
return it->second;
}
auto it_collide = mHashCollisionWords.find(word_hash);
if (it_collide != mHashCollisionWords.end()) {
auto it_collided_word = it_collide->second.find(word);
if (it_collided_word != it_collide->second.end()) {
return it_collided_word->second;
}
}
return -1;
}
/*
bool Mnemonic::isWordExist(const std::string& word) const
{
return getWordIndex(word.data()) != -1;
//DHASH word_hash = DRMakeStringHash(word.data());
//return mWordHashIndices.find(word_hash) != mWordHashIndices.end();
}
*/
void Mnemonic::clear()
{
@ -111,6 +179,7 @@ void Mnemonic::clear()
}
memset(mWords, 0, 2048);
mWordHashIndices.clear();
mHashCollisionWords.clear();
}
std::string Mnemonic::getCompleteWordList()

View File

@ -30,9 +30,9 @@ public:
int init(void(*fill_words_func)(unsigned char*), unsigned int original_size, unsigned int compressed_size);
inline const char* getWord(unsigned int index) const { if (index < 2048 && index >= 0) return mWords[index]; return nullptr; }
inline unsigned short getWordIndex(const char* word) const { DHASH word_hash = DRMakeStringHash(word); return mWordHashIndices.find(word_hash)->second; }
inline bool isWordExist(const std::string& word) const { DHASH word_hash = DRMakeStringHash(word.data()); return mWordHashIndices.find(word_hash) != mWordHashIndices.end(); }
inline const char* getWord(short index) const { if (index < 2048 && index >= 0) return mWords[index]; return nullptr; }
short getWordIndex(const char* word) const;
inline bool isWordExist(const std::string& word) const { return getWordIndex(word.data()) != -1; }
// using only for debugging
std::string getCompleteWordList();
@ -44,10 +44,17 @@ protected:
void clear();
struct HashCollisionWords {
DHASH hash;
std::vector<std::string> words;
};
char* mWords[2048];
//DRHashList mWordHashIndices;
typedef std::pair<DHASH, unsigned short> WordHashEntry;
typedef std::pair<std::string, unsigned short> HashCollideWordEntry;
std::map<DHASH, unsigned short> mWordHashIndices;
std::map<DHASH, std::map<std::string, unsigned short>> mHashCollisionWords;
Poco::Mutex mWorkingMutex;
};

View File

@ -66,6 +66,7 @@ namespace ServerConfig {
printf("[%s] error init bip0039 mnemonic set, error nr: %d\n", __FUNCTION__, iResult);
return false;
}
//g_Mnemonic_WordLists[i].printToFile("en_words.txt");
break;
default: printf("[%s] unknown MnemonicType\n", __FUNCTION__); return false;
}