0a641972c17d34107c0664e31d45c3e8a70d746c
[electrum-nvc.git] / lib / wallet.py
1 #!/usr/bin/env python
2 #
3 # Electrum - lightweight Bitcoin client
4 # Copyright (C) 2011 thomasv@gitorious
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 import sys
20 import os
21 import hashlib
22 import ast
23 import threading
24 import random
25 import time
26 import math
27
28 from util import print_msg, print_error
29
30 from bitcoin import *
31 from account import *
32 from version import *
33
34 from transaction import Transaction
35 from plugins import run_hook
36 import bitcoin
37 from synchronizer import WalletSynchronizer
38
39 COINBASE_MATURITY = 100
40 DUST_THRESHOLD = 5430
41
42 # internal ID for imported account
43 IMPORTED_ACCOUNT = '/x'
44
45
46 class WalletStorage(object):
47
48     def __init__(self, config):
49         self.lock = threading.RLock()
50         self.config = config
51         self.data = {}
52         self.file_exists = False
53         self.path = self.init_path(config)
54         print_error( "wallet path", self.path )
55         if self.path:
56             self.read(self.path)
57
58     def init_path(self, config):
59         """Set the path of the wallet."""
60
61         # command line -w option
62         path = config.get('wallet_path')
63         if path:
64             return path
65
66         # path in config file
67         path = config.get('default_wallet_path')
68         if path:
69             return path
70
71         # default path
72         dirpath = os.path.join(config.path, "wallets")
73         if not os.path.exists(dirpath):
74             os.mkdir(dirpath)
75
76         new_path = os.path.join(config.path, "wallets", "default_wallet")
77
78         # default path in pre 1.9 versions
79         old_path = os.path.join(config.path, "electrum.dat")
80         if os.path.exists(old_path) and not os.path.exists(new_path):
81             os.rename(old_path, new_path)
82
83         return new_path
84
85     def read(self, path):
86         """Read the contents of the wallet file."""
87         try:
88             with open(self.path, "r") as f:
89                 data = f.read()
90         except IOError:
91             return
92         try:
93             d = ast.literal_eval( data )  #parse raw data from reading wallet file
94         except Exception:
95             raise IOError("Cannot read wallet file.")
96
97         self.data = d
98         self.file_exists = True
99
100     def get(self, key, default=None):
101
102         with self.lock:
103             v = self.data.get(key)
104             if v is None:
105                 v = default
106             return v
107
108     def put(self, key, value, save = True):
109
110         with self.lock:
111             if value is not None:
112                 self.data[key] = value
113             elif key in self.data:
114                 self.data.pop(key)
115             if save:
116                 self.write()
117
118     def write(self):
119         s = repr(self.data)
120         f = open(self.path,"w")
121         f.write( s )
122         f.close()
123         if 'ANDROID_DATA' not in os.environ:
124             import stat
125             os.chmod(self.path,stat.S_IREAD | stat.S_IWRITE)
126
127
128 class Abstract_Wallet(object):
129     """
130     Wallet classes are created to handle various address generation methods.
131     Completion states (watching-only, single account, no seed, etc) are handled inside classes.
132     """
133     def __init__(self, storage):
134         self.storage = storage
135         self.electrum_version = ELECTRUM_VERSION
136         self.gap_limit_for_change = 3 # constant
137         # saved fields
138         self.seed_version          = storage.get('seed_version', NEW_SEED_VERSION)
139         self.gap_limit             = storage.get('gap_limit', 5)
140         self.use_change            = storage.get('use_change',True)
141         self.use_encryption        = storage.get('use_encryption', False)
142         self.seed                  = storage.get('seed', '')               # encrypted
143         self.labels                = storage.get('labels', {})
144         self.frozen_addresses      = storage.get('frozen_addresses',[])
145         self.addressbook           = storage.get('contacts', [])
146
147         self.history               = storage.get('addr_history',{})        # address -> list(txid, height)
148
149         self.fee                   = int(storage.get('fee_per_kb', 10000))
150
151         self.next_addresses = storage.get('next_addresses',{})
152
153         # This attribute is set when wallet.start_threads is called.
154         self.synchronizer = None
155
156         # imported_keys is deprecated. The GUI should call convert_imported_keys
157         self.imported_keys = self.storage.get('imported_keys',{})
158
159         self.load_accounts()
160
161         self.load_transactions()
162
163         # not saved
164         self.prevout_values = {}     # my own transaction outputs
165         self.spent_outputs = []
166         # spv
167         self.verifier = None
168         # there is a difference between wallet.up_to_date and interface.is_up_to_date()
169         # interface.is_up_to_date() returns true when all requests have been answered and processed
170         # wallet.up_to_date is true when the wallet is synchronized (stronger requirement)
171         self.up_to_date = False
172         self.lock = threading.Lock()
173         self.transaction_lock = threading.Lock()
174         self.tx_event = threading.Event()
175         for tx_hash, tx in self.transactions.items():
176             self.update_tx_outputs(tx_hash)
177
178     def load_transactions(self):
179         self.transactions = {}
180         tx_list = self.storage.get('transactions',{})
181         for k, raw in tx_list.items():
182             try:
183                 tx = Transaction.deserialize(raw)
184             except Exception:
185                 print_msg("Warning: Cannot deserialize transactions. skipping")
186                 continue
187             self.add_pubkey_addresses(tx)
188             self.transactions[k] = tx
189         for h,tx in self.transactions.items():
190             if not self.check_new_tx(h, tx):
191                 print_error("removing unreferenced tx", h)
192                 self.transactions.pop(h)
193
194     def add_pubkey_addresses(self, tx):
195         # find the address corresponding to pay-to-pubkey inputs
196         h = tx.hash()
197
198         # inputs
199         tx.add_pubkey_addresses(self.transactions)
200
201         # outputs of tx: inputs of tx2 
202         for type, x, v in tx.outputs:
203             if type == 'pubkey':
204                 for tx2 in self.transactions.values():
205                     tx2.add_pubkey_addresses({h:tx})
206
207     def get_action(self):
208         pass
209
210     def convert_imported_keys(self, password):
211         for k, v in self.imported_keys.items():
212             sec = pw_decode(v, password)
213             pubkey = public_key_from_private_key(sec)
214             address = public_key_to_bc_address(pubkey.decode('hex'))
215             assert address == k
216             self.import_key(sec, password)
217             self.imported_keys.pop(k)
218         self.storage.put('imported_keys', self.imported_keys)
219
220     def load_accounts(self):
221         self.accounts = {}
222
223         d = self.storage.get('accounts', {})
224         for k, v in d.items():
225             if k == 0:
226                 v['mpk'] = self.storage.get('master_public_key')
227                 self.accounts[k] = OldAccount(v)
228             elif v.get('imported'):
229                 self.accounts[k] = ImportedAccount(v)
230             elif v.get('xpub3'):
231                 self.accounts[k] = BIP32_Account_2of3(v)
232             elif v.get('xpub2'):
233                 self.accounts[k] = BIP32_Account_2of2(v)
234             elif v.get('xpub'):
235                 self.accounts[k] = BIP32_Account(v)
236             elif v.get('pending'):
237                 self.accounts[k] = PendingAccount(v)
238             else:
239                 print_error("cannot load account", v)
240
241     def synchronize(self):
242         pass
243
244     def can_create_accounts(self):
245         return False
246
247     def set_up_to_date(self,b):
248         with self.lock: self.up_to_date = b
249
250     def is_up_to_date(self):
251         with self.lock: return self.up_to_date
252
253     def update(self):
254         self.up_to_date = False
255         while not self.is_up_to_date():
256             time.sleep(0.1)
257
258     def is_imported(self, addr):
259         account = self.accounts.get(IMPORTED_ACCOUNT)
260         if account:
261             return addr in account.get_addresses(0)
262         else:
263             return False
264
265     def has_imported_keys(self):
266         account = self.accounts.get(IMPORTED_ACCOUNT)
267         return account is not None
268
269     def import_key(self, sec, password):
270         try:
271             pubkey = public_key_from_private_key(sec)
272             address = public_key_to_bc_address(pubkey.decode('hex'))
273         except Exception:
274             raise Exception('Invalid private key')
275
276         if self.is_mine(address):
277             raise Exception('Address already in wallet')
278
279         if self.accounts.get(IMPORTED_ACCOUNT) is None:
280             self.accounts[IMPORTED_ACCOUNT] = ImportedAccount({'imported':{}})
281         self.accounts[IMPORTED_ACCOUNT].add(address, pubkey, sec, password)
282         self.save_accounts()
283
284         if self.synchronizer:
285             self.synchronizer.subscribe_to_addresses([address])
286         return address
287
288     def delete_imported_key(self, addr):
289         account = self.accounts[IMPORTED_ACCOUNT]
290         account.remove(addr)
291         if not account.get_addresses(0):
292             self.accounts.pop(IMPORTED_ACCOUNT)
293         self.save_accounts()
294
295     def set_label(self, name, text = None):
296         changed = False
297         old_text = self.labels.get(name)
298         if text:
299             if old_text != text:
300                 self.labels[name] = text
301                 changed = True
302         else:
303             if old_text:
304                 self.labels.pop(name)
305                 changed = True
306
307         if changed:
308             self.storage.put('labels', self.labels, True)
309
310         run_hook('set_label', name, text, changed)
311         return changed
312
313     def addresses(self, include_change = True, _next=True):
314         o = []
315         for a in self.accounts.keys():
316             o += self.get_account_addresses(a, include_change)
317
318         if _next:
319             for addr in self.next_addresses.values():
320                 if addr not in o:
321                     o += [addr]
322         return o
323
324     def is_mine(self, address):
325         return address in self.addresses(True)
326
327     def is_change(self, address):
328         if not self.is_mine(address): return False
329         acct, s = self.get_address_index(address)
330         if s is None: return False
331         return s[0] == 1
332
333     def get_address_index(self, address):
334         for account in self.accounts.keys():
335             for for_change in [0,1]:
336                 addresses = self.accounts[account].get_addresses(for_change)
337                 for addr in addresses:
338                     if address == addr:
339                         return account, (for_change, addresses.index(addr))
340
341         for k,v in self.next_addresses.items():
342             if v == address:
343                 return k, (0,0)
344
345         raise Exception("Address not found", address)
346
347     def get_private_key(self, address, password):
348         if self.is_watching_only():
349             return []
350         account_id, sequence = self.get_address_index(address)
351         return self.accounts[account_id].get_private_key(sequence, self, password)
352
353     def get_public_keys(self, address):
354         account_id, sequence = self.get_address_index(address)
355         return self.accounts[account_id].get_pubkeys(*sequence)
356
357     def add_keypairs(self, tx, keypairs, password):
358         # first check the provided password. This will raise if invalid.
359         self.check_password(password)
360
361         addr_list, xpub_list = tx.inputs_to_sign()
362         for addr in addr_list:
363             if self.is_mine(addr):
364                 private_keys = self.get_private_key(addr, password)
365                 for sec in private_keys:
366                     pubkey = public_key_from_private_key(sec)
367                     keypairs[ pubkey ] = sec
368
369         for xpub, sequence in xpub_list:
370             # look for account that can sign
371             for k, account in self.accounts.items():
372                 if xpub in account.get_master_pubkeys():
373                     break
374             else:
375                 continue
376             pk = account.get_private_key(sequence, self, password)
377             for sec in pk:
378                 pubkey = public_key_from_private_key(sec)
379                 keypairs[pubkey] = sec
380
381     def signrawtransaction(self, tx, private_keys, password):
382         # check that the password is correct. This will raise if it's not.
383         self.get_seed(password)
384
385         # build a list of public/private keys
386         keypairs = {}
387
388         # add private keys from parameter
389         for sec in private_keys:
390             pubkey = public_key_from_private_key(sec)
391             keypairs[ pubkey ] = sec
392
393         # add private_keys
394         self.add_keypairs(tx, keypairs, password)
395
396         # sign the transaction
397         self.sign_transaction(tx, keypairs, password)
398
399     def sign_message(self, address, message, password):
400         keys = self.get_private_key(address, password)
401         assert len(keys) == 1
402         sec = keys[0]
403         key = regenerate_key(sec)
404         compressed = is_compressed(sec)
405         return key.sign_message(message, compressed, address)
406
407     def decrypt_message(self, pubkey, message, password):
408         address = public_key_to_bc_address(pubkey.decode('hex'))
409         keys = self.get_private_key(address, password)
410         secret = keys[0]
411         ec = regenerate_key(secret)
412         decrypted = ec.decrypt_message(message)
413         return decrypted
414
415     def is_found(self):
416         return self.history.values() != [[]] * len(self.history)
417
418     def add_contact(self, address, label=None):
419         self.addressbook.append(address)
420         self.storage.put('contacts', self.addressbook, True)
421         if label:
422             self.set_label(address, label)
423
424     def delete_contact(self, addr):
425         if addr in self.addressbook:
426             self.addressbook.remove(addr)
427             self.storage.put('addressbook', self.addressbook, True)
428
429     def fill_addressbook(self):
430         for tx_hash, tx in self.transactions.items():
431             is_relevant, is_send, _, _ = self.get_tx_value(tx)
432             if is_send:
433                 for addr in tx.get_output_addresses():
434                     if not self.is_mine(addr) and addr not in self.addressbook:
435                         self.addressbook.append(addr)
436         # redo labels
437         # self.update_tx_labels()
438
439     def get_num_tx(self, address):
440         n = 0
441         for tx in self.transactions.values():
442             if address in tx.get_output_addresses(): n += 1
443         return n
444
445     def get_tx_value(self, tx, account=None):
446         domain = self.get_account_addresses(account)
447         return tx.get_value(domain, self.prevout_values)
448
449     def update_tx_outputs(self, tx_hash):
450         tx = self.transactions.get(tx_hash)
451
452         for i, (addr, value) in enumerate(tx.get_outputs()):
453             key = tx_hash+ ':%d'%i
454             self.prevout_values[key] = value
455
456         for item in tx.inputs:
457             if self.is_mine(item.get('address')):
458                 key = item['prevout_hash'] + ':%d'%item['prevout_n']
459                 self.spent_outputs.append(key)
460
461     def get_addr_balance(self, address):
462         #assert self.is_mine(address)
463         h = self.history.get(address,[])
464         if h == ['*']: return 0,0
465         c = u = 0
466         received_coins = []   # list of coins received at address
467
468         for tx_hash, tx_height in h:
469             tx = self.transactions.get(tx_hash)
470             if not tx: continue
471
472             for i, (addr, value) in enumerate(tx.get_outputs()):
473                 if addr == address:
474                     key = tx_hash + ':%d'%i
475                     received_coins.append(key)
476
477         for tx_hash, tx_height in h:
478             tx = self.transactions.get(tx_hash)
479             if not tx: continue
480             v = 0
481
482             for item in tx.inputs:
483                 addr = item.get('address')
484                 if addr == address:
485                     key = item['prevout_hash']  + ':%d'%item['prevout_n']
486                     value = self.prevout_values.get( key )
487                     if key in received_coins:
488                         v -= value
489
490             for i, (addr, value) in enumerate(tx.get_outputs()):
491                 key = tx_hash + ':%d'%i
492                 if addr == address:
493                     v += value
494
495             if tx_height:
496                 c += v
497             else:
498                 u += v
499         return c, u
500
501     def get_account_name(self, k):
502         return self.labels.get(k, self.accounts[k].get_name(k))
503
504     def get_account_names(self):
505         account_names = {}
506         for k in self.accounts.keys():
507             account_names[k] = self.get_account_name(k)
508         return account_names
509
510     def get_account_addresses(self, a, include_change=True):
511         if a is None:
512             o = self.addresses(include_change)
513         elif a in self.accounts:
514             ac = self.accounts[a]
515             o = ac.get_addresses(0)
516             if include_change: o += ac.get_addresses(1)
517         return o
518
519     def get_account_balance(self, account):
520         return self.get_balance(self.get_account_addresses(account))
521
522     def get_frozen_balance(self):
523         return self.get_balance(self.frozen_addresses)
524
525     def get_balance(self, domain=None):
526         if domain is None: domain = self.addresses(True)
527         cc = uu = 0
528         for addr in domain:
529             c, u = self.get_addr_balance(addr)
530             cc += c
531             uu += u
532         return cc, uu
533
534     def get_unspent_coins(self, domain=None):
535         coins = []
536         if domain is None: domain = self.addresses(True)
537         for addr in domain:
538             h = self.history.get(addr, [])
539             if h == ['*']: continue
540             for tx_hash, tx_height in h:
541                 tx = self.transactions.get(tx_hash)
542                 if tx is None: raise Exception("Wallet not synchronized")
543                 is_coinbase = tx.inputs[0].get('prevout_hash') == '0'*64
544                 for i, (address, value) in enumerate(tx.get_outputs()):
545                     output = {'address':address, 'value':value, 'prevout_n':i}
546                     if address != addr: continue
547                     key = tx_hash + ":%d"%i
548                     if key in self.spent_outputs: continue
549                     output['prevout_hash'] = tx_hash
550                     output['height'] = tx_height
551                     output['coinbase'] = is_coinbase
552                     coins.append((tx_height, output))
553
554         # sort by age
555         if coins:
556             coins = sorted(coins)
557             if coins[-1][0] != 0:
558                 while coins[0][0] == 0:
559                     coins = coins[1:] + [ coins[0] ]
560         return [x[1] for x in coins]
561
562     def choose_tx_inputs( self, amount, fixed_fee, num_outputs, domain = None, coins = None ):
563         """ todo: minimize tx size """
564         total = 0
565         fee = self.fee if fixed_fee is None else fixed_fee
566
567         if not coins:
568             if domain is None:
569                 domain = self.addresses(True)
570             for i in self.frozen_addresses:
571                 if i in domain: domain.remove(i)
572             coins = self.get_unspent_coins(domain)
573
574         inputs = []
575
576         for item in coins:
577             if item.get('coinbase') and item.get('height') + COINBASE_MATURITY > self.network.get_local_height():
578                 continue
579             v = item.get('value')
580             total += v
581             inputs.append(item)
582             fee = self.estimated_fee(inputs, num_outputs) if fixed_fee is None else fixed_fee
583             if total >= amount + fee: break
584         else:
585             inputs = []
586
587         return inputs, total, fee
588
589     def set_fee(self, fee):
590         if self.fee != fee:
591             self.fee = fee
592             self.storage.put('fee_per_kb', self.fee, True)
593
594     def estimated_fee(self, inputs, num_outputs):
595         estimated_size =  len(inputs) * 180 + num_outputs * 34    # this assumes non-compressed keys
596         fee = self.fee * int(math.ceil(estimated_size/1000.))
597         return fee
598
599     def add_tx_change( self, inputs, outputs, amount, fee, total, change_addr=None):
600         "add change to a transaction"
601         change_amount = total - ( amount + fee )
602         if change_amount > DUST_THRESHOLD:
603             if not change_addr:
604
605                 # send change to one of the accounts involved in the tx
606                 address = inputs[0].get('address')
607                 account, _ = self.get_address_index(address)
608
609                 if not self.use_change or account == IMPORTED_ACCOUNT:
610                     change_addr = inputs[-1]['address']
611                 else:
612                     change_addr = self.accounts[account].get_addresses(1)[-self.gap_limit_for_change]
613
614             # Insert the change output at a random position in the outputs
615             posn = random.randint(0, len(outputs))
616             outputs[posn:posn] = [( 'address', change_addr,  change_amount)]
617         return outputs
618
619     def get_history(self, address):
620         with self.lock:
621             return self.history.get(address)
622
623     def get_status(self, h):
624         if not h: return None
625         if h == ['*']: return '*'
626         status = ''
627         for tx_hash, height in h:
628             status += tx_hash + ':%d:' % height
629         return hashlib.sha256( status ).digest().encode('hex')
630
631     def receive_tx_callback(self, tx_hash, tx, tx_height):
632
633         with self.transaction_lock:
634             self.add_pubkey_addresses(tx)
635             if not self.check_new_tx(tx_hash, tx):
636                 # may happen due to pruning
637                 print_error("received transaction that is no longer referenced in history", tx_hash)
638                 return
639             self.transactions[tx_hash] = tx
640             self.network.pending_transactions_for_notifications.append(tx)
641             self.save_transactions()
642             if self.verifier and tx_height>0:
643                 self.verifier.add(tx_hash, tx_height)
644             self.update_tx_outputs(tx_hash)
645
646     def save_transactions(self):
647         tx = {}
648         for k,v in self.transactions.items():
649             tx[k] = str(v)
650         self.storage.put('transactions', tx, True)
651
652     def receive_history_callback(self, addr, hist):
653
654         if not self.check_new_history(addr, hist):
655             raise Exception("error: received history for %s is not consistent with known transactions"%addr)
656
657         with self.lock:
658             self.history[addr] = hist
659             self.storage.put('addr_history', self.history, True)
660
661         if hist != ['*']:
662             for tx_hash, tx_height in hist:
663                 if tx_height>0:
664                     # add it in case it was previously unconfirmed
665                     if self.verifier: self.verifier.add(tx_hash, tx_height)
666
667     def get_tx_history(self, account=None):
668         if not self.verifier:
669             return []
670
671         with self.transaction_lock:
672             history = self.transactions.items()
673             history.sort(key = lambda x: self.verifier.get_txpos(x[0]))
674             result = []
675
676             balance = 0
677             for tx_hash, tx in history:
678                 is_relevant, is_mine, v, fee = self.get_tx_value(tx, account)
679                 if v is not None: balance += v
680
681             c, u = self.get_account_balance(account)
682
683             if balance != c+u:
684                 result.append( ('', 1000, 0, c+u-balance, None, c+u-balance, None ) )
685
686             balance = c + u - balance
687             for tx_hash, tx in history:
688                 is_relevant, is_mine, value, fee = self.get_tx_value(tx, account)
689                 if not is_relevant:
690                     continue
691                 if value is not None:
692                     balance += value
693
694                 conf, timestamp = self.verifier.get_confirmations(tx_hash) if self.verifier else (None, None)
695                 result.append( (tx_hash, conf, is_mine, value, fee, balance, timestamp) )
696
697         return result
698
699     def get_label(self, tx_hash):
700         label = self.labels.get(tx_hash)
701         is_default = (label == '') or (label is None)
702         if is_default: label = self.get_default_label(tx_hash)
703         return label, is_default
704
705     def get_default_label(self, tx_hash):
706         tx = self.transactions.get(tx_hash)
707         default_label = ''
708         if tx:
709             is_relevant, is_mine, _, _ = self.get_tx_value(tx)
710             if is_mine:
711                 for o_addr in tx.get_output_addresses():
712                     if not self.is_mine(o_addr):
713                         try:
714                             default_label = self.labels[o_addr]
715                         except KeyError:
716                             default_label = '>' + o_addr
717                         break
718                 else:
719                     default_label = '(internal)'
720             else:
721                 for o_addr in tx.get_output_addresses():
722                     if self.is_mine(o_addr) and not self.is_change(o_addr):
723                         break
724                 else:
725                     for o_addr in tx.get_output_addresses():
726                         if self.is_mine(o_addr):
727                             break
728                     else:
729                         o_addr = None
730
731                 if o_addr:
732                     try:
733                         default_label = self.labels[o_addr]
734                     except KeyError:
735                         default_label = '<' + o_addr
736
737         return default_label
738
739     def make_unsigned_transaction(self, outputs, fee=None, change_addr=None, domain=None, coins=None ):
740         for type, address, x in outputs:
741             if type == 'op_return':
742                 continue
743             if type == 'address':
744                 assert is_address(address), "Address " + address + " is invalid!"
745         amount = sum( map(lambda x:x[2], outputs) )
746         inputs, total, fee = self.choose_tx_inputs( amount, fee, len(outputs), domain, coins )
747         if not inputs:
748             raise ValueError("Not enough funds")
749         for txin in inputs:
750             self.add_input_info(txin)
751         outputs = self.add_tx_change(inputs, outputs, amount, fee, total, change_addr)
752         return Transaction(inputs, outputs)
753
754     def mktx(self, outputs, password, fee=None, change_addr=None, domain= None, coins = None ):
755         tx = self.make_unsigned_transaction(outputs, fee, change_addr, domain, coins)
756         keypairs = {}
757         self.add_keypairs(tx, keypairs, password)
758         if keypairs:
759             self.sign_transaction(tx, keypairs, password)
760         return tx
761
762     def add_input_info(self, txin):
763         address = txin['address']
764         account_id, sequence = self.get_address_index(address)
765         account = self.accounts[account_id]
766         redeemScript = account.redeem_script(*sequence)
767         pubkeys = account.get_pubkeys(*sequence)
768         x_pubkeys = account.get_xpubkeys(*sequence)
769         # sort pubkeys and x_pubkeys, using the order of pubkeys
770         pubkeys, x_pubkeys = zip( *sorted(zip(pubkeys, x_pubkeys)))
771         txin['pubkeys'] = list(pubkeys)
772         txin['x_pubkeys'] = list(x_pubkeys)
773         txin['signatures'] = [None] * len(pubkeys)
774
775         if redeemScript:
776             txin['redeemScript'] = redeemScript
777             txin['num_sig'] = 2
778         else:
779             txin['redeemPubkey'] = account.get_pubkey(*sequence)
780             txin['num_sig'] = 1
781
782     def sign_transaction(self, tx, keypairs, password):
783         tx.sign(keypairs)
784         run_hook('sign_transaction', tx, password)
785
786     def sendtx(self, tx):
787         # synchronous
788         h = self.send_tx(tx)
789         self.tx_event.wait()
790         return self.receive_tx(h, tx)
791
792     def send_tx(self, tx):
793         # asynchronous
794         self.tx_event.clear()
795         self.network.send([('blockchain.transaction.broadcast', [str(tx)])], self.on_broadcast)
796         return tx.hash()
797
798     def on_broadcast(self, i, r):
799         self.tx_result = r.get('result')
800         self.tx_event.set()
801
802     def receive_tx(self, tx_hash, tx):
803         out = self.tx_result
804         if out != tx_hash:
805             return False, "error: " + out
806         run_hook('receive_tx', tx, self)
807         return True, out
808
809     def update_password(self, old_password, new_password):
810         if new_password == '':
811             new_password = None
812
813         if self.has_seed():
814             decoded = self.get_seed(old_password)
815             self.seed = pw_encode( decoded, new_password)
816             self.storage.put('seed', self.seed, True)
817
818         imported_account = self.accounts.get(IMPORTED_ACCOUNT)
819         if imported_account:
820             imported_account.update_password(old_password, new_password)
821             self.save_accounts()
822
823         for k, v in self.master_private_keys.items():
824             b = pw_decode(v, old_password)
825             c = pw_encode(b, new_password)
826             self.master_private_keys[k] = c
827         self.storage.put('master_private_keys', self.master_private_keys, True)
828
829         self.use_encryption = (new_password != None)
830         self.storage.put('use_encryption', self.use_encryption,True)
831
832     def freeze(self,addr):
833         if self.is_mine(addr) and addr not in self.frozen_addresses:
834             self.frozen_addresses.append(addr)
835             self.storage.put('frozen_addresses', self.frozen_addresses, True)
836             return True
837         else:
838             return False
839
840     def unfreeze(self,addr):
841         if self.is_mine(addr) and addr in self.frozen_addresses:
842             self.frozen_addresses.remove(addr)
843             self.storage.put('frozen_addresses', self.frozen_addresses, True)
844             return True
845         else:
846             return False
847
848     def set_verifier(self, verifier):
849         self.verifier = verifier
850
851         # review transactions that are in the history
852         for addr, hist in self.history.items():
853             if hist == ['*']: continue
854             for tx_hash, tx_height in hist:
855                 if tx_height>0:
856                     # add it in case it was previously unconfirmed
857                     self.verifier.add(tx_hash, tx_height)
858
859         # if we are on a pruning server, remove unverified transactions
860         vr = self.verifier.transactions.keys() + self.verifier.verified_tx.keys()
861         for tx_hash in self.transactions.keys():
862             if tx_hash not in vr:
863                 self.transactions.pop(tx_hash)
864
865     def check_new_history(self, addr, hist):
866         # check that all tx in hist are relevant
867         if hist != ['*']:
868             for tx_hash, height in hist:
869                 tx = self.transactions.get(tx_hash)
870                 if not tx: continue
871                 if not tx.has_address(addr):
872                     return False
873
874         # check that we are not "orphaning" a transaction
875         old_hist = self.history.get(addr,[])
876         if old_hist == ['*']: return True
877
878         for tx_hash, height in old_hist:
879             if tx_hash in map(lambda x:x[0], hist): continue
880             found = False
881             for _addr, _hist in self.history.items():
882                 if _addr == addr: continue
883                 if _hist == ['*']: continue
884                 _tx_hist = map(lambda x:x[0], _hist)
885                 if tx_hash in _tx_hist:
886                     found = True
887                     break
888
889             if not found:
890                 tx = self.transactions.get(tx_hash)
891                 # tx might not be there
892                 if not tx: continue
893
894                 # already verified?
895                 if self.verifier.get_height(tx_hash):
896                     continue
897                 # unconfirmed tx
898                 print_error("new history is orphaning transaction:", tx_hash)
899                 # check that all outputs are not mine, request histories
900                 ext_requests = []
901                 for _addr in tx.get_output_addresses():
902                     # assert not self.is_mine(_addr)
903                     ext_requests.append( ('blockchain.address.get_history', [_addr]) )
904
905                 ext_h = self.network.synchronous_get(ext_requests)
906                 print_error("sync:", ext_requests, ext_h)
907                 height = None
908                 for h in ext_h:
909                     if h == ['*']: continue
910                     for item in h:
911                         if item.get('tx_hash') == tx_hash:
912                             height = item.get('height')
913                 if height:
914                     print_error("found height for", tx_hash, height)
915                     self.verifier.add(tx_hash, height)
916                 else:
917                     print_error("removing orphaned tx from history", tx_hash)
918                     self.transactions.pop(tx_hash)
919
920         return True
921
922     def check_new_tx(self, tx_hash, tx):
923         # 1 check that tx is referenced in addr_history.
924         addresses = []
925         for addr, hist in self.history.items():
926             if hist == ['*']:continue
927             for txh, height in hist:
928                 if txh == tx_hash:
929                     addresses.append(addr)
930
931         if not addresses:
932             return False
933
934         # 2 check that referencing addresses are in the tx
935         for addr in addresses:
936             if not tx.has_address(addr):
937                 return False
938
939         return True
940
941     def start_threads(self, network):
942         from verifier import TxVerifier
943         self.network = network
944         if self.network is not None:
945             self.verifier = TxVerifier(self.network, self.storage)
946             self.verifier.start()
947             self.set_verifier(self.verifier)
948             self.synchronizer = WalletSynchronizer(self, network)
949             self.synchronizer.start()
950         else:
951             self.verifier = None
952             self.synchronizer =None
953
954     def stop_threads(self):
955         if self.network:
956             self.verifier.stop()
957             self.synchronizer.stop()
958
959     def restore(self, cb):
960         pass
961
962     def get_accounts(self):
963         return self.accounts
964
965     def save_accounts(self):
966         d = {}
967         for k, v in self.accounts.items():
968             d[k] = v.dump()
969         self.storage.put('accounts', d, True)
970
971     def can_import(self):
972         return not self.is_watching_only()
973
974     def is_used(self, address):
975         h = self.history.get(address,[])
976         c, u = self.get_addr_balance(address)
977         return len(h), len(h) > 0 and c == -u
978
979     def address_is_old(self, address, age_limit=2):
980         age = -1
981         h = self.history.get(address, [])
982         if h == ['*']:
983             return True
984         for tx_hash, tx_height in h:
985             if tx_height == 0:
986                 tx_age = 0
987             else:
988                 tx_age = self.network.get_local_height() - tx_height + 1
989             if tx_age > age:
990                 age = tx_age
991         return age > age_limit
992
993
994 class Imported_Wallet(Abstract_Wallet):
995
996     def __init__(self, storage):
997         Abstract_Wallet.__init__(self, storage)
998         a = self.accounts.get(IMPORTED_ACCOUNT)
999         if not a:
1000             self.accounts[IMPORTED_ACCOUNT] = ImportedAccount({'imported':{}})
1001         self.storage.put('wallet_type', 'imported', True)
1002
1003     def is_watching_only(self):
1004         acc = self.accounts[IMPORTED_ACCOUNT]
1005         n = acc.keypairs.values()
1006         return n == [(None, None)] * len(n)
1007
1008     def has_seed(self):
1009         return False
1010
1011     def is_deterministic(self):
1012         return False
1013
1014     def check_password(self, password):
1015         self.accounts[IMPORTED_ACCOUNT].get_private_key((0,0), self, password)
1016
1017     def is_used(self, address):
1018         h = self.history.get(address,[])
1019         return len(h), False
1020
1021     def get_master_public_keys(self):
1022         return {}
1023
1024     def is_beyond_limit(self, address, account, is_change):
1025         return False
1026
1027
1028 class Deterministic_Wallet(Abstract_Wallet):
1029
1030     def __init__(self, storage):
1031         Abstract_Wallet.__init__(self, storage)
1032
1033     def has_seed(self):
1034         return self.seed != ''
1035
1036     def is_deterministic(self):
1037         return True
1038
1039     def is_watching_only(self):
1040         return not self.has_seed()
1041
1042     def add_seed(self, seed, password):
1043         if self.seed:
1044             raise Exception("a seed exists")
1045
1046         self.seed_version, self.seed = self.prepare_seed(seed)
1047         if password:
1048             self.seed = pw_encode( self.seed, password)
1049             self.use_encryption = True
1050         else:
1051             self.use_encryption = False
1052
1053         self.storage.put('seed', self.seed, True)
1054         self.storage.put('seed_version', self.seed_version, True)
1055         self.storage.put('use_encryption', self.use_encryption,True)
1056         self.create_master_keys(password)
1057
1058     def get_seed(self, password):
1059         return pw_decode(self.seed, password)
1060
1061     def get_mnemonic(self, password):
1062         return self.get_seed(password)
1063
1064     def change_gap_limit(self, value):
1065         if value >= self.gap_limit:
1066             self.gap_limit = value
1067             self.storage.put('gap_limit', self.gap_limit, True)
1068             #self.interface.poke('synchronizer')
1069             return True
1070
1071         elif value >= self.min_acceptable_gap():
1072             for key, account in self.accounts.items():
1073                 addresses = account[0]
1074                 k = self.num_unused_trailing_addresses(addresses)
1075                 n = len(addresses) - k + value
1076                 addresses = addresses[0:n]
1077                 self.accounts[key][0] = addresses
1078
1079             self.gap_limit = value
1080             self.storage.put('gap_limit', self.gap_limit, True)
1081             self.save_accounts()
1082             return True
1083         else:
1084             return False
1085
1086     def num_unused_trailing_addresses(self, addresses):
1087         k = 0
1088         for a in addresses[::-1]:
1089             if self.history.get(a):break
1090             k = k + 1
1091         return k
1092
1093     def min_acceptable_gap(self):
1094         # fixme: this assumes wallet is synchronized
1095         n = 0
1096         nmax = 0
1097
1098         for account in self.accounts.values():
1099             addresses = account.get_addresses(0)
1100             k = self.num_unused_trailing_addresses(addresses)
1101             for a in addresses[0:-k]:
1102                 if self.history.get(a):
1103                     n = 0
1104                 else:
1105                     n += 1
1106                     if n > nmax: nmax = n
1107         return nmax + 1
1108
1109     def create_new_address(self, account=None, for_change=0):
1110         if account is None:
1111             account = self.default_account()
1112         address = account.create_new_address(for_change)
1113         self.history[address] = []
1114         if self.synchronizer:
1115             self.synchronizer.add(address)
1116         self.save_accounts()
1117         return address
1118
1119     def synchronize_sequence(self, account, for_change):
1120         limit = self.gap_limit_for_change if for_change else self.gap_limit
1121         while True:
1122             addresses = account.get_addresses(for_change)
1123             if len(addresses) < limit:
1124                 self.create_new_address(account, for_change)
1125                 continue
1126             if map( lambda a: self.address_is_old(a), addresses[-limit:] ) == limit*[False]:
1127                 break
1128             else:
1129                 self.create_new_address(account, for_change)
1130
1131     def check_pending_accounts(self):
1132         for account_id, addr in self.next_addresses.items():
1133             if self.address_is_old(addr):
1134                 print_error( "creating account", account_id )
1135                 xpub = self.master_public_keys[account_id]
1136                 account = BIP32_Account({'xpub':xpub})
1137                 self.add_account(account_id, account)
1138                 self.next_addresses.pop(account_id)
1139
1140     def synchronize_account(self, account):
1141         self.synchronize_sequence(account, 0)
1142         self.synchronize_sequence(account, 1)
1143
1144     def synchronize(self):
1145         self.check_pending_accounts()
1146         for account in self.accounts.values():
1147             if type(account) in [ImportedAccount, PendingAccount]:
1148                 continue
1149             self.synchronize_account(account)
1150
1151     def restore(self, callback):
1152         from i18n import _
1153         def wait_for_wallet():
1154             self.set_up_to_date(False)
1155             while not self.is_up_to_date():
1156                 msg = "%s\n%s %d\n%s %.1f"%(
1157                     _("Please wait..."),
1158                     _("Addresses generated:"),
1159                     len(self.addresses(True)),
1160                     _("Kilobytes received:"),
1161                     self.network.interface.bytes_received/1024.)
1162
1163                 apply(callback, (msg,))
1164                 time.sleep(0.1)
1165
1166         def wait_for_network():
1167             while not self.network.is_connected():
1168                 msg = "%s \n" % (_("Connecting..."))
1169                 apply(callback, (msg,))
1170                 time.sleep(0.1)
1171
1172         # wait until we are connected, because the user might have selected another server
1173         if self.network:
1174             wait_for_network()
1175             wait_for_wallet()
1176         else:
1177             self.synchronize()
1178         self.fill_addressbook()
1179
1180     def create_account(self, name, password):
1181         i = self.num_accounts()
1182         account_id = self.account_id(i)
1183         account = self.make_account(account_id, password)
1184         self.add_account(account_id, account)
1185         if name:
1186             self.set_label(account_id, name)
1187
1188         # add address of the next account
1189         _, _ = self.next_account_address(password)
1190
1191
1192     def add_account(self, account_id, account):
1193         self.accounts[account_id] = account
1194         self.save_accounts()
1195
1196     def account_is_pending(self, k):
1197         return type(self.accounts.get(k)) == PendingAccount
1198
1199     def delete_pending_account(self, k):
1200         assert self.account_is_pending(k)
1201         self.accounts.pop(k)
1202         self.save_accounts()
1203
1204     def create_pending_account(self, name, password):
1205         account_id, addr = self.next_account_address(password)
1206         self.set_label(account_id, name)
1207         self.accounts[account_id] = PendingAccount({'pending':addr})
1208         self.save_accounts()
1209
1210     def is_beyond_limit(self, address, account, is_change):
1211         if type(account) == ImportedAccount:
1212             return False
1213         addr_list = account.get_addresses(is_change)
1214         i = addr_list.index(address)
1215         prev_addresses = addr_list[:max(0, i)]
1216         limit = self.gap_limit_for_change if is_change else self.gap_limit
1217         if len(prev_addresses) < limit:
1218             return False
1219         prev_addresses = prev_addresses[max(0, i - limit):]
1220         for addr in prev_addresses:
1221             if self.history.get(addr):
1222                 return False
1223         return True
1224
1225     def get_action(self):
1226         if not self.get_master_public_key():
1227             return 'create_seed'
1228         if not self.accounts:
1229             return 'create_accounts'
1230
1231
1232 class NewWallet(Deterministic_Wallet):
1233
1234     def __init__(self, storage):
1235         Deterministic_Wallet.__init__(self, storage)
1236         self.master_public_keys  = storage.get('master_public_keys', {})
1237         self.master_private_keys = storage.get('master_private_keys', {})
1238
1239     def default_account(self):
1240         return self.accounts["m/0'"]
1241
1242     def is_watching_only(self):
1243         return not bool(self.master_private_keys)
1244
1245     def can_create_accounts(self):
1246         return 'm/' in self.master_private_keys.keys()
1247
1248     def get_master_public_key(self):
1249         """xpub of the main account"""
1250         return self.master_public_keys.get("m/0'")
1251
1252     def get_master_public_keys(self):
1253         out = {}
1254         for k, account in self.accounts.items():
1255             name = self.get_account_name(k)
1256             mpk_text = '\n\n'.join( account.get_master_pubkeys() )
1257             out[name] = mpk_text
1258         return out
1259
1260     def get_master_private_key(self, account, password):
1261         k = self.master_private_keys.get(account)
1262         if not k: return
1263         xpriv = pw_decode( k, password)
1264         return xpriv
1265
1266     def check_password(self, password):
1267         xpriv = self.get_master_private_key( "m/", password )
1268         xpub = self.master_public_keys["m/"]
1269         assert deserialize_xkey(xpriv)[3] == deserialize_xkey(xpub)[3]
1270
1271     def create_xprv_wallet(self, xprv, password):
1272         xpub = bitcoin.xpub_from_xprv(xprv)
1273         account = BIP32_Account({'xpub':xpub})
1274         account_id = 'm/' + bitcoin.get_xkey_name(xpub)
1275         self.storage.put('seed_version', self.seed_version, True)
1276         self.add_master_private_key(account_id, xprv, password)
1277         self.add_master_public_key(account_id, xpub)
1278         self.add_account(account_id, account)
1279
1280     def create_watching_only_wallet(self, xpub):
1281         account = BIP32_Account({'xpub':xpub})
1282         account_id = 'm/' + bitcoin.get_xkey_name(xpub)
1283         self.storage.put('seed_version', self.seed_version, True)
1284         self.add_master_public_key(account_id, xpub)
1285         self.add_account(account_id, account)
1286
1287     def create_accounts(self, password):
1288         # First check the password is valid (this raises if it isn't).
1289         if not self.is_watching_only():
1290             self.check_password(password)
1291         self.create_account('Main account', password)
1292
1293     def add_master_public_key(self, name, xpub):
1294         self.master_public_keys[name] = xpub
1295         self.storage.put('master_public_keys', self.master_public_keys, True)
1296
1297     def add_master_private_key(self, name, xpriv, password):
1298         self.master_private_keys[name] = pw_encode(xpriv, password)
1299         self.storage.put('master_private_keys', self.master_private_keys, True)
1300
1301     def add_master_keys(self, root, account_id, password):
1302         x = self.master_private_keys.get(root)
1303         if x:
1304             master_xpriv = pw_decode(x, password )
1305             xpriv, xpub = bip32_private_derivation(master_xpriv, root, account_id)
1306             self.add_master_public_key(account_id, xpub)
1307             self.add_master_private_key(account_id, xpriv, password)
1308         else:
1309             master_xpub = self.master_public_keys[root]
1310             xpub = bip32_public_derivation(master_xpub, root, account_id)
1311             self.add_master_public_key(account_id, xpub)
1312         return xpub
1313
1314     def create_master_keys(self, password):
1315         xpriv, xpub = bip32_root(mnemonic_to_seed(self.get_seed(password),'').encode('hex'))
1316         self.add_master_public_key("m/", xpub)
1317         self.add_master_private_key("m/", xpriv, password)
1318
1319     def can_sign(self, tx):
1320         if self.is_watching_only():
1321             return False
1322         if tx.is_complete():
1323             return False
1324         addr_list, xpub_list = tx.inputs_to_sign()
1325         for addr in addr_list:
1326             if self.is_mine(addr):
1327                 return True
1328         mpk = [ self.master_public_keys[k] for k in self.master_private_keys.keys() ]
1329         for xpub, sequence in xpub_list:
1330             if xpub in mpk:
1331                 return True
1332         return False
1333
1334     def num_accounts(self):
1335         keys = []
1336         for k, v in self.accounts.items():
1337             if type(v) != BIP32_Account:
1338                 continue
1339             keys.append(k)
1340
1341         i = 0
1342         while True:
1343             account_id = self.account_id(i)
1344             if account_id not in keys: break
1345             i += 1
1346         return i
1347
1348     def next_account_address(self, password):
1349         i = self.num_accounts()
1350         account_id = self.account_id(i)
1351
1352         addr = self.next_addresses.get(account_id)
1353         if not addr:
1354             account = self.make_account(account_id, password)
1355             addr = account.first_address()
1356             self.next_addresses[account_id] = addr
1357             self.storage.put('next_addresses', self.next_addresses)
1358
1359         return account_id, addr
1360
1361     def account_id(self, i):
1362         return "m/%d'"%i
1363
1364     def make_account(self, account_id, password):
1365         """Creates and saves the master keys, but does not save the account"""
1366         xpub = self.add_master_keys("m/", account_id, password)
1367         account = BIP32_Account({'xpub':xpub})
1368         return account
1369
1370     def make_seed(self):
1371         import mnemonic, ecdsa
1372         entropy = ecdsa.util.randrange( pow(2,160) )
1373         nonce = 0
1374         while True:
1375             ss = "%040x"%(entropy+nonce)
1376             s = hashlib.sha256(ss.decode('hex')).digest().encode('hex')
1377             # we keep only 13 words, that's approximately 139 bits of entropy
1378             words = mnemonic.mn_encode(s)[0:13]
1379             seed = ' '.join(words)
1380             if is_new_seed(seed):
1381                 break  # this will remove 8 bits of entropy
1382             nonce += 1
1383         return seed
1384
1385     def prepare_seed(self, seed):
1386         import unicodedata
1387         return NEW_SEED_VERSION, unicodedata.normalize('NFC', unicode(seed.strip()))
1388
1389
1390 class Wallet_2of2(NewWallet):
1391     """ This class is used for multisignature addresses"""
1392
1393     def __init__(self, storage):
1394         NewWallet.__init__(self, storage)
1395         self.storage.put('wallet_type', '2of2', True)
1396
1397     def default_account(self):
1398         return self.accounts['m/']
1399
1400     def can_create_accounts(self):
1401         return False
1402
1403     def can_import(self):
1404         return False
1405
1406     def create_account(self, name, password):
1407         xpub1 = self.master_public_keys.get("m/")
1408         xpub2 = self.master_public_keys.get("cold/")
1409         account = BIP32_Account_2of2({'xpub':xpub1, 'xpub2':xpub2})
1410         self.add_account('m/', account)
1411
1412     def get_master_public_keys(self):
1413         xpub1 = self.master_public_keys.get("m/")
1414         xpub2 = self.master_public_keys.get("cold/")
1415         return {'hot':xpub1, 'cold':xpub2}
1416
1417     def get_action(self):
1418         xpub1 = self.master_public_keys.get("m/")
1419         xpub2 = self.master_public_keys.get("cold/")
1420         if xpub1 is None:
1421             return 'create_seed'
1422         if xpub2 is None:
1423             return 'add_cosigner'
1424         if not self.accounts:
1425             return 'create_accounts'
1426
1427
1428 class Wallet_2of3(Wallet_2of2):
1429     """ This class is used for multisignature addresses"""
1430
1431     def __init__(self, storage):
1432         Wallet_2of2.__init__(self, storage)
1433         self.storage.put('wallet_type', '2of3', True)
1434
1435     def create_account(self, name, password):
1436         xpub1 = self.master_public_keys.get("m/")
1437         xpub2 = self.master_public_keys.get("cold/")
1438         xpub3 = self.master_public_keys.get("remote/")
1439         account = BIP32_Account_2of3({'xpub':xpub1, 'xpub2':xpub2, 'xpub3':xpub3})
1440         self.add_account('m/', account)
1441
1442     def get_master_public_keys(self):
1443         xpub1 = self.master_public_keys.get("m/")
1444         xpub2 = self.master_public_keys.get("cold/")
1445         xpub3 = self.master_public_keys.get("remote/")
1446         return {'hot':xpub1, 'cold':xpub2, 'remote':xpub3}
1447
1448     def get_action(self):
1449         xpub1 = self.master_public_keys.get("m/")
1450         xpub2 = self.master_public_keys.get("cold/")
1451         xpub3 = self.master_public_keys.get("remote/")
1452         if xpub1 is None:
1453             return 'create_seed'
1454         if xpub2 is None or xpub3 is None:
1455             return 'add_two_cosigners'
1456         if not self.accounts:
1457             return 'create_accounts'
1458
1459
1460 class OldWallet(Deterministic_Wallet):
1461
1462     def default_account(self):
1463         return self.accounts[0]
1464
1465     def make_seed(self):
1466         import mnemonic
1467         seed = random_seed(128)
1468         return ' '.join(mnemonic.mn_encode(seed))
1469
1470     def prepare_seed(self, seed):
1471         import mnemonic
1472         # see if seed was entered as hex
1473         seed = seed.strip()
1474         try:
1475             assert seed
1476             seed.decode('hex')
1477             return OLD_SEED_VERSION, str(seed)
1478         except Exception:
1479             pass
1480
1481         words = seed.split()
1482         seed = mnemonic.mn_decode(words)
1483         if not seed:
1484             raise Exception("Invalid seed")
1485
1486         return OLD_SEED_VERSION, seed
1487
1488     def create_master_keys(self, password):
1489         seed = self.get_seed(password)
1490         mpk = OldAccount.mpk_from_seed(seed)
1491         self.storage.put('master_public_key', mpk, True)
1492
1493     def get_master_public_key(self):
1494         return self.storage.get("master_public_key")
1495
1496     def get_master_public_keys(self):
1497         return {'Main Account':self.get_master_public_key()}
1498
1499     def create_accounts(self, password):
1500         mpk = self.storage.get("master_public_key")
1501         self.create_account(mpk)
1502
1503     def create_account(self, mpk):
1504         self.accounts[0] = OldAccount({'mpk':mpk, 0:[], 1:[]})
1505         self.save_accounts()
1506
1507     def create_watching_only_wallet(self, mpk):
1508         self.seed_version = OLD_SEED_VERSION
1509         self.storage.put('seed_version', self.seed_version, True)
1510         self.storage.put('master_public_key', mpk, True)
1511         self.create_account(mpk)
1512
1513     def get_seed(self, password):
1514         seed = pw_decode(self.seed, password).encode('utf8')
1515         return seed
1516
1517     def check_password(self, password):
1518         seed = self.get_seed(password)
1519         self.accounts[0].check_seed(seed)
1520
1521     def get_mnemonic(self, password):
1522         import mnemonic
1523         s = self.get_seed(password)
1524         return ' '.join(mnemonic.mn_encode(s))
1525
1526     def check_pending_accounts(self):
1527         pass
1528
1529     def can_sign(self, tx):
1530         if self.is_watching_only():
1531             return False
1532         if tx.is_complete():
1533             return False
1534         addr_list, xpub_list = tx.inputs_to_sign()
1535         for addr in addr_list:
1536             if self.is_mine(addr):
1537                 return True
1538         for xpub, sequence in xpub_list:
1539             if xpub == self.master_public_key:
1540                 return True
1541         return False
1542
1543 # former WalletFactory
1544 class Wallet(object):
1545     """The main wallet "entry point".
1546     This class is actually a factory that will return a wallet of the correct
1547     type when passed a WalletStorage instance."""
1548
1549     def __new__(self, storage):
1550         config = storage.config
1551
1552         self.wallet_types = [ 
1553             ('standard', ("Standard wallet"),          NewWallet if config.get('bip32') else OldWallet),
1554             ('imported', ("Imported wallet"),          Imported_Wallet),
1555             ('2of2',     ("Multisig wallet (2 of 2)"), Wallet_2of2),
1556             ('2of3',     ("Multisig wallet (2 of 3)"), Wallet_2of3)
1557         ]
1558         run_hook('add_wallet_types', self.wallet_types)
1559
1560         for t, l, WalletClass in self.wallet_types:
1561             if t == storage.get('wallet_type'):
1562                 return WalletClass(storage)
1563
1564         if not storage.file_exists:
1565             seed_version = NEW_SEED_VERSION if config.get('bip32') is True else OLD_SEED_VERSION
1566         else:
1567             seed_version = storage.get('seed_version')
1568             if not seed_version:
1569                 seed_version = OLD_SEED_VERSION if len(storage.get('master_public_key')) == 128 else NEW_SEED_VERSION
1570
1571         if seed_version == OLD_SEED_VERSION:
1572             return OldWallet(storage)
1573         elif seed_version == NEW_SEED_VERSION:
1574             return NewWallet(storage)
1575         else:
1576             msg = "This wallet seed is not supported."
1577             if seed_version in [5]:
1578                 msg += "\nTo open this wallet, try 'git checkout seed_v%d'"%seed_version
1579             print msg
1580             sys.exit(1)
1581
1582     @classmethod
1583     def is_seed(self, seed):
1584         if not seed:
1585             return False
1586         elif is_old_seed(seed):
1587             return True
1588         elif is_new_seed(seed):
1589             return True
1590         else:
1591             return False
1592
1593     @classmethod
1594     def is_old_mpk(self, mpk):
1595         try:
1596             int(mpk, 16)
1597             assert len(mpk) == 128
1598             return True
1599         except:
1600             return False
1601
1602     @classmethod
1603     def is_xpub(self, text):
1604         try:
1605             assert text[0:4] == 'xpub'
1606             deserialize_xkey(text)
1607             return True
1608         except:
1609             return False
1610
1611     @classmethod
1612     def is_xprv(self, text):
1613         try:
1614             assert text[0:4] == 'xprv'
1615             deserialize_xkey(text)
1616             return True
1617         except:
1618             return False
1619
1620     @classmethod
1621     def is_address(self, text):
1622         if not text:
1623             return False
1624         for x in text.split():
1625             if not bitcoin.is_address(x):
1626                 return False
1627         return True
1628
1629     @classmethod
1630     def is_private_key(self, text):
1631         if not text:
1632             return False
1633         for x in text.split():
1634             if not bitcoin.is_private_key(x):
1635                 return False
1636         return True
1637
1638     @classmethod
1639     def from_seed(self, seed, storage):
1640         if is_old_seed(seed):
1641             klass = OldWallet
1642         elif is_new_seed(seed):
1643             klass = NewWallet
1644         w = klass(storage)
1645         return w
1646
1647     @classmethod
1648     def from_address(self, text, storage):
1649         w = Imported_Wallet(storage)
1650         for x in text.split():
1651             w.accounts[IMPORTED_ACCOUNT].add(x, None, None, None)
1652         w.save_accounts()
1653         return w
1654
1655     @classmethod
1656     def from_private_key(self, text, storage):
1657         w = Imported_Wallet(storage)
1658         for x in text.split():
1659             w.import_key(x, None)
1660         return w
1661
1662     @classmethod
1663     def from_old_mpk(self, mpk, storage):
1664         w = OldWallet(storage)
1665         w.seed = ''
1666         w.create_watching_only_wallet(mpk)
1667         return w
1668
1669     @classmethod
1670     def from_xpub(self, xpub, storage):
1671         w = NewWallet(storage)
1672         w.create_watching_only_wallet(xpub)
1673         return w
1674
1675     @classmethod
1676     def from_xprv(self, xprv, password, storage):
1677         w = NewWallet(storage)
1678         w.create_xprv_wallet(xprv, password)
1679         return w