From 5e41407b3cc392b3ce6c08619b542dd234be790c Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Mon, 21 Sep 2026 10:30:51 +0000 Subject: [PATCH] daemon, protocol, xmrwallet: improve handling of datadirs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default Monero wallet directory for both compat and non-compat modes is now `altcoins/xmr/tracking-wallets` under the user’s data directory. Formerly, this was the default for compat mode only, while non-compat defaulted to the current working directory. To get the previous behavior in non-compat mode, you must specify --wallet-dir=. on the command line. --- mmgen/daemon.py | 48 +++++++++++-------- mmgen/proto/btc/daemon.py | 18 +------- mmgen/proto/eth/daemon.py | 16 ++----- mmgen/proto/xmr/daemon.py | 33 +++++++------ mmgen/protocol.py | 18 +++++--- mmgen/xmrwallet/__init__.py | 5 +- mmgen/xmrwallet/ops/submit.py | 1 - mmgen/xmrwallet/ops/sweep.py | 1 - mmgen/xmrwallet/ops/wallet.py | 14 ++---- test/cmdtest_d/xmr_autosign.py | 31 +++++-------- test/cmdtest_d/xmrwallet.py | 84 +++++++++++++++------------------- 11 files changed, 119 insertions(+), 150 deletions(-) diff --git a/mmgen/daemon.py b/mmgen/daemon.py index 72a4ceb8..8f96114f 100755 --- a/mmgen/daemon.py +++ b/mmgen/daemon.py @@ -23,6 +23,7 @@ daemon: Daemon control interface for the MMGen suite import os, time, importlib from subprocess import run, PIPE, CompletedProcess from collections import namedtuple +from pathlib import Path from .cfg import gc from .base_obj import Lockable @@ -118,8 +119,7 @@ class Daemon(Lockable): @property def pid(self): if self.use_pidfile: - with open(self.pidfile) as fp: - return fp.read().strip() + return self.pidfile.read_text().strip() match gc.platform: case 'win32': @@ -278,7 +278,7 @@ class CoinDaemon(Daemon): cfg_file_hdr = '' avail_flags = ('keep_cfg_file',) avail_opts = ('no_daemonize', 'online') - testnet_dir = None + testnet_dir = 'testnet' test_suite_port_shift = 1237 rpc_user = None rpc_password = None @@ -411,12 +411,22 @@ class CoinDaemon(Daemon): getattr(self.proto.network_names, self.network), 'test suite ' if self.test_suite else '') - # user-set values take precedence - self.datadir = os.path.abspath(datadir or cfg.daemon_data_dir or self.init_datadir()) - self.has_non_dfl_datadir = bool(datadir or cfg.daemon_data_dir or self.test_suite or self.network == 'regtest') + self.datadir = Path(datadir or cfg.daemon_data_dir or self.dfl_datadir).absolute() - # init_datadir() may have already initialized logdir - self.logdir = os.path.abspath(getattr(self, 'logdir', self.datadir)) + if self.test_suite and cfg.test_user: + self.datadir = self.datadir / cfg.test_user + + self.has_non_dfl_datadir = bool(datadir or cfg.daemon_data_dir or self.test_suite) + + # location of the network's blockchain data and authentication cookie + self.network_datadir = ( + self.datadir / { + 'mainnet': '', + 'testnet': self.testnet_dir, + 'regtest': 'regtest', + }[self.network] + if self.proto.base_proto == 'Bitcoin' or not self.test_suite else + self.datadir) ps_adj = (port_shift or 0) + (self.test_suite_port_shift if self.test_suite else 0) @@ -432,20 +442,20 @@ class CoinDaemon(Daemon): self.private_port = getattr(self.private_ports, self.network) # bind_port == self.private_port or self.rpc_port - self.pidfile = f'{self.logdir}/{self.id}-{self.network}-daemon-{self.bind_port}.pid' - self.logfile = f'{self.logdir}/{self.id}-{self.network}-daemon-{self.bind_port}.log' + fn_stem = f'{self.id}-{self.network}-daemon-{self.bind_port}' + + self.logfile = self.network_datadir / (fn_stem + '.log') + + if self.use_pidfile: + self.pidfile = self.network_datadir / (fn_stem + '.pid') self.init_subclass() - def init_datadir(self): - if self.test_suite: - return os.path.join('test', 'daemons', self.network_id) - else: - return os.path.join(*self.datadirs[gc.platform]) - @property - def network_datadir(self): - return self.datadir + def dfl_datadir(self): + return ( + os.path.join('test', 'daemons', self.network_id) if self.test_suite else + os.path.join(*self.datadirs[gc.platform])) def get_rpc_port(self): return getattr(self.rpc_ports, self.network) @@ -484,7 +494,7 @@ class CoinDaemon(Daemon): if self.use_pidfile and os.path.exists(self.pidfile): # Parity overwrites the data in the existing pidfile without zeroing it first, leading # to interesting consequences when the new PID has fewer digits than the previous one. - os.unlink(self.pidfile) + self.pidfile.unlink() def remove_datadir(self): "remove the network's datadir" diff --git a/mmgen/proto/btc/daemon.py b/mmgen/proto/btc/daemon.py index be01b03e..8858d2f2 100755 --- a/mmgen/proto/btc/daemon.py +++ b/mmgen/proto/btc/daemon.py @@ -33,22 +33,6 @@ class bitcoin_core_daemon(CoinDaemon): 'win32': [os.getenv('APPDATA'), 'Bitcoin']} avail_opts = ('no_daemonize', 'online', 'bdb_wallet') - def init_datadir(self): - if self.network == 'regtest' and not self.test_suite: - return os.path.join(self.cfg.data_dir_root, 'regtest', self.cfg.coin.lower()) - else: - return super().init_datadir() - - @property - def network_datadir(self): - "location of the network's blockchain data and authentication cookie" - return os.path.join ( - self.datadir, { - 'mainnet': '', - 'testnet': self.testnet_dir, - 'regtest': 'regtest', - }[self.network]) - @property def auth_cookie_fn(self): return os.path.join(self.network_datadir, '.cookie') @@ -62,7 +46,7 @@ class bitcoin_core_daemon(CoinDaemon): self.rpc_password = MMGenRegtest.rpc_password self.shared_args = list_gen( - [f'--datadir={self.datadir}', self.nonstd_datadir or self.has_non_dfl_datadir], + [f'--datadir={self.datadir}', self.nonstd_datadir or self.has_non_dfl_datadir], [f'--rpcport={self.rpc_port}'], [f'--rpcuser={self.rpc_user}', self.network == 'regtest'], [f'--rpcpassword={self.rpc_password}', self.network == 'regtest'], diff --git a/mmgen/proto/eth/daemon.py b/mmgen/proto/eth/daemon.py index ed470e63..2bf2f19e 100755 --- a/mmgen/proto/eth/daemon.py +++ b/mmgen/proto/eth/daemon.py @@ -19,7 +19,6 @@ from ...util import list_gen, get_subclasses from ...daemon import CoinDaemon, RPCDaemon, _nw, _dd class ethereum_daemon(CoinDaemon): - chain_subdirs = _nw('ethereum', 'goerli', 'DevelopmentChain') base_rpc_port = 8545 # same for all networks! base_authrpc_port = 8551 # same for all networks! base_p2p_port = 30303 # same for all networks! @@ -49,13 +48,6 @@ class ethereum_daemon(CoinDaemon): def get_p2p_port(self): return self.base_p2p_port + self.port_offset - def init_datadir(self): - self.logdir = super().init_datadir() - return os.path.join( - self.logdir, - self.id, - getattr(self.chain_subdirs, self.network)) - class openethereum_daemon(ethereum_daemon): daemon_data = _dd('OpenEthereum', 3003005, '3.3.5') version_pat = r'OpenEthereum//v(\d+)\.(\d+)\.(\d+)' @@ -77,13 +69,13 @@ class openethereum_daemon(ethereum_daemon): ['--no-secretstore'], [f'--jsonrpc-port={self.rpc_port}'], [f'--port={self.p2p_port}', self.p2p_port], - [f'--base-path={self.datadir}', self.has_non_dfl_datadir], + [f'--base-path={self.network_datadir}', self.has_non_dfl_datadir], [f'--chain={self.proto.chain_name}', self.network!='regtest'], ['--config=dev', self.network=='regtest'], # no presets for mainnet or testnet ['--mode=offline', self.test_suite or self.network=='regtest'], [f'--log-file={self.logfile}', self.has_non_dfl_datadir], ['daemon', self.use_pidfile], - [self.pidfile, self.use_pidfile]) + [str(self.pidfile), self.use_pidfile]) class parity_daemon(openethereum_daemon): daemon_data = _dd('Parity', 2007002, '2.7.2') @@ -122,7 +114,7 @@ class geth_daemon(ethereum_daemon): [f'--port={self.p2p_port}', self.p2p_port], # geth binds p2p port even with --maxpeers=0 [f'--discovery.port={self.p2p_port}', self.id == 'reth' and self.p2p_port], ['--maxpeers=0', self.id == 'geth' and not self.opt.online], - [f'--datadir={self.datadir}', self.has_non_dfl_datadir], + [f'--datadir={self.network_datadir}', self.has_non_dfl_datadir], ['--holesky', self.network=='testnet' and self.id == 'geth'], ['--chain=holesky', self.network=='testnet' and self.id == 'reth'], ['--dev', self.network=='regtest']) @@ -157,7 +149,7 @@ class erigon_daemon(geth_daemon): [f'--port={self.p2p_port}', self.p2p_port], ['--maxpeers=0', not self.opt.online], [f'--private.api.addr=127.0.0.1:{self.private_port}'], - [f'--datadir={self.datadir}', self.has_non_dfl_datadir], + [f'--datadir={self.network_datadir}', self.has_non_dfl_datadir], ['--chain=goerli', self.network=='testnet'], [f'--torrent.port={self.torrent_ports.testnet}', self.network=='testnet'], ['--chain=dev', self.network=='regtest'], diff --git a/mmgen/proto/xmr/daemon.py b/mmgen/proto/xmr/daemon.py index 81960a3f..9d3983d2 100755 --- a/mmgen/proto/xmr/daemon.py +++ b/mmgen/proto/xmr/daemon.py @@ -12,7 +12,7 @@ proto.xmr.daemon: Monero base protocol daemon classes """ -import os +from pathlib import Path from ...cfg import gc from ...util import list_gen, die, contains_any @@ -31,12 +31,6 @@ class monero_daemon(CoinDaemon): 'darwin': [gc.home_dir, '.bitmonero'], 'win32': ['/', 'c', 'ProgramData', 'bitmonero']} - def init_datadir(self): - self.logdir = super().init_datadir() - return os.path.join( - self.logdir, - self.testnet_dir if self.network == 'testnet' else '') - def get_p2p_port(self): return self.rpc_port - 1 @@ -64,7 +58,7 @@ class monero_daemon(CoinDaemon): self.coind_args = list_gen( ['--hide-my-port'], ['--no-igd'], - [f'--data-dir={self.datadir}', self.has_non_dfl_datadir], + [f'--data-dir={self.network_datadir}', self.has_non_dfl_datadir], [f'--pidfile={self.pidfile}', self.use_pidfile], ['--detach', not (self.opt.no_daemonize or gc.platform=='win32')], ['--offline', not self.opt.online]) @@ -88,7 +82,10 @@ class MoneroWalletDaemon(RPCDaemon): networks = ('mainnet', 'testnet') rpc_ports = _nw(13131, 13141, None) # testnet is non-standard _reset_ok = ('debug', 'wait', 'pids', 'force_kill') - test_suite_datadir = os.path.join('test', 'daemons', 'xmrtest', 'wallet_rpc') + test_user_port_shifts = { + 'bob': 10, + 'alice': 20, + 'miner': 30} def __init__( self, @@ -112,17 +109,23 @@ class MoneroWalletDaemon(RPCDaemon): super().__init__(cfg, **kwargs) self.network = proto.network - self.wallet_dir = wallet_dir or (self.test_suite_datadir if self.test_suite else None) self.rpc_port = getattr(self.rpc_ports, self.network) + (11 if self.test_suite else 0) self.disable_authentication = disable_authentication if port_shift: self.rpc_port += port_shift + elif cfg.test_user: + self.rpc_port += self.test_user_port_shifts[cfg.test_user] - id_str = f'{self.exec_fn}-{self.bind_port}' - self.datadir = datadir or (self.test_suite_datadir if self.test_suite else self.exec_fn + '.d') - self.pidfile = os.path.join(self.datadir, id_str+'.pid') - self.logfile = os.path.join(self.datadir, id_str+'.log') + if wallet_dir or cfg.wallet_dir: + self.wallet_dir = Path(wallet_dir or cfg.wallet_dir) + else: + from .tw.ctl import MoneroTwCtl + self.wallet_dir = MoneroTwCtl.get_tw_dir(self.proto) + + fn_stem = f'{self.exec_fn}-{self.bind_port}' + self.pidfile = self.proto.network_datadir / (fn_stem + '.pid') + self.logfile = self.proto.network_datadir / (fn_stem + '.log') self.use_pidfile = gc.platform == 'linux' @@ -176,7 +179,7 @@ class MoneroWalletDaemon(RPCDaemon): def start(self, *args, **kwargs): try: # NB: required due to bug in v18.3.1: PID file not deleted on shutdown - os.unlink(self.pidfile) + self.pidfile.unlink() except FileNotFoundError: pass super().start(*args, **kwargs) diff --git a/mmgen/protocol.py b/mmgen/protocol.py index 6a10fd43..74e23e78 100755 --- a/mmgen/protocol.py +++ b/mmgen/protocol.py @@ -128,12 +128,18 @@ class CoinProtocol(MMGenObject): @property def network_datadir(self): from pathlib import Path - return Path( - self.cfg.data_dir_root, - self.cfg.test_user, - 'altcoins', - self.coin.lower(), - ('' if self.network == 'mainnet' else self.network)) + if self.coin == 'BTC': + return Path( + self.cfg.data_dir_root, + ('' if self.network == 'mainnet' else self.network), + self.cfg.test_user).absolute() + else: + return Path( + self.cfg.data_dir_root, + 'altcoins', + self.coin.lower(), + ('' if self.network == 'mainnet' else self.network), + self.cfg.test_user).absolute() @property def dcoin(self): diff --git a/mmgen/xmrwallet/__init__.py b/mmgen/xmrwallet/__init__.py index 1dba551d..c9b42eec 100755 --- a/mmgen/xmrwallet/__init__.py +++ b/mmgen/xmrwallet/__init__.py @@ -119,9 +119,7 @@ def op(op, cfg, infile, wallets, *, spec=None, compat_call=False): if compat_call or (cfg.compat if cfg.compat is not None else cfg.xmrwallet_compat): if cfg.wallet_dir and not cfg.offline: die(1, '--wallet-dir cannot be specified in xmrwallet compatibility mode') - from ..tw.ctl import TwCtl from ..cfg import Config - twctl_cls = cfg._proto.base_proto_subclass(TwCtl, 'tw.ctl') cfg = Config({ '_clone': cfg, 'compat': True, @@ -129,6 +127,5 @@ def op(op, cfg, infile, wallets, *, spec=None, compat_call=False): 'xmrwallet_compat': True} | ({} if cfg.offline else { 'no_start_wallet_daemon': cfg.no_start_wallet_daemon or compat_call, 'daemon': cfg.daemon or cfg.monero_daemon, - 'watch_only': cfg.watch_only or cfg.autosign or bool(cfg.autosign_mountpoint), - 'wallet_dir': twctl_cls.get_tw_dir(cfg._proto)})) + 'watch_only': cfg.watch_only or cfg.autosign or bool(cfg.autosign_mountpoint)})) return op_cls(op)(cfg, uargs(infile, wallets, spec, compat_call)) diff --git a/mmgen/xmrwallet/ops/submit.py b/mmgen/xmrwallet/ops/submit.py index d20a65ef..12f9b02c 100755 --- a/mmgen/xmrwallet/ops/submit.py +++ b/mmgen/xmrwallet/ops/submit.py @@ -62,7 +62,6 @@ class OpSubmit(OpWallet): wd = MoneroWalletDaemon( cfg = self.cfg, proto = self.proto, - wallet_dir = self.cfg.wallet_dir or '.', monerod_addr = relay_opt[1]) u = wd.usr_daemon_args = [] diff --git a/mmgen/xmrwallet/ops/sweep.py b/mmgen/xmrwallet/ops/sweep.py index 2fb3b884..4d3a3882 100755 --- a/mmgen/xmrwallet/ops/sweep.py +++ b/mmgen/xmrwallet/ops/sweep.py @@ -51,7 +51,6 @@ class OpSweep(OpMixinSpec, OpWallet): wd2 = MoneroWalletDaemon( cfg = self.cfg, proto = self.proto, - wallet_dir = self.cfg.wallet_dir or '.', monerod_addr = m[1], proxy = m[2]) diff --git a/mmgen/xmrwallet/ops/wallet.py b/mmgen/xmrwallet/ops/wallet.py index 96ffd5c9..0b6ea08e 100755 --- a/mmgen/xmrwallet/ops/wallet.py +++ b/mmgen/xmrwallet/ops/wallet.py @@ -13,7 +13,6 @@ xmrwallet.ops.wallet: xmrwallet wallet op for the MMGen Suite """ import asyncio, re, atexit -from pathlib import Path from ...color import orange, cyan from ...util import msg, gmsg, ymsg, die, suf @@ -66,7 +65,6 @@ class OpWallet(OpBase): self.wd = MoneroWalletDaemon( cfg = self.cfg, proto = self.proto, - wallet_dir = self.cfg.wallet_dir or '.', monerod_addr = self.cfg.daemon or None, disable_authentication = self.disable_authentication, trust_monerod = self.trust_monerod, @@ -204,13 +202,11 @@ class OpWallet(OpBase): def get_wallet_fn(self, data, *, watch_only=None): if watch_only is None: watch_only = self.cfg.watch_only - return Path( - (self.cfg.wallet_dir or '.'), - '{a}-{b}-Monero{c}Wallet{d}'.format( - a = self.kal.al_id.sid, - b = data.idx, - c = 'WatchOnly' if watch_only else '', - d = f'.{self.cfg.network}' if self.cfg.network != 'mainnet' else '')) + return self.wd.wallet_dir / '{a}-{b}-Monero{c}Wallet{d}'.format( + a = self.kal.al_id.sid, + b = data.idx, + c = 'WatchOnly' if watch_only else '', + d = f'.{self.cfg.network}' if self.cfg.network != 'mainnet' else '') @property def add_wallet_desc(self): diff --git a/test/cmdtest_d/xmr_autosign.py b/test/cmdtest_d/xmr_autosign.py index 4fddbafe..9e4dcfdb 100755 --- a/test/cmdtest_d/xmr_autosign.py +++ b/test/cmdtest_d/xmr_autosign.py @@ -113,17 +113,8 @@ class CmdTestXMRAutosign(CmdTestXMRWallet, CmdTestAutosignThreaded): if trunner is None: return - from mmgen.cfg import Config - self.alice_cfg = Config({ - 'coin': 'XMR', - 'outdir': self.users['alice'].udir, - 'wallet_rpc_password': 'passwOrd', - } | ({ - 'alice': True, - 'compat': True - } if self.compat else { - 'wallet_dir': self.users['alice'].udir - })) + self.alice_cfg = self.users['alice'].cfg + self.alice_datadir = self.users['alice'].cfg._proto.network_datadir self.burn_addr = make_burn_addr(cfg) @@ -144,8 +135,8 @@ class CmdTestXMRAutosign(CmdTestXMRWallet, CmdTestAutosignThreaded): seed = Wallet(self.alice_cfg, fn=data.mmwords).seed, skip_chksum_msg = True, key_address_validity_check = False) - kal.file.write(ask_overwrite=False) - fn = get_file_with_ext(data.udir, 'akeys') + kal.file.write(outdir=self.alice_datadir, ask_overwrite=False) + fn = get_file_with_ext(self.alice_datadir, 'akeys') m = op('create', self.alice_cfg, fn, '1-2') asyncio.run(m.main()) asyncio.run(m.stop_wallet_daemon()) @@ -194,7 +185,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet, CmdTestAutosignThreaded): t = self.spawn( 'mmgen-xmrwallet', self.extra_opts - + (['--alice', '--compat'] if self.compat else [f'--wallet-dir={data.udir}']) + + (['--alice', '--compat'] if self.compat else []) + [f'--daemon=localhost:{data.md.rpc_port}'] + (self.autosign_opts if autosign else []) + [op] @@ -347,7 +338,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet, CmdTestAutosignThreaded): args = ( self.extra_opts + self.autosign_opts - + (['--alice', '--compat'] if self.compat else [f'--wallet-dir={data.udir}']) + + (['--alice', '--compat'] if self.compat else []) + [f'--daemon=localhost:{data.md.rpc_port}'] + add_opts + [op] @@ -598,13 +589,13 @@ class CmdTestXMRCompat(CmdTestXMRAutosign): super().__init__(cfg, trunner, cfgs, spawn) if trunner is None: return - self.alice_tw_dir = os.path.join(self.tr.data_dir, 'alice', 'altcoins', 'xmr', 'tracking-wallets') + data = self.users['alice'] self.alice_dump_file = os.path.join( - self.alice_tw_dir, - '{}-2-MoneroWatchOnlyWallet.dump'.format(self.users['alice'].sid)) + data.wd.wallet_dir, + f'{data.sid}-2-MoneroWatchOnlyWallet.dump') self.alice_daemon_opts = [ - f'--monero-daemon=localhost:{self.users["alice"].md.rpc_port}', - '--monero-wallet-rpc-password=passwOrd'] + f'--monero-daemon=localhost:{data.md.rpc_port}', + '--monero-wallet-rpc-password=abc'] self.alice_opts = ['--alice', '--coin=xmr'] + self.alice_daemon_opts def addrimport_alice(self): diff --git a/test/cmdtest_d/xmrwallet.py b/test/cmdtest_d/xmrwallet.py index 0f04df80..5f12b514 100755 --- a/test/cmdtest_d/xmrwallet.py +++ b/test/cmdtest_d/xmrwallet.py @@ -24,7 +24,7 @@ import os, time, re, atexit, asyncio, shutil from subprocess import run from collections import namedtuple -from mmgen.cfg import gc +from mmgen.cfg import Config, gc from mmgen.util import capfirst, is_int, die, suf, list_gen from mmgen.obj import MMGenRange from mmgen.amt import XMRAmt @@ -156,14 +156,14 @@ class CmdTestXMRWallet(CmdTestBase): from mmgen.proto.xmr.daemon import MoneroWalletDaemon from mmgen.proto.xmr.rpc import MoneroRPCClient, MoneroWalletRPCClient self.users = {} - tmpdir_num = self.tmpdir_nums[0] ud = namedtuple('user_data', [ + 'cfg', 'sid', + 'udir', + 'twdir', 'mmwords', 'autosign', - 'udir', - 'daemon_datadir', 'kal_range', 'kafile', 'walletfile_fs', @@ -183,27 +183,18 @@ class CmdTestXMRWallet(CmdTestBase): kal_range, add_coind_args) in self.user_data: - tmpdir = os.path.join('test', 'tmp', str(tmpdir_num)) - udir = os.path.join(tmpdir, user) - daemon_datadir = os.path.join(self.daemon_datadir_base, user) - - if self.compat: - from mmgen.tw.ctl import TwCtl - twctl_cls = self.proto.base_proto_subclass(TwCtl, 'tw.ctl') - wallet_dir = os.path.join(self.tr.data_dir, user, 'altcoins', 'xmr', twctl_cls.tw_subdir) - else: - wallet_dir = udir + usr_cfg = Config({'_clone': self.cfg, user: True, 'wallet_rpc_password': 'abc'}) + udir = usr_cfg._proto.network_datadir md = CoinDaemon( - cfg = self.cfg, - proto = self.proto, + cfg = usr_cfg, + proto = usr_cfg._proto, port_shift = shift, - opts = ['online'], - datadir = daemon_datadir) + opts = ['online']) md_rpc = MoneroRPCClient( - cfg = self.cfg, - proto = self.proto, + cfg = usr_cfg, + proto = usr_cfg._proto, host = 'localhost', port = md.rpc_port, user = None, @@ -212,37 +203,35 @@ class CmdTestXMRWallet(CmdTestBase): daemon = md) wd = MoneroWalletDaemon( - cfg = self.cfg, - proto = self.proto, - wallet_dir = wallet_dir, + cfg = usr_cfg, + proto = usr_cfg._proto, + wallet_dir = None if autosign else + (usr_cfg._proto.network_datadir / 'tracking-wallets'), user = 'foo', passwd = 'bar', port_shift = shift, monerod_addr = f'127.0.0.1:{md.rpc_port}') wd_rpc = MoneroWalletRPCClient( - cfg = self.cfg, + cfg = usr_cfg, daemon = wd, test_connection = False) - if autosign: - kafile_suf = 'vkeys' - fn_stem = 'MoneroWatchOnlyWallet' - kafile_dir = self.asi_online.xmr_dir - else: - kafile_suf = 'akeys' - fn_stem = 'MoneroWallet' - kafile_dir = udir + kafile_suf, fn_stem = ( + ('vkeys', 'MoneroWatchOnlyWallet') if autosign else + ('akeys', 'MoneroWallet')) + self.users[user] = ud( + cfg = usr_cfg, sid = sid, mmwords = f'test/ref/{sid}.mmwords', autosign = autosign, udir = udir, - daemon_datadir = daemon_datadir, + twdir = wd.wallet_dir, kal_range = kal_range, - kafile = f'{kafile_dir}/{sid}-XMR-M[{kal_range}].{kafile_suf}', - walletfile_fs = f'{udir}/{sid}-{{}}-{fn_stem}', - addrfile_fs = f'{udir}/{sid}-{{}}-{fn_stem}.address.txt', + kafile = str(udir / f'{sid}-XMR-M[{kal_range}].{kafile_suf}'), + walletfile_fs = str(wd.wallet_dir / f'{sid}-{{}}-{fn_stem}'), + addrfile_fs = str(wd.wallet_dir / f'{sid}-{{}}-{fn_stem}.address.txt'), md = md, md_rpc = md_rpc, wd = wd, @@ -272,8 +261,7 @@ class CmdTestXMRWallet(CmdTestBase): for user, data in self.users.items(): if not user in users: continue - run(['mkdir', '-p', data.udir]) - run(f'rm -f {data.kafile}', shell=True) + run(['mkdir', '-p', str(data.udir)]) t = self.spawn( 'mmgen-keygen', ['--quiet', '--accept-defaults', '--coin=xmr', f'--outdir={data.udir}'] @@ -313,7 +301,8 @@ class CmdTestXMRWallet(CmdTestBase): t = self.spawn( 'mmgen-xmrwallet', self.extra_opts - + ([f'--{user}', '--compat'] if self.compat else [f'--wallet-dir={data.udir}']) + + [f'--{user}'] + + (['--compat'] if self.compat else []) + (self.autosign_opts if data.autosign else []) + add_opts + [op] @@ -330,7 +319,8 @@ class CmdTestXMRWallet(CmdTestBase): 'mmgen-xmrwallet', self.extra_opts + (self.autosign_opts if do_autosign else []) - + (['--alice', '--compat'] if self.compat else [f'--wallet-dir={data.udir}']) + + ['--alice'] + + (['--compat'] if self.compat else []) + [f'--daemon=localhost:{data.md.rpc_port}'] + (['--no-start-wallet-daemon'] if cfg in ('continue', 'stop') else []) + (['--no-stop-wallet-daemon'] if cfg in ('start', 'continue') else []) @@ -413,10 +403,11 @@ class CmdTestXMRWallet(CmdTestBase): def set_label_user(self, user, label_spec, add_timestr_resp, expect, add_opts=[]): data = self.users[user] - cmd_opts = [f'--wallet-dir={data.udir}', f'--daemon=localhost:{data.md.rpc_port}'] + cmd_opts = [f'--daemon=localhost:{data.md.rpc_port}'] t = self.spawn( 'mmgen-xmrwallet', self.extra_opts + + [f'--{user}'] + add_opts + cmd_opts + ['label', data.kafile, label_spec]) @@ -451,7 +442,8 @@ class CmdTestXMRWallet(CmdTestBase): t = self.spawn( 'mmgen-xmrwallet', self.extra_opts - + ([f'--{user}', '--compat'] if self.compat else [f'--wallet-dir={data.udir}']) + + [f'--{user}'] + + (['--compat'] if self.compat else [f'--wallet-dir={data.twdir}']) # test --wallet-dir option + [f'--daemon=localhost:{data.md.rpc_port}'] + (self.autosign_opts if data.autosign else []) + add_opts @@ -502,7 +494,8 @@ class CmdTestXMRWallet(CmdTestBase): t = self.spawn( 'mmgen-xmrwallet', self.extra_opts - + ([f'--{user}', '--compat'] if self.compat else [f'--wallet-dir={data.udir}']) + + [f'--{user}'] + + (['--compat'] if self.compat else []) + cmd_opts + add_opts + (self.autosign_opts if data.autosign else []) @@ -631,8 +624,8 @@ class CmdTestXMRWallet(CmdTestBase): self.do_mount_online() silence() kal = (ViewKeyAddrList if data.autosign else KeyAddrList)( - cfg = self.cfg, - proto = self.proto, + cfg = data.cfg, + proto = data.cfg._proto, infile = data.kafile, skip_chksum_msg = True, key_address_validity_check = False) @@ -853,7 +846,6 @@ class CmdTestXMRWallet(CmdTestBase): def start_daemons(self): for v in self.users.values(): - run(['mkdir', '-p', v.daemon_datadir]) v.md.start() if self.extra_daemons: start_test_daemons(*self.extra_daemons, verbose=True)