From 85df7cdd76085be784b0cc3cb6d643497a6f1f01 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Thu, 15 Feb 2024 09:28:07 +0000 Subject: [PATCH] autosign, xmrwallet: minor fixes and cleanups throughout --- mmgen/autosign.py | 19 +++----- mmgen/led.py | 7 ++- mmgen/main_autosign.py | 3 +- mmgen/main_xmrwallet.py | 4 +- test/cmdtest.py | 17 ++++--- test/cmdtest_py_d/ct_autosign.py | 67 ++++++++++++++++------------ test/cmdtest_py_d/ct_xmr_autosign.py | 35 ++++++++------- test/cmdtest_py_d/ct_xmrwallet.py | 26 +++++------ 8 files changed, 96 insertions(+), 82 deletions(-) diff --git a/mmgen/autosign.py b/mmgen/autosign.py index a7932d4e..fe4e39ed 100755 --- a/mmgen/autosign.py +++ b/mmgen/autosign.py @@ -39,6 +39,9 @@ class Signable: self.parent = parent self.cfg = parent.cfg self.dir = getattr(parent,self.dir_name) + self.long_desc = ( + 'non-Monero transaction' if self.desc == 'transaction' and 'XMR' in self.parent.coins else + self.desc) @property def unsigned(self): @@ -267,9 +270,6 @@ class Autosign: self.coins = cfg.coins.upper().split(',') if cfg.coins else [] - if cfg._args and cfg._args[0] == 'clean': - return - if cfg.xmrwallets and not 'XMR' in self.coins: self.coins.append('XMR') @@ -401,7 +401,7 @@ class Autosign: target.print_bad_list(bad) return not bad else: - msg(f'No unsigned {target.desc}s') + msg(f'No unsigned {target.long_desc}s') await asyncio.sleep(0.5) return True @@ -579,16 +579,9 @@ class Autosign: bmsg(f'{count} file{suf(count)} shredded') def get_insert_status(self): - if self.cfg.no_insert_check: - return True - try: - self.dev_disk_path.stat() - except: - return False - else: - return True + return self.cfg.no_insert_check or self.dev_disk_path.exists() - async def do_loop(self): + async def main_loop(self): if not self.cfg.stealth_led: self.led.set('standby') testing_xmr = self.cfg.test_suite_xmr_autosign diff --git a/mmgen/led.py b/mmgen/led.py index dbb389ba..c2e8fa60 100755 --- a/mmgen/led.py +++ b/mmgen/led.py @@ -117,8 +117,11 @@ class LEDControl: @classmethod def delete_dummy_control_files(cls): db = cls.boards['dummy'] - os.unlink(db.status) - os.unlink(db.trigger) + for fn in (db.status, db.trigger): + try: + os.unlink(fn) + except Exception as e: + msg(str(e)) def noop(self,*args,**kwargs): pass diff --git a/mmgen/main_autosign.py b/mmgen/main_autosign.py index 938595ad..e48c2914 100755 --- a/mmgen/main_autosign.py +++ b/mmgen/main_autosign.py @@ -149,7 +149,7 @@ def main(do_loop): async def do(): await asi.check_daemons_running() if do_loop: - await asi.do_loop() + await asi.main_loop() else: ret = await asi.do_sign() asi.at_exit(not ret) @@ -188,6 +188,7 @@ if cmd_args: if cfg.xmrwallets and keypress_confirm( cfg, '\nContinue with Monero setup?', default_yes=True ): msg('') asi.xmr_setup() + asi.do_umount() elif cmd == 'wait': main(do_loop=True) elif cmd == 'clean': diff --git a/mmgen/main_xmrwallet.py b/mmgen/main_xmrwallet.py index e1fe45cd..dc15f652 100755 --- a/mmgen/main_xmrwallet.py +++ b/mmgen/main_xmrwallet.py @@ -66,11 +66,11 @@ opts_data = { -d, --outdir=D Save transaction files to directory 'D' instead of the working directory -D, --daemon=H:P Connect to the monerod at {D} --R, --tx-relay-daemon=H:P[:H:P] Relay transactions via a monerod specified by - {R} -k, --use-internal-keccak-module Force use of the internal keccak module -p, --hash-preset=P Use scrypt hash preset 'P' for password hashing (default: '{gc.dfl_hash_preset}') +-R, --tx-relay-daemon=H:P[:H:P] Relay transactions via a monerod specified by + {R} -r, --restore-height=H Scan from height 'H' when creating wallets. Use special value ‘current’ to create empty wallet at current blockchain height. diff --git a/test/cmdtest.py b/test/cmdtest.py index b4011e44..2f05b7c2 100755 --- a/test/cmdtest.py +++ b/test/cmdtest.py @@ -95,7 +95,7 @@ else: from mmgen.cfg import Config,gc from mmgen.color import red,yellow,green,blue,cyan,gray,nocolor,init_color -from mmgen.util import Msg,bmsg,die,suf,make_timestr,async_run +from mmgen.util import msg,Msg,bmsg,die,suf,make_timestr,async_run from test.include.common import ( set_globals, @@ -222,6 +222,8 @@ type(cfg)._reset_ok += ( 'resuming', 'skipping_deps' ) +logging = cfg.log or os.getenv('MMGEN_EXEC_WRAPPER') + cfg.resuming = any(k in po.user_opts for k in ('resume','resume_after')) cfg.skipping_deps = cfg.resuming or 'skip_deps' in po.user_opts @@ -547,7 +549,7 @@ class CmdTestRunner: 'cmdtest.py test runner' def __del__(self): - if cfg.log: + if logging: self.log_fd.close() def __init__(self,data_dir,trash_dir): @@ -562,7 +564,7 @@ class CmdTestRunner: self.resume_cmd = None self.deps_only = None - if cfg.log: + if logging: self.log_fd = open(cmdtest_py_log_fn,'a') self.log_fd.write(f'\nLog started: {make_timestr()} UTC\n') omsg(f'INFO → Logging to file {cmdtest_py_log_fn!r}') @@ -630,10 +632,15 @@ class CmdTestRunner: self.tg.extra_spawn_args + args ) - qargs = ['{q}{}{q}'.format( a, q = "'" if ' ' in a else '' ) for a in args] + try: + qargs = ['{q}{}{q}'.format( a, q = "'" if ' ' in a else '' ) for a in args] + except: + msg(f'args: {args}') + raise + cmd_disp = ' '.join(qargs).replace('\\','/') # for mingw - if cfg.log: + if logging: self.log_fd.write('[{}][{}:{}] {}\n'.format( proto.coin.lower(), self.tg.group_name, diff --git a/test/cmdtest_py_d/ct_autosign.py b/test/cmdtest_py_d/ct_autosign.py index 3a77f076..c44b43d4 100755 --- a/test/cmdtest_py_d/ct_autosign.py +++ b/test/cmdtest_py_d/ct_autosign.py @@ -122,10 +122,10 @@ class CmdTestAutosignBase(CmdTestBase): ) self.mountpoint = self.asi.mountpoint - if self.simulate and not cfg.exact_output: + if self.simulate_led and not cfg.exact_output: die(1,red('This command must be run with --exact-output enabled!')) - if self.simulate or not self.live: + if self.simulate_led or not self.live: LEDControl.create_dummy_control_files() self.spawn_env['MMGEN_TEST_SUITE_AUTOSIGN_LED_SIMULATE'] = '1' @@ -133,7 +133,7 @@ class CmdTestAutosignBase(CmdTestBase): if self.live: check_mountpoint(self.asi) - init_led(self.simulate) + init_led(self.simulate_led) else: self.asi.tx_dir.mkdir(parents=True,exist_ok=True) # creates mountpoint self.wallet_dir.mkdir(parents=True,exist_ok=True) @@ -163,7 +163,7 @@ class CmdTestAutosignBase(CmdTestBase): def __del__(self): if sys.platform == 'win32' or self.tr is None: return - if self.simulate or not self.live: + if self.simulate_led or not self.live: LEDControl.delete_dummy_control_files() def start_daemons(self): @@ -244,29 +244,34 @@ class CmdTestAutosignBase(CmdTestBase): assert op in ('copy','set_count','remove_signed') - fdata = [e for e in filedir_map if e[0] in (txfile_coins or self.txfile_coins)] - from .ct_ref import CmdTestRef - tfns = [CmdTestRef.sources['ref_tx_file'][c][1] for c,d in fdata] + \ - [CmdTestRef.sources['ref_tx_file'][c][0] for c,d in fdata] + \ - ['25EFA3[2.34].testnet.rawtx'] # TX with 2 non-MMGen outputs - self.tx_count = len([fn for fn in tfns if fn]) + def gen(): + d = CmdTestRef.sources['ref_tx_file'] + dirmap = [e for e in filedir_map if e[0] in (txfile_coins or self.txfile_coins)] + for coin,coindir in dirmap: + for network in (0,1): + fn = d[coin][network] + if fn: + yield (coindir,fn) + + data = list(gen()) + [('','25EFA3[2.34].testnet.rawtx')] # TX with 2 non-MMGen outputs + + self.tx_count = len(data) if op == 'set_count': return - tfs = [joinpath(ref_dir,d[1],fn) for d,fn in zip(fdata+fdata+[('btc','')],tfns)] - for f,fn in zip(tfs,tfns): - if fn: # use empty fn to skip file - if cfg.debug_utf8: - ext = '.testnet.rawtx' if fn.endswith('.testnet.rawtx') else '.rawtx' - fn = fn[:-len(ext)] + '-α' + ext - target = joinpath(self.mountpoint,'tx',fn) - if not op == 'remove_signed': - shutil.copyfile(f,target) - try: - os.unlink(target.replace('.rawtx','.sigtx')) - except: - pass + for coindir,fn in data: + src = joinpath(ref_dir,coindir,fn) + if cfg.debug_utf8: + ext = '.testnet.rawtx' if fn.endswith('.testnet.rawtx') else '.rawtx' + fn = fn[:-len(ext)] + '-α' + ext + target = joinpath(self.asi.mountpoint,'tx',fn) + if not op == 'remove_signed': + shutil.copyfile(src,target) + try: + os.unlink(target.replace('.rawtx','.sigtx')) + except: + pass return 'ok' @@ -276,6 +281,9 @@ class CmdTestAutosignBase(CmdTestBase): def remove_bad_txfiles(self): return self.bad_txfiles('remove') + create_bad_txfiles2 = create_bad_txfiles + remove_bad_txfiles2 = remove_bad_txfiles + def bad_txfiles(self,op): if self.live: do_mount(self.mountpoint) @@ -367,13 +375,16 @@ class CmdTestAutosignBase(CmdTestBase): imsg('') return t + def insert_device(self): + self.asi.dev_disk_path.touch() + class CmdTestAutosign(CmdTestAutosignBase): 'autosigning transactions for all supported coins' coins = ['btc','bch','ltc','eth'] daemon_coins = ['btc','bch','ltc'] txfile_coins = ['btc','bch','ltc','eth','mm1','etc'] live = False - simulate = False + simulate_led = False bad_tx_count = 0 cmd_group = ( ('start_daemons', 'starting daemons'), @@ -395,12 +406,12 @@ class CmdTestAutosign(CmdTestAutosignBase): ('copy_msgfiles', 'copying message files'), ('sign_quiet_msg', 'signing transactions and messages (--quiet)'), ('remove_signed_txfiles', 'removing signed transaction files'), - ('create_bad_txfiles', 'creating bad transaction files'), + ('create_bad_txfiles2', 'creating bad transaction files'), ('remove_signed_msgfiles', 'removing signed message files'), ('create_invalid_msgfile', 'creating invalid message file'), ('sign_full_summary_msg', 'signing transactions and messages (--full-summary)'), ('remove_invalid_msgfile', 'removing invalid message file'), - ('remove_bad_txfiles', 'removing bad transaction files'), + ('remove_bad_txfiles2', 'removing bad transaction files'), ('sign_no_unsigned_msg', 'signing transactions and messages (nothing to sign)'), ('stop_daemons', 'stopping daemons'), ) @@ -507,10 +518,10 @@ class CmdTestAutosignLive(CmdTestAutosignBTC): imsg(purple('\nKilling wait loop!')) t.kill(2) # 2 = SIGINT t.req_exit_val = 1 - if self.simulate and led_opts: + if self.simulate_led and led_opts: t.expect("Stopping LED") return t class CmdTestAutosignLiveSimulate(CmdTestAutosignLive): 'live autosigning BTC transactions with simulated LED support' - simulate = True + simulate_led = True diff --git a/test/cmdtest_py_d/ct_xmr_autosign.py b/test/cmdtest_py_d/ct_xmr_autosign.py index 29b04c06..47d11cde 100755 --- a/test/cmdtest_py_d/ct_xmr_autosign.py +++ b/test/cmdtest_py_d/ct_xmr_autosign.py @@ -58,7 +58,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): daemon_coins = [] txfile_coins = [] live = False - simulate = False + simulate_led = False bad_tx_count = 0 tx_relay_user = 'miner' no_insert_check = False @@ -108,8 +108,8 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): def __init__(self,trunner,cfgs,spawn): - CmdTestXMRWallet.__init__(self,trunner,cfgs,spawn) CmdTestAutosignBase.__init__(self,trunner,cfgs,spawn) + CmdTestXMRWallet.__init__(self,trunner,cfgs,spawn) if trunner is None: return @@ -221,9 +221,6 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): def fund_alice2(self): return self.fund_alice(wallet=2) - def insert_device(self): - self.asi.dev_disk_path.touch() - def autosign_setup(self): self.insert_device() Path(self.autosign_xmr_dir).mkdir(parents=True,exist_ok=True) @@ -240,7 +237,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): if self.asi.dev_disk_path.exists(): self.asi.dev_disk_path.unlink() def run(): - t = self.spawn('mmgen-autosign', self.opts + ['wait'], direct_exec=True ) + t = self.spawn('mmgen-autosign', self.opts + ['wait'], direct_exec=True) self.write_to_tmpfile('autosign_thread_pid',str(t.ep.pid)) import threading threading.Thread( target=run, name='Autosign wait loop' ).start() @@ -263,7 +260,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): return self.create_wallets( 'alice', op='restore' ) def restore_wallets(self): - return self.create_wallets( 'alice', op='restore' ) + return self.create_watchonly_wallets() def _create_transfer_tx(self,amt): t = self.do_op('transfer','alice',f'1:0:{self.burn_addr},{amt}',no_relay=True,do_ret=True) @@ -279,6 +276,15 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): get_file_with_ext(self.asi.xmr_tx_dir,'sigtx',delete_all=True) return self._create_transfer_tx('0.257') + def _wait_signed(self,dtype): + oqmsg_r(gray(f'→ offline wallet{"s" if dtype.endswith("s") else ""} signing {dtype}')) + while True: + oqmsg_r(gray('.')) + if not self.asi.dev_disk_path.exists(): + break + time.sleep(0.5) + oqmsg(gray('done')) + def _xmr_autosign_op( self, op, @@ -289,13 +295,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): add_opts = [], wait_signed = False): if wait_signed: - oqmsg_r(gray(f'→ offline wallet{"s" if dtype.endswith("s") else ""} signing {dtype}')) - while True: - oqmsg_r(gray('.')) - if not self.asi.dev_disk_path.exists(): - break - time.sleep(0.5) - oqmsg(gray('done')) + self._wait_signed(dtype) data = self.users['alice'] args = ( self.extra_opts @@ -380,11 +380,12 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): return self._export_outputs('1-2') def _import_key_images(self,wallet_arg): - return self._xmr_autosign_op( + t = self._xmr_autosign_op( op = 'import-key-images', wallet_arg = wallet_arg, dtype = 'wallet outputs', wait_signed = True ) + return t def import_key_images1(self): return self._import_key_images(None) @@ -448,7 +449,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): self.create_fake_tx_files() before = '\n'.join(self._gen_listing()) - t = self.spawn( 'mmgen-autosign', [f'--mountpoint={self.mountpoint}','clean'] ) + t = self.spawn('mmgen-autosign', self.opts + ['clean']) out = t.read() after = '\n'.join(self._gen_listing()) @@ -482,7 +483,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase): def check_tx_dirs(self): before = '\n'.join(self._gen_listing()) - t = self.spawn( 'mmgen-autosign', [f'--mountpoint={self.mountpoint}','clean'] ) + t = self.spawn('mmgen-autosign', self.opts + ['clean']) t.read() after = '\n'.join(self._gen_listing()) imsg(f'\nBefore cleaning:\n{before}') diff --git a/test/cmdtest_py_d/ct_xmrwallet.py b/test/cmdtest_py_d/ct_xmrwallet.py index 15f41ced..ddce2f11 100755 --- a/test/cmdtest_py_d/ct_xmrwallet.py +++ b/test/cmdtest_py_d/ct_xmrwallet.py @@ -124,11 +124,9 @@ class CmdTestXMRWallet(CmdTestBase): from mmgen.protocol import init_proto self.proto = init_proto( cfg, 'XMR', network='mainnet' ) self.extra_opts = ['--wallet-rpc-password=passw0rd'] - self.autosign_mountpoint = os.path.join(self.tmpdir,'mmgen_autosign') self.autosign_xmr_dir = os.path.join(self.tmpdir,'mmgen_autosign','xmr') self.init_users() self.init_daemon_args() - self.autosign_opts = [] for v in self.users.values(): run(['mkdir','-p',v.udir]) @@ -340,9 +338,7 @@ class CmdTestXMRWallet(CmdTestBase): def gen_kafiles(self): for user,data in self.users.items(): - if not data.kal_range: - continue - if data.autosign: + if data.autosign or not data.kal_range: continue run(['mkdir','-p',data.udir]) run(f'rm -f {data.kafile}',shell=True) @@ -394,12 +390,12 @@ class CmdTestXMRWallet(CmdTestBase): data = self.users['alice'] t = self.spawn( 'mmgen-xmrwallet', - self.extra_opts + - [f'--wallet-dir={data.udir}'] + - [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 []) + - ['new', (kafile or data.kafile), spec] ) + self.extra_opts + + [f'--wallet-dir={data.udir}'] + + [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 []) + + ['new', (kafile or data.kafile), spec]) t.expect(expect, 'y', regex=True) return t @@ -467,7 +463,9 @@ class CmdTestXMRWallet(CmdTestBase): cmd_opts = [f'--wallet-dir={data.udir}', f'--daemon=localhost:{data.md.rpc_port}'] t = self.spawn( 'mmgen-xmrwallet', - self.extra_opts + cmd_opts + ['label', data.kafile, label_spec] + self.extra_opts + + cmd_opts + + ['label', data.kafile, label_spec] ) t.expect('(y/N): ','y') t.expect(f'Label successfully {expect}') @@ -492,7 +490,7 @@ class CmdTestXMRWallet(CmdTestBase): 'mmgen-xmrwallet', self.extra_opts + cmd_opts - + self.autosign_opts + + (self.autosign_opts if data.autosign else []) + add_opts + [op] + ([] if data.autosign else [data.kafile]) @@ -536,7 +534,6 @@ class CmdTestXMRWallet(CmdTestBase): [f'--daemon=localhost:{data.md.rpc_port}'], [f'--tx-relay-daemon={tx_relay_parm}', tx_relay_parm], ['--no-relay', no_relay and not data.autosign], - [f'--autosign-mountpoint={self.autosign_mountpoint}', data.autosign], ) add_desc = (', ' + add_desc) if add_desc else '' @@ -544,6 +541,7 @@ class CmdTestXMRWallet(CmdTestBase): 'mmgen-xmrwallet', self.extra_opts + cmd_opts + + (self.autosign_opts if data.autosign else []) + [op] + ([] if data.autosign else [data.kafile]) + [arg2],