fixes and cleanups throughout

This commit is contained in:
The MMGen Project 2025-06-21 11:14:08 +00:00
commit 5409ef4c2d
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
11 changed files with 79 additions and 55 deletions

View file

@ -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):

View file

@ -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)

View file

@ -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)

View file

@ -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 = ' '

View file

@ -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:

View file

@ -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)

View file

@ -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)

View file

@ -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])

View file

@ -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

View file

@ -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,

View file

@ -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):