From f269881990e6b2c825d3c327a97f545f123d51ae Mon Sep 17 00:00:00 2001 From: tecnovert Date: Mon, 26 May 2025 21:52:49 +0200 Subject: [PATCH] Start Simplex client in run.py --- basicswap/bin/run.py | 32 +++++++++------ basicswap/network/simplex_chat.py | 6 +-- basicswap/util/daemon.py | 13 +++++++ .../basicswap/extended/test_xmr_persistent.py | 39 ++++++++++++++++++- 4 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 basicswap/util/daemon.py diff --git a/basicswap/bin/run.py b/basicswap/bin/run.py index bffb522..3d46798 100755 --- a/basicswap/bin/run.py +++ b/basicswap/bin/run.py @@ -17,12 +17,13 @@ import traceback import basicswap.config as cfg from basicswap import __version__ -from basicswap.ui.util import getCoinName from basicswap.basicswap import BasicSwap from basicswap.chainparams import chainparams, Coins, isKnownCoinName -from basicswap.http_server import HttpThread from basicswap.contrib.websocket_server import WebsocketServer - +from basicswap.http_server import HttpThread +from basicswap.network.simplex_chat import startSimplexClient +from basicswap.ui.util import getCoinName +from basicswap.util.daemon import Daemon initial_logger = logging.getLogger() initial_logger.level = logging.DEBUG @@ -33,14 +34,6 @@ logger = initial_logger swap_client = None -class Daemon: - __slots__ = ("handle", "files") - - def __init__(self, handle, files): - self.handle = handle - self.files = files - - def signal_handler(sig, frame): os.write( sys.stdout.fileno(), f"Signal {sig} detected, ending program.\n".encode("utf-8") @@ -332,6 +325,23 @@ def runClient( try: # Try start daemons + for network in settings.get("networks", []): + network_type = network.get("type", "unknown") + if network_type == "simplex": + simplex_dir = os.path.join(data_dir, "simplex") + daemons.append( + startSimplexClient( + network["client_path"], + simplex_dir, + network["server_address"], + network["ws_port"], + logger, + swap_client.delay_event, + ) + ) + pid = daemons[-1].handle.pid + swap_client.log.info(f"Started Simpelx client {pid}") + for c, v in settings["chainclients"].items(): if len(start_only_coins) > 0 and c not in start_only_coins: continue diff --git a/basicswap/network/simplex_chat.py b/basicswap/network/simplex_chat.py index b924f5d..b43581f 100644 --- a/basicswap/network/simplex_chat.py +++ b/basicswap/network/simplex_chat.py @@ -10,7 +10,7 @@ import select import subprocess import time -from basicswap.bin.run import Daemon +from basicswap.util.daemon import Daemon def initSimplexClient(args, logger, delay_event): @@ -29,7 +29,7 @@ def initSimplexClient(args, logger, delay_event): def readOutput(): buf = os.read(pipe_r, 1024).decode("utf-8") response = None - # logging.debug(f"simplex-chat output: {buf}") + # logger.debug(f"simplex-chat output: {buf}") if "display name:" in buf: logger.debug("Setting display name") response = b"user\n" @@ -45,7 +45,7 @@ def initSimplexClient(args, logger, delay_event): max_wait_seconds: int = 60 while p.poll() is None: if time.time() > start_time + max_wait_seconds: - raise ValueError("Timed out") + raise RuntimeError("Timed out") if os.name == "nt": readOutput() delay_event.wait(0.1) diff --git a/basicswap/util/daemon.py b/basicswap/util/daemon.py new file mode 100644 index 0000000..4a8da8f --- /dev/null +++ b/basicswap/util/daemon.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2025 The Basicswap developers +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + + +class Daemon: + __slots__ = ("handle", "files") + + def __init__(self, handle, files): + self.handle = handle + self.files = files diff --git a/tests/basicswap/extended/test_xmr_persistent.py b/tests/basicswap/extended/test_xmr_persistent.py index 0393b36..aa3efd6 100644 --- a/tests/basicswap/extended/test_xmr_persistent.py +++ b/tests/basicswap/extended/test_xmr_persistent.py @@ -35,6 +35,9 @@ import sys import threading import time import unittest + +import basicswap.config as cfg + from unittest.mock import patch from basicswap.rpc_xmr import ( @@ -87,7 +90,16 @@ TEST_COINS_LIST = os.getenv("TEST_COINS_LIST", "bitcoin,monero") NUM_NODES = int(os.getenv("NUM_NODES", 3)) EXTRA_CONFIG_JSON = json.loads(os.getenv("EXTRA_CONFIG_JSON", "{}")) -SIMPLEX_SERVER_ADDRESS = os.getenv("SIMPLEX_SERVER_ADDRESS", "") +SIMPLEX_SERVER_FINGERPRINT = os.getenv("SIMPLEX_SERVER_FINGERPRINT", "") +SIMPLEX_SERVER_PASSWORD = os.getenv("SIMPLEX_SERVER_PASSWORD", "password") +SIMPLEX_SERVER_HOST = os.getenv("SIMPLEX_SERVER_HOST", "127.0.0.1") +SIMPLEX_SERVER_PORT = os.getenv("SIMPLEX_SERVER_PORT", "5223") +SIMPLEX_SERVER_ADDRESS = os.getenv( + "SIMPLEX_SERVER_ADDRESS", + f"smp://{SIMPLEX_SERVER_FINGERPRINT}:{SIMPLEX_SERVER_PASSWORD}@{SIMPLEX_SERVER_HOST}:{SIMPLEX_SERVER_PORT}", +) +SIMPLEX_WS_PORT = int(os.getenv("SIMPLEX_WS_PORT", "5225")) +SIMPLEX_GROUP_LINK = os.getenv("SIMPLEX_GROUP_LINK", "") SIMPLEX_CLIENT_PATH = os.path.expanduser(os.getenv("SIMPLEX_CLIENT_PATH", "")) logger = logging.getLogger() @@ -321,7 +333,7 @@ def start_processes(self): self.btc_addr = callbtcrpc(0, "getnewaddress", ["mining_addr", "bech32"]) num_blocks: int = 500 # Mine enough to activate segwit if callbtcrpc(0, "getblockcount") < num_blocks: - logging.info("Mining %d Bitcoin blocks to %s", num_blocks, self.btc_addr) + logging.info(f"Mining {num_blocks} Bitcoin blocks to {self.btc_addr}") callbtcrpc(0, "generatetoaddress", [num_blocks, self.btc_addr]) logging.info("BTC blocks: %d", callbtcrpc(0, "getblockcount")) @@ -479,6 +491,26 @@ def start_processes(self): assert particl_blocks >= num_blocks +def modifyConfig(test_path, i): + config_path = os.path.join(test_path, f"client{i}", cfg.CONFIG_FILENAME) + with open(config_path) as fp: + settings = json.load(fp) + + if SIMPLEX_CLIENT_PATH != "": + settings["networks"] = [ + { + "type": "simplex", + "server_address": SIMPLEX_SERVER_ADDRESS, + "client_path": SIMPLEX_CLIENT_PATH, + "ws_port": SIMPLEX_WS_PORT + i, + "group_link": SIMPLEX_GROUP_LINK, + }, + ] + + with open(config_path, "w") as fp: + json.dump(settings, fp, indent=4) + + class BaseTestWithPrepare(unittest.TestCase): __test__ = False @@ -525,6 +557,9 @@ class BaseTestWithPrepare(unittest.TestCase): PORT_OFS, ) + for i in range(NUM_NODES): + modifyConfig(test_path, i) + signal.signal( signal.SIGINT, lambda signal, frame: signal_handler(cls, signal, frame) )