electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 0b7f8e74d50e9bf29c5e86e41b219ad1263794d5
parent 3dc69df7021e839ca1bab5bd7705fcb381adc614
Author: ThomasV <thomasv@gitorious>
Date:   Tue,  9 Sep 2014 17:31:15 +0200

move synchronize_account logic to account.py

Diffstat:
Mlib/account.py | 33+++++++++++++++++++++++++++++++++
Mlib/wallet.py | 130++++++++++++++++++++++++++-----------------------------------------------------
2 files changed, 76 insertions(+), 87 deletions(-)

diff --git a/lib/account.py b/lib/account.py @@ -75,11 +75,37 @@ class Account(object): def redeem_script(self, for_change, n): return None + def synchronize_sequence(self, wallet, for_change): + limit = self.gap_limit_for_change if for_change else self.gap_limit + while True: + addresses = self.get_addresses(for_change) + if len(addresses) < limit: + address = self.create_new_address(for_change) + wallet.add_address(address) + continue + if map( lambda a: wallet.address_is_old(a), addresses[-limit:] ) == limit*[False]: + break + else: + address = self.create_new_address(for_change) + wallet.add_address(address) + + def synchronize(self, wallet): + self.synchronize_sequence(wallet, False) + self.synchronize_sequence(wallet, True) + class PendingAccount(Account): def __init__(self, v): self.pending_address = v['pending'] + def synchronize(self, wallet): + if wallet.address_is_old(self.pending_address): + print_error( "creating account", account_id ) + xpub = wallet.master_public_keys[account_id] + account = BIP32_Account({'xpub':xpub}) + wallet.add_account(account_id, account) + #self.next_addresses.pop(account_id) + def get_addresses(self, is_change): return [self.pending_address] @@ -102,6 +128,9 @@ class ImportedAccount(Account): def __init__(self, d): self.keypairs = d['imported'] + def synchronize(self, wallet): + return + def get_addresses(self, for_change): return [] if for_change else sorted(self.keypairs.keys()) @@ -151,6 +180,8 @@ class ImportedAccount(Account): class OldAccount(Account): """ Privatekey(type,n) = Master_private_key + H(n|S|type) """ + gap_limit = 5 + gap_limit_for_change = 3 def __init__(self, v): Account.__init__(self, v) @@ -248,6 +279,8 @@ class OldAccount(Account): class BIP32_Account(Account): + gap_limit = 20 + gap_limit_for_change = 3 def __init__(self, v): Account.__init__(self, v) diff --git a/lib/wallet.py b/lib/wallet.py @@ -166,8 +166,6 @@ class Abstract_Wallet(object): self.fee_per_kb = int(storage.get('fee_per_kb', 10000)) - self.next_addresses = storage.get('next_addresses',{}) - # This attribute is set when wallet.start_threads is called. self.synchronizer = None @@ -333,15 +331,10 @@ class Abstract_Wallet(object): run_hook('set_label', name, text, changed) return changed - def addresses(self, include_change = True, _next=True): + def addresses(self, include_change = True): o = [] for a in self.accounts.keys(): o += self.get_account_addresses(a, include_change) - - if _next: - for addr in self.next_addresses.values(): - if addr not in o: - o += [addr] return o def is_mine(self, address): @@ -360,11 +353,6 @@ class Abstract_Wallet(object): for addr in addresses: if address == addr: return account, (for_change, addresses.index(addr)) - - for k,v in self.next_addresses.items(): - if v == address: - return k, (0,0) - raise Exception("Address not found", address) def get_private_key(self, address, password): @@ -1161,37 +1149,18 @@ class Deterministic_Wallet(Abstract_Wallet): if account is None: account = self.default_account() address = account.create_new_address(for_change) + self.add_address(address) + return address + + def add_address(self, address): self.history[address] = [] if self.synchronizer: self.synchronizer.add(address) self.save_accounts() - return address - - def synchronize_sequence(self, account, for_change): - limit = self.gap_limit_for_change if for_change else self.gap_limit - while True: - addresses = account.get_addresses(for_change) - if len(addresses) < limit: - self.create_new_address(account, for_change) - continue - if map( lambda a: self.address_is_old(a), addresses[-limit:] ) == limit*[False]: - break - else: - self.create_new_address(account, for_change) - - def check_pending_accounts(self): - pass - - def synchronize_account(self, account): - self.synchronize_sequence(account, 0) - self.synchronize_sequence(account, 1) def synchronize(self): - self.check_pending_accounts() for account in self.accounts.values(): - if type(account) in [ImportedAccount, PendingAccount]: - continue - self.synchronize_account(account) + account.synchronize(self) def restore(self, callback): from i18n import _ @@ -1359,15 +1328,38 @@ class BIP32_Simple_Wallet(BIP32_Wallet): class BIP32_HD_Wallet(BIP32_Wallet): # wallet that can create accounts - def create_main_account(self, password): - # First check the password is valid (this raises if it isn't). - if not self.is_watching_only(): - self.check_password(password) - self.create_account('Main account', password) - def can_create_accounts(self): return self.root_name in self.master_private_keys.keys() + def num_accounts(self): + keys = [] + for k, v in self.accounts.items(): + if type(v) != BIP32_Account: + continue + keys.append(k) + i = 0 + while True: + account_id = '%d'%i + if account_id not in keys: + break + i += 1 + return i + + def next_account_address(self, password): + account_id = '%d'%self.num_accounts() + account = self.make_account(account_id, password) + addr = account.first_address() + return account_id, addr + + def make_account(self, account_id, password): + """Creates and saves the master keys, but does not save the account""" + derivation = self.root_name + "%d'"%int(account_id) + xpub, xprv = self.derive_xkeys(self.root_name, derivation, password) + self.add_master_public_key(derivation, xpub) + self.add_master_private_key(derivation, xprv, password) + account = BIP32_Account({'xpub':xpub}) + return account + def create_account(self, name, password): account_id = "%d"%self.num_accounts() account = self.make_account(account_id, password) @@ -1375,7 +1367,14 @@ class BIP32_HD_Wallet(BIP32_Wallet): if name: self.set_label(account_id, name) # add address of the next account - _, _ = self.next_account_address(password) + account_id, addr = self.next_account_address(password) + self.storage.put('next_address',(account_id, addr)) + + def create_main_account(self, password): + # First check the password is valid (this raises if it isn't). + if not self.is_watching_only(): + self.check_password(password) + self.create_account('Main account', password) def account_is_pending(self, k): return type(self.accounts.get(k)) == PendingAccount @@ -1391,49 +1390,6 @@ class BIP32_HD_Wallet(BIP32_Wallet): self.accounts[account_id] = PendingAccount({'pending':addr}) self.save_accounts() - def check_pending_accounts(self): - for account_id, addr in self.next_addresses.items(): - if self.address_is_old(addr): - print_error( "creating account", account_id ) - xpub = self.master_public_keys[account_id] - account = BIP32_Account({'xpub':xpub}) - self.add_account(account_id, account) - self.next_addresses.pop(account_id) - - def next_account_address(self, password): - account_id = '%d'%self.num_accounts() - addr = self.next_addresses.get(account_id) - if not addr: - account = self.make_account(account_id, password) - addr = account.first_address() - self.next_addresses[account_id] = addr - self.storage.put('next_addresses', self.next_addresses) - return account_id, addr - - def make_account(self, account_id, password): - """Creates and saves the master keys, but does not save the account""" - derivation = self.root_name + "%d'"%int(account_id) - xpub, xprv = self.derive_xkeys(self.root_name, derivation, password) - self.add_master_public_key(derivation, xpub) - if xprv: - self.add_master_private_key(derivation, xprv, password) - - account = BIP32_Account({'xpub':xpub}) - return account - - def num_accounts(self): - keys = [] - for k, v in self.accounts.items(): - if type(v) != BIP32_Account: - continue - keys.append(k) - i = 0 - while True: - account_id = '%d'%i - if account_id not in keys: - break - i += 1 - return i