From 0f29984f07ea73ffff4397a37544019b66732b15 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Sun, 31 May 2015 10:37:43 +0900 Subject: [PATCH] Speed up freezing and unfreezing of many addresses Speedup mainly from writing to storage only once. Make frozen_addresses a set in memory, as sets give cleaner code and are more efficient. Minor change in behaviour: command line freezing used to return False if the address isn't in the wallet OR the address was already frozen. Now it returns more like a success code: it returns False only if the address isn't in the wallet regardless of frozen state. Similarly for unfreezing. --- gui/gtk.py | 7 ++----- gui/qt/main_window.py | 13 ++++--------- lib/commands.py | 4 ++-- lib/wallet.py | 25 ++++++++++--------------- 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/gui/gtk.py b/gui/gtk.py index 775f147d1..4f4950db3 100644 --- a/gui/gtk.py +++ b/gui/gtk.py @@ -1079,10 +1079,7 @@ class ElectrumWindow: path, col = treeview.get_cursor() if path: address = liststore.get_value( liststore.get_iter(path), 0) - if address in wallet.frozen_addresses: - wallet.unfreeze(address) - else: - wallet.freeze(address) + wallet.set_frozen_state([address], not wallet.is_frozen(address)) self.update_receiving_tab() button.connect("clicked", freeze_address, treeview, liststore, self.wallet) button.show() @@ -1151,7 +1148,7 @@ class ElectrumWindow: if address in self.wallet.imported_keys.keys(): Type = "I" c, u, x = self.wallet.get_addr_balance(address) - if address in self.wallet.frozen_addresses: Type = Type + "F" + if self.wallet.is_frozen(address): Type = Type + "F" label = self.wallet.labels.get(address) h = self.wallet.history.get(address,[]) n = len(h) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py index 0cebd292a..d41ac527e 100644 --- a/gui/qt/main_window.py +++ b/gui/qt/main_window.py @@ -1291,13 +1291,8 @@ class ElectrumWindow(QMainWindow): run_hook('do_clear') - def set_addrs_frozen(self,addrs,freeze): - for addr in addrs: - if not addr: continue - if addr in self.wallet.frozen_addresses and not freeze: - self.wallet.unfreeze(addr) - elif addr not in self.wallet.frozen_addresses and freeze: - self.wallet.freeze(addr) + def set_frozen_state(self, addrs, freeze): + self.wallet.set_frozen_state(addrs, freeze) self.update_address_tab() self.update_fee(False) @@ -1416,9 +1411,9 @@ class ElectrumWindow(QMainWindow): menu.addAction(_("View on block explorer"), lambda: webbrowser.open(addr_URL)) if any(addr not in self.wallet.frozen_addresses for addr in addrs): - menu.addAction(_("Freeze"), lambda: self.set_addrs_frozen(addrs, True)) + menu.addAction(_("Freeze"), lambda: self.set_frozen_state(addrs, True)) if any(addr in self.wallet.frozen_addresses for addr in addrs): - menu.addAction(_("Unfreeze"), lambda: self.set_addrs_frozen(addrs, False)) + menu.addAction(_("Unfreeze"), lambda: self.set_frozen_state(addrs, False)) def can_send(addr): return addr not in self.wallet.frozen_addresses and self.wallet.get_addr_balance(addr) != (0, 0) diff --git a/lib/commands.py b/lib/commands.py index 49847e47d..9487d60b5 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -322,10 +322,10 @@ class Commands: return {'address':address, 'redeemScript':redeem_script} def freeze(self,addr): - return self.wallet.freeze(addr) + return self.wallet.set_frozen_state([addr], True) def unfreeze(self,addr): - return self.wallet.unfreeze(addr) + return self.wallet.set_frozen_state([addr], False) def getprivatekeys(self, addr): return self.wallet.get_private_key(addr, self.password) diff --git a/lib/wallet.py b/lib/wallet.py index 908a6a21a..592866213 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -149,7 +149,7 @@ class Abstract_Wallet(object): self.use_encryption = storage.get('use_encryption', False) self.seed = storage.get('seed', '') # encrypted self.labels = storage.get('labels', {}) - self.frozen_addresses = storage.get('frozen_addresses',[]) + self.frozen_addresses = set(storage.get('frozen_addresses',[])) self.stored_height = storage.get('stored_height', 0) # last known height (for offline mode) self.history = storage.get('addr_history',{}) # address -> list(txid, height) @@ -1016,21 +1016,16 @@ class Abstract_Wallet(object): def is_frozen(self, addr): return addr in self.frozen_addresses - def freeze(self,addr): - if self.is_mine(addr) and self.is_frozen(addr): - self.frozen_addresses.append(addr) - self.storage.put('frozen_addresses', self.frozen_addresses, True) - return True - else: - return False - - def unfreeze(self,addr): - if self.is_mine(addr) and self.is_frozen(addr): - self.frozen_addresses.remove(addr) - self.storage.put('frozen_addresses', self.frozen_addresses, True) + def set_frozen_state(self, addrs, freeze): + '''Set frozen state of the addresses to FREEZE, True or False''' + if all(self.is_mine(addr) for addr in addrs): + if freeze: + self.frozen_addresses |= set(addrs) + else: + self.frozen_addresses -= set(addrs) + self.storage.put('frozen_addresses', list(self.frozen_addresses), True) return True - else: - return False + return False def set_verifier(self, verifier): self.verifier = verifier