upgrade to type 2 wallet

This commit is contained in:
thomasv 2011-12-15 15:41:50 +01:00
parent deaa5745a4
commit ca32d29a9c
4 changed files with 202 additions and 120 deletions

View File

@ -19,6 +19,7 @@
import sys, base64, os, re, hashlib, socket, getpass, copy, operator, ast import sys, base64, os, re, hashlib, socket, getpass, copy, operator, ast
from decimal import Decimal from decimal import Decimal
from ecdsa.util import string_to_number
try: try:
import ecdsa import ecdsa
@ -215,8 +216,7 @@ class InvalidPassword(Exception):
SEED_VERSION = 3 # bump this everytime the seed generation is modified from version import ELECTRUM_VERSION, SEED_VERSION
from version import ELECTRUM_VERSION
class Wallet: class Wallet:
@ -230,13 +230,13 @@ class Wallet:
self.port = 50000 self.port = 50000
self.fee = 50000 self.fee = 50000
self.servers = ['ecdsa.org','electrum.novit.ro'] # list of default servers self.servers = ['ecdsa.org','electrum.novit.ro'] # list of default servers
self.master_public_key = None
# saved fields # saved fields
self.use_encryption = False self.use_encryption = False
self.addresses = [] self.addresses = [] # receiving addresses visible for user
self.change_addresses = [] # addresses used as change
self.seed = '' # encrypted self.seed = '' # encrypted
self.private_keys = repr([]) # encrypted
self.change_addresses = [] # index of addresses used as change
self.status = {} # current status of addresses self.status = {} # current status of addresses
self.history = {} self.history = {}
self.labels = {} # labels for addresses and transactions self.labels = {} # labels for addresses and transactions
@ -262,25 +262,31 @@ class Wallet:
elif "LOCALAPPDATA" in os.environ: elif "LOCALAPPDATA" in os.environ:
wallet_dir = os.path.join( os.environ["LOCALAPPDATA"], 'Electrum' ) wallet_dir = os.path.join( os.environ["LOCALAPPDATA"], 'Electrum' )
elif "APPDATA" in os.environ: elif "APPDATA" in os.environ:
wallet_dir = os.path.join( os.environ["APPDATA"], 'Electrum' ) wallet_dir = os.path.join( os.environ["APPDATA"], 'Electrum' )
else: else:
raise BaseException("No home directory found in environment variables.") raise BaseException("No home directory found in environment variables.")
if not os.path.exists( wallet_dir ): os.mkdir( wallet_dir ) if not os.path.exists( wallet_dir ): os.mkdir( wallet_dir )
self.path = os.path.join( wallet_dir, 'electrum.dat') self.path = os.path.join( wallet_dir, 'electrum.dat' )
def new_seed(self, password): def new_seed(self, password):
seed = "%032x"%ecdsa.util.randrange( pow(2,128) ) seed = "%032x"%ecdsa.util.randrange( pow(2,128) )
self.seed = wallet.pw_encode( seed, password) self.init_mpk(seed)
# encrypt
self.seed = wallet.pw_encode( seed, password )
def init_mpk(self,seed):
# public key
curve = SECP256k1
secexp = self.stretch_key(seed)
master_private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 )
self.master_public_key = master_private_key.get_verifying_key().to_string()
def is_mine(self, address): def is_mine(self, address):
return address in self.addresses return address in self.addresses or address in self.change_addresses
def is_change(self, address): def is_change(self, address):
if not self.is_mine(address): return address in self.change_addresses
return False
k = self.addresses.index(address)
return k in self.change_addresses
def is_valid(self,addr): def is_valid(self,addr):
ADDRESS_RE = re.compile('[1-9A-HJ-NP-Za-km-z]{26,}\\Z') ADDRESS_RE = re.compile('[1-9A-HJ-NP-Za-km-z]{26,}\\Z')
@ -288,43 +294,61 @@ class Wallet:
h = bc_address_to_hash_160(addr) h = bc_address_to_hash_160(addr)
return addr == hash_160_to_bc_address(h) return addr == hash_160_to_bc_address(h)
def create_new_address(self, for_change, password): def stretch_key(self,seed):
seed = self.pw_decode( self.seed, password)
# strenghtening
oldseed = seed oldseed = seed
for i in range(100000): for i in range(100000):
seed = hashlib.sha512(seed + oldseed).digest() seed = hashlib.sha256(seed + oldseed).digest()
i = len( self.addresses ) - len(self.change_addresses) if not for_change else len(self.change_addresses) return string_to_number( seed )
seed = Hash( "%d:%d:"%(i,for_change) + seed )
def get_sequence(self,n,for_change):
return string_to_number( Hash( "%d:%d:"%(n,for_change) + self.master_public_key ) )
def get_private_key2(self, address, password):
""" Privatekey(type,n) = Master_private_key + H(n|S|type) """
if address in self.addresses:
n = self.addresses.index(address)
for_change = False
elif address in self.change_addresses:
n = self.change_addresses.index(address)
for_change = True
else:
raise BaseException("unknown address")
seed = self.pw_decode( self.seed, password)
secexp = self.stretch_key(seed)
order = generator_secp256k1.order() order = generator_secp256k1.order()
secexp = ecdsa.util.randrange_from_seed__trytryagain( seed, order ) privkey_number = ( secexp + self.get_sequence(n,for_change) ) % order
secret = SecretToASecret( ('%064x' % secexp).decode('hex') ) private_key = ecdsa.SigningKey.from_secret_exponent( privkey_number, curve = SECP256k1 )
private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 ) # sanity check
public_key = private_key.get_verifying_key() #public_key = private_key.get_verifying_key()
address = public_key_to_bc_address( '04'.decode('hex') + public_key.to_string() ) #assert address == public_key_to_bc_address( '04'.decode('hex') + public_key.to_string() )
try: return private_key
private_keys = ast.literal_eval( self.pw_decode( self.private_keys, password) )
private_keys.append(secret)
except: def create_new_address2(self, for_change):
raise InvalidPassword("") """ Publickey(type,n) = Master_public_key + H(n|S|type)*point """
self.private_keys = self.pw_encode( repr(private_keys), password) curve = SECP256k1
self.addresses.append(address) n = len(self.change_addresses) if for_change else len(self.addresses)
if for_change: self.change_addresses.append( len(self.addresses) - 1 ) z = self.get_sequence(n,for_change)
self.history[address] = [] master_public_key = ecdsa.VerifyingKey.from_string( self.master_public_key, curve = SECP256k1 )
self.status[address] = None pubkey_point = master_public_key.pubkey.point + z*curve.generator
public_key2 = ecdsa.VerifyingKey.from_public_point( pubkey_point, curve = SECP256k1 )
address = public_key_to_bc_address( '04'.decode('hex') + public_key2.to_string() )
if for_change:
self.change_addresses.append(address)
else:
self.addresses.append(address)
self.save() self.save()
return address return address
def recover(self):
def recover(self, password):
seed = self.pw_decode( self.seed, password)
# todo: recover receiving addresses from tx # todo: recover receiving addresses from tx
is_found = False is_found = False
while True: while True:
addr = self.create_new_address(True, password) addr = self.create_new_address2(True)
self.history[addr] = h = self.retrieve_history(addr) self.history[addr] = h = self.retrieve_history(addr)
self.status[addr] = h[-1]['blk_hash'] if h else None self.status[addr] = h[-1]['blk_hash'] if h else None
#print "recovering", addr print "recovering", addr
if self.status[addr] is not None: if self.status[addr] is not None:
is_found = True is_found = True
else: else:
@ -332,10 +356,10 @@ class Wallet:
num_gap = 0 num_gap = 0
while True: while True:
addr = self.create_new_address(False, password) addr = self.create_new_address2(False)
self.history[addr] = h = self.retrieve_history(addr) self.history[addr] = h = self.retrieve_history(addr)
self.status[addr] = h[-1]['blk_hash'] if h else None self.status[addr] = h[-1]['blk_hash'] if h else None
#print "recovering", addr print "recovering", addr
if self.status[addr] is None: if self.status[addr] is None:
num_gap += 1 num_gap += 1
if num_gap == self.gap_limit: break if num_gap == self.gap_limit: break
@ -345,12 +369,9 @@ class Wallet:
if not is_found: return False if not is_found: return False
# remove limit-1 addresses. [ this is ok, because change addresses are at the beginning of the list] # remove limit-1 addresses.
n = self.gap_limit n = self.gap_limit
self.addresses = self.addresses[:-n] self.addresses = self.addresses[:-n]
private_keys = ast.literal_eval( self.pw_decode( self.private_keys, password))
private_keys = private_keys[:-n]
self.private_keys = self.pw_encode( repr(private_keys), password)
# history and addressbook # history and addressbook
self.update_tx_history() self.update_tx_history()
@ -364,12 +385,24 @@ class Wallet:
return True return True
def save(self): def save(self):
s = repr( (self.seed_version, self.use_encryption, self.fee, self.host, self.port, self.blocks, s = {
self.seed, self.addresses, self.private_keys, 'seed_version':self.seed_version,
self.change_addresses, self.status, self.history, 'use_encryption':self.use_encryption,
self.labels, self.addressbook) ) 'master_public_key': self.master_public_key,
'fee':self.fee,
'host':self.host,
'port':self.port,
'blocks':self.blocks,
'seed':self.seed,
'addresses':self.addresses,
'change_addresses':self.change_addresses,
'status':self.status,
'history':self.history,
'labels':self.labels,
'contacts':self.addressbook
}
f = open(self.path,"w") f = open(self.path,"w")
f.write(s) f.write( repr(s) )
f.close() f.close()
def read(self): def read(self):
@ -380,32 +413,41 @@ class Wallet:
except: except:
return False return False
try: try:
sequence = ast.literal_eval( data ) d = ast.literal_eval( data )
(self.seed_version, self.use_encryption, self.fee, self.host, self.port, self.blocks, self.seed_version = d.get('seed_version')
self.seed, self.addresses, self.private_keys, self.master_public_key = d.get('master_public_key')
self.change_addresses, self.status, self.history, self.use_encryption = d.get('use_encryption')
self.labels, self.addressbook) = sequence self.fee = int( d.get('fee') )
self.fee = int(self.fee) self.host = d.get('host')
self.port = d.get('port')
self.blocks = d.get('blocks')
self.seed = d.get('seed')
self.addresses = d.get('addresses')
self.change_addresses = d.get('change_addresses')
self.status = d.get('status')
self.history = d.get('history')
self.labels = d.get('labels')
self.addressbook = d.get('contacts')
except: except:
# it is safer to exit immediately raise BaseException("Error; could not parse wallet. If this is an old wallet format, please use upgrade.py.",0)
print "Error; could not parse wallet."
exit(1)
if self.seed_version != SEED_VERSION: if self.seed_version != SEED_VERSION:
raise BaseException("Seed version mismatch.\nPlease move your balance to a new wallet.\nSee the release notes for more information.") raise BaseException("""Seed version mismatch: your wallet seed is deprecated.
Please create a new wallet, and send your coins to the new wallet.
We apologize for the inconvenience. We try to keep this kind of upgrades as rare as possible.
See the release notes for more information.""",1)
self.update_tx_history() self.update_tx_history()
return True return True
def get_new_address(self, password): def get_new_address(self):
n = 0 n = 0
for addr in self.addresses[-self.gap_limit:]: for addr in self.addresses[-self.gap_limit:]:
if self.history[addr] == []: if not self.history.get(addr):
n = n + 1 n = n + 1
if n < self.gap_limit: if n < self.gap_limit:
try: new_address = self.create_new_address2(False)
new_address = self.create_new_address(False, password) self.history[new_address] = [] #get from server
except InvalidPassword:
return False, "wrong password"
self.save()
return True, new_address return True, new_address
else: else:
return False, "The last %d addresses in your list have never been used. You should use them first, or increase the allowed gap size in your preferences. "%self.gap_limit return False, "The last %d addresses in your list have never been used. You should use them first, or increase the allowed gap size in your preferences. "%self.gap_limit
@ -516,19 +558,17 @@ class Wallet:
inputs = [] inputs = []
return inputs, total, fee return inputs, total, fee
def choose_tx_outputs( self, to_addr, amount, fee, total, password ): def choose_tx_outputs( self, to_addr, amount, fee, total ):
outputs = [ (to_addr, amount) ] outputs = [ (to_addr, amount) ]
change_amount = total - ( amount + fee ) change_amount = total - ( amount + fee )
if change_amount != 0: if change_amount != 0:
# first look for unused change addresses # first look for unused change addresses
for addr in self.addresses: for addr in self.change_addresses:
i = self.addresses.index(addr)
if i not in self.change_addresses: continue
if self.history.get(addr): continue if self.history.get(addr): continue
change_address = addr change_address = addr
break break
else: else:
change_address = self.create_new_address(True, password) change_address = self.create_new_address2(True)
print "new change address", change_address print "new change address", change_address
outputs.append( (change_address, change_amount) ) outputs.append( (change_address, change_amount) )
return outputs return outputs
@ -537,7 +577,7 @@ class Wallet:
s_inputs = [] s_inputs = []
for i in range(len(inputs)): for i in range(len(inputs)):
addr, v, p_hash, p_pos, p_scriptPubKey, _, _ = inputs[i] addr, v, p_hash, p_pos, p_scriptPubKey, _, _ = inputs[i]
private_key = self.get_private_key(addr, password) private_key = self.get_private_key2(addr, password)
public_key = private_key.get_verifying_key() public_key = private_key.get_verifying_key()
pubkey = public_key.to_string() pubkey = public_key.to_string()
tx = filter( raw_tx( inputs, outputs, for_sig = i ) ) tx = filter( raw_tx( inputs, outputs, for_sig = i ) )
@ -556,24 +596,15 @@ class Wallet:
def pw_decode(self, s, password): def pw_decode(self, s, password):
if password: if password:
secret = Hash(password) secret = Hash(password)
return DecodeAES(secret, s) d = DecodeAES(secret, s)
try:
d.decode('hex')
except:
raise InvalidPassword()
return d
else: else:
return s return s
def get_private_key( self, addr, password ):
try:
private_keys = ast.literal_eval( self.pw_decode( self.private_keys, password ) )
except:
raise InvalidPassword("")
k = self.addresses.index(addr)
secret = private_keys[k]
b = ASecretToSecret(secret)
secexp = int( b.encode('hex'), 16)
private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve=SECP256k1 )
public_key = private_key.get_verifying_key()
assert addr == public_key_to_bc_address( chr(4) + public_key.to_string() )
return private_key
def get_tx_history(self): def get_tx_history(self):
lines = self.tx_history.values() lines = self.tx_history.values()
lines = sorted(lines, key=operator.itemgetter("nTime")) lines = sorted(lines, key=operator.itemgetter("nTime"))
@ -623,7 +654,7 @@ class Wallet:
inputs, total, fee = wallet.choose_tx_inputs( amount, fee ) inputs, total, fee = wallet.choose_tx_inputs( amount, fee )
if not inputs: return False, "Not enough funds %d %d"%(total, fee) if not inputs: return False, "Not enough funds %d %d"%(total, fee)
try: try:
outputs = wallet.choose_tx_outputs( to_address, amount, fee, total, password ) outputs = wallet.choose_tx_outputs( to_address, amount, fee, total )
s_inputs = wallet.sign_inputs( inputs, outputs, password ) s_inputs = wallet.sign_inputs( inputs, outputs, password )
except InvalidPassword: except InvalidPassword:
return False, "Wrong password" return False, "Wrong password"
@ -648,7 +679,7 @@ class Wallet:
from optparse import OptionParser from optparse import OptionParser
if __name__ == '__main__': if __name__ == '__main__':
known_commands = ['help', 'validateaddress', 'balance', 'contacts', 'create', 'payto', 'sendtx', 'password', 'newaddress', 'addresses', 'history', 'label', 'gui', 'mktx','seed'] known_commands = ['help', 'validateaddress', 'balance', 'contacts', 'create', 'payto', 'sendtx', 'password', 'newaddress', 'addresses', 'history', 'label', 'gui', 'mktx','seed','t2']
usage = "usage: %prog [options] command args\nCommands: "+ (', '.join(known_commands)) usage = "usage: %prog [options] command args\nCommands: "+ (', '.join(known_commands))
@ -713,7 +744,7 @@ if __name__ == '__main__':
gap = raw_input("gap limit (default 5):") gap = raw_input("gap limit (default 5):")
if gap: wallet.gap_limit = int(gap) if gap: wallet.gap_limit = int(gap)
print "recovering wallet..." print "recovering wallet..."
r = wallet.recover(password) r = wallet.recover()
if r: if r:
print "recovery successful" print "recovery successful"
wallet.save() wallet.save()
@ -724,7 +755,7 @@ if __name__ == '__main__':
print "Your seed is", wallet.seed print "Your seed is", wallet.seed
print "Please store it safely" print "Please store it safely"
# generate first key # generate first key
wallet.create_new_address(False, None) wallet.create_new_address2(False)
# check syntax # check syntax
if cmd in ['payto', 'mktx']: if cmd in ['payto', 'mktx']:
@ -738,13 +769,13 @@ if __name__ == '__main__':
cmd = 'help' cmd = 'help'
# open session # open session
if cmd not in ['password', 'mktx', 'history', 'label','contacts','help','validateaddress']: if cmd not in ['password', 'mktx', 'history', 'label', 'contacts', 'help', 'validateaddress']:
wallet.new_session() wallet.new_session()
wallet.update() wallet.update()
wallet.save() wallet.save()
# commands needing password # commands needing password
if cmd in ['payto', 'password', 'newaddress','mktx','seed'] or ( cmd=='addresses' and options.show_keys): if cmd in ['payto', 'password', 'mktx', 'seed' ] or ( cmd=='addresses' and options.show_keys):
password = getpass.getpass('Password:') if wallet.use_encryption else None password = getpass.getpass('Password:') if wallet.use_encryption else None
if cmd=='help': if cmd=='help':
@ -790,6 +821,9 @@ if __name__ == '__main__':
addr = args[1] addr = args[1]
print wallet.is_valid(addr) print wallet.is_valid(addr)
elif cmd == 't2':
wallet.create_t2_address(password)
elif cmd == 'balance': elif cmd == 'balance':
c, u = wallet.get_balance() c, u = wallet.get_balance()
if u: if u:
@ -861,19 +895,18 @@ if __name__ == '__main__':
else: else:
print h print h
elif cmd=='sendtx': elif cmd == 'sendtx':
tx = args[1] tx = args[1]
r, h = wallet.sendtx( tx ) r, h = wallet.sendtx( tx )
print h print h
elif cmd == 'newaddress': elif cmd == 'newaddress':
s, a = wallet.get_new_address(password) s, a = wallet.get_new_address()
print a print a
elif cmd == 'password': elif cmd == 'password':
try: try:
seed = wallet.pw_decode( wallet.seed, password) seed = wallet.pw_decode( wallet.seed, password)
private_keys = ast.literal_eval( wallet.pw_decode( wallet.private_keys, password) )
except: except:
print "sorry" print "sorry"
sys.exit(1) sys.exit(1)
@ -881,7 +914,6 @@ if __name__ == '__main__':
if new_password == getpass.getpass('Confirm new password:'): if new_password == getpass.getpass('Confirm new password:'):
wallet.use_encryption = (new_password != '') wallet.use_encryption = (new_password != '')
wallet.seed = wallet.pw_encode( seed, new_password) wallet.seed = wallet.pw_encode( seed, new_password)
wallet.private_keys = wallet.pw_encode( repr( private_keys ), new_password)
wallet.save() wallet.save()
else: else:
print "error: mismatch" print "error: mismatch"

View File

@ -64,7 +64,6 @@ def show_seed_dialog(wallet, password, parent):
import mnemonic import mnemonic
try: try:
seed = wallet.pw_decode( wallet.seed, password) seed = wallet.pw_decode( wallet.seed, password)
private_keys = ast.literal_eval( wallet.pw_decode( wallet.private_keys, password) )
except: except:
show_message("Incorrect password") show_message("Incorrect password")
return return
@ -85,8 +84,13 @@ def init_wallet(wallet):
try: try:
found = wallet.read() found = wallet.read()
except BaseException, e: except BaseException, e:
show_message(e.message) show_message(e.args[0])
if e.args[1] == 0: exit(1)
found = 1 found = 1
except:
exit()
if not found: if not found:
# ask if the user wants to create a new wallet, or recover from a seed. # ask if the user wants to create a new wallet, or recover from a seed.
@ -114,7 +118,7 @@ def init_wallet(wallet):
run_settings_dialog(wallet, is_create=True, is_recovery=False, parent=None) run_settings_dialog(wallet, is_create=True, is_recovery=False, parent=None)
# generate first key # generate first key
wallet.create_new_address(False, None) wallet.create_new_address2(False)
# run a dialog indicating the seed, ask the user to remember it # run a dialog indicating the seed, ask the user to remember it
show_seed_dialog(wallet, None, None) show_seed_dialog(wallet, None, None)
@ -133,13 +137,14 @@ def init_wallet(wallet):
message_format = "Please wait..." ) message_format = "Please wait..." )
dialog.show() dialog.show()
def recover_thread( wallet, dialog, password ): def recover_thread( wallet, dialog ):
wallet.is_found = wallet.recover( password ) wallet.init_mpk( wallet.seed ) # not encrypted at this point
wallet.is_found = wallet.recover()
if wallet.is_found: if wallet.is_found:
wallet.save() wallet.save()
gobject.idle_add( dialog.destroy ) gobject.idle_add( dialog.destroy )
thread.start_new_thread( recover_thread, ( wallet, dialog, None ) ) # no password thread.start_new_thread( recover_thread, ( wallet, dialog ) )
r = dialog.run() r = dialog.run()
dialog.destroy() dialog.destroy()
if r==gtk.RESPONSE_CANCEL: sys.exit(1) if r==gtk.RESPONSE_CANCEL: sys.exit(1)
@ -354,7 +359,6 @@ def change_password_dialog(wallet, parent, icon):
try: try:
seed = wallet.pw_decode( wallet.seed, password) seed = wallet.pw_decode( wallet.seed, password)
private_keys = ast.literal_eval( wallet.pw_decode( wallet.private_keys, password) )
except: except:
show_message("Incorrect password") show_message("Incorrect password")
return return
@ -365,7 +369,6 @@ def change_password_dialog(wallet, parent, icon):
wallet.use_encryption = (new_password != '') wallet.use_encryption = (new_password != '')
wallet.seed = wallet.pw_encode( seed, new_password) wallet.seed = wallet.pw_encode( seed, new_password)
wallet.private_keys = wallet.pw_encode( repr( private_keys ), new_password)
wallet.save() wallet.save()
if icon: if icon:
@ -1020,8 +1023,7 @@ class BitcoinGUI:
errorDialog.run() errorDialog.run()
errorDialog.destroy() errorDialog.destroy()
else: else:
password = password_dialog() if self.wallet.use_encryption else None success, ret = self.wallet.get_new_address()
success, ret = self.wallet.get_new_address(password)
self.update_session = True # we created a new address self.update_session = True # we created a new address
if success: if success:
address = ret address = ret

View File

@ -1,9 +1,12 @@
import electrum, getpass, base64,ast,sys import electrum, getpass, base64,ast,sys,os
from version import SEED_VERSION
def upgrade_wallet(wallet): def upgrade_wallet(wallet):
if wallet.version == 1 and wallet.use_encryption: print "walet path:",wallet.path
print "seed version:", wallet.seed_version
if wallet.seed_version == 1 and wallet.use_encryption:
# version 1 used pycrypto for wallet encryption # version 1 used pycrypto for wallet encryption
import Crypto import Crypto
from Crypto.Cipher import AES from Crypto.Cipher import AES
@ -27,21 +30,65 @@ def upgrade_wallet(wallet):
wallet.private_keys = wallet.pw_encode( repr( private_keys ), password) wallet.private_keys = wallet.pw_encode( repr( private_keys ), password)
wallet.save() wallet.save()
print "upgraded to version 2" print "upgraded to version 2"
if wallet.version < 3: exit(1)
print """
Your wallet is deprecated; its generation seed will not work with versions 0.31 and above.
In order to upgrade, you need to create a new wallet (you may use your current seed), and
to send your bitcoins to the new wallet.
We apologize for the inconvenience. We try to keep this kind of upgrades as rare as possible. if wallet.seed_version < SEED_VERSION:
""" print """Note: your wallet seed is deprecated. Please create a new wallet, and move your coins to the new wallet."""
if __name__ == "__main__": if __name__ == "__main__":
try: try:
path = sys.argv[1] path = sys.argv[1]
except: except:
path = None # backward compatibility: look for wallet file in the default data directory
if "HOME" in os.environ:
wallet_dir = os.path.join( os.environ["HOME"], '.electrum')
elif "LOCALAPPDATA" in os.environ:
wallet_dir = os.path.join( os.environ["LOCALAPPDATA"], 'Electrum' )
elif "APPDATA" in os.environ:
wallet_dir = os.path.join( os.environ["APPDATA"], 'Electrum' )
else:
raise BaseException("No home directory found in environment variables.")
path = os.path.join( wallet_dir, 'electrum.dat')
try:
f = open(path,"r")
data = f.read()
f.close()
except:
print "file not found", path
exit(1)
try:
x = ast.literal_eval(data)
except:
print "error: could not parse wallet"
exit(1)
if type(x) == tuple:
seed_version, use_encryption, fee, host, port, blocks, seed, addresses, private_keys, change_addresses, status, history, labels, addressbook = x
s = {
'seed_version':seed_version,
'use_encryption':use_encryption,
'master_public_key':None,
'fee':fee,
'host':host,
'port':port,
'blocks':blocks,
'seed':seed,
'addresses':addresses,
'change_addresses':change_addresses,
'status':status,
'history':history,
'labels':labels,
'contacts':addressbook
}
f = open(path,"w")
f.write( repr(s) )
f.close()
print "wallet format was upgraded."
exit(1)
wallet = electrum.Wallet(path) wallet = electrum.Wallet(path)
try: try:
found = wallet.read() found = wallet.read()

View File

@ -1 +1,2 @@
ELECTRUM_VERSION = "0.33" ELECTRUM_VERSION = "0.34"
SEED_VERSION = 4 # bump this everytime the seed generation is modified