From 5409ef4c2da4caf6435254f386ef0928e3c864e4 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 21 Jun 2025 11:14:08 +0000 Subject: [PATCH] fixes and cleanups throughout --- mmgen/autosign.py | 16 +++++++--------- mmgen/crypto.py | 8 ++++---- mmgen/main_autosign.py | 6 +++--- mmgen/tx/base.py | 4 ++-- mmgen/tx/keys.py | 12 +++++++----- mmgen/tx/new.py | 2 +- mmgen/xmrwallet/ops/create.py | 2 +- test/cmdtest_d/automount.py | 11 +++++------ test/cmdtest_d/autosign.py | 27 ++++++++++++++++----------- test/cmdtest_d/regtest.py | 16 ++++++++++------ test/cmdtest_d/swap.py | 28 ++++++++++++++++++++++------ 11 files changed, 78 insertions(+), 54 deletions(-) diff --git a/mmgen/autosign.py b/mmgen/autosign.py index 243e0a1a..57be8ffc 100755 --- a/mmgen/autosign.py +++ b/mmgen/autosign.py @@ -23,6 +23,7 @@ from .color import yellow, red, orange, brown, blue from .wallet import Wallet, get_wallet_cls from .addrlist import AddrIdxList from .filename import find_file_in_dir +from .fileutil import shred_file from .ui import keypress_confirm def SwapMgr(*args, **kwargs): @@ -239,10 +240,9 @@ class Signable: suf(files), fmt_list(map(str, files), fmt='col', indent=' ')), do_exit = True) - for f in files: - msg(f'Shredding file ‘{f}’') - from .fileutil import shred_file - shred_file(f) + for fn in files: + msg(f'Shredding file ‘{fn}’') + shred_file(fn) sys.exit(0) async def get_last_created(self): @@ -276,7 +276,7 @@ class Signable: tx1, seedfiles = self.parent.wallet_files[:], passwdfile = str(self.parent.keyfile), - auto = True).keys) + autosign = True).keys) if tx2: tx2.file.write(ask_write=False, outdir=self.dir) return tx2 @@ -693,7 +693,6 @@ class Autosign: def wipe_encryption_key(self): if self.keyfile.exists(): - from .fileutil import shred_file ymsg(f'Shredding wallet encryption key ‘{self.keyfile}’') shred_file(self.keyfile, verbose=self.cfg.verbose) else: @@ -818,11 +817,10 @@ class Autosign: def clean_old_files(self): - def do_shred(f): + def do_shred(fn): nonlocal count msg_r('.') - from .fileutil import shred_file - shred_file(f, verbose=self.cfg.verbose) + shred_file(fn, verbose=self.cfg.verbose) count += 1 def clean_dir(s_name): diff --git a/mmgen/crypto.py b/mmgen/crypto.py index 85f4a0e5..a212c1bd 100755 --- a/mmgen/crypto.py +++ b/mmgen/crypto.py @@ -399,7 +399,7 @@ class Crypto: from .ui import get_words_from_user return ' '.join(get_words_from_user(self.cfg, f'Enter {pw_desc} for {data_desc}: ')) - def mmgen_encrypt(self, data, *, desc='data', hash_preset=None): + def mmgen_encrypt(self, data, *, passwd=None, desc='data', hash_preset=None): salt = self.get_random(self.mmenc_salt_len) iv = self.get_random(self.aesctr_iv_len) nonce = self.get_random(self.mmenc_nonce_len) @@ -407,7 +407,7 @@ class Crypto: m = ('user-requested', 'default')[hp=='3'] self.util.vmsg(f'Encrypting {desc}') self.util.qmsg(f'Using {m} hash preset of {hp!r}') - passwd = self.get_new_passphrase( + passwd = passwd or self.get_new_passphrase( data_desc = desc, hash_preset = hp, passwd_file = self.cfg.passwd_file) @@ -416,7 +416,7 @@ class Crypto: enc_d = self.encrypt_data(sha256(nonce+data).digest() + nonce + data, key=key, iv=iv, desc=desc) return salt+iv+enc_d - def mmgen_decrypt(self, data, *, desc='data', hash_preset=None): + def mmgen_decrypt(self, data, *, passwd=None, desc='data', hash_preset=None): self.util.vmsg(f'Preparing to decrypt {desc}') dstart = self.mmenc_salt_len + self.aesctr_iv_len salt = data[:self.mmenc_salt_len] @@ -425,7 +425,7 @@ class Crypto: hp = hash_preset or self.cfg.hash_preset or self.get_hash_preset_from_user(data_desc=desc) m = ('user-requested', 'default')[hp=='3'] self.util.qmsg(f'Using {m} hash preset of {hp!r}') - passwd = self.get_passphrase( + passwd = passwd or self.get_passphrase( data_desc = desc, passwd_file = self.cfg.passwd_file) key = self.make_key(passwd, salt, hp) diff --git a/mmgen/main_autosign.py b/mmgen/main_autosign.py index f5d6c395..7310ed3c 100755 --- a/mmgen/main_autosign.py +++ b/mmgen/main_autosign.py @@ -202,14 +202,14 @@ if cmd not in Autosign.cmds + Autosign.util_cmds: die(1, f'‘{cmd}’: unrecognized command') if cmd != 'setup': - for opt in ('seed_len', 'mnemonic_fmt'): + for opt in ('seed_len', 'mnemonic_fmt', 'keys_from_file'): if getattr(cfg, opt): - die(1, f'--{opt.replace("_", "-")} makes sense only for the ‘setup’ operation') + die(1, f'--{opt.replace("_", "-")} is valid only for the ‘setup’ operation') if cmd not in ('sign', 'wait'): for opt in ('no_summary', 'led', 'stealth_led', 'full_summary'): if getattr(cfg, opt): - die(1, f'--{opt.replace("_", "-")} makes no sense for the ‘{cmd}’ operation') + die(1, f'--{opt.replace("_", "-")} is not valid for the ‘{cmd}’ operation') asi = Autosign(cfg, cmd=cmd) diff --git a/mmgen/tx/base.py b/mmgen/tx/base.py index eabfb383..98c97619 100755 --- a/mmgen/tx/base.py +++ b/mmgen/tx/base.py @@ -99,7 +99,7 @@ class Base(MMGenObject): as autosigning does not support the use of key files. Non-{gc.proj_name} addresses found in inputs: - {{}} + {{}} """ class Input(MMGenTxIO): @@ -212,7 +212,7 @@ class Base(MMGenObject): edesc = 'non-MMGen address', quiet = True) - def check_non_mmgen_inputs(self, caller, *, non_mmaddrs=None): + def check_non_mmgen_inputs(self, *, caller, non_mmaddrs=None): non_mmaddrs = non_mmaddrs or self.get_non_mmaddrs('inputs') if non_mmaddrs: indent = ' ' diff --git a/mmgen/tx/keys.py b/mmgen/tx/keys.py index 8ddf42d0..fc262640 100755 --- a/mmgen/tx/keys.py +++ b/mmgen/tx/keys.py @@ -82,12 +82,12 @@ class TxKeys: keylist = None, keyaddrlist = None, passwdfile = None, - auto = False): + autosign = False): self.cfg = cfg self.tx = tx self.seedfiles = seedfiles or pop_seedfiles(cfg) - self.keylist = None if auto else keylist or get_keylist(cfg) - self.keyaddrlist = None if auto else keyaddrlist or get_keyaddrlist(cfg, tx.proto) + self.keylist = keylist if autosign else keylist or get_keylist(cfg) + self.keyaddrlist = keyaddrlist if autosign else keyaddrlist or get_keyaddrlist(cfg, tx.proto) self.passwdfile = passwdfile self.saved_seeds = {} @@ -95,7 +95,9 @@ class TxKeys: err_fs = 'ERROR: a key file must be supplied for the following non-{} address{}:{}' sep = '\n ' if addrs := self.tx.get_non_mmaddrs('inputs'): - self.tx.check_non_mmgen_inputs(caller='txsign', non_mmaddrs=addrs) + self.tx.check_non_mmgen_inputs( + caller = 'txsign', + non_mmaddrs = addrs) kal = KeyAddrList( cfg = self.cfg, proto = self.tx.proto, @@ -209,7 +211,7 @@ class TxKeys: ret = self.get_keys_for_non_mmgen_inputs() memo_output = self.tx.check_swap_memo() # do this for non-swap transactions too! - if self.cfg.mmgen_keys_from_file: + if self.keyaddrlist: ret += self.add_keys('inputs', self.tx.inputs, from_keyaddrlist=True) self.add_keys('outputs', self.tx.outputs, from_keyaddrlist=True) if memo_output: diff --git a/mmgen/tx/new.py b/mmgen/tx/new.py index 27c645d4..e8f4da9b 100755 --- a/mmgen/tx/new.py +++ b/mmgen/tx/new.py @@ -508,7 +508,7 @@ class New(Base): desc)) is not None: break - self.check_non_mmgen_inputs(caller) + self.check_non_mmgen_inputs(caller=caller) self.update_change_output(funds_left) diff --git a/mmgen/xmrwallet/ops/create.py b/mmgen/xmrwallet/ops/create.py index ba3f0e90..7116df29 100755 --- a/mmgen/xmrwallet/ops/create.py +++ b/mmgen/xmrwallet/ops/create.py @@ -78,7 +78,7 @@ class OpCreateOffline(OpCreate): for f in Path(self.asi.xmr_dir).iterdir(): if f.name.endswith(vkf.ext): from ...fileutil import shred_file - msg(f"\nShredding old viewkey-address file '{f}'") + msg(f'\nShredding old viewkey-address file ‘{f}’') shred_file(f, verbose=self.cfg.verbose) vkf.write(outdir=self.asi.xmr_dir) diff --git a/test/cmdtest_d/automount.py b/test/cmdtest_d/automount.py index 3da8f919..0b442afd 100755 --- a/test/cmdtest_d/automount.py +++ b/test/cmdtest_d/automount.py @@ -27,6 +27,10 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): rt_data = { 'rtFundAmt': {'btc':'500', 'bch':'500', 'ltc':'5500'}, } + bal2_chk = { + 'btc': '491.11002204', + 'bch': '498.7653392', + 'ltc': '5491.11002204'} cmd_group = ( ('setup', 'regtest mode setup'), @@ -267,9 +271,4 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): output_args = ['data:message for posterity', f'{self.burn_addr},7.654321', f'{sid}:C:1']) def alice_bal2(self): - bals = { - 'btc': '491.11002204', - 'ltc': '5491.11002204', - 'bch': '498.7653392', - } - return self.user_bal('alice', bals.get(self.coin, None)) + return self.user_bal('alice', self.bal2_chk[self.coin]) diff --git a/test/cmdtest_d/autosign.py b/test/cmdtest_d/autosign.py index e191365e..f7e15d48 100755 --- a/test/cmdtest_d/autosign.py +++ b/test/cmdtest_d/autosign.py @@ -196,7 +196,8 @@ class CmdTestAutosignBase(CmdTestBase): use_dfl_wallet = False, seed_len = None, usr_entry_modes = False, - passwd = 'abc', + wallet_passwd = None, + add_opts = [], expect_args = []): mn_desc = mn_type or 'default' @@ -209,7 +210,7 @@ class CmdTestAutosignBase(CmdTestBase): t = self.spawn( 'mmgen-autosign', - self.opts + self.opts + add_opts + ([] if mn_desc == 'default' else [f'--mnemonic-fmt={mn_type}']) + ([f'--seed-len={seed_len}'] if seed_len else []) + ['setup'], @@ -217,7 +218,7 @@ class CmdTestAutosignBase(CmdTestBase): if use_dfl_wallet: t.expect('Use default wallet for autosigning? (Y/n): ', 'y') - t.passphrase('MMGen wallet', passwd) + t.passphrase('MMGen wallet', wallet_passwd) else: if use_dfl_wallet is not None: # None => no dfl wallet present t.expect('Use default wallet for autosigning? (Y/n): ', 'n') @@ -447,11 +448,13 @@ class CmdTestAutosignThreaded(CmdTestAutosignBase): self, user, progname = 'txcreate', - input_handler = None, + ui_handler = None, chg_addr = None, opts = [], output_args = [], exit_val = 0, + inputs = '1', + tweaks = [], expect_str = None, data_arg = None, need_rbf = False): @@ -486,10 +489,11 @@ class CmdTestAutosignThreaded(CmdTestAutosignBase): if exit_val: return do_return() - t = (input_handler or self.txcreate_ui_common)( + t = (ui_handler or self.txcreate_ui_common)( t, - inputs = '1', + inputs = inputs, interactive_fee = '32s', + tweaks = tweaks, file_desc = 'Unsigned automount transaction') return do_return() @@ -615,6 +619,7 @@ class CmdTestAutosign(CmdTestAutosignBase): live = False simulate_led = True no_insert_check = True + wallet_passwd = 'abc' filedir_map = ( ('btc', ''), @@ -719,7 +724,7 @@ class CmdTestAutosign(CmdTestAutosignBase): 'test/ref/98831F3A.hex' ] ) - t.passphrase_new('new MMGen wallet', 'abc') + t.passphrase_new('new MMGen wallet', self.wallet_passwd) t.written_to_file('MMGen wallet') return t @@ -729,16 +734,16 @@ class CmdTestAutosign(CmdTestAutosignBase): return t def bad_opt1(self): - return self._bad_opt(['--seed-len=128'], 'makes sense') + return self._bad_opt(['--seed-len=128'], 'is valid') def bad_opt2(self): - return self._bad_opt(['--mnemonic-fmt=bip39', 'wait'], 'makes sense') + return self._bad_opt(['--mnemonic-fmt=bip39', 'wait'], 'is valid') def bad_opt3(self): - return self._bad_opt(['--led', 'gen_key'], 'makes no sense') + return self._bad_opt(['--led', 'gen_key'], 'is not valid') def run_setup_dfl_wallet(self): - return self.run_setup(mn_type='default', use_dfl_wallet=True) + return self.run_setup(mn_type='default', use_dfl_wallet=True, wallet_passwd=self.wallet_passwd) def run_setup_bip39(self): from mmgen.cfgfile import mmgen_cfg_file diff --git a/test/cmdtest_d/regtest.py b/test/cmdtest_d/regtest.py index adcd03dd..9b446590 100755 --- a/test/cmdtest_d/regtest.py +++ b/test/cmdtest_d/regtest.py @@ -707,7 +707,7 @@ class CmdTestRegtest(CmdTestBase, CmdTestShared): [f'{addr},{rtFundAmt}', self.burn_addr], utxo_nums, extra_args = [f'--keys-from-file={keyfile}'], - tweaks = 'confirm_chg_non_mmgen', + tweaks = ['confirm_chg_non_mmgen'], skip_passphrase = skip_passphrase) def fund_bob_deterministic(self): @@ -745,23 +745,27 @@ class CmdTestRegtest(CmdTestBase, CmdTestShared): return 'skip' return self.addrimport('bob', add_opts=['--rescan']) - def fund_wallet(self, user, mmtype, amt, sid=None, addr_range='1-5', proto=None): + def fund_wallet(self, user, amt, *, addr=None, mmtype=None, sid=None, addr_range='1-5', proto=None): proto = proto or self.proto if self.deterministic: return 'skip' if not sid: sid = self._user_sid(user) - addr = self.get_addr_from_addrlist(user, sid, mmtype, 0, addr_range=addr_range, proto=proto) - t = self.spawn('mmgen-regtest', [f'--coin={proto.coin}', 'send', str(addr), str(amt)], no_passthru_opts=True) + addr = addr or self.get_addr_from_addrlist( + user, sid, mmtype, 0, addr_range=addr_range, proto=proto) + t = self.spawn( + 'mmgen-regtest', + [f'--coin={proto.coin}', 'send', str(addr), str(amt)], + no_passthru_opts = True) t.expect(f'Sending {amt} miner {proto.coin}') t.expect('Mined 1 block') return t def fund_bob(self): - return self.fund_wallet('bob', 'C', rtFundAmt) + return self.fund_wallet('bob', rtFundAmt, mmtype='C') def fund_alice(self): - return self.fund_wallet('alice', ('L', 'S')[self.proto.cap('segwit')], rtFundAmt) + return self.fund_wallet('alice', rtFundAmt, mmtype=('L', 'S')[self.proto.cap('segwit')]) def user_twview( self, diff --git a/test/cmdtest_d/swap.py b/test/cmdtest_d/swap.py index d54b6d40..619d907f 100755 --- a/test/cmdtest_d/swap.py +++ b/test/cmdtest_d/swap.py @@ -74,7 +74,7 @@ class CmdTestSwapMethods: return self.addrimport('bob', mmtypes=['S', 'B'], proto=self.protos[proto_idx]) def _fund_bob(self, proto_idx, addrtype_code, amt): - return self.fund_wallet('bob', addrtype_code, amt, proto=self.protos[proto_idx]) + return self.fund_wallet('bob', amt, mmtype=addrtype_code, proto=self.protos[proto_idx]) def _bob_bal(self, proto_idx, bal, skip_check=False): return self.user_bal('bob', bal, proto=self.protos[proto_idx], skip_check=skip_check) @@ -142,6 +142,7 @@ class CmdTestSwapMethods: inputs = '1', interactive_fee = None, file_desc = 'Unsigned transaction', + tweaks = [], reload_quote = False, sign_and_send = False, need_passphrase = True, @@ -238,10 +239,25 @@ class CmdTestSwapMethods: exit_val = exit_val) return self._swaptxbump_ui_common(t, interactive_fee=fee, new_outputs=bool(output_args)) - def _swaptxbump_ui_common_new_outputs(self, t, *, inputs=None, interactive_fee=None, file_desc=None): - return self._swaptxbump_ui_common(t, interactive_fee=interactive_fee, new_outputs=True) + def _swaptxbump_ui_common_new_outputs( + self, + t, + *, + tweaks = [], + inputs = None, + interactive_fee = None, + file_desc = None): + return self._swaptxbump_ui_common( + t, + inputs = inputs, + interactive_fee = interactive_fee, + file_desc = file_desc, + new_outputs = True) - def _swaptxbump_ui_common(self, t, *, + def _swaptxbump_ui_common( + self, + t, + *, inputs = None, interactive_fee = None, file_desc = None, @@ -780,7 +796,7 @@ class CmdTestSwap(CmdTestSwapMethods, CmdTestRegtest, CmdTestAutosignThreaded): return self._user_txcreate( 'bob', progname = 'swaptxcreate', - input_handler = self._swaptxcreate_ui_common, + ui_handler = self._swaptxcreate_ui_common, output_args = ['BTC', '8.88', f'{self.sid}:S:3', 'LTC', f'{self.sid}:S:3']) def autosign_swaptxsend1(self): @@ -790,7 +806,7 @@ class CmdTestSwap(CmdTestSwapMethods, CmdTestRegtest, CmdTestAutosignThreaded): return self._user_txcreate( 'bob', progname = 'txbump', - input_handler = self._swaptxbump_ui_common_new_outputs, + ui_handler = self._swaptxbump_ui_common_new_outputs, output_args = [f'{self.sid}:S:3']) def autosign_swaptxsend2(self):