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