Browse Source

mnemonic: add type hints

master
SomberNight 2 years ago
parent
commit
7007a0c1c9
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 2
      electrum/keystore.py
  2. 25
      electrum/mnemonic.py
  3. 2
      electrum/plugins/trustedcoin/trustedcoin.py

2
electrum/keystore.py

@ -1159,7 +1159,7 @@ def from_seed(seed, passphrase, is_p2sh=False):
keystore = BIP32_KeyStore({}) keystore = BIP32_KeyStore({})
keystore.add_seed(seed) keystore.add_seed(seed)
keystore.passphrase = passphrase keystore.passphrase = passphrase
bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase) bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase=passphrase)
if t == 'standard': if t == 'standard':
der = "m/" der = "m/"
xtype = 'standard' xtype = 'standard'

25
electrum/mnemonic.py

@ -27,7 +27,7 @@ import math
import hashlib import hashlib
import unicodedata import unicodedata
import string import string
from typing import Sequence, Dict from typing import Sequence, Dict, Iterator, Optional
from types import MappingProxyType from types import MappingProxyType
from .util import resource_path, bfh, randrange from .util import resource_path, bfh, randrange
@ -69,10 +69,11 @@ CJK_INTERVALS = [
(0xA490, 0xA4CF, 'Yi Radicals'), (0xA490, 0xA4CF, 'Yi Radicals'),
] ]
def is_CJK(c): def is_CJK(c: str) -> bool:
n = ord(c) n = ord(c)
for imin, imax, name in CJK_INTERVALS: for imin, imax, name in CJK_INTERVALS:
if n>=imin and n<=imax: return True if imin <= n <= imax:
return True
return False return False
@ -110,13 +111,13 @@ class Wordlist(tuple):
index_from_word = {w: i for i, w in enumerate(words)} index_from_word = {w: i for i, w in enumerate(words)}
self._index_from_word = MappingProxyType(index_from_word) # no mutation self._index_from_word = MappingProxyType(index_from_word) # no mutation
def index(self, word, start=None, stop=None) -> int: def index(self, word: str, start=None, stop=None) -> int:
try: try:
return self._index_from_word[word] return self._index_from_word[word]
except KeyError as e: except KeyError as e:
raise ValueError from e raise ValueError from e
def __contains__(self, word) -> bool: def __contains__(self, word: str) -> bool:
try: try:
self.index(word) self.index(word)
except ValueError: except ValueError:
@ -125,7 +126,7 @@ class Wordlist(tuple):
return True return True
@classmethod @classmethod
def from_file(cls, filename) -> 'Wordlist': def from_file(cls, filename: str) -> 'Wordlist':
path = resource_path('wordlist', filename) path = resource_path('wordlist', filename)
if path not in _WORDLIST_CACHE: if path not in _WORDLIST_CACHE:
with open(path, 'r', encoding='utf-8') as f: with open(path, 'r', encoding='utf-8') as f:
@ -157,7 +158,7 @@ class Mnemonic(Logger):
# Seed derivation does not follow BIP39 # Seed derivation does not follow BIP39
# Mnemonic phrase uses a hash based checksum, instead of a wordlist-dependent checksum # Mnemonic phrase uses a hash based checksum, instead of a wordlist-dependent checksum
def __init__(self, lang=None): def __init__(self, lang: str = None):
Logger.__init__(self) Logger.__init__(self)
lang = lang or 'en' lang = lang or 'en'
self.logger.info(f'language {lang}') self.logger.info(f'language {lang}')
@ -166,14 +167,14 @@ class Mnemonic(Logger):
self.logger.info(f"wordlist has {len(self.wordlist)} words") self.logger.info(f"wordlist has {len(self.wordlist)} words")
@classmethod @classmethod
def mnemonic_to_seed(self, mnemonic, passphrase) -> bytes: def mnemonic_to_seed(cls, mnemonic: str, *, passphrase: Optional[str]) -> bytes:
PBKDF2_ROUNDS = 2048 PBKDF2_ROUNDS = 2048
mnemonic = normalize_text(mnemonic) mnemonic = normalize_text(mnemonic)
passphrase = passphrase or '' passphrase = passphrase or ''
passphrase = normalize_text(passphrase) passphrase = normalize_text(passphrase)
return hashlib.pbkdf2_hmac('sha512', mnemonic.encode('utf-8'), b'electrum' + passphrase.encode('utf-8'), iterations = PBKDF2_ROUNDS) return hashlib.pbkdf2_hmac('sha512', mnemonic.encode('utf-8'), b'electrum' + passphrase.encode('utf-8'), iterations = PBKDF2_ROUNDS)
def mnemonic_encode(self, i): def mnemonic_encode(self, i: int) -> str:
n = len(self.wordlist) n = len(self.wordlist)
words = [] words = []
while i: while i:
@ -182,12 +183,12 @@ class Mnemonic(Logger):
words.append(self.wordlist[x]) words.append(self.wordlist[x])
return ' '.join(words) return ' '.join(words)
def get_suggestions(self, prefix): def get_suggestions(self, prefix: str) -> Iterator[str]:
for w in self.wordlist: for w in self.wordlist:
if w.startswith(prefix): if w.startswith(prefix):
yield w yield w
def mnemonic_decode(self, seed): def mnemonic_decode(self, seed: str) -> int:
n = len(self.wordlist) n = len(self.wordlist)
words = seed.split() words = seed.split()
i = 0 i = 0
@ -197,7 +198,7 @@ class Mnemonic(Logger):
i = i*n + k i = i*n + k
return i return i
def make_seed(self, *, seed_type=None, num_bits=None) -> str: def make_seed(self, *, seed_type: str = None, num_bits: int = None) -> str:
from .keystore import bip39_is_checksum_valid from .keystore import bip39_is_checksum_valid
if seed_type is None: if seed_type is None:
seed_type = 'segwit' seed_type = 'segwit'

2
electrum/plugins/trustedcoin/trustedcoin.py

@ -548,7 +548,7 @@ class TrustedCoinPlugin(BasePlugin):
def get_xkeys(self, seed, t, passphrase, derivation): def get_xkeys(self, seed, t, passphrase, derivation):
assert is_any_2fa_seed_type(t) assert is_any_2fa_seed_type(t)
xtype = 'standard' if t == '2fa' else 'p2wsh' xtype = 'standard' if t == '2fa' else 'p2wsh'
bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase) bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase=passphrase)
rootnode = BIP32Node.from_rootseed(bip32_seed, xtype=xtype) rootnode = BIP32Node.from_rootseed(bip32_seed, xtype=xtype)
child_node = rootnode.subkey_at_private_derivation(derivation) child_node = rootnode.subkey_at_private_derivation(derivation)
return child_node.to_xprv(), child_node.to_xpub() return child_node.to_xprv(), child_node.to_xpub()

Loading…
Cancel
Save