mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
All Daemon creation was preceded by Network creation, based on config, and passing it to Daemon. As config is passed to Daemon, it might as well create its own network and the code is in one place.
181 lines
6.4 KiB
Python
181 lines
6.4 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Electrum - lightweight Bitcoin client
|
|
# Copyright (C) 2015 Thomas Voegtlin
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import ast, os
|
|
|
|
import jsonrpclib
|
|
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
|
|
|
|
from util import json_decode, DaemonThread
|
|
from wallet import WalletStorage, Wallet
|
|
from wizard import WizardBase
|
|
from commands import known_commands, Commands
|
|
from simple_config import SimpleConfig
|
|
from network import Network
|
|
|
|
def lockfile(config):
|
|
return os.path.join(config.path, 'daemon')
|
|
|
|
def get_daemon(config):
|
|
try:
|
|
with open(lockfile(config)) as f:
|
|
host, port = ast.literal_eval(f.read())
|
|
except:
|
|
return
|
|
server = jsonrpclib.Server('http://%s:%d' % (host, port))
|
|
# check if daemon is running
|
|
try:
|
|
server.ping()
|
|
return server
|
|
except:
|
|
pass
|
|
|
|
|
|
class RequestHandler(SimpleJSONRPCRequestHandler):
|
|
|
|
def do_OPTIONS(self):
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
|
|
def end_headers(self):
|
|
self.send_header("Access-Control-Allow-Headers",
|
|
"Origin, X-Requested-With, Content-Type, Accept")
|
|
self.send_header("Access-Control-Allow-Origin", "*")
|
|
SimpleJSONRPCRequestHandler.end_headers(self)
|
|
|
|
|
|
|
|
class Daemon(DaemonThread):
|
|
|
|
def __init__(self, config):
|
|
DaemonThread.__init__(self)
|
|
self.config = config
|
|
if not config.get('offline'):
|
|
self.network = Network(config)
|
|
self.network.start()
|
|
else:
|
|
# FIXME: some of the daemon code assumes self.network is not None
|
|
# This is not something this change has introduced
|
|
self.network = None
|
|
self.gui = None
|
|
self.wallets = {}
|
|
self.wallet = None
|
|
self.cmd_runner = Commands(self.config, self.wallet, self.network)
|
|
host = config.get('rpchost', 'localhost')
|
|
port = config.get('rpcport', 0)
|
|
self.server = SimpleJSONRPCServer((host, port), requestHandler=RequestHandler, logRequests=False)
|
|
with open(lockfile(config), 'w') as f:
|
|
f.write(repr(self.server.socket.getsockname()))
|
|
self.server.timeout = 0.1
|
|
for cmdname in known_commands:
|
|
self.server.register_function(getattr(self.cmd_runner, cmdname), cmdname)
|
|
self.server.register_function(self.run_cmdline, 'run_cmdline')
|
|
self.server.register_function(self.ping, 'ping')
|
|
self.server.register_function(self.run_daemon, 'daemon')
|
|
self.server.register_function(self.run_gui, 'gui')
|
|
self.start()
|
|
|
|
def ping(self):
|
|
return True
|
|
|
|
def run_daemon(self, config):
|
|
sub = config.get('subcommand')
|
|
assert sub in ['start', 'stop', 'status']
|
|
if sub == 'start':
|
|
response = "Daemon already running"
|
|
elif sub == 'status':
|
|
p = self.network.get_parameters()
|
|
response = {
|
|
'path': self.network.config.path,
|
|
'server': p[0],
|
|
'blockchain_height': self.network.get_local_height(),
|
|
'server_height': self.network.get_server_height(),
|
|
'nodes': self.network.get_interfaces(),
|
|
'connected': self.network.is_connected(),
|
|
'auto_connect': p[4],
|
|
'wallets': dict([ (k, w.is_up_to_date()) for k, w in self.wallets.items()]),
|
|
}
|
|
elif sub == 'stop':
|
|
self.stop()
|
|
response = "Daemon stopped"
|
|
return response
|
|
|
|
def run_gui(self, config_options):
|
|
config = SimpleConfig(config_options)
|
|
if self.gui:
|
|
if hasattr(self.gui, 'new_window'):
|
|
path = config.get_wallet_path()
|
|
self.gui.new_window(path, config.get('url'))
|
|
response = "ok"
|
|
else:
|
|
response = "error: current GUI does not support multiple windows"
|
|
else:
|
|
response = "Error: Electrum is running in daemon mode. Please stop the daemon first."
|
|
return response
|
|
|
|
def load_wallet(self, path, get_wizard=None):
|
|
if path in self.wallets:
|
|
wallet = self.wallets[path]
|
|
else:
|
|
storage = WalletStorage(path)
|
|
if get_wizard:
|
|
if storage.file_exists:
|
|
wallet = Wallet(storage)
|
|
action = wallet.get_action()
|
|
else:
|
|
action = 'new'
|
|
if action:
|
|
wizard = get_wizard()
|
|
wallet = wizard.run(self.network, storage)
|
|
else:
|
|
wallet.start_threads(self.network)
|
|
else:
|
|
wallet = Wallet(storage)
|
|
wallet.start_threads(self.network)
|
|
if wallet:
|
|
self.wallets[path] = wallet
|
|
return wallet
|
|
|
|
def run_cmdline(self, config_options):
|
|
config = SimpleConfig(config_options)
|
|
cmdname = config.get('cmd')
|
|
cmd = known_commands[cmdname]
|
|
path = config.get_wallet_path()
|
|
wallet = self.load_wallet(path) if cmd.requires_wallet else None
|
|
# arguments passed to function
|
|
args = map(lambda x: config.get(x), cmd.params)
|
|
# decode json arguments
|
|
args = map(json_decode, args)
|
|
# options
|
|
args += map(lambda x: config.get(x), cmd.options)
|
|
cmd_runner = Commands(config, wallet, self.network,
|
|
password=config_options.get('password'),
|
|
new_password=config_options.get('new_password'))
|
|
func = getattr(cmd_runner, cmd.name)
|
|
result = func(*args)
|
|
return result
|
|
|
|
def run(self):
|
|
while self.is_running():
|
|
self.server.handle_request()
|
|
os.unlink(lockfile(self.config))
|
|
|
|
def stop(self):
|
|
for k, wallet in self.wallets.items():
|
|
wallet.stop_threads()
|
|
DaemonThread.stop(self)
|