added bit_per_word method
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+
+"""MnemonicDictionaries class definition and associated tests"""
import math
import os
class MnemonicDictionaries:
- """Manage dictionary based conversion between index list and mnemonic phrase"""
+ """Manage dictionary based conversions between entropy,
+ word indexes, and mnemonic phrase
+ """
def __init__(self):
# https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt
@@ -15,6 +21,7 @@ class MnemonicDictionaries:
languages = self.language_files.keys()
# empy dictionaries
self.dictionaries = dict(zip(languages, [None]*len(languages)))
+ self.bpw = dict(zip(languages, [None]*len(languages)))
def load_language_if_not_available(self, lang):
assert lang in self.dictionaries.keys(), "unknown language" + lang
@@ -25,17 +32,25 @@ class MnemonicDictionaries:
# folder,
filename)
lines = open(path, 'r').readlines()
- assert len(lines) % 2 == 0, "dictionary with an odd number of words"
+ # no enforcing of 2048 lines...
+ words = len(lines)
+ assert words % 2 == 0, "dictionary with an odd number of words"
+ self.bpw[lang] = int(math.log(words, 2))
# clean up and normalization are missing, but removal of \n
self.dictionaries[lang] = [line[:-1] for line in lines]
+ def bit_per_word(self, lang):
+ self.load_language_if_not_available(lang)
+ return self.bpw[lang]
+
def indexes_from_entropy(self, entropy, lang):
self.load_language_if_not_available(lang)
assert int(entropy, 2) >= 0, "entropy must be a binary string"
- bpw = int(math.log(len(self.dictionaries[lang]), 2))
- words = len(entropy)//bpw
- indexes = [int(entropy[i*bpw:(i+1)*bpw], 2) for i in range(0, words)]
+ words = len(entropy)//self.bpw[lang]
+ # to be revised:
+ # left-most bits are used, any traling extra are unused
+ indexes = [int(entropy[i*self.bpw[lang]:(i+1)*self.bpw[lang]], 2) for i in range(0, words)]
return indexes
def mnemonic_from_indexes(self, indexes, lang):
@@ -57,20 +72,20 @@ class MnemonicDictionaries:
def entropy_from_indexes(self, indexes, lang):
self.load_language_if_not_available(lang)
- bpw = int(math.log(len(self.dictionaries[lang]), 2))
entropy = ''
for i in indexes:
word_bits = bin(i)
word_bits = word_bits[2:]
- word_bits = word_bits.zfill(bpw)
+ word_bits = word_bits.zfill(self.bpw[lang])
entropy += word_bits
return entropy
mnemonic_dict = MnemonicDictionaries()
def main():
- mnemonic = "ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic"
lang = "en"
+ assert mnemonic_dict.bit_per_word(lang) == 11
+ mnemonic = "ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic"
test_vector = mnemonic_dict.indexes_from_mnemonic(mnemonic, lang)
assert test_vector == [1268, 535, 810, 685, 433, 811, 1385, 1790, 421, 570, 567, 1313]
assert mnemonic == mnemonic_dict.mnemonic_from_indexes(test_vector, lang)
