tMerge pull request #1260 from kyuupichan/avoid_addr_reuse - electrum - Electrum Bitcoin wallet (HTM) git clone https://git.parazyd.org/electrum (DIR) Log (DIR) Files (DIR) Refs (DIR) Submodules --- (DIR) commit ed5747fbcf5b1f9f9053c8af4c7c18dad92e22df (DIR) parent 48f98f75dbf4b043949f08f3a84e8a8e1adbdc62 (HTM) Author: ThomasV <electrumdev@gmail.com> Date: Sat, 30 May 2015 10:20:47 +0200 Merge pull request #1260 from kyuupichan/avoid_addr_reuse Avoid change address reuse if possible Diffstat: M lib/wallet.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) --- (DIR) diff --git a/lib/wallet.py b/lib/wallet.py t@@ -142,7 +142,7 @@ class Abstract_Wallet(object): def __init__(self, storage): self.storage = storage self.electrum_version = ELECTRUM_VERSION - self.gap_limit_for_change = 3 # constant + self.gap_limit_for_change = 6 # constant # saved fields self.seed_version = storage.get('seed_version', NEW_SEED_VERSION) self.use_change = storage.get('use_change',True) t@@ -170,7 +170,7 @@ class Abstract_Wallet(object): self.unverified_tx = {} # Verified transactions. Each value is a (height, timestamp, block_pos) tuple. Access with self.lock. self.verified_tx = storage.get('verified_tx3',{}) - + # there is a difference between wallet.up_to_date and interface.is_up_to_date() # interface.is_up_to_date() returns true when all requests have been answered and processed # wallet.up_to_date is true when the wallet is synchronized (stronger requirement) t@@ -398,7 +398,7 @@ class Abstract_Wallet(object): if tx_hash not in self.verified_tx and tx_height <= self.get_local_height(): txs.append((tx_hash, tx_height)) return txs - + def undo_verifications(self, height): '''Used by the verifier when a reorg has happened''' txs = [] t@@ -690,7 +690,7 @@ class Abstract_Wallet(object): _type, x, v = txo if _type == 'address': addr = x - elif _type == 'pubkey': + elif _type == 'pubkey': addr = public_key_to_bc_address(x.decode('hex')) else: addr = None t@@ -887,10 +887,17 @@ class Abstract_Wallet(object): # send change to one of the accounts involved in the tx address = inputs[0].get('address') account, _ = self.get_address_index(address) - if not self.use_change or not self.accounts[account].has_change(): - change_addr = address + if self.use_change and self.accounts[account].has_change(): + # New change addresses are created only after a few confirmations. + # Choose an unused change address if any, otherwise take one at random + change_addrs = self.accounts[account].get_addresses(1)[-self.gap_limit_for_change:] + for change_addr in change_addrs: + if self.get_num_tx(change_addr) == 0: + break + else: + change_addr = random.choice(change_addrs) else: - change_addr = self.accounts[account].get_addresses(1)[-self.gap_limit_for_change] + change_addr = address # if change is above dust threshold, add a change output. change_amount = total - ( amount + fee )