Browse Source

commands/wallet: separate out 'create' and 'restore' core parts

so that they are easier to use from python scripts
sqlite_db
SomberNight 6 years ago
parent
commit
ae80f143e7
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 87
      electrum/commands.py
  2. 79
      electrum/wallet.py

87
electrum/commands.py

@ -46,7 +46,7 @@ from .paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
from .synchronizer import Notifier
from .storage import WalletStorage
from . import keystore
from .wallet import Wallet, Imported_Wallet, Abstract_Wallet
from .wallet import Wallet, Imported_Wallet, Abstract_Wallet, create_new_wallet, restore_wallet_from_text
from .address_synchronizer import TX_HEIGHT_LOCAL
from .mnemonic import Mnemonic
@ -139,22 +139,16 @@ class Commands:
@command('')
def create(self, passphrase=None, password=None, encrypt_file=True, segwit=False):
"""Create a new wallet"""
storage = WalletStorage(self.config.get_wallet_path())
if storage.file_exists():
raise Exception("Remove the existing wallet first!")
seed_type = 'segwit' if segwit else 'standard'
seed = Mnemonic('en').make_seed(seed_type)
k = keystore.from_seed(seed, passphrase)
storage.put('keystore', k.dump())
storage.put('wallet_type', 'standard')
wallet = Wallet(storage)
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
wallet.synchronize()
msg = "Please keep your seed in a safe place; if you lose it, you will not be able to restore your wallet."
wallet.storage.write()
return {'seed': seed, 'path': wallet.storage.path, 'msg': msg}
d = create_new_wallet(path=self.config.get_wallet_path(),
passphrase=passphrase,
password=password,
encrypt_file=encrypt_file,
segwit=segwit)
return {
'seed': d['seed'],
'path': d['wallet'].storage.path,
'msg': d['msg'],
}
@command('')
def restore(self, text, passphrase=None, password=None, encrypt_file=True):
@ -162,55 +156,16 @@ class Commands:
public key, a master private key, a list of bitcoin addresses
or bitcoin private keys. If you want to be prompted for your
seed, type '?' or ':' (concealed) """
storage = WalletStorage(self.config.get_wallet_path())
if storage.file_exists():
raise Exception("Remove the existing wallet first!")
text = text.strip()
if keystore.is_address_list(text):
wallet = Imported_Wallet(storage)
addresses = text.split()
good_inputs, bad_inputs = wallet.import_addresses(addresses, write_to_disk=False)
# FIXME tell user about bad_inputs
if not good_inputs:
raise Exception("None of the given addresses can be imported")
elif keystore.is_private_key_list(text, allow_spaces_inside_key=False):
k = keystore.Imported_KeyStore({})
storage.put('keystore', k.dump())
wallet = Imported_Wallet(storage)
keys = keystore.get_private_keys(text)
good_inputs, bad_inputs = wallet.import_private_keys(keys, None, write_to_disk=False)
# FIXME tell user about bad_inputs
if not good_inputs:
raise Exception("None of the given privkeys can be imported")
else:
if keystore.is_seed(text):
k = keystore.from_seed(text, passphrase)
elif keystore.is_master_key(text):
k = keystore.from_master_key(text)
else:
raise Exception("Seed or key not recognized")
storage.put('keystore', k.dump())
storage.put('wallet_type', 'standard')
wallet = Wallet(storage)
assert not storage.file_exists(), "file was created too soon! plaintext keys might have been written to disk"
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
wallet.synchronize()
if self.network:
wallet.start_network(self.network)
print_error("Recovering wallet...")
wallet.wait_until_synchronized()
wallet.stop_threads()
# note: we don't wait for SPV
msg = "Recovery successful" if wallet.is_found() else "Found no history for this wallet"
else:
msg = ("This wallet was restored offline. It may contain more addresses than displayed. "
"Start a daemon (not offline) to sync history.")
wallet.storage.write()
return {'path': wallet.storage.path, 'msg': msg}
d = restore_wallet_from_text(text,
path=self.config.get_wallet_path(),
passphrase=passphrase,
password=password,
encrypt_file=encrypt_file,
network=self.network)
return {
'path': d['wallet'].storage.path,
'msg': d['msg'],
}
@command('wp')
def password(self, password=None, new_password=None):

79
electrum/wallet.py

@ -45,10 +45,11 @@ from .util import (NotEnoughFunds, PrintError, UserCancelled, profiler,
format_satoshis, format_fee_satoshis, NoDynamicFeeEstimates,
WalletFileException, BitcoinException,
InvalidPassword, format_time, timestamp_to_datetime, Satoshis,
Fiat, bfh, bh2u, TxMinedInfo)
Fiat, bfh, bh2u, TxMinedInfo, print_error)
from .bitcoin import (COIN, TYPE_ADDRESS, is_address, address_to_script,
is_minikey, relayfee, dust_threshold)
from .crypto import sha256d
from . import keystore
from .keystore import load_keystore, Hardware_KeyStore
from .util import multisig_type
from .storage import STO_EV_PLAINTEXT, STO_EV_USER_PW, STO_EV_XPUB_PW, WalletStorage
@ -62,6 +63,7 @@ from .paymentrequest import (PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED,
from .contacts import Contacts
from .interface import RequestTimedOut
from .ecc_fast import is_using_fast_ecc
from .mnemonic import Mnemonic
if TYPE_CHECKING:
from .network import Network
@ -1848,3 +1850,78 @@ class Wallet(object):
if wallet_type in wallet_constructors:
return wallet_constructors[wallet_type]
raise WalletFileException("Unknown wallet type: " + str(wallet_type))
def create_new_wallet(*, path, passphrase=None, password=None, encrypt_file=True, segwit=True):
"""Create a new wallet"""
storage = WalletStorage(path)
if storage.file_exists():
raise Exception("Remove the existing wallet first!")
seed_type = 'segwit' if segwit else 'standard'
seed = Mnemonic('en').make_seed(seed_type)
k = keystore.from_seed(seed, passphrase)
storage.put('keystore', k.dump())
storage.put('wallet_type', 'standard')
wallet = Wallet(storage)
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
wallet.synchronize()
msg = "Please keep your seed in a safe place; if you lose it, you will not be able to restore your wallet."
wallet.storage.write()
return {'seed': seed, 'wallet': wallet, 'msg': msg}
def restore_wallet_from_text(text, *, path, network, passphrase=None, password=None, encrypt_file=True):
"""Restore a wallet from text. Text can be a seed phrase, a master
public key, a master private key, a list of bitcoin addresses
or bitcoin private keys."""
storage = WalletStorage(path)
if storage.file_exists():
raise Exception("Remove the existing wallet first!")
text = text.strip()
if keystore.is_address_list(text):
wallet = Imported_Wallet(storage)
addresses = text.split()
good_inputs, bad_inputs = wallet.import_addresses(addresses, write_to_disk=False)
# FIXME tell user about bad_inputs
if not good_inputs:
raise Exception("None of the given addresses can be imported")
elif keystore.is_private_key_list(text, allow_spaces_inside_key=False):
k = keystore.Imported_KeyStore({})
storage.put('keystore', k.dump())
wallet = Imported_Wallet(storage)
keys = keystore.get_private_keys(text)
good_inputs, bad_inputs = wallet.import_private_keys(keys, None, write_to_disk=False)
# FIXME tell user about bad_inputs
if not good_inputs:
raise Exception("None of the given privkeys can be imported")
else:
if keystore.is_seed(text):
k = keystore.from_seed(text, passphrase)
elif keystore.is_master_key(text):
k = keystore.from_master_key(text)
else:
raise Exception("Seed or key not recognized")
storage.put('keystore', k.dump())
storage.put('wallet_type', 'standard')
wallet = Wallet(storage)
assert not storage.file_exists(), "file was created too soon! plaintext keys might have been written to disk"
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
wallet.synchronize()
if network:
wallet.start_network(network)
print_error("Recovering wallet...")
wallet.wait_until_synchronized()
wallet.stop_threads()
# note: we don't wait for SPV
msg = "Recovery successful" if wallet.is_found() else "Found no history for this wallet"
else:
msg = ("This wallet was restored offline. It may contain more addresses than displayed. "
"Start a daemon (not offline) to sync history.")
wallet.storage.write()
return {'wallet': wallet, 'msg': msg}

Loading…
Cancel
Save