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:
M | lib/account.py | | | 33 | +++++++++++++++++++++++++++++++++ |
M | lib/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