Skip to content

Commit 06055bf

Browse files
committed
Changes
1 parent 1e82417 commit 06055bf

File tree

2 files changed

+389
-1
lines changed

2 files changed

+389
-1
lines changed

contrib/build-wine/deterministic.spec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
home = 'C:\\electrum\\'
44

55
# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports
6-
a = Analysis([home+'electrum-navcoin',
6+
a = Analysis([home+'electrum',
77
home+'gui/qt/main_window.py',
88
home+'gui/text.py',
99
home+'lib/util.py',

electrum

Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
#!/usr/bin/env python2
2+
# -*- mode: python -*-
3+
#
4+
# Electrum - lightweight NavCoin client
5+
# Copyright (C) 2011 thomasv@gitorious
6+
#
7+
# Permission is hereby granted, free of charge, to any person
8+
# obtaining a copy of this software and associated documentation files
9+
# (the "Software"), to deal in the Software without restriction,
10+
# including without limitation the rights to use, copy, modify, merge,
11+
# publish, distribute, sublicense, and/or sell copies of the Software,
12+
# and to permit persons to whom the Software is furnished to do so,
13+
# subject to the following conditions:
14+
#
15+
# The above copyright notice and this permission notice shall be
16+
# included in all copies or substantial portions of the Software.
17+
#
18+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22+
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23+
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
# SOFTWARE.
26+
27+
import os
28+
import sys
29+
30+
31+
script_dir = os.path.dirname(os.path.realpath(__file__))
32+
is_bundle = getattr(sys, 'frozen', False)
33+
is_local = not is_bundle and os.path.exists(os.path.join(script_dir, "setup-release.py"))
34+
is_android = 'ANDROID_DATA' in os.environ
35+
36+
# move this back to gui/kivy/__init.py once plugins are moved
37+
os.environ['KIVY_DATA_DIR'] = os.path.abspath(os.path.dirname(__file__)) + '/gui/kivy/data/'
38+
39+
if is_local or is_android:
40+
sys.path.insert(0, os.path.join(script_dir, 'packages'))
41+
elif is_bundle and sys.platform=='darwin':
42+
sys.path.insert(0, os.getcwd() + "/lib/python2.7/packages")
43+
44+
45+
def check_imports():
46+
# pure-python dependencies need to be imported here for pyinstaller
47+
try:
48+
import dns
49+
import aes
50+
import ecdsa
51+
import requests
52+
import six
53+
import qrcode
54+
import pbkdf2
55+
import google.protobuf
56+
import jsonrpclib
57+
except ImportError as e:
58+
sys.exit("Error: %s. Try 'sudo pip install <module-name>'"%e.message)
59+
# the following imports are for pyinstaller
60+
from google.protobuf import descriptor
61+
from google.protobuf import message
62+
from google.protobuf import reflection
63+
from google.protobuf import descriptor_pb2
64+
from jsonrpclib import SimpleJSONRPCServer
65+
# check that we have the correct version of ecdsa
66+
try:
67+
from ecdsa.ecdsa import curve_secp256k1, generator_secp256k1
68+
except Exception:
69+
sys.exit("cannot import ecdsa.curve_secp256k1. You probably need to upgrade ecdsa.\nTry: sudo pip install --upgrade ecdsa")
70+
# make sure that certificates are here
71+
assert os.path.exists(requests.utils.DEFAULT_CA_BUNDLE_PATH)
72+
73+
74+
if not is_android:
75+
check_imports()
76+
77+
# load local module as electrum
78+
if is_bundle or is_local or is_android:
79+
import imp
80+
imp.load_module('electrum', *imp.find_module('lib'))
81+
imp.load_module('electrum_gui', *imp.find_module('gui'))
82+
83+
84+
from electrum import SimpleConfig, Network, Wallet, WalletStorage
85+
from electrum.util import print_msg, print_stderr, json_encode, json_decode
86+
from electrum.util import set_verbosity, InvalidPassword, check_www_dir
87+
from electrum.commands import get_parser, known_commands, Commands, config_variables
88+
from electrum import daemon
89+
90+
91+
# get password routine
92+
def prompt_password(prompt, confirm=True):
93+
import getpass
94+
password = getpass.getpass(prompt, stream=None)
95+
if password and confirm:
96+
password2 = getpass.getpass("Confirm: ")
97+
if password != password2:
98+
sys.exit("Error: Passwords do not match.")
99+
if not password:
100+
password = None
101+
return password
102+
103+
104+
105+
def run_non_RPC(config):
106+
cmdname = config.get('cmd')
107+
108+
storage = WalletStorage(config.get_wallet_path())
109+
if storage.file_exists:
110+
sys.exit("Error: Remove the existing wallet first!")
111+
112+
def password_dialog():
113+
return prompt_password("Password (hit return if you do not wish to encrypt your wallet):")
114+
115+
if cmdname == 'restore':
116+
text = config.get('text')
117+
password = password_dialog() if Wallet.is_seed(text) or Wallet.is_xprv(text) or Wallet.is_private_key(text) else None
118+
try:
119+
wallet = Wallet.from_text(text, password, storage)
120+
except BaseException as e:
121+
sys.exit(str(e))
122+
wallet.create_main_account()
123+
if not config.get('offline'):
124+
network = Network(config)
125+
network.start()
126+
wallet.start_threads(network)
127+
print_msg("Recovering wallet...")
128+
wallet.synchronize()
129+
wallet.wait_until_synchronized()
130+
msg = "Recovery successful" if wallet.is_found() else "Found no history for this wallet"
131+
else:
132+
msg = "This wallet was restored offline. It may contain more addresses than displayed."
133+
print_msg(msg)
134+
135+
elif cmdname == 'create':
136+
password = password_dialog()
137+
wallet = Wallet(storage)
138+
seed = wallet.make_seed()
139+
wallet.add_seed(seed, password)
140+
wallet.create_master_keys(password)
141+
wallet.create_main_account()
142+
wallet.synchronize()
143+
print_msg("Your wallet generation seed is:\n\"%s\"" % seed)
144+
print_msg("Please keep it in a safe place; if you lose it, you will not be able to restore your wallet.")
145+
146+
elif cmdname == 'deseed':
147+
if not wallet.seed:
148+
print_msg("Error: This wallet has no seed")
149+
else:
150+
ns = wallet.storage.path + '.seedless'
151+
print_msg("Warning: you are going to create a seedless wallet'\nIt will be saved in '%s'" % ns)
152+
if raw_input("Are you sure you want to continue? (y/n) ") in ['y', 'Y', 'yes']:
153+
wallet.storage.path = ns
154+
wallet.seed = ''
155+
wallet.storage.put('seed', '')
156+
wallet.use_encryption = False
157+
wallet.storage.put('use_encryption', wallet.use_encryption)
158+
for k in wallet.imported_keys.keys():
159+
wallet.imported_keys[k] = ''
160+
wallet.storage.put('imported_keys', wallet.imported_keys)
161+
print_msg("Done.")
162+
else:
163+
print_msg("Action canceled.")
164+
wallet.storage.write()
165+
sys.exit(0)
166+
167+
wallet.storage.write()
168+
print_msg("Wallet saved in '%s'" % wallet.storage.path)
169+
sys.exit(0)
170+
171+
172+
def init_cmdline(config_options):
173+
config = SimpleConfig(config_options)
174+
cmdname = config.get('cmd')
175+
cmd = known_commands[cmdname]
176+
177+
if cmdname == 'signtransaction' and config.get('privkey'):
178+
cmd.requires_wallet = False
179+
cmd.requires_password = False
180+
181+
if cmdname in ['payto', 'paytomany'] and config.get('unsigned'):
182+
cmd.requires_password = False
183+
184+
if cmdname in ['payto', 'paytomany'] and config.get('broadcast'):
185+
cmd.requires_network = True
186+
187+
if cmdname in ['createrawtx'] and config.get('unsigned'):
188+
cmd.requires_password = False
189+
cmd.requires_wallet = False
190+
191+
# instanciate wallet for command-line
192+
storage = WalletStorage(config.get_wallet_path())
193+
194+
if cmd.requires_wallet and not storage.file_exists:
195+
print_msg("Error: Wallet file not found.")
196+
print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option")
197+
sys.exit(0)
198+
199+
# important warning
200+
if cmd.name in ['getprivatekeys']:
201+
print_stderr("WARNING: ALL your private keys are secret.")
202+
print_stderr("Exposing a single private key can compromise your entire wallet!")
203+
print_stderr("In particular, DO NOT use 'redeem private key' services proposed by third parties.")
204+
205+
# commands needing password
206+
if cmd.requires_password and storage.get('use_encryption'):
207+
if config.get('password'):
208+
password = config.get('password')
209+
else:
210+
password = prompt_password('Password:', False)
211+
if not password:
212+
print_msg("Error: Password required")
213+
sys.exit(1)
214+
else:
215+
password = None
216+
217+
config_options['password'] = password
218+
219+
if cmd.name == 'password':
220+
new_password = prompt_password('New password:')
221+
config_options['new_password'] = new_password
222+
223+
return cmd, password
224+
225+
226+
def run_offline_command(config, config_options):
227+
cmdname = config.get('cmd')
228+
cmd = known_commands[cmdname]
229+
storage = WalletStorage(config.get_wallet_path())
230+
wallet = Wallet(storage) if cmd.requires_wallet else None
231+
# check password
232+
if cmd.requires_password and storage.get('use_encryption'):
233+
password = config_options.get('password')
234+
try:
235+
seed = wallet.check_password(password)
236+
except InvalidPassword:
237+
print_msg("Error: This password does not decode this wallet.")
238+
sys.exit(1)
239+
if cmd.requires_network:
240+
print_stderr("Warning: running command offline")
241+
# arguments passed to function
242+
args = map(lambda x: config.get(x), cmd.params)
243+
# decode json arguments
244+
args = map(json_decode, args)
245+
# options
246+
args += map(lambda x: config.get(x), cmd.options)
247+
cmd_runner = Commands(config, wallet, None,
248+
password=config_options.get('password'),
249+
new_password=config_options.get('new_password'))
250+
func = getattr(cmd_runner, cmd.name)
251+
result = func(*args)
252+
# save wallet
253+
if wallet:
254+
wallet.storage.write()
255+
return result
256+
257+
def init_plugins(config, gui_name):
258+
from electrum.plugins import Plugins
259+
return Plugins(config, is_bundle or is_local or is_android, gui_name)
260+
261+
if __name__ == '__main__':
262+
263+
# on osx, delete Process Serial Number arg generated for apps launched in Finder
264+
sys.argv = filter(lambda x: not x.startswith('-psn'), sys.argv)
265+
266+
# old 'help' syntax
267+
if len(sys.argv)>1 and sys.argv[1] == 'help':
268+
sys.argv.remove('help')
269+
sys.argv.append('-h')
270+
271+
# read arguments from stdin pipe and prompt
272+
for i, arg in enumerate(sys.argv):
273+
if arg == '-':
274+
if not sys.stdin.isatty():
275+
sys.argv[i] = sys.stdin.read()
276+
break
277+
else:
278+
raise BaseException('Cannot get argument from stdin')
279+
elif arg == '?':
280+
sys.argv[i] = raw_input("Enter argument:")
281+
elif arg == ':':
282+
sys.argv[i] = prompt_password('Enter argument (will not echo):', False)
283+
284+
# parse command line
285+
parser = get_parser()
286+
args = parser.parse_args()
287+
288+
# config is an object passed to the various constructors (wallet, interface, gui)
289+
if is_android:
290+
config_options = {
291+
'verbose': True,
292+
'cmd': 'gui',
293+
'gui': 'kivy',
294+
}
295+
else:
296+
config_options = args.__dict__
297+
for k, v in config_options.items():
298+
if v is None or (k in config_variables.get(args.cmd, {}).keys()):
299+
config_options.pop(k)
300+
if config_options.get('server'):
301+
config_options['auto_connect'] = False
302+
303+
config_options['cwd'] = os.getcwd()
304+
305+
if config_options.get('portable'):
306+
config_options['electrum_path'] = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'electrum_navcoin_data')
307+
308+
set_verbosity(config_options.get('verbose'))
309+
310+
# check uri
311+
uri = config_options.get('url')
312+
if uri:
313+
if not uri.startswith('navcoin:'):
314+
print_stderr('unknown command:', uri)
315+
sys.exit(1)
316+
config_options['url'] = uri
317+
318+
config = SimpleConfig(config_options)
319+
cmdname = config.get('cmd')
320+
321+
# run non-RPC commands separately
322+
if cmdname in ['create', 'restore', 'deseed']:
323+
run_non_RPC(config)
324+
sys.exit(0)
325+
326+
if cmdname == 'gui':
327+
fd, server = daemon.get_fd_or_server(config)
328+
if fd is not None:
329+
plugins = init_plugins(config, config.get('gui', 'qt'))
330+
d = daemon.Daemon(config, fd)
331+
d.start()
332+
d.init_gui(config, plugins)
333+
sys.exit(0)
334+
else:
335+
result = server.gui(config_options)
336+
337+
elif cmdname == 'daemon':
338+
subcommand = config.get('subcommand')
339+
assert subcommand in ['start', 'stop', 'status']
340+
if subcommand == 'start':
341+
fd, server = daemon.get_fd_or_server(config)
342+
if fd is not None:
343+
pid = os.fork()
344+
if pid:
345+
print_stderr("starting daemon (PID %d)" % pid)
346+
sys.exit(0)
347+
init_plugins(config, 'cmdline')
348+
d = daemon.Daemon(config, fd)
349+
d.start()
350+
if config.get('websocket_server'):
351+
from electrum import websockets
352+
websockets.WebSocketServer(config, d.network).start()
353+
if config.get('requests_dir'):
354+
check_www_dir(config.get('requests_dir'))
355+
d.join()
356+
sys.exit(0)
357+
else:
358+
result = server.daemon(config_options)
359+
else:
360+
server = daemon.get_server(config)
361+
if server is not None:
362+
result = server.daemon(config_options)
363+
else:
364+
print_msg("Daemon not running")
365+
sys.exit(1)
366+
else:
367+
# command line
368+
init_cmdline(config_options)
369+
server = daemon.get_server(config)
370+
if server is not None:
371+
result = server.run_cmdline(config_options)
372+
else:
373+
cmd = known_commands[cmdname]
374+
if cmd.requires_network:
375+
print_msg("Daemon not running; try 'electrum daemon start'")
376+
sys.exit(1)
377+
else:
378+
init_plugins(config, 'cmdline')
379+
result = run_offline_command(config, config_options)
380+
381+
# print result
382+
if type(result) in [str, unicode]:
383+
print_msg(result)
384+
elif type(result) is dict and result.get('error'):
385+
print_stderr(result.get('error'))
386+
elif result is not None:
387+
print_msg(json_encode(result))
388+
sys.exit(0)

0 commit comments

Comments
 (0)