def handle_process_finish(self, exit_code: int, exit_status: QProcess.ExitStatus): log.debug('process finish', binary=self.binary, exit_code=exit_code, exit_status=exit_status) self.update_status(NodeStatus.STOPPED)
def update_status(self, new_status: NodeStatus): log.debug('update_status', binary=self.binary, new_status=new_status, current_status=self.current_status) self.current_status = new_status self.status.emit(str(new_status))
def open_channel(self, **kwargs): kwargs['node_pubkey'] = codecs.decode(kwargs['node_pubkey_string'], 'hex') request = ln.OpenChannelRequest(**kwargs) log.debug('open_channel', request=MessageToDict(request)) response = self.lnd_client.OpenChannel(request) return response
def deb_install_tor(): dist = platform.dist() dist = list(dist) codename = dist[2] deba = 'deb http://deb.torproject.org/torproject.org ', str( codename), ' main\n' deb_line = '' deb_line = deb_line.join(deba) debb = 'deb-src http://deb.torproject.org/torproject.org ', str( codename), ' main' deb_src = '' deb_src = deb_src.join(debb) f = open('/etc/apt/sources.list', 'a') f.write(deb_line) f.write(str(deb_src)) f.close() log.debug('Installing Tor.....') bash_command_gpg_key = 'gpg --keyserver keys.gnupg.net --recv 886DDD89' bash_command_gpg_export = 'gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add -' bash_command_update = 'sudo apt-get update' bash_command_install_tor = 'sudo apt-get install tor deb.torproject.org-keyring' subprocess.run(['bash', '-c', bash_command_gpg_key]) subprocess.run(['bash', '-c', bash_command_gpg_export]) subprocess.run(['bash', '-c', bash_command_update]) subprocess.run(['bash', '-c', bash_command_install_tor])
def update_status(self, new_status: NodeStatus): log.debug(f'update_status {self.network} node', network=self.network, old_status=self.current_status, new_status=new_status) self.current_status = new_status self.status.emit(str(new_status)) self.start_process()
def check(self): log.debug('datadir', datadir=self['datadir']) if (self['datadir'] is None or not os.path.exists(self['datadir'])): self.autoconfigure_datadir() if os.path.exists(os.path.join(self['datadir'], 'blocks')): if self['prune'] is None: self.set_prune(False) else: if self['prune'] is None: should_prune = self.hard_drives.should_prune(self['datadir']) self.set_prune(should_prune) self.wallet_paths = self.get_wallet_paths() if self['server'] is None: self['server'] = True if self['disablewallet'] is None and not self.wallet_paths: self['disablewallet'] = True elif self['disablewallet'] is None and self.wallet_paths: self['disablewallet'] = False if self['timeout'] is None: self['timeout'] = 6000 if self['rpcuser'] is None: self['rpcuser'] = '******' if self['rpcpassword'] is None: self['rpcpassword'] = get_random_password() self.zmq_block_port = get_zmq_port() self.zmq_tx_port = get_zmq_port() self['zmqpubrawblock'] = f'tcp://127.0.0.1:{self.zmq_block_port}' self['zmqpubrawtx'] = f'tcp://127.0.0.1:{self.zmq_tx_port}' self['proxy'] = '127.0.0.1:9050' self['listen'] = True self['bind'] = '127.0.0.1' self['debug'] = 'tor' self['discover'] = True # noinspection PyBroadException try: memory = psutil.virtual_memory() free_mb = round(memory.available / 1000000) free_mb -= int(free_mb * .3) if 'dbcache' in self: del self['dbcache'] self['dbcache'] = min(free_mb, 10000) self['maxmempool'] = 500 self['mempoolexpiry'] = 2000 except: log.warning('dbcache psutil.virtual_memory', exc_info=True) self['dbcache'] = 1000
def update_status(self, new_status: NodeStatus): log.debug(f'update_status {self.network} node', network=self.network, old_status=self.current_status, new_status=new_status) self.current_status = new_status self.status.emit(str(new_status)) self.start_process() if new_status == NodeStatus.STOPPED and self.restart: self.update_status(NodeStatus.RESTART)
def run_command(self, command: str, **kwargs): log.debug('LndThreadedClient call', command=command, kwargs=kwargs) worker = Worker(fn=self.client_work, command=command, configuration=self.configuration, **kwargs) worker.signals.finished.connect(self.handle_finished) worker.signals.error.connect(self.handle_error) worker.signals.result.connect(self.handle_result) worker.signals.progress.connect(self.handle_progress) self.threadpool.start(worker)
def handle_output(self): while self.canReadLine(): line_bytes: QByteArray = self.readLine() try: line_str = line_bytes.data().decode('utf-8').strip() except UnicodeDecodeError: log.error('handle_output decode error', exc_info=True) continue log.debug(f'Process output', line=line_str, binary=self.binary) self.process_output_line(line_str) self.log_line.emit(line_str)
def parse_litecoin_cli_commands(message: str): log.debug('parse_litecoin_cli_commands') commands = [] for line in message.split(sep='\n'): line = line.strip() if not line or line.startswith('=='): continue command = line.split()[0] command = command.strip() commands.append(command) return commands
def link_static_bin(source_directory, destination_directory): log.debug( 'Linking from downloaded bin directory to static bin directory', source_directory=source_directory, destination_directory=destination_directory) os.makedirs(destination_directory, exist_ok=True) for executable in os.listdir(source_directory): source = os.path.join(source_directory, executable) destination = os.path.join(destination_directory, executable) if os.path.exists(destination): os.remove(destination) os.link(source, destination)
def download(progress_callback, source_url: str, destination_directory: str, destination_file: str): log.debug('Downloading', source_url=source_url, destination_directory=destination_directory, destination_file=destination_file) os.makedirs(destination_directory, exist_ok=True) destination = os.path.join(destination_directory, destination_file) response = requests.get(source_url, stream=True) log.debug('Download response', headers=dict(response.headers)) if response.status_code != 200: log.debug('Download error', status_code=response.status_code, reason=response.reason) response.raise_for_status() with open(destination, 'wb') as f: total_length = float(response.headers['content-length']) downloaded = 0.0 old_progress = 0 for chunk in response.iter_content(chunk_size=4096): downloaded += len(chunk) f.write(chunk) new_progress = int((downloaded / total_length) * 100) if new_progress > old_progress: log.debug('Download progress', progress=new_progress) progress_callback.emit(new_progress) old_progress = new_progress
def install(self): # Todo: move to a thread so it doesn't block the GUI log.debug('Installing software') self.update_status(SoftwareStatus.INSTALLING_SOFTWARE) self.extract( source=self.download_destination_file_path, destination=self.software_directory ) self.link_static_bin( source_directory=self.downloaded_bin_path, destination_directory=self.static_bin_path ) self.update_status(SoftwareStatus.SOFTWARE_INSTALLED) self.update_status(SoftwareStatus.SOFTWARE_READY)
def deb_modify_user(): for line in open('/usr/share/tor/tor-service-defaults-torrc'): if 'User' in line: newline = line.replace('User ', '''''') newline = str(newline.rstrip()) tor_user = str(newline) continue username = str(getpass.getuser()) bash_command_modify = 'sudo usermod -a -G ', str(tor_user), ' ', str( username) bash_command_usermod = '' bash_command_usermod = bash_command_usermod.join(bash_command_modify) subprocess.run(['bash', '-c', bash_command_usermod]) log.debug('Tor setup is complete!') input('Press enter to exit...')
def quit_app(self): log.debug('quit_app') self.system_tray.show_message(title='Stopping LND...') self.node_set.lnd_node.stop() self.node_set.lnd_node.process.waitForFinished(-1) self.node_set.bitcoind_node.stop() self.system_tray.show_message(title='Stopping bitcoind...') self.node_set.bitcoind_node.process.waitForFinished(-1) self.node_set.tor_node.process.kill() self.node_set.tor_node.process.waitForFinished(-1) self.system_tray.show_message(title='Exiting Node Launcher', timeout=1) QCoreApplication.exit(0)
def parse_lncli_commands(self, message: str): log.debug('parse_lncli_commands') at_commands = False commands = [] for line in message.split(sep='\n'): line = line.strip() if not at_commands: if 'COMMANDS:' in line: at_commands = True log.debug('commands line', line=line) continue elif 'GLOBAL OPTIONS' in line: return commands elif line.endswith(':') or not line: continue command = line.split()[0] command = command.strip().replace(',', '') commands.append(command) return commands
def extract(self, source, destination): os.makedirs(destination, exist_ok=True) log.debug('Extracting downloaded software', source=source, destination=destination) if self.compressed_suffix == '.zip': with zipfile.ZipFile(source) as zip_file: zip_file.extractall(path=destination) elif 'tar' in self.compressed_suffix: with tarfile.open(source) as tar: tar.extractall(path=destination) elif self.compressed_suffix == '.dmg': log.debug('Attaching disk image', source=source) escaped_source = source.replace(' ', '\ ') result = subprocess.run( [ f'hdiutil attach {escaped_source}' ], shell=True, capture_output=True) log.debug('hdiutil attach output', stdout=result.stdout, stderr=result.stderr) if result.stderr == b'hdiutil: attach failed - no mountable file systems\n': os.remove(source) self.update() return # app_source_path = '/Volumes/Tor Browser/Tor Browser.app' app_source_path = os.path.join( '/Volumes', 'Tor Browser', 'Tor Browser.app', 'Contents', 'MacOS', 'Tor', 'tor.real' ) log.debug('Copying app from disk image', app_source_path=app_source_path, destination=self.downloaded_bin_path) os.makedirs(self.downloaded_bin_path) shutil.copy(src=app_source_path, dst=self.downloaded_bin_path) disk_image_path = '/Volumes/Tor\ Browser' log.debug('Detaching disk image', disk_image_path=disk_image_path) subprocess.run([ f'hdiutil detach {disk_image_path}' ], shell=True)
def download(progress_callback, source_url: str, destination_directory: str, destination_file: str): log.debug( 'Downloading', source_url=source_url, destination_directory=destination_directory, destination_file=destination_file ) os.makedirs(destination_directory, exist_ok=True) destination = os.path.join(destination_directory, destination_file) with open(destination, 'wb') as f: response = requests.get(source_url, stream=True) log.debug('Download response', headers=dict(response.headers)) total_length = float(response.headers['content-length']) downloaded = 0.0 for chunk in response.iter_content(chunk_size=4096): downloaded += len(chunk) f.write(chunk) progress = int((downloaded / total_length) * 100) log.debug('Download progress', progress=progress) progress_callback.emit(progress)
def handle_progress(self, percentage: int): log.debug('LndThreadedClient call progress', percentage=percentage)
def deb_permissions(): log.debug('Updating user permissions') bash_command_chmod = 'sudo chmod a+rw /etc/apt/sources.list' subprocess.run(['bash', '-c', bash_command_chmod])
def handle_process_error(self, error: QProcess.ProcessError): log.debug('process error', binary=self.binary, error=error)
def update_status(self, new_status: SoftwareStatus): log.debug(f'update_status {self.software_name} software', new_status=new_status) self.current_status = new_status self.status.emit(str(new_status))
def __init__(self, configuration_file_path: str): self.hard_drives = HardDrives() self.software = BitcoinSoftware() self.file = ConfigurationFile(configuration_file_path) self.running = False self.process = None log.debug('datadir', datadir=self.file['datadir']) if (self.file['datadir'] is None or not os.path.exists(self.file['datadir'])): self.autoconfigure_datadir() if 'bitcoin.conf' in os.listdir(self.file['datadir']): actual_conf_file = os.path.join(self.file['datadir'], 'bitcoin.conf') if configuration_file_path != actual_conf_file: log.info( 'datadir_redirect', configuration_file_path=configuration_file_path, actual_conf_file=actual_conf_file ) self.file = ConfigurationFile(actual_conf_file) if (self.file['datadir'] is None or not os.path.exists(self.file['datadir'])): self.autoconfigure_datadir() if os.path.exists(os.path.join(self.file['datadir'], 'blocks')): if self.file['prune'] is None: self.set_prune(False) self.wallet_paths = self.get_wallet_paths() if self.file['server'] is None: self.file['server'] = True if self.file['disablewallet'] is None and not self.wallet_paths: self.file['disablewallet'] = True elif self.file['disablewallet'] is None and self.wallet_paths: self.file['disablewallet'] = False if self.file['timeout'] is None: self.file['timeout'] = 6000 if self.file['rpcuser'] is None: self.file['rpcuser'] = '******' if self.file['rpcpassword'] is None: self.file['rpcpassword'] = get_random_password() if self.file['prune'] is None: should_prune = self.hard_drives.should_prune(self.file['datadir'], has_bitcoin=True) self.set_prune(should_prune) self.zmq_block_port = get_zmq_port() self.zmq_tx_port = get_zmq_port() self.file['zmqpubrawblock'] = f'tcp://127.0.0.1:{self.zmq_block_port}' self.file['zmqpubrawtx'] = f'tcp://127.0.0.1:{self.zmq_tx_port}' # noinspection PyBroadException try: memory = psutil.virtual_memory() free_mb = round(memory.available / 1000000) free_mb -= int(free_mb * .3) self.file['dbcache'] = free_mb except: log.warning( 'dbcache psutil.virtual_memory', exc_info=True ) self.file['dbcache'] = 1000 self.config_snapshot = self.file.snapshot.copy() self.file.file_watcher.fileChanged.connect(self.config_file_changed) self.process = QProcess() self.process.setProgram(self.software.bitcoind) self.process.setProcessChannelMode(QProcess.MergedChannels) self.process.setArguments(self.args)
def extract(self, source: str, destination: str): os.makedirs(destination, exist_ok=True) log.debug('Extracting downloaded software', source=source, destination=destination) if self.compressed_suffix == '.zip': try: with ZipFile(source) as zip_file: if self.software_name != 'tor': zip_file.extractall(path=destination) else: os.makedirs(self.downloaded_bin_path, exist_ok=True) for file in zip_file.filelist: if file.filename.endswith( 'dll') or file.filename.endswith('exe'): destination_exe = os.path.join( self.downloaded_bin_path, file.filename.split('/')[-1]) with zip_file.open(file.filename) as zf, open( destination_exe, 'wb') as f: shutil.copyfileobj(zf, f) except BadZipFile: log.debug('BadZipFile', destination=destination, exc_info=True) os.remove(source) self.update() elif 'tar' in self.compressed_suffix: with tarfile.open(source) as tar: if self.software_name != 'tor': tar.extractall(path=destination) else: os.makedirs(self.downloaded_bin_path, exist_ok=True) tor_files = [ 'libcrypto.so.1.0.0', 'libevent-2.1.so.6', 'libssl.so.1.0.0', 'tor' ] for tor_file in tor_files: file_name = 'tor-browser_en-US/Browser/TorBrowser/Tor/' + tor_file destination_file = os.path.join( self.downloaded_bin_path, tor_file) extracted_file = tar.extractfile(file_name) with open(destination_file, 'wb') as f: shutil.copyfileobj(extracted_file, f) if tor_file == 'tor': st = os.stat(destination_file) os.chmod(destination_file, st.st_mode | stat.S_IEXEC) elif self.compressed_suffix == '.dmg': log.debug('Attaching disk image', source=source) escaped_source = source.replace(' ', '\ ') result = subprocess.run([f'hdiutil attach {escaped_source}'], shell=True, capture_output=True) log.debug('hdiutil attach output', stdout=result.stdout, stderr=result.stderr) if result.stderr == b'hdiutil: attach failed - no mountable file systems\n': os.remove(source) self.update() return # app_source_path = '/Volumes/Tor Browser/Tor Browser.app' app_source_path = os.path.join('/Volumes', 'Tor Browser', 'Tor Browser.app', 'Contents', 'MacOS', 'Tor', 'tor.real') log.debug('Copying app from disk image', app_source_path=app_source_path, destination=self.downloaded_bin_path) os.makedirs(self.downloaded_bin_path, exist_ok=True) shutil.copy(src=app_source_path, dst=self.downloaded_bin_path) disk_image_path = '/Volumes/Tor\ Browser' log.debug('Detaching disk image', disk_image_path=disk_image_path) subprocess.run([f'hdiutil detach {disk_image_path}'], shell=True)
def start(self): log.debug('Starting node set') self.tor_node.software.update()
def check(self): log.debug('datadir', datadir=self.file['datadir']) if (self.file['datadir'] is None or not os.path.exists(self.file['datadir'])): self.autoconfigure_datadir() if 'bitcoin.conf' in os.listdir(self.file['datadir']): actual_conf_file = os.path.join(self.file['datadir'], 'bitcoin.conf') if self.file_path != actual_conf_file: log.info('datadir_redirect', configuration_file_path=self.file_path, actual_conf_file=actual_conf_file) self.file = ConfigurationFile(actual_conf_file) if (self.file['datadir'] is None or not os.path.exists(self.file['datadir'])): self.autoconfigure_datadir() if os.path.exists(os.path.join(self.file['datadir'], 'blocks')): if self.file['prune'] is None: self.set_prune(False) self.wallet_paths = self.get_wallet_paths() if self.file['server'] is None: self.file['server'] = True if self.file['disablewallet'] is None and not self.wallet_paths: self.file['disablewallet'] = True elif self.file['disablewallet'] is None and self.wallet_paths: self.file['disablewallet'] = False if self.file['timeout'] is None: self.file['timeout'] = 6000 if self.file['rpcuser'] is None: self.file['rpcuser'] = '******' if self.file['rpcpassword'] is None: self.file['rpcpassword'] = get_random_password() if self.file['prune'] is None: should_prune = self.hard_drives.should_prune(self.file['datadir'], has_bitcoin=True) self.set_prune(should_prune) self.zmq_block_port = get_zmq_port() self.zmq_tx_port = get_zmq_port() self.file['zmqpubrawblock'] = f'tcp://127.0.0.1:{self.zmq_block_port}' self.file['zmqpubrawtx'] = f'tcp://127.0.0.1:{self.zmq_tx_port}' self.file['proxy'] = '127.0.0.1:9050' self.file['listen'] = True self.file['bind'] = '127.0.0.1' self.file['debug'] = 'tor' self.file['discover'] = True # noinspection PyBroadException try: memory = psutil.virtual_memory() free_mb = round(memory.available / 1000000) free_mb -= int(free_mb * .3) self.file['dbcache'] = free_mb except: log.warning('dbcache psutil.virtual_memory', exc_info=True) self.file['dbcache'] = 1000 self.config_snapshot = self.file.snapshot.copy()
def handle_result(self, result): log.debug('LndThreadedClient call result', result=result)
def handle_error(self, error_tuple): exctype, value, traceback = error_tuple log.debug('LndThreadedClient call error', exctype=exctype, value=value, traceback=traceback)
def get_graph(self) -> ln.ChannelGraph: request = ln.ChannelGraphRequest() request.include_unannounced = True log.debug('get_graph', request=MessageToDict(request)) response = self.lnd_client.DescribeGraph(request) return response
def handle_finished(self): log.debug('LndThreadedClient call finished')