tQt address list speedup: wallet.is_beyond_limit was slow - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 1ca6f6f306a1f9f376c7519b9b80662aa39768ee DIR parent a0b096dcb2292c2826f7beae173c529d335142f0 HTML Author: SomberNight <somber.night@protonmail.com> Date: Sat, 29 Feb 2020 07:28:13 +0100 Qt address list speedup: wallet.is_beyond_limit was slow Diffstat: M electrum/gui/qt/address_list.py | 3 ++- M electrum/wallet.py | 38 ++++++++++++++++--------------- 2 files changed, 22 insertions(+), 19 deletions(-) --- DIR diff --git a/electrum/gui/qt/address_list.py b/electrum/gui/qt/address_list.py t@@ -150,6 +150,7 @@ class AddressList(MyTreeView): self.refresh_headers() fx = self.parent.fx set_address = None + addresses_beyond_gap_limit = self.wallet.get_all_known_addresses_beyond_gap_limit() for address in addr_list: num = self.wallet.get_address_history_len(address) label = self.wallet.labels.get(address, '') t@@ -189,7 +190,7 @@ class AddressList(MyTreeView): # setup column 1 if self.wallet.is_frozen_address(address): address_item[self.Columns.ADDRESS].setBackground(ColorScheme.BLUE.as_color(True)) - if self.wallet.is_beyond_limit(address): + if address in addresses_beyond_gap_limit: address_item[self.Columns.ADDRESS].setBackground(ColorScheme.RED.as_color(True)) # add item count = self.model().rowCount() DIR diff --git a/electrum/wallet.py b/electrum/wallet.py t@@ -1866,7 +1866,7 @@ class Abstract_Wallet(AddressSynchronizer, ABC): pass @abstractmethod - def is_beyond_limit(self, address: str) -> bool: + def get_all_known_addresses_beyond_gap_limit(self) -> Set[str]: pass t@@ -1942,8 +1942,8 @@ class Imported_Wallet(Simple_Wallet): def is_change(self, address): return False - def is_beyond_limit(self, address): - return False + def get_all_known_addresses_beyond_gap_limit(self) -> Set[str]: + return set() def get_fingerprint(self): return '' t@@ -2231,21 +2231,23 @@ class Deterministic_Wallet(Abstract_Wallet): self.synchronize_sequence(False) self.synchronize_sequence(True) - def is_beyond_limit(self, address): - is_change, i = self.get_address_index(address) - limit = self.gap_limit_for_change if is_change else self.gap_limit - if i < limit: - return False - slice_start = max(0, i - limit) - slice_stop = max(0, i) - if is_change: - prev_addresses = self.get_change_addresses(slice_start=slice_start, slice_stop=slice_stop) - else: - prev_addresses = self.get_receiving_addresses(slice_start=slice_start, slice_stop=slice_stop) - for addr in prev_addresses: - if self.db.get_addr_history(addr): - return False - return True + def get_all_known_addresses_beyond_gap_limit(self): + # note that we don't stop at first large gap + found = set() + + def process_addresses(addrs, gap_limit): + rolling_num_unused = 0 + for addr in addrs: + if self.db.get_addr_history(addr): + rolling_num_unused = 0 + else: + if rolling_num_unused >= gap_limit: + found.add(addr) + rolling_num_unused += 1 + + process_addresses(self.get_receiving_addresses(), self.gap_limit) + process_addresses(self.get_change_addresses(), self.gap_limit_for_change) + return found def get_address_index(self, address) -> Optional[Sequence[int]]: return self.db.get_address_index(address) or self._ephemeral_addr_to_addr_index.get(address)