trezor / python-mnemonic

:snake: Mnemonic code for generating deterministic keys, BIP39
https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
MIT License
843 stars 372 forks source link

read wordlist from specefic file out of the package #94

Closed salamzadeh closed 10 months ago

salamzadeh commented 2 years ago

i added some code for read wordlist from specefic file out of the package

prusnak commented 2 years ago

There is a lot of code reuse, you can refactor it like this to avoid the code reuse:

        d = os.path.join(os.path.dirname(__file__), f"wordlist/{language}.txt")
        if not(os.path.exists(d) and os.path.isfile(d)):
            d = language
            if not(os.path.exists(d) and os.path.isfile(d)):
                raise ConfigurationError("Language not found")
        with open(d, "r", encoding="utf-8") as f:
            ...
matejcik commented 2 years ago

please add a separate argument wordlist: Optional[str] = None then

if wordlist is None:
     wordlist = os.path.join(os.path.dirname(__file__), f"wordlist/{language}.txt")
# use wordlist in place of d in the subsequent code
salamzadeh commented 2 years ago

i chaged the init method like this :

   def __init__(self, language: str = "english", wordlist: Optional[str] = None):
        self.language = language
        self.radix = 2048
        if wordlist is None:
            wordlist = os.path.join(os.path.dirname(__file__), f"wordlist/{language}.txt")
            if os.path.exists(wordlist) and os.path.isfile(wordlist):
                with open(wordlist, "r", encoding="utf-8") as f:
                    self.wordlist = [w.strip() for w in f.readlines()]
                if len(self.wordlist) != self.radix:
                    raise ConfigurationError(
                        f"Wordlist should contain {self.radix} words, but it's {len(self.wordlist)} words long instead."
                    )
            else:
                raise ConfigurationError("Language not detected")
        else:
            self.wordlist = wordlist # if you use custom wordlist you need to set language parameter other than english
            if len(self.wordlist) != self.radix:
                raise ConfigurationError(
                    f"Wordlist should contain {self.radix} words, but it's {len(self.wordlist)} words long instead."
                )

if it is okey, i push it into master and send pull request again. Notic : If you use custom wordlist, you must set a language parameter other than 'english'

matejcik commented 2 years ago

i originally thought that wordlist would be a path to the wordlist file, but this is probably even better. One modification: type of wordlist should be Optional[List[str]]

also you're needlessly repeating the check "len(wordlist) == radix" instead:

if wordlist is None:
    d = os.path.join(...)
    if not exists(d):
        raise ConfigurationError
    with open(...):
        wordlist = ....

if len(wordlist) != self.radix:
    raise ...

self.wordlist = wordlist

please push the modified code to your master (not force-push, but on top of the existing changes), then the PR will be updated automatically

matejcik commented 2 years ago

If you use custom wordlist, you must set a language parameter other than 'english'

why?

salamzadeh commented 2 years ago

Becacuse in to_entropy method you checked language for use_binary_search and when i used a custom wordlist with 2048 words, i got this error

\mnemonic.py", line 171, in to_entropy
    raise LookupError('Unable to find "%s" in word list.' % word)
LookupError: Unable to find "link" in word list.

I checked my list, the word link was exist in my custom wordlist but binary search raise with this error

prusnak commented 2 years ago

You should set self.language to None if custom wordlist is provided.

matejcik commented 10 months ago

modified and merged in 41f1c6bd0d079bc87907a3fcb3618ce24f0e620f