|
@ -107,37 +107,17 @@ def init_gui(config, network, plugins): |
|
|
return gui |
|
|
return gui |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_non_RPC(config): |
|
|
def init_cmdline(config): |
|
|
|
|
|
|
|
|
|
|
|
cmdname = config.get('cmd') |
|
|
cmdname = config.get('cmd') |
|
|
cmd = known_commands[cmdname] |
|
|
|
|
|
|
|
|
|
|
|
if cmdname == 'signtransaction' and config.get('privkey'): |
|
|
|
|
|
cmd.requires_wallet = False |
|
|
|
|
|
cmd.requires_password = False |
|
|
|
|
|
|
|
|
|
|
|
if cmdname in ['payto', 'paytomany'] and config.get('unsigned'): |
|
|
|
|
|
cmd.requires_password = False |
|
|
|
|
|
|
|
|
|
|
|
if cmdname in ['payto', 'paytomany'] and config.get('broadcast'): |
|
|
|
|
|
cmd.requires_network = True |
|
|
|
|
|
|
|
|
|
|
|
if cmdname in ['createrawtx'] and config.get('unsigned'): |
|
|
|
|
|
cmd.requires_password = False |
|
|
|
|
|
cmd.requires_wallet = False |
|
|
|
|
|
|
|
|
|
|
|
# instanciate wallet for command-line |
|
|
|
|
|
storage = WalletStorage(config.get_wallet_path()) |
|
|
storage = WalletStorage(config.get_wallet_path()) |
|
|
|
|
|
|
|
|
if cmd.name in ['create', 'restore']: |
|
|
|
|
|
if storage.file_exists: |
|
|
if storage.file_exists: |
|
|
sys.exit("Error: Remove the existing wallet first!") |
|
|
sys.exit("Error: Remove the existing wallet first!") |
|
|
|
|
|
|
|
|
def password_dialog(): |
|
|
def password_dialog(): |
|
|
return prompt_password("Password (hit return if you do not wish to encrypt your wallet):") |
|
|
return prompt_password("Password (hit return if you do not wish to encrypt your wallet):") |
|
|
|
|
|
|
|
|
if cmd.name == 'restore': |
|
|
if cmdname == 'restore': |
|
|
text = config.get('text') |
|
|
text = config.get('text') |
|
|
password = password_dialog() if Wallet.is_seed(text) or Wallet.is_xprv(text) or Wallet.is_private_key(text) else None |
|
|
password = password_dialog() if Wallet.is_seed(text) or Wallet.is_xprv(text) or Wallet.is_private_key(text) else None |
|
|
try: |
|
|
try: |
|
@ -156,7 +136,7 @@ def init_cmdline(config): |
|
|
msg = "This wallet was restored offline. It may contain more addresses than displayed." |
|
|
msg = "This wallet was restored offline. It may contain more addresses than displayed." |
|
|
print_msg(msg) |
|
|
print_msg(msg) |
|
|
|
|
|
|
|
|
else: |
|
|
elif cmdname == 'create': |
|
|
password = password_dialog() |
|
|
password = password_dialog() |
|
|
wallet = Wallet(storage) |
|
|
wallet = Wallet(storage) |
|
|
seed = wallet.make_seed() |
|
|
seed = wallet.make_seed() |
|
@ -167,21 +147,59 @@ def init_cmdline(config): |
|
|
print_msg("Your wallet generation seed is:\n\"%s\"" % seed) |
|
|
print_msg("Your wallet generation seed is:\n\"%s\"" % seed) |
|
|
print_msg("Please keep it in a safe place; if you lose it, you will not be able to restore your wallet.") |
|
|
print_msg("Please keep it in a safe place; if you lose it, you will not be able to restore your wallet.") |
|
|
|
|
|
|
|
|
|
|
|
elif cmdname == 'deseed': |
|
|
|
|
|
if not wallet.seed: |
|
|
|
|
|
print_msg("Error: This wallet has no seed") |
|
|
|
|
|
else: |
|
|
|
|
|
ns = wallet.storage.path + '.seedless' |
|
|
|
|
|
print_msg("Warning: you are going to create a seedless wallet'\nIt will be saved in '%s'" % ns) |
|
|
|
|
|
if raw_input("Are you sure you want to continue? (y/n) ") in ['y', 'Y', 'yes']: |
|
|
|
|
|
wallet.storage.path = ns |
|
|
|
|
|
wallet.seed = '' |
|
|
|
|
|
wallet.storage.put('seed', '') |
|
|
|
|
|
wallet.use_encryption = False |
|
|
|
|
|
wallet.storage.put('use_encryption', wallet.use_encryption) |
|
|
|
|
|
for k in wallet.imported_keys.keys(): |
|
|
|
|
|
wallet.imported_keys[k] = '' |
|
|
|
|
|
wallet.storage.put('imported_keys', wallet.imported_keys) |
|
|
|
|
|
print_msg("Done.") |
|
|
|
|
|
else: |
|
|
|
|
|
print_msg("Action canceled.") |
|
|
|
|
|
wallet.storage.write() |
|
|
|
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
wallet.storage.write() |
|
|
wallet.storage.write() |
|
|
print_msg("Wallet saved in '%s'" % wallet.storage.path) |
|
|
print_msg("Wallet saved in '%s'" % wallet.storage.path) |
|
|
sys.exit(0) |
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def init_cmdline(config_options): |
|
|
|
|
|
config = SimpleConfig(config_options) |
|
|
|
|
|
cmdname = config.get('cmd') |
|
|
|
|
|
cmd = known_commands[cmdname] |
|
|
|
|
|
|
|
|
|
|
|
if cmdname == 'signtransaction' and config.get('privkey'): |
|
|
|
|
|
cmd.requires_wallet = False |
|
|
|
|
|
cmd.requires_password = False |
|
|
|
|
|
|
|
|
|
|
|
if cmdname in ['payto', 'paytomany'] and config.get('unsigned'): |
|
|
|
|
|
cmd.requires_password = False |
|
|
|
|
|
|
|
|
|
|
|
if cmdname in ['payto', 'paytomany'] and config.get('broadcast'): |
|
|
|
|
|
cmd.requires_network = True |
|
|
|
|
|
|
|
|
|
|
|
if cmdname in ['createrawtx'] and config.get('unsigned'): |
|
|
|
|
|
cmd.requires_password = False |
|
|
|
|
|
cmd.requires_wallet = False |
|
|
|
|
|
|
|
|
|
|
|
# instanciate wallet for command-line |
|
|
|
|
|
storage = WalletStorage(config.get_wallet_path()) |
|
|
|
|
|
|
|
|
if cmd.requires_wallet and not storage.file_exists: |
|
|
if cmd.requires_wallet and not storage.file_exists: |
|
|
print_msg("Error: Wallet file not found.") |
|
|
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") |
|
|
print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option") |
|
|
sys.exit(0) |
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
# create wallet instance |
|
|
|
|
|
wallet = Wallet(storage) if cmd.requires_wallet else None |
|
|
|
|
|
|
|
|
|
|
|
# notify plugins |
|
|
|
|
|
always_hook('cmdline_load_wallet', wallet) |
|
|
|
|
|
|
|
|
|
|
|
# important warning |
|
|
# important warning |
|
|
if cmd.name in ['getprivatekeys']: |
|
|
if cmd.name in ['getprivatekeys']: |
|
|
print_stderr("WARNING: ALL your private keys are secret.") |
|
|
print_stderr("WARNING: ALL your private keys are secret.") |
|
@ -189,7 +207,7 @@ def init_cmdline(config): |
|
|
print_stderr("In particular, DO NOT use 'redeem private key' services proposed by third parties.") |
|
|
print_stderr("In particular, DO NOT use 'redeem private key' services proposed by third parties.") |
|
|
|
|
|
|
|
|
# commands needing password |
|
|
# commands needing password |
|
|
if cmd.requires_password and wallet.use_encryption: |
|
|
if cmd.requires_password and storage.get('use_encryption'): |
|
|
if config.get('password'): |
|
|
if config.get('password'): |
|
|
password = config.get('password') |
|
|
password = config.get('password') |
|
|
else: |
|
|
else: |
|
@ -197,57 +215,48 @@ def init_cmdline(config): |
|
|
if not password: |
|
|
if not password: |
|
|
print_msg("Error: Password required") |
|
|
print_msg("Error: Password required") |
|
|
sys.exit(1) |
|
|
sys.exit(1) |
|
|
# check password |
|
|
|
|
|
try: |
|
|
|
|
|
seed = wallet.check_password(password) |
|
|
|
|
|
except InvalidPassword: |
|
|
|
|
|
print_msg("Error: This password does not decode this wallet.") |
|
|
|
|
|
sys.exit(1) |
|
|
|
|
|
else: |
|
|
else: |
|
|
password = None |
|
|
password = None |
|
|
|
|
|
|
|
|
# run the command |
|
|
config_options['password'] = password |
|
|
if cmd.name == 'deseed': |
|
|
|
|
|
if not wallet.seed: |
|
|
|
|
|
print_msg("Error: This wallet has no seed") |
|
|
|
|
|
else: |
|
|
|
|
|
ns = wallet.storage.path + '.seedless' |
|
|
|
|
|
print_msg("Warning: you are going to create a seedless wallet'\nIt will be saved in '%s'" % ns) |
|
|
|
|
|
if raw_input("Are you sure you want to continue? (y/n) ") in ['y', 'Y', 'yes']: |
|
|
|
|
|
wallet.storage.path = ns |
|
|
|
|
|
wallet.seed = '' |
|
|
|
|
|
wallet.storage.put('seed', '') |
|
|
|
|
|
wallet.use_encryption = False |
|
|
|
|
|
wallet.storage.put('use_encryption', wallet.use_encryption) |
|
|
|
|
|
for k in wallet.imported_keys.keys(): |
|
|
|
|
|
wallet.imported_keys[k] = '' |
|
|
|
|
|
wallet.storage.put('imported_keys', wallet.imported_keys) |
|
|
|
|
|
print_msg("Done.") |
|
|
|
|
|
else: |
|
|
|
|
|
print_msg("Action canceled.") |
|
|
|
|
|
wallet.storage.write() |
|
|
|
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
|
|
|
elif cmd.name == 'password': |
|
|
if cmd.name == 'password': |
|
|
new_password = prompt_password('New password:') |
|
|
new_password = prompt_password('New password:') |
|
|
wallet.update_password(password, new_password) |
|
|
config_options['new_password'] = new_password |
|
|
wallet.storage.write() |
|
|
|
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
|
|
|
return cmd, password, wallet |
|
|
return cmd, password |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_offline_command(config, cmd, wallet, password): |
|
|
def run_offline_command(config, config_options): |
|
|
|
|
|
cmdname = config.get('cmd') |
|
|
|
|
|
cmd = known_commands[cmdname] |
|
|
|
|
|
storage = WalletStorage(config.get_wallet_path()) |
|
|
|
|
|
wallet = Wallet(storage) if cmd.requires_wallet else None |
|
|
|
|
|
# check password |
|
|
|
|
|
if cmd.requires_password and storage.get('use_encryption'): |
|
|
|
|
|
password = config_options.get('password') |
|
|
|
|
|
try: |
|
|
|
|
|
seed = wallet.check_password(password) |
|
|
|
|
|
except InvalidPassword: |
|
|
|
|
|
print_msg("Error: This password does not decode this wallet.") |
|
|
|
|
|
sys.exit(1) |
|
|
|
|
|
if cmd.requires_network: |
|
|
|
|
|
print_stderr("Warning: running command offline") |
|
|
|
|
|
# notify plugins |
|
|
|
|
|
always_hook('cmdline_load_wallet', wallet) |
|
|
# arguments passed to function |
|
|
# arguments passed to function |
|
|
args = map(lambda x: config.get(x), cmd.params) |
|
|
args = map(lambda x: config.get(x), cmd.params) |
|
|
# decode json arguments |
|
|
# decode json arguments |
|
|
args = map(json_decode, args) |
|
|
args = map(json_decode, args) |
|
|
# options |
|
|
# options |
|
|
args += map(lambda x: config.get(x), cmd.options) |
|
|
args += map(lambda x: config.get(x), cmd.options) |
|
|
cmd_runner = Commands(config, wallet, None) |
|
|
cmd_runner = Commands(config, wallet, None, |
|
|
cmd_runner.password = password |
|
|
password=config_options.get('password'), |
|
|
|
|
|
new_password=config_options.get('new_password')) |
|
|
func = getattr(cmd_runner, cmd.name) |
|
|
func = getattr(cmd_runner, cmd.name) |
|
|
result = func(*args) |
|
|
result = func(*args) |
|
|
|
|
|
# save wallet |
|
|
|
|
|
wallet.storage.write() |
|
|
return result |
|
|
return result |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -317,19 +326,22 @@ if __name__ == '__main__': |
|
|
gui_name = config.get('gui', 'qt') if cmd_name == 'gui' else 'cmdline' |
|
|
gui_name = config.get('gui', 'qt') if cmd_name == 'gui' else 'cmdline' |
|
|
plugins = Plugins(config, is_bundle or is_local or is_android, gui_name) |
|
|
plugins = Plugins(config, is_bundle or is_local or is_android, gui_name) |
|
|
|
|
|
|
|
|
# run command offline |
|
|
# run non-RPC commands separately |
|
|
if cmd_name not in ['gui', 'daemon']: |
|
|
if cmd_name in ['create', 'restore', 'deseed']: |
|
|
cmd, password, wallet = init_cmdline(config) |
|
|
run_non_RPC(config) |
|
|
if not (cmd.requires_network or cmd.requires_wallet) or config.get('offline'): |
|
|
|
|
|
result = run_offline_command(config, cmd, wallet, password) |
|
|
|
|
|
print_msg(json_encode(result)) |
|
|
|
|
|
wallet.storage.write() |
|
|
|
|
|
sys.exit(0) |
|
|
sys.exit(0) |
|
|
else: |
|
|
|
|
|
config_options['password'] = password |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# check if a daemon is running |
|
|
server = get_daemon(config) |
|
|
server = get_daemon(config) |
|
|
|
|
|
|
|
|
|
|
|
# if no daemon is running, run the command offline |
|
|
|
|
|
if cmd_name not in ['gui', 'daemon']: |
|
|
|
|
|
init_cmdline(config_options) |
|
|
|
|
|
if server is None: #not (cmd.requires_network or cmd.requires_wallet) or config.get('offline'): |
|
|
|
|
|
result = run_offline_command(config, config_options) |
|
|
|
|
|
print_msg(json_encode(result)) |
|
|
|
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
# daemon is running |
|
|
# daemon is running |
|
|
if server is not None: |
|
|
if server is not None: |
|
|
cmdname = config_options.get('cmd') |
|
|
cmdname = config_options.get('cmd') |
|
|