From 934aab9d8a074f8b22385005617c9f5dcb424dc1 Mon Sep 17 00:00:00 2001 From: tecnovert Date: Wed, 16 Apr 2025 15:08:13 +0200 Subject: [PATCH] Allow starting with a subset of configured coins. --- basicswap/basicswap.py | 18 +++++++++++--- basicswap/bin/prepare.py | 10 ++++---- basicswap/bin/run.py | 53 +++++++++++++++++++++++++++++++--------- basicswap/chainparams.py | 4 +++ doc/notes.md | 5 ++++ 5 files changed, 69 insertions(+), 21 deletions(-) diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 9c42a0f..2b30e6c 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -295,6 +295,7 @@ class BasicSwap(BaseApp): chain, log_name="BasicSwap", transient_instance=False, + extra_opts={}, ): super().__init__(data_dir, settings, chain, log_name) @@ -486,6 +487,9 @@ class BasicSwap(BaseApp): ) self.zmqSubscriber.setsockopt_string(zmq.SUBSCRIBE, "smsg") + self.with_coins_override = extra_opts.get("with_coins", set()) + self.without_coins_override = extra_opts.get("without_coins", set()) + for c in Coins: if c in chainparams: self.setCoinConnectParams(c) @@ -573,14 +577,22 @@ class BasicSwap(BaseApp): # Set anything that does not require the daemon to be running chain_client_settings = self.getChainClientSettings(coin) + coin_chainparams = chainparams[coin] + coin_name: str = coin_chainparams["name"] + bindir = os.path.expanduser(chain_client_settings.get("bindir", "")) datadir = os.path.expanduser( chain_client_settings.get( - "datadir", os.path.join(cfg.TEST_DATADIRS, chainparams[coin]["name"]) + "datadir", os.path.join(cfg.TEST_DATADIRS, coin_name) ) ) connection_type = chain_client_settings.get("connection_type", "none") + if ( + len(self.with_coins_override) > 0 + and coin_name not in self.with_coins_override + ) or coin_name in self.without_coins_override: + connection_type = "none" rpcauth = None if connection_type == "rpc": if "rpcauth" in chain_client_settings: @@ -600,7 +612,6 @@ class BasicSwap(BaseApp): try: cursor = self.openDB() - coin_name: str = chainparams[coin]["name"] last_height_checked = self.getIntKV( "last_height_checked_" + coin_name, cursor, 0 ) @@ -613,12 +624,11 @@ class BasicSwap(BaseApp): finally: self.closeDB(cursor) - coin_chainparams = chainparams[coin] default_segwit = coin_chainparams.get("has_segwit", False) default_csv = coin_chainparams.get("has_csv", True) self.coin_clients[coin] = { "coin": coin, - "name": coin_chainparams["name"], + "name": coin_name, "connection_type": connection_type, "bindir": bindir, "datadir": datadir, diff --git a/basicswap/bin/prepare.py b/basicswap/bin/prepare.py index 0efd9cd..d80fad5 100755 --- a/basicswap/bin/prepare.py +++ b/basicswap/bin/prepare.py @@ -2232,11 +2232,11 @@ def check_btc_fastsync_data(base_dir, sync_filename): ensureValidSignatureBy(verified, "nicolasdorier") -def ensure_coin_valid(coin: str, test_disabled: bool = True) -> None: - if coin not in known_coins: - exitWithError(f"Unknown coin {coin.capitalize()}") - if test_disabled and not OVERRIDE_DISABLED_COINS and coin in disabled_coins: - exitWithError(f"{coin.capitalize()} is disabled") +def ensure_coin_valid(coin_name: str, test_disabled: bool = True) -> None: + if coin_name not in known_coins: + exitWithError(f"Unknown coin {coin_name.capitalize()}") + if test_disabled and not OVERRIDE_DISABLED_COINS and coin_name in disabled_coins: + exitWithError(f"{coin_name.capitalize()} is disabled") def main(): diff --git a/basicswap/bin/run.py b/basicswap/bin/run.py index 55b5c44..2587601 100755 --- a/basicswap/bin/run.py +++ b/basicswap/bin/run.py @@ -19,7 +19,7 @@ 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 +from basicswap.chainparams import chainparams, Coins, isKnownCoinName from basicswap.http_server import HttpThread from basicswap.contrib.websocket_server import WebsocketServer @@ -31,6 +31,8 @@ if not len(initial_logger.handlers): logger = initial_logger swap_client = None +with_coins = set() +without_coins = set() class Daemon: @@ -41,13 +43,6 @@ class Daemon: self.files = files -def is_known_coin(coin_name: str) -> bool: - for k, v in chainparams.items(): - if coin_name == v["name"]: - return True - return False - - def signal_handler(sig, frame): os.write( sys.stdout.fileno(), f"Signal {sig} detected, ending program.\n".encode("utf-8") @@ -302,7 +297,16 @@ def runClient( with open(settings_path) as fs: settings = json.load(fs) - swap_client = BasicSwap(data_dir, settings, chain, log_name=log_prefix) + extra_opts = dict() + if len(with_coins) > 0: + with_coins.add("particl") + extra_opts["with_coins"] = with_coins + if len(without_coins) > 0: + extra_opts["without_coins"] = without_coins + + swap_client = BasicSwap( + data_dir, settings, chain, log_name=log_prefix, extra_opts=extra_opts + ) logger = swap_client.log if os.path.exists(pids_path): @@ -321,6 +325,14 @@ def runClient( for c, v in settings["chainclients"].items(): if len(start_only_coins) > 0 and c not in start_only_coins: continue + if (len(with_coins) > 0 and c not in with_coins) or c in without_coins: + if v.get("manage_daemon", False) or v.get( + "manage_wallet_daemon", False + ): + logger.warning( + f"Not starting coin {c.capitalize()}, disabled by arguments." + ) + continue try: coin_id = swap_client.getCoinIdFromName(c) display_name = getCoinName(coin_id) @@ -576,6 +588,11 @@ def printVersion(): ) +def ensure_coin_valid(coin: str) -> bool: + if isKnownCoinName(coin) is False: + raise ValueError(f"Unknown coin: {coin}") + + def printHelp(): print("Usage: basicswap-run ") print("\n--help, -h Print help.") @@ -586,6 +603,8 @@ def printHelp(): print("--mainnet Run in mainnet mode.") print("--testnet Run in testnet mode.") print("--regtest Run in regtest mode.") + print("--withcoin= Run only with coin/s.") + print("--withoutcoin= Run without coin/s.") print( "--startonlycoin Only start the provides coin daemon/s, use this if a chain requires extra processing." ) @@ -620,7 +639,18 @@ def main(): if name in ("mainnet", "testnet", "regtest"): chain = name continue - + if name in ("withcoin", "withcoins"): + for coin in [s.strip().lower() for s in s[1].split(",")]: + ensure_coin_valid(coin) + with_coins.add(coin) + continue + if name in ("withoutcoin", "withoutcoins"): + for coin in [s.strip().lower() for s in s[1].split(",")]: + if coin == "particl": + raise ValueError("Particl is required.") + ensure_coin_valid(coin) + without_coins.add(coin) + continue if len(s) == 2: if name == "datadir": data_dir = os.path.expanduser(s[1]) @@ -630,8 +660,7 @@ def main(): continue if name == "startonlycoin": for coin in [s.lower() for s in s[1].split(",")]: - if is_known_coin(coin) is False: - raise ValueError(f"Unknown coin: {coin}") + ensure_coin_valid(coin) start_only_coins.add(coin) continue diff --git a/basicswap/chainparams.py b/basicswap/chainparams.py index efbb58b..bb79cb5 100644 --- a/basicswap/chainparams.py +++ b/basicswap/chainparams.py @@ -571,3 +571,7 @@ def getCoinIdFromName(name: str) -> str: return name_map[name.lower()] except Exception: raise ValueError(f"Unknown coin {name}") + + +def isKnownCoinName(name: str) -> bool: + return params["name"].lower() in name_map diff --git a/doc/notes.md b/doc/notes.md index 20acd7e..d0558b6 100644 --- a/doc/notes.md +++ b/doc/notes.md @@ -125,6 +125,11 @@ Observe progress with tail -f /tmp/firo.log +## Start a subset of the configured coins using docker + + docker compose run --service-ports swapclient basicswap-run -datadir=/coindata -withcoins=monero + + ## FAQ