From 7f3b627aa4d9e55e25a445de47b5badd9ed5d304 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Sat, 27 Jan 2018 17:33:26 +0100 Subject: [PATCH 1/5] make wallet.get_address_index faster by storing an addr->index dict --- gui/qt/main_window.py | 2 ++ lib/wallet.py | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py index fb66005eb..593673213 100644 --- a/gui/qt/main_window.py +++ b/gui/qt/main_window.py @@ -62,6 +62,7 @@ from .fee_slider import FeeSlider from .util import * +from electrum.util import profiler class StatusBarButton(QPushButton): def __init__(self, icon, tooltip, func): @@ -325,6 +326,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): self.print_error('close_wallet', self.wallet.storage.path) run_hook('close_wallet', self.wallet) + @profiler def load_wallet(self, wallet): wallet.thread = TaskThread(self, self.on_error) self.wallet = wallet diff --git a/lib/wallet.py b/lib/wallet.py index a9dc646bc..11337bc94 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -340,6 +340,8 @@ class Abstract_Wallet(PrintError): return address in self.change_addresses def get_address_index(self, address): + if hasattr(self, '_addr_to_addr_index'): + return self._addr_to_addr_index[address] if address in self.receiving_addresses: return False, self.receiving_addresses.index(address) if address in self.change_addresses: @@ -1029,8 +1031,10 @@ class Abstract_Wallet(PrintError): def is_used(self, address): h = self.history.get(address,[]) + if len(h) == 0: + return False c, u, x = self.get_addr_balance(address) - return len(h) > 0 and c + u + x == 0 + return c + u + x == 0 def is_empty(self, address): c, u, x = self.get_addr_balance(address) @@ -1647,6 +1651,14 @@ class Deterministic_Wallet(Abstract_Wallet): if n > nmax: nmax = n return nmax + 1 + def load_addresses(self): + super().load_addresses() + self._addr_to_addr_index = {} # key: address, value: (is_change, index) + for i, addr in enumerate(self.receiving_addresses): + self._addr_to_addr_index[addr] = (False, i) + for i, addr in enumerate(self.change_addresses): + self._addr_to_addr_index[addr] = (True, i) + def create_new_address(self, for_change=False): assert type(for_change) is bool addr_list = self.change_addresses if for_change else self.receiving_addresses @@ -1654,6 +1666,7 @@ class Deterministic_Wallet(Abstract_Wallet): x = self.derive_pubkeys(for_change, n) address = self.pubkeys_to_address(x) addr_list.append(address) + self._addr_to_addr_index[address] = (for_change, n) self.save_addresses() self.add_address(address) return address @@ -1685,12 +1698,11 @@ class Deterministic_Wallet(Abstract_Wallet): def is_beyond_limit(self, address, is_change): addr_list = self.get_change_addresses() if is_change else self.get_receiving_addresses() - i = addr_list.index(address) - prev_addresses = addr_list[:max(0, i)] + i = self.get_address_index(address)[1] limit = self.gap_limit_for_change if is_change else self.gap_limit - if len(prev_addresses) < limit: + if i < limit: return False - prev_addresses = prev_addresses[max(0, i - limit):] + prev_addresses = addr_list[max(0, i - limit):max(0, i)] for addr in prev_addresses: if self.history.get(addr): return False From 1c67cfe01b5cb21e2aa806eac1b0acb8a6004073 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Sat, 27 Jan 2018 17:51:24 +0100 Subject: [PATCH 2/5] optimise wallet.is_mine --- lib/wallet.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/wallet.py b/lib/wallet.py index 11337bc94..b836394ad 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -332,6 +332,10 @@ class Abstract_Wallet(PrintError): return changed def is_mine(self, address): + if hasattr(self, '_addr_to_addr_index'): # Deterministic_Wallet + return address in self._addr_to_addr_index + if hasattr(self, 'addresses'): # Imported_Wallet + return address in self.addresses return address in self.get_addresses() def is_change(self, address): From d1e2ca4bc543e6e5a13cc82a5e9bc72a7d1486ef Mon Sep 17 00:00:00 2001 From: SomberNight Date: Sat, 27 Jan 2018 18:16:31 +0100 Subject: [PATCH 3/5] make wallet.is_change faster --- lib/wallet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wallet.py b/lib/wallet.py index b836394ad..e38901e8e 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -341,7 +341,7 @@ class Abstract_Wallet(PrintError): def is_change(self, address): if not self.is_mine(address): return False - return address in self.change_addresses + return self.get_address_index(address)[0] def get_address_index(self, address): if hasattr(self, '_addr_to_addr_index'): From d92a6d46eb4b534100ceafefa7379ea4f425dd5c Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 30 Jan 2018 00:44:40 +0100 Subject: [PATCH 4/5] wallet.is_mine: use inheritance for more readable code --- lib/wallet.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/wallet.py b/lib/wallet.py index e38901e8e..7087e9181 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -332,10 +332,6 @@ class Abstract_Wallet(PrintError): return changed def is_mine(self, address): - if hasattr(self, '_addr_to_addr_index'): # Deterministic_Wallet - return address in self._addr_to_addr_index - if hasattr(self, 'addresses'): # Imported_Wallet - return address in self.addresses return address in self.get_addresses() def is_change(self, address): @@ -1466,6 +1462,9 @@ class Imported_Wallet(Simple_Wallet): def is_beyond_limit(self, address, is_change): return False + def is_mine(self, address): + return address in self.addresses + def get_fingerprint(self): return '' @@ -1712,6 +1711,9 @@ class Deterministic_Wallet(Abstract_Wallet): return False return True + def is_mine(self, address): + return address in self._addr_to_addr_index + def get_master_public_keys(self): return [self.get_master_public_key()] From ac69f628fe889e18695852cd3f9033a8f5b38aad Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 30 Jan 2018 00:59:12 +0100 Subject: [PATCH 5/5] clean-up wallet.get_address_index --- lib/wallet.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/wallet.py b/lib/wallet.py index 7087e9181..adc285e83 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -340,13 +340,7 @@ class Abstract_Wallet(PrintError): return self.get_address_index(address)[0] def get_address_index(self, address): - if hasattr(self, '_addr_to_addr_index'): - return self._addr_to_addr_index[address] - if address in self.receiving_addresses: - return False, self.receiving_addresses.index(address) - if address in self.change_addresses: - return True, self.change_addresses.index(address) - raise Exception("Address not found", address) + raise NotImplementedError() def export_private_key(self, address, password): """ extended WIF format """ @@ -1714,6 +1708,9 @@ class Deterministic_Wallet(Abstract_Wallet): def is_mine(self, address): return address in self._addr_to_addr_index + def get_address_index(self, address): + return self._addr_to_addr_index[address] + def get_master_public_keys(self): return [self.get_master_public_key()]