From bf3c81ae6c2d75c175db450db7a68e57d35b98c2 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 28 Apr 2023 11:23:24 +0000 Subject: [PATCH] mmgen-autosign: add `clean` op, clean tx dirs on setup --- mmgen/autosign.py | 57 ++++++++++++++++++---- mmgen/data/version | 2 +- mmgen/main_autosign.py | 5 ++ test/test_py_d/ts_xmr_autosign.py | 79 +++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 10 deletions(-) diff --git a/mmgen/autosign.py b/mmgen/autosign.py index 3cd2bea2..6b80887d 100755 --- a/mmgen/autosign.py +++ b/mmgen/autosign.py @@ -29,8 +29,11 @@ class AutosignConfig(Config): class Signable: + signables = ('transaction','message','xmr_transaction','xmr_wallet_outputs_file') + class base: + clean_all = False multiple_ok = True def __init__(self,parent): @@ -152,6 +155,7 @@ class Signable: rawext = 'raw' sigext = 'sig' dir_name = 'xmr_outputs_dir' + clean_all = True async def sign(self,f): from .xmrwallet import MoneroWalletOps,xmrwallet_uargs @@ -255,6 +259,9 @@ 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') @@ -507,18 +514,50 @@ class Autosign: self.xmr_tx_dir.mkdir(exist_ok=True) - from .addrfile import ViewKeyAddrFile - from .fileutil import shred_file - for f in self.xmr_dir.iterdir(): - if f.name.endswith(ViewKeyAddrFile.ext): - msg(f'Shredding old viewkey-address file {f.name!r}') - shred_file(f) - - if len(self.wallet_files) > 1: - ymsg(f'Warning: more that one wallet file, using the first ({self.wallet_files[0]}) for xmrwallet generation') + self.clean_old_files() create_signing_wallets() + def clean_old_files(self): + + def do_shred(f): + nonlocal count + msg_r('.') + shred_file( f, verbose=self.cfg.verbose ) + count += 1 + + def clean_dir(s_name): + + def clean_files(rawext,sigext): + for f in s.dir.iterdir(): + if s.clean_all and (f.name.endswith(f'.{rawext}') or f.name.endswith(f'.{sigext}')): + do_shred(f) + elif f.name.endswith(f'.{sigext}'): + raw = f.parent / ( f.name[:-len(sigext)] + rawext ) + if raw.is_file(): + do_shred(raw) + + s = getattr(Signable,s_name)(asi) + + msg_r(f"Cleaning directory '{s.dir}'..") + + if s.dir.is_dir(): + clean_files( s.rawext, s.sigext ) + if hasattr(s,'subext'): + clean_files( s.rawext, s.subext ) + clean_files( s.sigext, s.subext ) + + msg('done' if s.dir.is_dir() else 'skipped (no dir)') + + asi = get_autosign_obj( self.cfg, 'btc,xmr' ) + count = 0 + + from .fileutil import shred_file + for s_name in Signable.signables: + clean_dir(s_name) + + bmsg(f'{count} file{suf(count)} shredded') + def get_insert_status(self): if self.cfg.no_insert_check: return True diff --git a/mmgen/data/version b/mmgen/data/version index 5ac39dbd..27f7c1ad 100644 --- a/mmgen/data/version +++ b/mmgen/data/version @@ -1 +1 @@ -13.3.dev48 +13.3.dev49 diff --git a/mmgen/main_autosign.py b/mmgen/main_autosign.py index 7a0a7676..946e103a 100755 --- a/mmgen/main_autosign.py +++ b/mmgen/main_autosign.py @@ -36,6 +36,7 @@ opts_data = { -h, --help Print this help message --, --longhelp Print help message for long options (common options) -c, --coins=c Coins to sign for (comma-separated list) +-C, --clean Remove unneeded files on the removable device -I, --no-insert-check Don’t check for device insertion -l, --led Use status LED to signal standby, busy and error -m, --mountpoint=M Specify an alternate mountpoint 'M' @@ -192,6 +193,10 @@ if cmd_args: asi.xmr_setup() elif cmd == 'wait': main(do_loop=True) + elif cmd == 'clean': + asi.do_mount() + asi.clean_old_files() + asi.do_umount() else: die(1,f'{cmd!r}: unrecognized command') else: diff --git a/test/test_py_d/ts_xmr_autosign.py b/test/test_py_d/ts_xmr_autosign.py index f40db0f4..6ae891f0 100755 --- a/test/test_py_d/ts_xmr_autosign.py +++ b/test/test_py_d/ts_xmr_autosign.py @@ -55,6 +55,7 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase): ('new_address_alice_label', 'adding an address to Alice’s tmp wallet (with label)'), ('dump_tmp_wallets', 'dumping Alice’s tmp wallets'), ('delete_tmp_wallets', 'deleting Alice’s tmp wallets'), + ('clean', 'cleaning signable file directories'), ('autosign_setup', 'autosign setup with Alice’s seed'), ('create_watchonly_wallets', 'creating online (watch-only) wallets for Alice'), ('delete_tmp_dump_files', 'deleting Alice’s dump files'), @@ -279,3 +280,81 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase): return self._xmr_autosign_op( op = 'import-key-images', desc = 'importing key images' ) + + def create_fake_tx_files(self): + imsg('Creating fake transaction files') + + self.asi.msg_dir.mkdir(exist_ok=True) + self.asi.xmr_dir.mkdir(exist_ok=True) + self.asi.xmr_tx_dir.mkdir(exist_ok=True) + self.asi.xmr_outputs_dir.mkdir(exist_ok=True) + + for fn in ( + 'a.rawtx', 'a.sigtx', + 'b.rawtx', 'b.sigtx', + 'c.rawtx', + 'd.sigtx', + ): + (self.asi.tx_dir / fn).touch() + + for fn in ( + 'a.rawmsg.json', 'a.sigmsg.json', + 'b.rawmsg.json', + 'c.sigmsg.json', + 'd.rawmsg.json', 'd.sigmsg.json', + ): + (self.asi.msg_dir / fn).touch() + + for fn in ( + 'a.rawtx', 'a.sigtx', 'a.subtx', + 'b.rawtx', 'b.sigtx', + 'c.subtx', + 'd.rawtx', 'd.subtx', + 'e.rawtx', + 'f.sigtx','f.subtx', + ): + (self.asi.xmr_tx_dir / fn).touch() + + for fn in ( + 'a.raw', 'a.sig', + 'b.raw', + 'c.sig', + ): + (self.asi.xmr_outputs_dir / fn).touch() + + return 'ok' + + def clean(self): + + def gen_listing(): + for k in ('tx_dir','msg_dir','xmr_tx_dir','xmr_outputs_dir'): + d = getattr(self.asi,k) + if d.is_dir(): + yield '{:12} {}'.format( + str(Path(*d.parts[4:])) + ':', + ' '.join(sorted(i.name for i in d.iterdir()))).strip() + + self.create_fake_tx_files() + before = '\n'.join(gen_listing()) + + t = self.spawn( 'mmgen-autosign', [f'--mountpoint={self.mountpoint}','clean'] ) + out = t.read() + + after = '\n'.join(gen_listing()) + chk = """ + tx: a.sigtx b.sigtx c.rawtx d.sigtx + msg: a.sigmsg.json b.rawmsg.json c.sigmsg.json d.sigmsg.json + xmr/tx: a.subtx b.sigtx c.subtx d.subtx e.rawtx f.subtx + xmr/outputs: + """ + + shutil.rmtree(self.asi.mountpoint) + self.asi.tx_dir.mkdir(parents=True) + + imsg(f'\nBefore cleaning:\n{before}') + imsg(f'\nAfter cleaning:\n{after}') + + assert '13 files shredded' in out + assert after + '\n' == fmt(chk), f'\n{after}\n!=\n{fmt(chk)}' + + return t