# instanciate wallet for command-line
storage = WalletStorage(config)
- if cmd.requires_wallet:
- wallet = Wallet(storage)
- else:
- wallet = None
-
- if cmd.name not in ['create', 'restore'] and cmd.requires_wallet and not storage.file_exists:
- print_msg("Error: Wallet file not found.")
- print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option")
- sys.exit(0)
-
-
if cmd.name in ['create', 'restore']:
if storage.file_exists:
if not config.get('server'):
config.set_key('server', pick_random_server())
- fee = options.tx_fee if options.tx_fee else raw_input("fee (default:%s):" % (str(Decimal(wallet.fee)/100000000)))
- gap = options.gap_limit if options.gap_limit else raw_input("gap limit (default 5):")
-
- if fee:
- wallet.set_fee(float(fee)*100000000)
- if gap:
- wallet.change_gap_limit(int(gap))
+ #fee = options.tx_fee if options.tx_fee else raw_input("fee (default:%s):" % (str(Decimal(wallet.fee)/100000000)))
+ #gap = options.gap_limit if options.gap_limit else raw_input("gap limit (default 5):")
+ #if fee:
+ # wallet.set_fee(float(fee)*100000000)
+ #if gap:
+ # wallet.change_gap_limit(int(gap))
if cmd.name == 'restore':
import getpass
seed = getpass.getpass(prompt="seed:", stream=None) if options.concealed else raw_input("seed:")
- try:
- seed.decode('hex')
- except Exception:
- print_error("Warning: Not hex, trying decode.")
- seed = mnemonic_decode(seed.split(' '))
- if not seed:
- sys.exit("Error: No seed")
-
- wallet.init_seed(str(seed))
+ wallet = Wallet.from_seed(str(seed),storage)
+ if not wallet:
+ sys.exit("Error: Invalid seed")
wallet.save_seed(password)
if not options.offline:
network = Network(config)
network.start()
wallet.start_threads(network)
-
print_msg("Recovering wallet...")
wallet.restore(lambda x: x)
-
if wallet.is_found():
print_msg("Recovery successful")
else:
print_msg("Warning: This wallet was restored offline. It may contain more addresses than displayed.")
else:
+ wallet = Wallet(storage)
wallet.init_seed(None)
wallet.save_seed(password)
wallet.synchronize()
# terminate
sys.exit(0)
+
+ if cmd.name not in ['create', 'restore'] and cmd.requires_wallet and not storage.file_exists:
+ print_msg("Error: Wallet file not found.")
+ print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option")
+ sys.exit(0)
+
+
+ if cmd.requires_wallet:
+ wallet = Wallet(storage)
+ else:
+ wallet = None
+
+
# important warning
if cmd.name in ['dumpprivkey', 'dumpprivkeys']:
print_msg("WARNING: ALL your private keys are secret.")
self.seed = unicodedata.normalize('NFC', unicode(seed.strip()))
return
- # find out what kind of wallet we are
- try:
- seed.strip().decode('hex')
- self.seed_version = 4
- self.seed = str(seed)
- return
- except Exception:
- pass
-
- words = seed.split()
- try:
- mnemonic.mn_decode(words)
- uses_electrum_words = True
- except Exception:
- uses_electrum_words = False
-
- if uses_electrum_words and len(words) != 13:
- self.seed_version = 4
- self.seed = mnemonic.mn_decode(words)
- else:
- #assert is_seed(seed)
- self.seed_version = SEED_VERSION
- self.seed = seed
def save_seed(self, password):
self.create_accounts(password)
- def create_watching_only_wallet(self, params):
- K0, c0 = params
- if not K0:
- return
-
- if not c0:
- self.seed_version = 4
- self.storage.put('seed_version', self.seed_version, True)
- self.create_old_account(K0)
- return
-
- cK0 = ""
+ def create_watching_only_wallet(self, K0, c0):
+ cK0 = "" #FIXME
self.master_public_keys = {
"m/0'/": (c0, K0, cK0),
}
def create_accounts(self, password):
seed = pw_decode(self.seed, password)
-
- if self.seed_version == 4:
- mpk = OldAccount.mpk_from_seed(seed)
- self.create_old_account(mpk)
- else:
- # create default account
- self.create_master_keys('1', password)
- self.create_account('1','Main account')
+ # create default account
+ self.create_master_keys('1', password)
+ self.create_account('1','Main account')
def create_master_keys(self, account_type, password):
self.set_label(k, name)
- def create_old_account(self, mpk):
- self.storage.put('master_public_key', mpk, True)
- self.accounts[0] = OldAccount({'mpk':mpk, 0:[], 1:[]})
- self.save_accounts()
-
-
def save_accounts(self):
d = {}
for k, v in self.accounts.items():
return s[0] == 1
def get_master_public_key(self):
- if self.seed_version == 4:
- return self.storage.get("master_public_key")
- else:
- c, K, cK = self.storage.get("master_public_keys")["m/0'/"]
- return repr((c, K))
+ c, K, cK = self.storage.get("master_public_keys")["m/0'/"]
+ return repr((c, K))
def get_master_private_key(self, account, password):
k = self.master_private_keys.get(account)
def get_seed(self, password):
s = pw_decode(self.seed, password)
- if self.seed_version == 4:
- seed = s
- self.accounts[0].check_seed(seed)
- else:
- seed = mnemonic_to_seed(s,'').encode('hex')
+ seed = mnemonic_to_seed(s,'').encode('hex')
return seed
-
+
def get_mnemonic(self, password):
- import mnemonic
- s = pw_decode(self.seed, password)
- if self.seed_version == 4:
- return ' '.join(mnemonic.mn_encode(s))
- else:
- return s
+ return pw_decode(self.seed, password)
def get_private_key(self, address, password):
for txin in tx.inputs:
keyid = txin.get('KeyID')
if keyid:
-
- if self.seed_version == 4:
- m = re.match("old\(([0-9a-f]+),(\d+),(\d+)", keyid)
- if not m: continue
- mpk = m.group(1)
- if mpk != self.storage.get('master_public_key'): continue
- for_change = int(m.group(2))
- num = int(m.group(3))
- account = self.accounts[0]
- addr = account.get_address(for_change, num)
- txin['address'] = addr # fixme: side effect
- pk = account.get_private_key(seed, (for_change, num))
- pubkey = public_key_from_private_key(pk)
- keypairs[pubkey] = pk
- continue
-
-
roots = []
for s in keyid.split('&'):
m = re.match("bip32\(([0-9a-f]+),([0-9a-f]+),(/\d+/\d+/\d+)", s)
def get_account_name(self, k):
- if k == 0:
- if self.seed_version == 4:
- name = 'Main account'
+ default = "Unnamed account"
+ m = re.match("m/0'/(\d+)", k)
+ if m:
+ num = m.group(1)
+ if num == '0':
+ default = "Main account"
else:
- name = 'Old account'
- else:
- default = "Unnamed account"
- m = re.match("m/0'/(\d+)", k)
- if m:
- num = m.group(1)
- if num == '0':
- default = "Main account"
- else:
- default = "Account %s"%num
+ default = "Account %s"%num
- m = re.match("m/1'/(\d+) & m/2'/(\d+)", k)
- if m:
- num = m.group(1)
- default = "2of2 account %s"%num
- name = self.labels.get(k, default)
-
+ m = re.match("m/1'/(\d+) & m/2'/(\d+)", k)
+ if m:
+ num = m.group(1)
+ default = "2of2 account %s"%num
+ name = self.labels.get(k, default)
return name
+
def get_account_names(self):
accounts = {}
for k, account in self.accounts.items():
accounts[-1] = 'Imported keys'
return accounts
+
def get_account_addresses(self, a, include_change=True):
if a is None:
o = self.addresses(True)
self.was_updated = False
+
+
+class OldWallet(Wallet):
+
+ def init_seed(self, seed):
+ import mnemonic
+
+ if self.seed:
+ raise Exception("a seed exists")
+
+ if not seed:
+ raise
+
+ self.seed_version = 4
+
+ # see if seed was entered as hex
+ try:
+ seed.strip().decode('hex')
+ self.seed = str(seed)
+ return
+ except Exception:
+ pass
+
+ words = seed.split()
+ try:
+ mnemonic.mn_decode(words)
+ except Exception:
+ raise
+
+ self.seed = mnemonic.mn_decode(words)
+
+
+ def get_master_public_key(self):
+ return self.storage.get("master_public_key")
+
+ def create_accounts(self, password):
+ seed = pw_decode(self.seed, password)
+ mpk = OldAccount.mpk_from_seed(seed)
+ self.create_account(mpk)
+
+ def create_account(self, mpk):
+ self.storage.put('master_public_key', mpk, True)
+ self.accounts[0] = OldAccount({'mpk':mpk, 0:[], 1:[]})
+ self.save_accounts()
+
+ def create_watching_only_wallet(self, K0):
+ self.seed_version = 4
+ self.storage.put('seed_version', self.seed_version, True)
+ self.create_account(K0)
+
+ def get_seed(self, password):
+ seed = pw_decode(self.seed, password)
+ self.accounts[0].check_seed(seed)
+ return seed
+
+ def get_mnemonic(self, password):
+ import mnemonic
+ s = pw_decode(self.seed, password)
+ return ' '.join(mnemonic.mn_encode(s))
+
+
+ def add_keypairs_from_KeyID(self, tx, keypairs, password):
+ # first check the provided password
+ seed = self.get_seed(password)
+ for txin in tx.inputs:
+ keyid = txin.get('KeyID')
+ if keyid:
+ m = re.match("old\(([0-9a-f]+),(\d+),(\d+)", keyid)
+ if not m: continue
+ mpk = m.group(1)
+ if mpk != self.storage.get('master_public_key'): continue
+ for_change = int(m.group(2))
+ num = int(m.group(3))
+ account = self.accounts[0]
+ addr = account.get_address(for_change, num)
+ txin['address'] = addr # fixme: side effect
+ pk = account.get_private_key(seed, (for_change, num))
+ pubkey = public_key_from_private_key(pk)
+ keypairs[pubkey] = pk
+
+
+ def get_account_name(self, k):
+ assert k == 0
+ return 'Main account'
+