From f73b6b5d2398f14b353fbdd83145214b157a02ad Mon Sep 17 00:00:00 2001 From: SomberNight Date: Mon, 9 Dec 2019 03:35:20 +0100 Subject: [PATCH] keystore: cache derive_pubkey --- electrum/base_wizard.py | 2 +- electrum/keystore.py | 16 +++++++++++----- run_electrum | 4 ++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py index 54cee186d..bb757a5f2 100644 --- a/electrum/base_wizard.py +++ b/electrum/base_wizard.py @@ -369,7 +369,7 @@ class BaseWizard(Logger): elif purpose == HWD_SETUP_DECRYPT_WALLET: derivation = get_derivation_used_for_hw_device_encryption() xpub = self.plugin.get_xpub(device_info.device.id_, derivation, 'standard', self) - password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()) + password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()).hex() try: storage.decrypt(password) except InvalidPassword: diff --git a/electrum/keystore.py b/electrum/keystore.py index 572771c9c..95c6cb239 100644 --- a/electrum/keystore.py +++ b/electrum/keystore.py @@ -28,6 +28,7 @@ from unicodedata import normalize import hashlib import re from typing import Tuple, TYPE_CHECKING, Union, Sequence, Optional, Dict, List, NamedTuple +from functools import lru_cache from . import bitcoin, ecc, constants, bip32 from .bitcoin import deserialize_privkey, serialize_privkey @@ -402,8 +403,8 @@ class Xpub: self._root_fingerprint = root_fingerprint self._derivation_prefix = normalize_bip32_derivation(derivation_prefix) - def derive_pubkey(self, for_change, n) -> str: - for_change = int(for_change) + @lru_cache(maxsize=None) + def _derive_pubkey_bytes(self, for_change: int, n: int) -> bytes: assert for_change in (0, 1) xpub = self.xpub_change if for_change else self.xpub_receive if xpub is None: @@ -415,10 +416,15 @@ class Xpub: self.xpub_receive = xpub return self.get_pubkey_from_xpub(xpub, (n,)) + def derive_pubkey(self, for_change: int, n: int) -> str: + for_change = int(for_change) + assert for_change in (0, 1) + return self._derive_pubkey_bytes(for_change, n).hex() + @classmethod - def get_pubkey_from_xpub(self, xpub, sequence): + def get_pubkey_from_xpub(self, xpub: str, sequence) -> bytes: node = BIP32Node.from_xkey(xpub).subkey_at_public_derivation(sequence) - return node.eckey.get_public_key_hex(compressed=True) + return node.eckey.get_public_key_bytes(compressed=True) class BIP32_KeyStore(Deterministic_KeyStore, Xpub): @@ -692,7 +698,7 @@ class Hardware_KeyStore(KeyStore, Xpub): client = self.plugin.get_client(self) derivation = get_derivation_used_for_hw_device_encryption() xpub = client.get_xpub(derivation, "standard") - password = self.get_pubkey_from_xpub(xpub, ()) + password = self.get_pubkey_from_xpub(xpub, ()).hex() return password def has_usable_connection_with_device(self) -> bool: diff --git a/run_electrum b/run_electrum index efa742909..d68a368cf 100755 --- a/run_electrum +++ b/run_electrum @@ -178,7 +178,7 @@ def get_connected_hw_devices(plugins): return devices -def get_password_for_hw_device_encrypted_storage(plugins): +def get_password_for_hw_device_encrypted_storage(plugins) -> str: devices = get_connected_hw_devices(plugins) if len(devices) == 0: print_msg("Error: No connected hw device found. Cannot decrypt this wallet.") @@ -194,7 +194,7 @@ def get_password_for_hw_device_encrypted_storage(plugins): xpub = plugin.get_xpub(device_info.device.id_, derivation, 'standard', plugin.handler) except UserCancelled: sys.exit(0) - password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()) + password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()).hex() return password