Browse Source

whitespace, comments, docstrings (test suite)

The MMGen Project 1 year ago
parent
commit
01430166e5

+ 4 - 0
scripts/create-token.py

@@ -16,6 +16,10 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+scripts/create-token.py: Automated ERC20 token creation for the MMGen suite
+"""
+
 import sys,os,json,re
 from subprocess import run,PIPE
 from collections import namedtuple

+ 13 - 1
scripts/exec_wrapper.py

@@ -1,4 +1,16 @@
 #!/usr/bin/env python3
+#
+# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
+# Copyright (C)2013-2023 The MMGen Project <mmgen@tuta.io>
+# Licensed under the GNU General Public License, Version 3:
+#   https://www.gnu.org/licenses
+# Public project repositories:
+#   https://github.com/mmgen/mmgen
+#   https://gitlab.com/mmgen/mmgen
+
+"""
+scripts/exec_wrapper.py: wrapper to launch MMGen scripts in a testing environment
+"""
 
 # Import as few modules and define as few names as possible at module level before exec'ing the
 # file, as all names will be seen by the exec'ed code.  To prevent name collisions, all names
@@ -14,7 +26,7 @@ def exec_wrapper_get_colors():
 def exec_wrapper_init():
 
 	if exec_wrapper_os.path.dirname(exec_wrapper_sys.argv[1]) == 'test':
-		'support running of test scripts under wrapper'
+		# support running of test scripts under wrapper
 		cwd = exec_wrapper_os.getcwd() # assume we’re in repo root
 		exec_wrapper_sys.path[0] = cwd
 		exec_wrapper_sys.path[1] = exec_wrapper_os.path.join(cwd,'test')

+ 1 - 3
scripts/gendiff.py

@@ -53,9 +53,7 @@ if len(fns) != 2:
 cleaned_texts = [cleanup_file(fn) for fn in fns]
 
 if len(fns) == 2:
-	"""
-	chunk headers have trailing newlines, hence the rstrip()
-	"""
+	# chunk headers have trailing newlines, hence the rstrip()
 	sys.stderr.write('Generating diff\n')
 	print(
 		f'diff a/{fns[0]} b/{fns[1]}\n' +

+ 22 - 4
test/gentest.py

@@ -200,7 +200,8 @@ class GenToolPycoin(GenTool):
 		try:
 			from pycoin.networks.registry import network_for_netcode
 		except:
-			raise ImportError('Unable to import pycoin.networks.registry. Is pycoin installed on your system?')
+			raise ImportError(
+				'Unable to import pycoin.networks.registry. Is pycoin installed on your system?')
 		self.nfnc = network_for_netcode
 
 	def run(self,sec,vcoin):
@@ -233,7 +234,8 @@ class GenToolMonero_python(GenTool):
 		try:
 			from monero.seed import Seed
 		except:
-			raise ImportError('Unable to import monero-python. Is monero-python installed on your system?')
+			raise ImportError(
+				'Unable to import monero-python. Is monero-python installed on your system?')
 		self.Seed = Seed
 
 	def run(self,sec,vcoin):
@@ -393,9 +395,25 @@ def ab_test(proto,scfg):
 
 	if scfg.all_backends: # check all backends against external tool
 		for n in range(len(get_backends(addr_type.pubkey_type))):
-			do_ab_test( proto, scfg, addr_type, gen1=n+1, kg2=kg2, ag=ag, tool=tool, cache_data=scfg.rounds < 1000 and not n )
+			do_ab_test(
+					proto,
+					scfg,
+					addr_type,
+					gen1       = n+1,
+					kg2        = kg2,
+					ag         = ag,
+					tool       = tool,
+					cache_data = scfg.rounds < 1000 and not n)
 	else:                # check specific backend against external tool or another backend
-		do_ab_test( proto, scfg, addr_type, gen1=scfg.gen1, kg2=kg2, ag=ag, tool=tool, cache_data=False )
+		do_ab_test(
+				proto,
+				scfg,
+				addr_type,
+				gen1       = scfg.gen1,
+				kg2        = kg2,
+				ag         = ag,
+				tool       = tool,
+				cache_data = False)
 
 def speed_test(proto,kg,ag,rounds):
 	qmsg(green('Testing speed of address generator {!r} for coin {}'.format(

+ 8 - 4
test/hashfunc.py

@@ -29,10 +29,13 @@ test = sys.argv[1].capitalize()
 assert test in ('Sha256','Sha512','Keccak'), "Valid choices for test are 'sha256','sha512' or 'keccak'"
 random_rounds = int(sys.argv[2]) if len(sys.argv) == 3 else 500
 
-def msg(s): sys.stderr.write(s)
-def green(s): return '\033[32;1m' + s + '\033[0m'
+def msg(s):
+	sys.stderr.write(s)
 
-class TestHashFunc(object):
+def green(s):
+	return '\033[32;1m' + s + '\033[0m'
+
+class TestHashFunc:
 
 	def test_constants(self):
 		msg('Testing generated constants: ')
@@ -122,7 +125,8 @@ class TestKeccak(TestHashFunc):
 			import sha3
 			self.hashlib = sha3
 
-	def test_constants(self): pass
+	def test_constants(self):
+		pass
 
 class TestSha2(TestHashFunc):
 

+ 12 - 6
test/include/common.py

@@ -124,8 +124,10 @@ def getrandstr(num_chars,no_space=False):
 def cleandir(d,do_msg=False):
 	d_enc = d.encode()
 
-	try:    files = os.listdir(d_enc)
-	except: return
+	try:
+		files = os.listdir(d_enc)
+	except:
+		return
 
 	from shutil import rmtree
 	if do_msg:
@@ -187,8 +189,10 @@ def cmp_or_die(s,t,desc=None):
 def init_coverage():
 	coverdir = os.path.join('test','trace')
 	acc_file = os.path.join('test','trace.acc')
-	try: os.mkdir(coverdir,0o755)
-	except: pass
+	try:
+		os.mkdir(coverdir,0o755)
+	except:
+		pass
 	return coverdir,acc_file
 
 def silence():
@@ -283,8 +287,10 @@ def check_solc_ver():
 def get_ethkey():
 	cmdnames = ('ethkey','openethereum-ethkey')
 	for cmdname in cmdnames:
-		try: run([cmdname,'--help'],stdout=PIPE)
-		except: pass
+		try:
+			run([cmdname,'--help'],stdout=PIPE)
+		except:
+			pass
 		else:
 			return cmdname
 	else:

+ 9 - 3
test/include/pexpect.py

@@ -70,8 +70,13 @@ class MMGenPexpect:
 			if cfg.exact_output:
 				self.p.logfile = sys.stdout
 
-	def do_decrypt_ka_data(self,hp,pw,desc='key-address data',check=True,have_yes_opt=False):
-#		self.hash_preset(desc,hp)
+	def do_decrypt_ka_data(
+			self,
+			hp,
+			pw,
+			desc         = 'key-address data',
+			check        = True,
+			have_yes_opt = False):
 		self.passphrase(desc,pw)
 		if not have_yes_opt:
 			self.expect('Check key-to-address validity? (y/N): ',('n','y')[check])
@@ -127,7 +132,8 @@ class MMGenPexpect:
 		self.expect('Repeat passphrase: ',passphrase+'\n')
 
 	def passphrase(self,desc,passphrase,pwtype=''):
-		if pwtype: pwtype += ' '
+		if pwtype:
+			pwtype += ' '
 		self.expect(f'Enter {pwtype}passphrase for {desc}.*?: ',passphrase+'\n',regex=True)
 
 	def hash_preset(self,desc,preset=''):

+ 4 - 2
test/objattrtest.py

@@ -81,7 +81,8 @@ def get_descriptor_obj(objclass,attrname):
 
 def test_attr_perm(obj,attrname,perm_name,perm_value,dobj,attrval_type):
 
-	class SampleObjError(Exception): pass
+	class SampleObjError(Exception):
+		pass
 
 	pname = perm_name.replace('_ok','')
 	pstem = pname.rstrip('e')
@@ -168,7 +169,8 @@ def do_loop():
 
 	utests = cfg._args
 	for obj in test_data:
-		if utests and obj not in utests: continue
+		if utests and obj not in utests:
+			continue
 		msg((blue if cfg.verbose else nocolor)(f'Testing {obj}'))
 		test_object(mod,test_data,obj)
 

+ 11 - 5
test/objtest.py

@@ -116,8 +116,11 @@ def run_test(mod,test,arg,input_data,arg1,exc_name):
 
 		bad_ret = list() if issubclass(cls,list) else None
 
-		if isinstance(ret_chk,str): ret_chk = ret_chk.encode()
-		if isinstance(ret,str): ret = ret.encode()
+		if isinstance(ret_chk,str):
+			ret_chk = ret_chk.encode()
+
+		if isinstance(ret,str):
+			ret = ret.encode()
 
 		if cfg.getobj:
 			if input_data == 'bad':
@@ -141,8 +144,10 @@ def run_test(mod,test,arg,input_data,arg1,exc_name):
 		if cfg.getobj and (not cfg.silent and input_data == 'bad'):
 			pass
 		else:
-			try: ret_disp = ret.decode()
-			except: ret_disp = ret
+			try:
+				ret_disp = ret.decode()
+			except:
+				ret_disp = ret
 			msg(f'==> {ret_disp!r}')
 
 		if cfg.verbose and issubclass(cls,MMGenObject):
@@ -180,7 +185,8 @@ def do_loop():
 	utests = cfg._args
 	for test in test_data:
 		arg1 = test_data[test].get('arg1')
-		if utests and test not in utests: continue
+		if utests and test not in utests:
+			continue
 		nl = ('\n','')[bool(cfg.super_silent) or clr == None]
 		clr = (blue,nocolor)[bool(cfg.super_silent)]
 

+ 4 - 2
test/overlay/fakemods/mmgen/tw/view.py

@@ -15,8 +15,10 @@ if overlay_fake_os.getenv('MMGEN_TEST_SUITE_DETERMINISTIC'):
 
 	TwView.date_formatter = {
 		'days':      lambda rpc,secs: (next(overlay_fake_data.time_iter) - secs) // 86400,
-		'date':      lambda rpc,secs: '{}-{:02}-{:02}'.format(*time.gmtime(next(overlay_fake_data.time_iter))[:3])[2:],
-		'date_time': lambda rpc,secs: '{}-{:02}-{:02} {:02}:{:02}'.format(*time.gmtime(next(overlay_fake_data.time_iter))[:5]),
+		'date':      lambda rpc,secs: '{}-{:02}-{:02}'.format(
+			*time.gmtime(next(overlay_fake_data.time_iter))[:3])[2:],
+		'date_time': lambda rpc,secs: '{}-{:02}-{:02} {:02}:{:02}'.format(
+			*time.gmtime(next(overlay_fake_data.time_iter))[:5]),
 	}
 
 if overlay_fake_os.getenv('MMGEN_BOGUS_UNSPENT_DATA'):

+ 29 - 19
test/test.py

@@ -32,10 +32,13 @@ def create_shm_dir(data_dir,trash_dir):
 	from subprocess import run
 	if gc.platform == 'win':
 		for tdir in (data_dir,trash_dir):
-			try: os.listdir(tdir)
-			except: pass
+			try:
+				os.listdir(tdir)
+			except:
+				pass
 			else:
-				try: shutil.rmtree(tdir)
+				try:
+					shutil.rmtree(tdir)
 				except: # we couldn't remove data dir - perhaps regtest daemon is running
 					try:
 						run(['python3',os.path.join('cmds','mmgen-regtest'),'stop'],check=True)
@@ -191,8 +194,10 @@ data_dir = Config.test_datadir
 
 # step 1: delete data_dir symlink in ./test;
 if not po.user_opts.get('skipping_deps'):
-	try: os.unlink(data_dir)
-	except: pass
+	try:
+		os.unlink(data_dir)
+	except:
+		pass
 
 # step 2: opts.init will create new data_dir in ./test (if not cfg.skipping_deps)
 cfg = Config(opts_data=opts_data)
@@ -589,18 +594,20 @@ class TestSuiteRunner(object):
 		else:
 			self.spawn_env['MMGEN_COLUMNS'] = '120'
 
-	def spawn_wrapper(self,cmd,
-			args         = [],
-			extra_desc   = '',
-			no_output    = False,
-			msg_only     = False,
-			no_msg       = False,
-			cmd_dir      = 'cmds',
+	def spawn_wrapper(
+			self,
+			cmd,
+			args            = [],
+			extra_desc      = '',
+			no_output       = False,
+			msg_only        = False,
+			no_msg          = False,
+			cmd_dir         = 'cmds',
 			no_exec_wrapper = False,
-			timeout       = None,
-			pexpect_spawn = None,
-			direct_exec   = False,
-			env           = {} ):
+			timeout         = None,
+			pexpect_spawn   = None,
+			direct_exec     = False,
+			env             = {}):
 
 		desc = self.ts.test_name if cfg.names else self.gm.dpy_data[self.ts.test_name][1]
 		if extra_desc:
@@ -821,11 +828,13 @@ class TestSuiteRunner(object):
 
 		self.end_msg()
 
-	def check_needs_rerun(self,cmd,
+	def check_needs_rerun(
+			self,
+			cmd,
 			build        = False,
 			root         = True,
 			force_delete = False,
-			dpy          = False ):
+			dpy          = False):
 
 		self.ts.test_name = cmd
 
@@ -842,7 +851,8 @@ class TestSuiteRunner(object):
 				for ext in ret[1]:
 					fn = get_file_with_ext(cfgs[ret[0]]['tmpdir'],ext,delete=build)
 					if fn:
-						if force_delete: os.unlink(fn)
+						if force_delete:
+							os.unlink(fn)
 						else: fns.append(fn)
 					else: rerun = True
 

+ 12 - 6
test/test_py_d/ts_autosign.py

@@ -78,13 +78,17 @@ def check_mountpoint(asi):
 
 def do_mount(mountpoint):
 	if not os.path.ismount(mountpoint):
-		try: run(['mount',mountpoint],check=True)
-		except: pass
+		try:
+			run(['mount',mountpoint],check=True)
+		except:
+			pass
 
 def do_umount(mountpoint):
 	if os.path.ismount(mountpoint):
-		try: run(['umount',mountpoint],check=True)
-		except: pass
+		try:
+			run(['umount',mountpoint],check=True)
+		except:
+			pass
 
 class TestSuiteAutosignBase(TestSuiteBase):
 	networks     = ('btc',)
@@ -287,8 +291,10 @@ class TestSuiteAutosignBase(TestSuiteBase):
 			self.bad_tx_count = 2
 		elif op == 'remove':
 			for fn in fns:
-				try: os.unlink(fn)
-				except: pass
+				try:
+					os.unlink(fn)
+				except:
+					pass
 			self.bad_tx_count = 0
 		return 'ok'
 

+ 24 - 9
test/test_py_d/ts_chainsplit.py

@@ -74,11 +74,20 @@ class TestSuiteChainsplit(TestSuiteRegtest):
 		t.expect('done')
 		t.ok()
 
-	def split_start_btc(self): self.regtest_start(coin='BTC')
-	def split_start_b2x(self): self.regtest_start(coin='B2X')
-	def split_gen_btc(self):   self.regtest_generate(coin='BTC')
-	def split_gen_b2x(self):   self.regtest_generate(coin='B2X',num_blocks=100)
-	def split_gen_b2x2(self):  self.regtest_generate(coin='B2X')
+	def split_start_btc(self):
+		self.regtest_start(coin='BTC')
+
+	def split_start_b2x(self):
+		self.regtest_start(coin='B2X')
+
+	def split_gen_btc(self):
+		self.regtest_generate(coin='BTC')
+
+	def split_gen_b2x(self):
+		self.regtest_generate(coin='B2X',num_blocks=100)
+
+	def split_gen_b2x2(self):
+		self.regtest_generate(coin='B2X')
 
 	def split_do_split(self):
 		self.coin = 'B2X'
@@ -92,7 +101,8 @@ class TestSuiteChainsplit(TestSuiteRegtest):
 		t.expect('outputs to spend: ','1\n')
 
 		for tx in ('timelocked','split'):
-			for q in ('fee','change'): t.expect('OK? (Y/n): ','y')
+			for q in ('fee','change'):
+				t.expect('OK? (Y/n): ','y')
 			t.do_comment(False)
 			t.view_tx('t')
 
@@ -126,9 +136,14 @@ class TestSuiteChainsplit(TestSuiteRegtest):
 	def split_txdo_timelock(self,coin,locktime,bad_locktime):
 		self.coin = coin
 		sid = self.regtest_user_sid('bob')
-		self.regtest_user_txdo( 'bob','0.0001',[sid+':S:5'],'1',pw=rt_pw,
-								extra_args=['--locktime='+str(locktime)],
-								bad_locktime=bad_locktime)
+		self.regtest_user_txdo(
+			'bob',
+			'0.0001',
+			[sid+':S:5'],
+			'1',
+			pw           = rt_pw,
+			extra_args   = ['--locktime='+str(locktime)],
+			bad_locktime = bad_locktime)
 
 	def split_txdo_timelock_bad_btc(self):
 		self.regtest_txdo_timelock('BTC',locktime=8888,bad_locktime=True)

+ 136 - 78
test/test_py_d/ts_ethdev.py

@@ -566,8 +566,10 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		t.expect('version')
 		return t
 
-	def wallet_upgrade1(self): return self.wallet_upgrade('tracking-wallet-v1.json')
-	def wallet_upgrade2(self): return self.wallet_upgrade('tracking-wallet-v2.json')
+	def wallet_upgrade1(self):
+		return self.wallet_upgrade('tracking-wallet-v1.json')
+	def wallet_upgrade2(self):
+		return self.wallet_upgrade('tracking-wallet-v2.json')
 
 	def addrgen(self,addrs='1-3,11-13,21-23'):
 		t = self.spawn('mmgen-addrgen', self.eth_args + [dfl_words_file,addrs])
@@ -595,7 +597,8 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 	def addrimport_burn_addr(self):
 		return self.addrimport_one_addr(addr=burn_addr)
 
-	def txcreate(self,
+	def txcreate(
+			self,
 			args            = [],
 			menu            = [],
 			acct            = '1',
@@ -603,23 +606,24 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 			interactive_fee = '50G',
 			fee_info_data   = ('0.00105','50'),
 			no_read         = False,
-			tweaks          = [] ):
+			tweaks          = []):
 		fee_info_pat = r'\D{}\D.*{c} .*\D{}\D.*gas price in Gwei'.format( *fee_info_data, c=self.proto.coin )
 		t = self.spawn('mmgen-'+caller, self.eth_args + ['-B'] + args)
 		t.expect(r'add \[l\]abel, .*?:.','p', regex=True)
 		t.written_to_file('Account balances listing')
-		t = self.txcreate_ui_common(t,
-			menu              = menu,
-			caller            = caller,
-			input_sels_prompt = 'to spend from',
-			inputs            = acct,
-			file_desc         = 'transaction',
-			bad_input_sels    = True,
-			interactive_fee   = interactive_fee,
-			fee_info_pat      = fee_info_pat,
-			fee_desc          = 'transaction fee or gas price',
-			add_comment       = tx_comment_jp,
-			tweaks            = tweaks )
+		t = self.txcreate_ui_common(
+				t,
+				menu              = menu,
+				caller            = caller,
+				input_sels_prompt = 'to spend from',
+				inputs            = acct,
+				file_desc         = 'transaction',
+				bad_input_sels    = True,
+				interactive_fee   = interactive_fee,
+				fee_info_pat      = fee_info_pat,
+				fee_desc          = 'transaction fee or gas price',
+				add_comment       = tx_comment_jp,
+				tweaks            = tweaks)
 		if not no_read:
 			t.read()
 		return t
@@ -628,25 +632,27 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		ext = ext.format('-α' if cfg.debug_utf8 else '')
 		keyfile = joinpath(self.tmpdir,parity_devkey_fn)
 		txfile = self.get_file_with_ext(ext,no_dot=True)
-		t = self.spawn('mmgen-txsign',
-			[f'--outdir={self.tmpdir}']
-			+ [f'--coin={self.proto.coin}']
-			+ ['--quiet']
-			+ ['--rpc-host=bad_host'] # ETH signing must work without RPC
-			+ add_args
-			+ ([],['--yes'])[ni]
-			+ ([f'--keys-from-file={keyfile}'] if dev_send else [])
-			+ [txfile, dfl_words_file] )
+		t = self.spawn(
+				'mmgen-txsign',
+				[f'--outdir={self.tmpdir}']
+				+ [f'--coin={self.proto.coin}']
+				+ ['--quiet']
+				+ ['--rpc-host=bad_host'] # ETH signing must work without RPC
+				+ add_args
+				+ ([],['--yes'])[ni]
+				+ ([f'--keys-from-file={keyfile}'] if dev_send else [])
+				+ [txfile, dfl_words_file])
 		return self.txsign_ui_common(t,ni=ni,has_label=True)
 
 	def txsend(self,ni=False,ext='{}.regtest.sigtx',add_args=[]):
 		ext = ext.format('-α' if cfg.debug_utf8 else '')
 		txfile = self.get_file_with_ext(ext,no_dot=True)
 		t = self.spawn('mmgen-txsend', self.eth_args + add_args + [txfile])
-		txid = self.txsend_ui_common(t,
-			quiet      = not cfg.debug,
-			bogus_send = False,
-			has_label  = True )
+		self.txsend_ui_common(
+				t,
+				quiet      = not cfg.debug,
+				bogus_send = False,
+				has_label  = True)
 		return t
 
 	def txview(self,ext_fs):
@@ -682,28 +688,38 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		return self.txcreate(args=args,menu=menu,acct='1',tweaks=['confirm_non_mmgen'])
 	def txview1_raw(self):
 		return self.txview(ext_fs='{}.regtest.rawtx')
-	def txsign1(self):    return self.txsign(add_args=['--use-internal-keccak-module'],dev_send=True)
+	def txsign1(self):
+		return self.txsign(add_args=['--use-internal-keccak-module'],dev_send=True)
 	def tx_status0_bad(self):
 		return self.tx_status(ext='{}.regtest.sigtx',expect_str='neither in mempool nor blockchain',exit_val=1)
-	def txsign1_ni(self): return self.txsign(ni=True,dev_send=True)
-	def txsend1(self):    return self.txsend()
+	def txsign1_ni(self):
+		return self.txsign(ni=True,dev_send=True)
+	def txsend1(self):
+		return self.txsend()
 	def txview1_sig(self): # do after send so that TxID is displayed
 		return self.txview(ext_fs='{}.regtest.sigtx')
-	def bal1(self):       return self.bal(n='1')
+	def bal1(self):
+		return self.bal(n='1')
 
 	def txcreate2(self):
 		args = ['98831F3A:E:11,1.234']
 		return self.txcreate(args=args,acct='10',tweaks=['confirm_non_mmgen'])
-	def txsign2(self): return self.txsign(ni=True,ext='1.234,50000]{}.regtest.rawtx',dev_send=True)
-	def txsend2(self): return self.txsend(ext='1.234,50000]{}.regtest.sigtx')
-	def bal2(self):    return self.bal(n='2')
+	def txsign2(self):
+		return self.txsign(ni=True,ext='1.234,50000]{}.regtest.rawtx',dev_send=True)
+	def txsend2(self):
+		return self.txsend(ext='1.234,50000]{}.regtest.sigtx')
+	def bal2(self):
+		return self.bal(n='2')
 
 	def txcreate3(self):
 		args = ['98831F3A:E:21,2.345']
 		return self.txcreate(args=args,acct='10',tweaks=['confirm_non_mmgen'])
-	def txsign3(self): return self.txsign(ni=True,ext='2.345,50000]{}.regtest.rawtx',dev_send=True)
-	def txsend3(self): return self.txsend(ext='2.345,50000]{}.regtest.sigtx')
-	def bal3(self):    return self.bal(n='3')
+	def txsign3(self):
+		return self.txsign(ni=True,ext='2.345,50000]{}.regtest.rawtx',dev_send=True)
+	def txsend3(self):
+		return self.txsend(ext='2.345,50000]{}.regtest.sigtx')
+	def bal3(self):
+		return self.bal(n='3')
 
 	def tx_status(self,ext,expect_str,expect_str2='',add_args=[],exit_val=0):
 		ext = ext.format('-α' if cfg.debug_utf8 else '')
@@ -816,16 +832,22 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		t.expect('or gas price: ',fee+'\n')
 		return t
 
-	def txsign4(self): return self.txsign(ni=True,ext='.45495,50000]{}.regtest.rawtx',dev_send=True)
-	def txsend4(self): return self.txsend(ext='.45495,50000]{}.regtest.sigtx')
-	def bal4(self):    return self.bal(n='4')
+	def txsign4(self):
+		return self.txsign(ni=True,ext='.45495,50000]{}.regtest.rawtx',dev_send=True)
+	def txsend4(self):
+		return self.txsend(ext='.45495,50000]{}.regtest.sigtx')
+	def bal4(self):
+		return self.bal(n='4')
 
 	def txcreate5(self):
 		args = [burn_addr + ','+amt1]
 		return self.txcreate(args=args,acct='10',tweaks=['confirm_non_mmgen'])
-	def txsign5(self): return self.txsign(ni=True,ext=amt1+',50000]{}.regtest.rawtx',dev_send=True)
-	def txsend5(self): return self.txsend(ext=amt1+',50000]{}.regtest.sigtx')
-	def bal5(self):    return self.bal(n='5')
+	def txsign5(self):
+		return self.txsign(ni=True,ext=amt1+',50000]{}.regtest.rawtx',dev_send=True)
+	def txsend5(self):
+		return self.txsend(ext=amt1+',50000]{}.regtest.sigtx')
+	def bal5(self):
+		return self.bal(n='5')
 
 	#bal_corr = Decimal('0.0000032') # gas use for token sends varies between ETH and ETC!
 	bal_corr = Decimal('0.0000000') # update: OpenEthereum team seems to have corrected this
@@ -879,10 +901,14 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		t.expect(fr'{addr}\b.*{comment_pat}',regex=True)
 		return t
 
-	def add_comment1(self): return self.add_comment(comment=tw_comment_zh)
-	def chk_comment1(self): return self.chk_comment(comment_pat=tw_comment_zh[:3])
-	def add_comment2(self): return self.add_comment(comment=tw_comment_lat_cyr_gr)
-	def chk_comment2(self): return self.chk_comment(comment_pat=tw_comment_lat_cyr_gr[:3])
+	def add_comment1(self):
+		return self.add_comment(comment=tw_comment_zh)
+	def chk_comment1(self):
+		return self.chk_comment(comment_pat=tw_comment_zh[:3])
+	def add_comment2(self):
+		return self.add_comment(comment=tw_comment_lat_cyr_gr)
+	def chk_comment2(self):
+		return self.chk_comment(comment_pat=tw_comment_lat_cyr_gr[:3])
 
 	def remove_comment(self,addr='98831F3A:E:3'):
 		t = self.spawn('mmgen-tool', self.eth_args + ['remove_label',addr])
@@ -897,8 +923,10 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		self.spawn('',msg_only=True)
 		cmd_args = [f'--{k}={v}' for k,v in list(token_data.items())]
 		imsg("Compiling solidity token contract '{}' with 'solc'".format( token_data['symbol'] ))
-		try: os.mkdir(odir)
-		except: pass
+		try:
+			os.mkdir(odir)
+		except:
+			pass
 		cmd = [
 			'python3',
 			'scripts/exec_wrapper.py',
@@ -969,18 +997,27 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 			imsg(f'\nToken MM{num} deployed!')
 		return t
 
-	async def token_deploy1a(self): return await self.token_deploy(num=1,key='SafeMath',gas=500_000)
-	async def token_deploy1b(self): return await self.token_deploy(num=1,key='Owned',   gas=1_000_000)
-	async def token_deploy1c(self): return await self.token_deploy(num=1,key='Token',   gas=4_000_000,tx_fee='7G')
+	async def token_deploy1a(self):
+		return await self.token_deploy(num=1,key='SafeMath',gas=500_000)
+	async def token_deploy1b(self):
+		return await self.token_deploy(num=1,key='Owned',   gas=1_000_000)
+	async def token_deploy1c(self):
+		return await self.token_deploy(num=1,key='Token',   gas=4_000_000,tx_fee='7G')
 
 	def tx_status2(self):
-		return self.tx_status(ext=self.proto.coin+'[0,7000]{}.regtest.sigtx',expect_str='successfully executed')
+		return self.tx_status(
+				ext        = self.proto.coin+'[0,7000]{}.regtest.sigtx',
+				expect_str = 'successfully executed')
 
-	def bal6(self): return self.bal5()
+	def bal6(self):
+		return self.bal5()
 
-	async def token_deploy2a(self): return await self.token_deploy(num=2,key='SafeMath',gas=500_000)
-	async def token_deploy2b(self): return await self.token_deploy(num=2,key='Owned',   gas=1_000_000)
-	async def token_deploy2c(self): return await self.token_deploy(num=2,key='Token',   gas=4_000_000)
+	async def token_deploy2a(self):
+		return await self.token_deploy(num=2,key='SafeMath',gas=500_000)
+	async def token_deploy2b(self):
+		return await self.token_deploy(num=2,key='Owned',   gas=1_000_000)
+	async def token_deploy2c(self):
+		return await self.token_deploy(num=2,key='Token',   gas=4_000_000)
 
 	async def contract_deploy(self): # test create,sign,send
 		return await self.token_deploy(num=2,key='SafeMath',gas=500_000,mmgen_cmd='txcreate')
@@ -1085,8 +1122,10 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 			expect   = '3/3',
 			add_args = ['--token=MM2'] )
 
-	def bal7(self):       return self.bal5()
-	def token_bal1(self): return self.token_bal(n='1')
+	def bal7(self):
+		return self.bal5()
+	def token_bal1(self):
+		return self.token_bal(n='1')
 
 	def token_txcreate(self,args=[],token='',inputs='1',fee='50G'):
 		return self.txcreate_ui_common(
@@ -1163,8 +1202,10 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 	def txsend_noamt(self):
 		return self.txsend(ext='99.99895,50000]{}.regtest.sigtx')
 
-	def bal8(self):       return self.bal(n='8')
-	def token_bal5(self): return self.token_bal(n='5')
+	def bal8(self):
+		return self.bal(n='8')
+	def token_bal5(self):
+		return self.token_bal(n='5')
 
 	def token_txcreate_noamt(self):
 		return self.token_txcreate(args=['98831F3A:E:13'],token='mm1',inputs='2',fee='51G')
@@ -1173,8 +1214,10 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 	def token_txsend_noamt(self):
 		return self.token_txsend(ext='1.23456,51000]{}.regtest.sigtx',token='mm1')
 
-	def bal9(self):       return self.bal(n='9')
-	def token_bal6(self): return self.token_bal(n='6')
+	def bal9(self):
+		return self.bal(n='9')
+	def token_bal6(self):
+		return self.token_bal(n='6')
 
 	def listaddresses(self,args=[],tool_args=['all_labels=1']):
 		return self.spawn('mmgen-tool', self.eth_args + args + ['listaddresses'] + tool_args)
@@ -1209,25 +1252,27 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		args=['--cached-balances','--fee=12G','98831F3A:E:12,1.2789']
 		return self.token_txcreate(args=args,token='mm1')
 
-	def txdo_cached_balances(self,
+	def txdo_cached_balances(
+			self,
 			acct          = '2',
 			fee_info_data = ('0.00105','50'),
-			add_args      = ['98831F3A:E:3,0.4321'] ):
+			add_args      = ['98831F3A:E:3,0.4321']):
 		t = self.txcreate(
-			args          = ['--fee=20G','--cached-balances'] + add_args + [dfl_words_file],
-			acct          = acct,
-			caller        = 'txdo',
-			fee_info_data = fee_info_data,
-			no_read       = True )
+				args          = ['--fee=20G','--cached-balances'] + add_args + [dfl_words_file],
+				acct          = acct,
+				caller        = 'txdo',
+				fee_info_data = fee_info_data,
+				no_read       = True)
 		self._do_confirm_send(t,quiet=not cfg.debug,sure=False)
 		return t
 
-	def txcreate_refresh_balances(self,
+	def txcreate_refresh_balances(
+			self,
 			bals       = ['2','3'],
 			args       = ['-B','--cached-balances','-i'],
 			total      = vbal5,
 			adj_total  = True,
-			total_coin = None ):
+			total_coin = None):
 
 		if total_coin is None:
 			total_coin = self.proto.coin
@@ -1243,7 +1288,8 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		t.expect(rf'Total unspent:.*\D{total}\D.*{total_coin}',regex=True)
 		return t
 
-	def bal10(self): return self.bal(n='10')
+	def bal10(self):
+		return self.bal(n='10')
 
 	def token_txdo_cached_balances(self):
 		return self.txdo_cached_balances(
@@ -1259,7 +1305,8 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 			adj_total  = False,
 			total_coin = 'MM1' )
 
-	def token_bal7(self): return self.token_bal(n='7')
+	def token_bal7(self):
+		return self.token_bal(n='7')
 
 	def twview1(self):
 		return self.twview()
@@ -1287,7 +1334,14 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 	def token_twview3(self):
 		return self.twview(args=['--token=mm1'],tool_args=['wide=1','sort=age'])
 
-	def edit_comment(self,out_num,args=[],action='l',comment_text=None,changed=False,pexpect_spawn=None):
+	def edit_comment(
+			self,
+			out_num,
+			args          = [],
+			action        = 'l',
+			comment_text  = None,
+			changed       = False,
+			pexpect_spawn = None):
 		t = self.spawn('mmgen-txcreate', self.eth_args + args + ['-B','-i'],pexpect_spawn=pexpect_spawn)
 
 		menu_prompt = 'efresh balance:\b'
@@ -1321,7 +1375,11 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
 		return self.edit_comment(out_num=del_addrs[0],comment_text=tw_comment_zh[:3])
 	def edit_comment2(self):
 		spawn = False if gc.platform == 'win' else True
-		return self.edit_comment(out_num=del_addrs[0],comment_text=tw_comment_zh[3:],changed=True,pexpect_spawn=spawn)
+		return self.edit_comment(
+				out_num       = del_addrs[0],
+				comment_text  = tw_comment_zh[3:],
+				changed       = True,
+				pexpect_spawn = spawn)
 	def edit_comment3(self):
 		return self.edit_comment(out_num=del_addrs[1],comment_text=tw_comment_lat_cyr_gr)
 	def edit_comment4(self):

+ 26 - 14
test/test_py_d/ts_input.py

@@ -444,17 +444,29 @@ class TestSuiteInput(TestSuiteBase):
 			'wd',
 			'busy')
 		return self._user_seed_entry('words',entry_mode='minimal',mn=mn)
-	def mnemonic_entry_mmgen(self):           return self._user_seed_entry('words',entry_mode='full')
-	def mnemonic_entry_bip39(self):           return self._user_seed_entry('bip39',entry_mode='full')
-	def mnemonic_entry_bip39_short(self):     return self._user_seed_entry('bip39',entry_mode='short')
-
-	def mn2hex_interactive_mmgen(self):       return self._mn2hex('mmgen',entry_mode='full')
-	def mn2hex_interactive_mmgen_fixed(self): return self._mn2hex('mmgen',entry_mode='fixed')
-	def mn2hex_interactive_bip39(self):       return self._mn2hex('bip39',entry_mode='full')
-	def mn2hex_interactive_bip39_short(self): return self._mn2hex('bip39',entry_mode='short',pad_entry=True)
-	def mn2hex_interactive_bip39_fixed(self): return self._mn2hex('bip39',entry_mode='fixed',enter_for_dfl=True)
-	def mn2hex_interactive_xmr(self):         return self._mn2hex('xmrseed',entry_mode='full')
-	def mn2hex_interactive_xmr_short(self):   return self._mn2hex('xmrseed',entry_mode='short')
-
-	def dieroll_entry(self):         return self._user_seed_entry('dieroll')
-	def dieroll_entry_usrrand(self): return self._user_seed_entry('dieroll',usr_rand=True,out_fmt='bip39')
+	def mnemonic_entry_mmgen(self):
+		return self._user_seed_entry('words',entry_mode='full')
+	def mnemonic_entry_bip39(self):
+		return self._user_seed_entry('bip39',entry_mode='full')
+	def mnemonic_entry_bip39_short(self):
+		return self._user_seed_entry('bip39',entry_mode='short')
+
+	def mn2hex_interactive_mmgen(self):
+		return self._mn2hex('mmgen',entry_mode='full')
+	def mn2hex_interactive_mmgen_fixed(self):
+		return self._mn2hex('mmgen',entry_mode='fixed')
+	def mn2hex_interactive_bip39(self):
+		return self._mn2hex('bip39',entry_mode='full')
+	def mn2hex_interactive_bip39_short(self):
+		return self._mn2hex('bip39',entry_mode='short',pad_entry=True)
+	def mn2hex_interactive_bip39_fixed(self):
+		return self._mn2hex('bip39',entry_mode='fixed',enter_for_dfl=True)
+	def mn2hex_interactive_xmr(self):
+		return self._mn2hex('xmrseed',entry_mode='full')
+	def mn2hex_interactive_xmr_short(self):
+		return self._mn2hex('xmrseed',entry_mode='short')
+
+	def dieroll_entry(self):
+		return self._user_seed_entry('dieroll')
+	def dieroll_entry_usrrand(self):
+		return self._user_seed_entry('dieroll',usr_rand=True,out_fmt='bip39')

+ 185 - 88
test/test_py_d/ts_main.py

@@ -99,79 +99,169 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 	color = True
 	need_daemon = True
 	cmd_group = (
-		('walletgen_dfl_wallet', (15,'wallet generation (default wallet)',[[[],15]])),
-		('subwalletgen_dfl_wallet', (15,'subwallet generation (default wallet)',[[[pwfile],15]])),
-		('export_seed_dfl_wallet',(15,'seed export to mmseed format (default wallet)',[[[pwfile],15]])),
-		('addrgen_dfl_wallet',(15,'address generation (default wallet)',[[[pwfile],15]])),
-		('txcreate_dfl_wallet',(15,'transaction creation (default wallet)',[[['addrs'],15]])),
-		('txsign_dfl_wallet',(15,'transaction signing (default wallet)',[[['rawtx',pwfile],15]])),
-		('passchg_dfl_wallet',(16,'password, label and hash preset change (default wallet)',[[[pwfile],15]])),
-		('walletchk_newpass_dfl_wallet',(16,'wallet check with new pw, label and hash preset',[[[pwfile],16]])),
-		('delete_dfl_wallet',(15,'delete default wallet',[[[pwfile],15]])),
-
-		('walletgen',       (1,'wallet generation',        [[['del_dw_run'],15]])),
-		('subwalletgen',    (1,'subwallet generation',     [[['mmdat'],1]])),
-		('subwalletgen_mnemonic',(1,'subwallet generation (to mnemonic format)',[[['mmdat'],1]])),
-#		('walletchk',       (1,'wallet check',             [[['mmdat'],1]])),
-		('passchg',         (5,'password, label and hash preset change',[[['mmdat',pwfile],1]])),
-		('passchg_keeplabel',(5,'password, label and hash preset change (keep label)',[[['mmdat',pwfile],1]])),
-		('passchg_usrlabel',(5,'password, label and hash preset change (interactive label)',[[['mmdat',pwfile],1]])),
-		('walletchk_newpass',(5,'wallet check with new pw, label and hash preset',[[['mmdat',pwfile],5]])),
-		('addrgen',         (1,'address generation',       [[['mmdat',pwfile],1]])),
-		('txcreate',        (1,'transaction creation',     [[['addrs'],1]])),
-		('txbump',          (1,'transaction fee bumping (no send)',[[['rawtx'],1]])),
-		('txsign',          (1,'transaction signing',      [[['mmdat','rawtx',pwfile,'txbump'],1]])),
-		('txsend',          (1,'transaction sending',      [[['sigtx'],1]])),
+		('walletgen_dfl_wallet',    (15,'wallet generation (default wallet)',            [[[],15]])),
+		('subwalletgen_dfl_wallet', (15,'subwallet generation (default wallet)',         [[[pwfile],15]])),
+		('export_seed_dfl_wallet',  (15,'seed export to mmseed format (default wallet)', [[[pwfile],15]])),
+		('addrgen_dfl_wallet',      (15,'address generation (default wallet)',           [[[pwfile],15]])),
+		('txcreate_dfl_wallet',     (15,'transaction creation (default wallet)',         [[['addrs'],15]])),
+		('txsign_dfl_wallet',       (15,'transaction signing (default wallet)',          [[['rawtx',pwfile],15]])),
+		('passchg_dfl_wallet',      (16,'password, label and hash preset change (default wallet)',[[[pwfile],15]])),
+		('walletchk_newpass_dfl_wallet', (16,'wallet check with new pw, label and hash preset',   [[[pwfile],16]])),
+		('delete_dfl_wallet',       (15,'delete default wallet',                         [[[pwfile],15]])),
+
+		('walletgen',             (1,'wallet generation',                         [[['del_dw_run'],15]])),
+		('subwalletgen',          (1,'subwallet generation',                      [[['mmdat'],1]])),
+		('subwalletgen_mnemonic', (1,'subwallet generation (to mnemonic format)', [[['mmdat'],1]])),
+		# ('walletchk',             (1,'wallet check',                              [[['mmdat'],1]])),
+		('passchg',          (5,'password, label and hash preset change',              [[['mmdat',pwfile],1]])),
+		('passchg_keeplabel',(5,'password, label and hash preset change (keep label)', [[['mmdat',pwfile],1]])),
+		('passchg_usrlabel', (
+				5,
+				'password, label and hash preset change (interactive label)',
+				[
+					[['mmdat',pwfile],1]
+				]
+			)
+		),
+		('walletchk_newpass',(5,'wallet check with new pw, label and hash preset', [[['mmdat',pwfile],5]])),
+		('addrgen',          (1,'address generation',                [[['mmdat',pwfile],1]])),
+		('txcreate',         (1,'transaction creation',              [[['addrs'],1]])),
+		('txbump',           (1,'transaction fee bumping (no send)', [[['rawtx'],1]])),
+		('txsign',           (1,'transaction signing',               [[['mmdat','rawtx',pwfile,'txbump'],1]])),
+		('txsend',           (1,'transaction sending',               [[['sigtx'],1]])),
 		# txdo must go after txsign
-		('txdo',            (1,'online transaction',       [[['sigtx','mmdat'],1]])),
-
-		('export_seed',     (1,'seed export to mmseed format',   [[['mmdat'],1]])),
-		('export_hex',      (1,'seed export to hexadecimal format',  [[['mmdat'],1]])),
-		('export_mnemonic', (1,'seed export to mmwords format',  [[['mmdat'],1]])),
-		('export_bip39',    (1,'seed export to bip39 format',    [[['mmdat'],1]])),
-		('export_incog',    (1,'seed export to mmincog format',  [[['mmdat'],1]])),
-		('export_incog_hex',(1,'seed export to mmincog hex format', [[['mmdat'],1]])),
+		('txdo',             (1,'online transaction',                [[['sigtx','mmdat'],1]])),
+
+		('export_seed',     (1,'seed export to mmseed format',            [[['mmdat'],1]])),
+		('export_hex',      (1,'seed export to hexadecimal format',       [[['mmdat'],1]])),
+		('export_mnemonic', (1,'seed export to mmwords format',           [[['mmdat'],1]])),
+		('export_bip39',    (1,'seed export to bip39 format',             [[['mmdat'],1]])),
+		('export_incog',    (1,'seed export to mmincog format',           [[['mmdat'],1]])),
+		('export_incog_hex',(1,'seed export to mmincog hex format',       [[['mmdat'],1]])),
 		('export_incog_hidden',(1,'seed export to hidden mmincog format', [[['mmdat'],1]])),
 
-		('addrgen_seed',    (1,'address generation from mmseed file', [[['mmseed','addrs'],1]])),
-		('addrgen_hex',     (1,'address generation from mmhex file', [[['mmhex','addrs'],1]])),
-		('addrgen_mnemonic',(1,'address generation from mmwords file',[[['mmwords','addrs'],1]])),
-		('addrgen_incog',   (1,'address generation from mmincog file',[[['mmincog','addrs'],1]])),
-		('addrgen_incog_hex',(1,'address generation from mmincog hex file',[[['mmincox','addrs'],1]])),
+		('addrgen_seed',    (1,'address generation from mmseed file',             [[['mmseed','addrs'],1]])),
+		('addrgen_hex',     (1,'address generation from mmhex file',              [[['mmhex','addrs'],1]])),
+		('addrgen_mnemonic',(1,'address generation from mmwords file',            [[['mmwords','addrs'],1]])),
+		('addrgen_incog',   (1,'address generation from mmincog file',            [[['mmincog','addrs'],1]])),
+		('addrgen_incog_hex',(1,'address generation from mmincog hex file',       [[['mmincox','addrs'],1]])),
 		('addrgen_incog_hidden',(1,'address generation from hidden mmincog file', [[[hincog_fn,'addrs'],1]])),
 
-		('keyaddrgen',    (1,'key-address file generation', [[['mmdat',pwfile],1]])),
+		('keyaddrgen',    (1,'key-address file generation',               [[['mmdat',pwfile],1]])),
 		('txsign_keyaddr',(1,'transaction signing with key-address file', [[['akeys.mmenc','rawtx'],1]])),
 
-		('txcreate_ni',   (1,'transaction creation (non-interactive)',     [[['addrs'],1]])),
-
-		('walletgen2',(2,'wallet generation (2), 128-bit seed',     [[['del_dw_run'],15]])),
-		('addrgen2',  (2,'address generation (2)',    [[['mmdat'],2]])),
-		('txcreate2', (2,'transaction creation (2)',  [[['addrs'],2]])),
-		('txsign2',   (2,'transaction signing, two transactions',[[['mmdat','rawtx'],1],[['mmdat','rawtx'],2]])),
-		('export_mnemonic2', (2,'seed export to mmwords format (2)',[[['mmdat'],2]])),
-
-		('walletgen3',(3,'wallet generation (3)',                  [[['del_dw_run'],15]])),
-		('addrgen3',  (3,'address generation (3)',                 [[['mmdat'],3]])),
-		('txcreate3', (3,'tx creation with inputs and outputs from two wallets', [[['addrs'],1],[['addrs'],3]])),
-		('txsign3',   (3,'tx signing with inputs and outputs from two wallets',[[['mmdat'],1],[['mmdat','rawtx'],3]])),
-
-		('walletgen14', (14,'wallet generation (14)',        [[['del_dw_run'],15]],14)),
-		('addrgen14',   (14,'address generation (14)',        [[['mmdat'],14]])),
+		('txcreate_ni',   (1,'transaction creation (non-interactive)',    [[['addrs'],1]])),
+
+		('walletgen2',(2,'wallet generation (2), 128-bit seed', [[['del_dw_run'],15]])),
+		('addrgen2',  (2,'address generation (2)',              [[['mmdat'],2]])),
+		('txcreate2', (2,'transaction creation (2)',            [[['addrs'],2]])),
+		('txsign2', (
+				2,
+				'transaction signing, two transactions',
+				[
+					[['mmdat','rawtx'],1],
+					[['mmdat','rawtx'],2]
+				]
+			)
+		),
+		('export_mnemonic2', (
+				2,
+				'seed export to mmwords format (2)',
+				[
+					[['mmdat'],2]
+				]
+			)
+		),
+		('walletgen3',(3,'wallet generation (3)',  [[['del_dw_run'],15]])),
+		('addrgen3',  (3,'address generation (3)', [[['mmdat'],3]])),
+		('txcreate3', (
+				3,
+				'tx creation with inputs and outputs from two wallets',
+				[
+					[['addrs'],1],
+					[['addrs'],3]
+				]
+			)
+		),
+		('txsign3', (
+				3,
+				'tx signing with inputs and outputs from two wallets',
+				[
+					[['mmdat'],1],
+					[['mmdat','rawtx'],3]
+				]
+			)
+		),
+		('walletgen14', (14,'wallet generation (14)',           [[['del_dw_run'],15]],14)),
+		('addrgen14',   (14,'address generation (14)',          [[['mmdat'],14]])),
 		('keyaddrgen14',(14,'key-address file generation (14)', [[['mmdat'],14]],14)),
-		('walletgen4',(4,'wallet generation (4) (brainwallet)',    [[['del_dw_run'],15]])),
-		('addrgen4',  (4,'address generation (4)',                 [[['mmdat'],4]])),
-		('txcreate4', (4,'tx creation with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['addrs'],1],[['addrs'],2],[['addrs'],3],[['addrs'],4],[['addrs','akeys.mmenc'],14]])),
-		('txsign4',   (4,'tx signing with inputs and outputs from incog file, mnemonic file, wallet, brainwallet, key-address file and non-MMGen inputs and outputs', [[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['mmbrain','rawtx'],4],[['akeys.mmenc'],14]])),
-		('txdo4', (4,'tx creation,signing and sending with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['addrs'],1],[['addrs'],2],[['addrs'],3],[['addrs'],4],[['addrs','akeys.mmenc'],14],[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['mmbrain','rawtx'],4],[['akeys.mmenc'],14]])), # must go after txsign4
-		('txbump4', (4,'tx fee bump + send with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['akeys.mmenc'],14],[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['akeys.mmenc'],14],[['mmbrain','sigtx','mmdat','txdo'],4]])), # must go after txsign4
-
-		('walletgen5',(20,'wallet generation (5)',                   [[['del_dw_run'],15]],20)),
-		('addrgen5',  (20,'address generation (5)',                  [[['mmdat'],20]])),
-		('txcreate5', (20,'transaction creation with bad vsize (5)', [[['addrs'],20]])),
-		('txsign5',   (20,'transaction signing with bad vsize',      [[['mmdat','rawtx'],20]])),
-		('walletgen6',(21,'wallet generation (6)',                   [[['del_dw_run'],15]],21)),
-		('addrgen6',  (21,'address generation (6)',                  [[['mmdat'],21]])),
+		('walletgen4',(4,'wallet generation (4) (brainwallet)', [[['del_dw_run'],15]])),
+		('addrgen4',  (4,'address generation (4)',              [[['mmdat'],4]])),
+		('txcreate4', (
+				4,
+				'tx creation with inputs and outputs from four seed sources, key-address file '
+				'and non-MMGen inputs and outputs',
+				[
+					[['addrs'],1],
+					[['addrs'],2],
+					[['addrs'],3],
+					[['addrs'],4],
+					[['addrs','akeys.mmenc'],14]
+				]
+			)
+		),
+		('txsign4', (
+				4,
+				'tx signing with inputs and outputs from incog file, mnemonic file, wallet, '
+				'brainwallet, key-address file and non-MMGen inputs and outputs',
+				[
+					[['mmincog'],1],
+					[['mmwords'],2],
+					[['mmdat'],3],
+					[['mmbrain','rawtx'],4],
+					[['akeys.mmenc'],14]
+				]
+			)
+		),
+		('txdo4', (
+				4,
+				'tx creation,signing and sending with inputs and outputs from four seed sources, '
+				'key-address file and non-MMGen inputs and outputs',
+				[
+					[['addrs'],1],
+					[['addrs'],2],
+					[['addrs'],3],
+					[['addrs'],4],
+					[['addrs','akeys.mmenc'],14],
+					[['mmincog'],1],
+					[['mmwords'],2],
+					[['mmdat'],3],
+					[['mmbrain','rawtx'],4],
+					[['akeys.mmenc'],14]
+				]
+			)
+		), # must go after txsign4
+		('txbump4', (
+				4,
+				'tx fee bump + send with inputs and outputs from four seed sources, key-address file '
+				'and non-MMGen inputs and outputs',
+				[
+					[['akeys.mmenc'],14],
+					[['mmincog'],1],
+					[['mmwords'],2],
+					[['mmdat'],3],
+					[['akeys.mmenc'],14],
+					[['mmbrain','sigtx','mmdat','txdo'],4]
+				]
+			)
+		), # must go after txsign4
+
+		('walletgen5',(20,'wallet generation (5)',                         [[['del_dw_run'],15]],20)),
+		('addrgen5',  (20,'address generation (5)',                        [[['mmdat'],20]])),
+		('txcreate5', (20,'transaction creation with bad vsize (5)',       [[['addrs'],20]])),
+		('txsign5',   (20,'transaction signing with bad vsize',            [[['mmdat','rawtx'],20]])),
+		('walletgen6',(21,'wallet generation (6)',                         [[['del_dw_run'],15]],21)),
+		('addrgen6',  (21,'address generation (6)',                        [[['mmdat'],21]])),
 		('txcreate6', (21,'transaction creation with corrected vsize (6)', [[['addrs'],21]])),
 		('txsign6',   (21,'transaction signing with corrected vsize',      [[['mmdat','rawtx'],21]])),
 	)
@@ -275,8 +365,10 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 	def walletgen(self,del_dw_run='dummy',seed_len=None,gen_dfl_wallet=False):
 		self.write_to_tmpfile(pwfile,self.wpasswd+'\n')
 		args = ['-p1']
-		if not gen_dfl_wallet: args += ['-d',self.tmpdir]
-		if seed_len: args += ['-l',str(seed_len)]
+		if not gen_dfl_wallet:
+			args += ['-d',self.tmpdir]
+		if seed_len:
+			args += ['-l',str(seed_len)]
 		t = self.spawn('mmgen-walletgen', args + [self.usr_rand_arg])
 		t.license()
 		t.usr_rand(self.usr_rand_chars)
@@ -291,7 +383,8 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 
 	def subwalletgen(self,wf):
 		args = [self.usr_rand_arg,'-p1','-d',self.tr.trash_dir,'-L','Label']
-		if wf != 'default': args += [wf]
+		if wf != 'default':
+			args += [wf]
 		t = self.spawn('mmgen-subwalletgen', args + ['10s'])
 		t.license()
 		wcls = MMGenWallet
@@ -321,10 +414,11 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 		silence()
 		self.write_to_tmpfile( pwfile, get_data_from_file(cfg,pf) )
 		end_silence()
-		add_args = {'cmdline': ['-d',self.tmpdir,'-L','Changed label (UTF-8) α'],
-					'keep':    ['-d',self.tr.trash_dir,'--keep-label'],
-					'user':    ['-d',self.tr.trash_dir]
-					}[label_action]
+		add_args = {
+			'cmdline': ['-d',self.tmpdir,'-L','Changed label (UTF-8) α'],
+			'keep':    ['-d',self.tr.trash_dir,'--keep-label'],
+			'user':    ['-d',self.tr.trash_dir]
+		}[label_action]
 		t = self.spawn('mmgen-passchg', add_args + [self.usr_rand_arg, '-p2'] + ([wf] if wf else []))
 		t.license()
 		wcls = MMGenWallet
@@ -371,7 +465,8 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 		if comment:
 			comment = ' ' + comment
 		k = coinaddr.addr_fmt
-		if not segwit and k == 'p2sh': k = 'p2pkh'
+		if not segwit and k == 'p2sh':
+			k = 'p2pkh'
 		s_beg,s_end = { 'p2pkh':  ('76a914','88ac'),
 						'p2sh':   ('a914','87'),
 						'bech32': (self.proto.witness_vernum_hex + '14','') }[k]
@@ -487,17 +582,18 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 
 		return cmd_args + [tx_data[num]['addrfile'] for num in tx_data]
 
-	def txcreate_common(self,
-						sources                    = ['1'],
-						non_mmgen_input            = '',
-						do_label                   = False,
-						txdo_args                  = [],
-						add_args                   = [],
-						view                       = 'n',
-						addrs_per_wallet           = addrs_per_wallet,
-						non_mmgen_input_compressed = True,
-						cmdline_inputs             = False,
-						tweaks                     = [] ):
+	def txcreate_common(
+			self,
+			sources                    = ['1'],
+			non_mmgen_input            = '',
+			do_label                   = False,
+			txdo_args                  = [],
+			add_args                   = [],
+			view                       = 'n',
+			addrs_per_wallet           = addrs_per_wallet,
+			non_mmgen_input_compressed = True,
+			cmdline_inputs             = False,
+			tweaks                     = []):
 
 		if cfg.verbose or cfg.exact_output:
 			sys.stderr.write(green('Generating fake tracking wallet info\n'))
@@ -514,9 +610,9 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 			from mmgen.tw.shared import TwLabel
 			cmd_args = [
 				'--inputs={},{},{},{},{},{}'.format(
-					TwLabel(self.proto,dfake[0][self.lbl_id]).mmid,dfake[1]['address'],
-					TwLabel(self.proto,dfake[2][self.lbl_id]).mmid,dfake[3]['address'],
-					TwLabel(self.proto,dfake[4][self.lbl_id]).mmid,dfake[5]['address']
+					TwLabel(self.proto,dfake[0][self.lbl_id]).mmid, dfake[1]['address'],
+					TwLabel(self.proto,dfake[2][self.lbl_id]).mmid, dfake[3]['address'],
+					TwLabel(self.proto,dfake[4][self.lbl_id]).mmid, dfake[5]['address']
 				),
 				f'--outdir={self.tr.trash_dir}'
 			] + cmd_args[1:]
@@ -570,7 +666,8 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 
 	def txbump(self,txfile,prepend_args=[],seed_args=[]):
 		if not self.proto.cap('rbf'):
-			msg('Skipping RBF'); return 'skip'
+			msg('Skipping RBF')
+			return 'skip'
 		args = prepend_args + ['--quiet','--outdir='+self.tmpdir,txfile] + seed_args
 		t = self.spawn('mmgen-txbump',args)
 		if seed_args:

+ 24 - 14
test/test_py_d/ts_misc.py

@@ -289,10 +289,14 @@ class TestSuiteOutput(TestSuiteBase):
 	def screen_output(self,lang):
 		return self.spawn('test/misc/utf8_output.py',[lang],cmd_dir='.')
 
-	def output_gr(self): return self.screen_output('gr')
-	def output_ru(self): return self.screen_output('ru')
-	def output_zh(self): return self.screen_output('zh')
-	def output_jp(self): return self.screen_output('jp')
+	def output_gr(self):
+		return self.screen_output('gr')
+	def output_ru(self):
+		return self.screen_output('ru')
+	def output_zh(self):
+		return self.screen_output('zh')
+	def output_jp(self):
+		return self.screen_output('jp')
 
 	def oneshot_warning(self,pexpect_spawn=None):
 		t = self.spawn('test/misc/oneshot_warning.py',cmd_dir='.',pexpect_spawn=pexpect_spawn)
@@ -352,17 +356,23 @@ class TestSuiteRefTX(TestSuiteMain,TestSuiteBase):
 			return
 		return self.spawn('mmgen-addrgen',['--outdir='+self.tmpdir,'--type='+atype,dfl_words_file,'1-2'])
 
-	def ref_tx_addrgen1(self): return self.ref_tx_addrgen(atype='L')
-	def ref_tx_addrgen2(self): return self.ref_tx_addrgen(atype='C')
-	def ref_tx_addrgen3(self): return self.ref_tx_addrgen(atype='S')
-	def ref_tx_addrgen4(self): return self.ref_tx_addrgen(atype='B')
+	def ref_tx_addrgen1(self):
+		return self.ref_tx_addrgen(atype='L')
+	def ref_tx_addrgen2(self):
+		return self.ref_tx_addrgen(atype='C')
+	def ref_tx_addrgen3(self):
+		return self.ref_tx_addrgen(atype='S')
+	def ref_tx_addrgen4(self):
+		return self.ref_tx_addrgen(atype='B')
 
 	def ref_tx_txcreate(self,f1,f2,f3,f4):
 		sources = ['31','32']
-		if 'S' in self.proto.mmtypes: sources += ['33']
-		if 'B' in self.proto.mmtypes: sources += ['34']
+		if 'S' in self.proto.mmtypes:
+			sources += ['33']
+		if 'B' in self.proto.mmtypes:
+			sources += ['34']
 		return self.txcreate_common(
-									addrs_per_wallet = 2,
-									sources          = sources,
-									add_args         = ['--locktime=1320969600'],
-									do_label         = True )
+				addrs_per_wallet = 2,
+				sources          = sources,
+				add_args         = ['--locktime=1320969600'],
+				do_label         = True)

+ 33 - 20
test/test_py_d/ts_ref.py

@@ -229,13 +229,13 @@ class TestSuiteRef(TestSuiteBase,TestSuiteShared):
 
 	def ref_addrfile_chk(
 			self,
-			ftype    = 'addr',
-			coin     = None,
-			subdir   = None,
-			pfx      = None,
-			mmtype   = None,
-			id_key   = None,
-			pat      = None ):
+			ftype  = 'addr',
+			coin   = None,
+			subdir = None,
+			pfx    = None,
+			mmtype = None,
+			id_key = None,
+			pat    = None):
 
 		pat = pat or f'{self.nw_desc}.*Legacy'
 		af_key = f'ref_{ftype}file' + ('_' + id_key if id_key else '')
@@ -272,22 +272,35 @@ class TestSuiteRef(TestSuiteBase,TestSuiteShared):
 	def ref_passwdfile_chk(self,key,pat):
 		return self.ref_addrfile_chk(ftype='passwd',id_key=key,pat=pat)
 
-	def ref_passwdfile_chk_b58_20(self): return self.ref_passwdfile_chk(key='b58_20',pat=r'Base58.*len.* 20\b')
-	def ref_passwdfile_chk_b58_10(self): return self.ref_passwdfile_chk(key='b58_10',pat=r'Base58.*len.* 10\b')
-	def ref_passwdfile_chk_b32_24(self): return self.ref_passwdfile_chk(key='b32_24',pat=r'Base32.*len.* 24\b')
-	def ref_passwdfile_chk_b32_12(self): return self.ref_passwdfile_chk(key='b32_12',pat=r'Base32.*len.* 12\b')
-	def ref_passwdfile_chk_hex_32(self): return self.ref_passwdfile_chk(key='hex_32',pat=r'Hexadec.*len.* 32\b')
-	def ref_passwdfile_chk_hex_48(self): return self.ref_passwdfile_chk(key='hex_48',pat=r'Hexadec.*len.* 48\b')
-	def ref_passwdfile_chk_hex_64(self): return self.ref_passwdfile_chk(key='hex_64',pat=r'Hexadec.*len.* 64\b')
-	def ref_passwdfile_chk_bip39_12(self): return self.ref_passwdfile_chk(key='bip39_12',pat=r'BIP39.*len.* 12\b')
-	def ref_passwdfile_chk_bip39_18(self): return self.ref_passwdfile_chk(key='bip39_18',pat=r'BIP39.*len.* 18\b')
-	def ref_passwdfile_chk_bip39_24(self): return self.ref_passwdfile_chk(key='bip39_24',pat=r'BIP39.*len.* 24\b')
-	def ref_passwdfile_chk_xmrseed_25(self): return self.ref_passwdfile_chk(key='xmrseed_25',pat=r'Mon.*len.* 25\b')
-	def ref_passwdfile_chk_hex2bip39_12(self): return self.ref_passwdfile_chk(key='hex2bip39_12',pat=r'BIP39.*len.* 12\b')
+	def ref_passwdfile_chk_b58_20(self):
+		return self.ref_passwdfile_chk(key='b58_20',pat=r'Base58.*len.* 20\b')
+	def ref_passwdfile_chk_b58_10(self):
+		return self.ref_passwdfile_chk(key='b58_10',pat=r'Base58.*len.* 10\b')
+	def ref_passwdfile_chk_b32_24(self):
+		return self.ref_passwdfile_chk(key='b32_24',pat=r'Base32.*len.* 24\b')
+	def ref_passwdfile_chk_b32_12(self):
+		return self.ref_passwdfile_chk(key='b32_12',pat=r'Base32.*len.* 12\b')
+	def ref_passwdfile_chk_hex_32(self):
+		return self.ref_passwdfile_chk(key='hex_32',pat=r'Hexadec.*len.* 32\b')
+	def ref_passwdfile_chk_hex_48(self):
+		return self.ref_passwdfile_chk(key='hex_48',pat=r'Hexadec.*len.* 48\b')
+	def ref_passwdfile_chk_hex_64(self):
+		return self.ref_passwdfile_chk(key='hex_64',pat=r'Hexadec.*len.* 64\b')
+	def ref_passwdfile_chk_bip39_12(self):
+		return self.ref_passwdfile_chk(key='bip39_12',pat=r'BIP39.*len.* 12\b')
+	def ref_passwdfile_chk_bip39_18(self):
+		return self.ref_passwdfile_chk(key='bip39_18',pat=r'BIP39.*len.* 18\b')
+	def ref_passwdfile_chk_bip39_24(self):
+		return self.ref_passwdfile_chk(key='bip39_24',pat=r'BIP39.*len.* 24\b')
+	def ref_passwdfile_chk_xmrseed_25(self):
+		return self.ref_passwdfile_chk(key='xmrseed_25',pat=r'Mon.*len.* 25\b')
+	def ref_passwdfile_chk_hex2bip39_12(self):
+		return self.ref_passwdfile_chk(key='hex2bip39_12',pat=r'BIP39.*len.* 12\b')
 
 	def ref_tx_chk(self):
 		fn = self.sources['ref_tx_file'][self.proto.coin.lower()][bool(self.tn_ext)]
-		if not fn: return
+		if not fn:
+			return
 		tf = joinpath(ref_dir,self.ref_subdir,fn)
 		wf = dfl_words_file
 		self.write_to_tmpfile(pwfile,wpasswd)

+ 54 - 30
test/test_py_d/ts_ref_3seed.py

@@ -192,12 +192,18 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared):
 				fn )
 		return t
 
-	def ref_walletconv_words(self):        return self.ref_walletconv(ofmt='mn')
-	def ref_walletconv_bip39(self):        return self.ref_walletconv(ofmt='bip39')
-	def ref_walletconv_seed(self):         return self.ref_walletconv(ofmt='mmseed')
-	def ref_walletconv_hexseed(self):      return self.ref_walletconv(ofmt='mmhex')
-	def ref_walletconv_plainhexseed(self): return self.ref_walletconv(ofmt='hex')
-	def ref_walletconv_dieroll(self):      return self.ref_walletconv(ofmt='dieroll')
+	def ref_walletconv_words(self):
+		return self.ref_walletconv(ofmt='mn')
+	def ref_walletconv_bip39(self):
+		return self.ref_walletconv(ofmt='bip39')
+	def ref_walletconv_seed(self):
+		return self.ref_walletconv(ofmt='mmseed')
+	def ref_walletconv_hexseed(self):
+		return self.ref_walletconv(ofmt='mmhex')
+	def ref_walletconv_plainhexseed(self):
+		return self.ref_walletconv(ofmt='hex')
+	def ref_walletconv_dieroll(self):
+		return self.ref_walletconv(ofmt='dieroll')
 
 	def ref_walletconv_incog(self,ofmt='incog',ext='mmincog'):
 		args = ['-r0','-p1']
@@ -370,31 +376,44 @@ class TestSuiteRef3Addr(TestSuiteRef3Seed):
 		pf = joinpath(self.tmpdir,pwfile)
 		return getattr(self,pfx+'gen')(wf,pf=pf,check_ref=True,mmtype=mmtype)
 
-	def refaddrgen_legacy(self):        return self.call_addrgen('legacy')
-	def refaddrgen_compressed(self):    return self.call_addrgen('compressed')
-	def refaddrgen_segwit(self):        return self.call_addrgen('segwit')
-	def refaddrgen_bech32(self):        return self.call_addrgen('bech32')
-
-	def refkeyaddrgen_legacy(self):     return self.call_addrgen('legacy','keyaddr')
-	def refkeyaddrgen_compressed(self): return self.call_addrgen('compressed','keyaddr')
-	def refkeyaddrgen_segwit(self):     return self.call_addrgen('segwit','keyaddr')
-	def refkeyaddrgen_bech32(self):     return self.call_addrgen('bech32','keyaddr')
+	def refaddrgen_legacy(self):
+		return self.call_addrgen('legacy')
+	def refaddrgen_compressed(self):
+		return self.call_addrgen('compressed')
+	def refaddrgen_segwit(self):
+		return self.call_addrgen('segwit')
+	def refaddrgen_bech32(self):
+		return self.call_addrgen('bech32')
+
+	def refkeyaddrgen_legacy(self):
+		return self.call_addrgen('legacy','keyaddr')
+	def refkeyaddrgen_compressed(self):
+		return self.call_addrgen('compressed','keyaddr')
+	def refkeyaddrgen_segwit(self):
+		return self.call_addrgen('segwit','keyaddr')
+	def refkeyaddrgen_bech32(self):
+		return self.call_addrgen('bech32','keyaddr')
 
 	def pwgen(self,ftype,id_str,pwfmt=None,pwlen=None,extra_args=[],stdout=False):
 		wf = self.get_file_with_ext('mmdat')
 		pf = joinpath(self.tmpdir,pwfile)
 		pwfmt = (['--passwd-fmt='+pwfmt] if pwfmt else [])
 		pwlen = (['--passwd-len='+str(pwlen)] if pwlen else [])
-		return self.addrgen(wf, pf,
-					check_ref  = True,
-					ftype      = ftype,
-					id_str     = id_str,
-					extra_args = pwfmt + pwlen + extra_args,
-					stdout     = stdout )
-
-	def refpasswdgen(self):      return self.pwgen('pass','alice@crypto.org')
-	def refpasswdgen_half(self): return self.pwgen('pass','alice@crypto.org',pwlen='h')
-	def ref_b32passwdgen(self):  return self.pwgen('pass32','фубар@crypto.org','b32',17)
+		return self.addrgen(
+				wf,
+				pf,
+				check_ref  = True,
+				ftype      = ftype,
+				id_str     = id_str,
+				extra_args = pwfmt + pwlen + extra_args,
+				stdout     = stdout)
+
+	def refpasswdgen(self):
+		return self.pwgen('pass','alice@crypto.org')
+	def refpasswdgen_half(self):
+		return self.pwgen('pass','alice@crypto.org',pwlen='h')
+	def ref_b32passwdgen(self):
+		return self.pwgen('pass32','фубар@crypto.org','b32',17)
 
 	def ref_hexpasswdgen(self):
 		pwlen = {'1':32,'2':48,'3':64}[self.test_name[-1]]
@@ -411,8 +430,13 @@ class TestSuiteRef3Addr(TestSuiteRef3Seed):
 		ea = ['--accept-defaults']
 		return self.pwgen(ftype,'фубар@crypto.org',pwfmt,pwlen,ea,stdout=stdout)
 
-	def ref_bip39_12_passwdgen(self):     return self.mn_pwgen(12,'bip39',stdout=True)
-	def ref_bip39_18_passwdgen(self):     return self.mn_pwgen(18,'bip39',stdout=True)
-	def ref_bip39_24_passwdgen(self):     return self.mn_pwgen(24,'bip39')
-	def ref_hex2bip39_24_passwdgen(self): return self.mn_pwgen(24,'hex2bip39')
-	def ref_xmrseed_25_passwdgen(self):   return self.mn_pwgen(24,'xmrseed',ftype='passxmrseed')
+	def ref_bip39_12_passwdgen(self):
+		return self.mn_pwgen(12,'bip39',stdout=True)
+	def ref_bip39_18_passwdgen(self):
+		return self.mn_pwgen(18,'bip39',stdout=True)
+	def ref_bip39_24_passwdgen(self):
+		return self.mn_pwgen(24,'bip39')
+	def ref_hex2bip39_24_passwdgen(self):
+		return self.mn_pwgen(24,'hex2bip39')
+	def ref_xmrseed_25_passwdgen(self):
+		return self.mn_pwgen(24,'xmrseed',ftype='passxmrseed')

+ 122 - 55
test/test_py_d/ts_regtest.py

@@ -410,14 +410,17 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		('bob_auto_chg_addrtype4', 'creating an automatic change address transaction by addrtype (single address)'),
 		('bob_add_comment_uua1',   'adding a comment for unused address in tracking wallet (C)'),
 		('bob_auto_chg5',          'creating an auto-chg-address TX, skipping unused address with label (C)'),
-		('bob_auto_chg_addrtype5', 'creating an auto-chg-address TX by addrtype, skipping unused address with label (C)'),
+		('bob_auto_chg_addrtype5', 'creating an auto-chg-address TX by addrtype, skipping unused address '
+									'with label (C)'),
 		('bob_auto_chg6',          'creating an auto-chg-address TX, using unused address with label (C)'),
-		('bob_auto_chg_addrtype6', 'creating an auto-chg-address TX by addrtype, using unused address with label (C)'),
+		('bob_auto_chg_addrtype6', 'creating an auto-chg-address TX by addrtype, using unused address with '
+									'label (C)'),
 		('bob_remove_comment_uua1', 'removing a comment for unused address in tracking wallet (C)'),
-		('bob_auto_chg_bad1', 'error handling for auto change address transaction (bad ID FFFFFFFF:C)'),
-		('bob_auto_chg_bad2', 'error handling for auto change address transaction (bad ID 00000000:C)'),
-		('bob_auto_chg_bad3', 'error handling for auto change address transaction (no unused addresses)'),
-		('bob_auto_chg_bad4', 'error handling for auto change address transaction by addrtype (no unused addresses)'),
+		('bob_auto_chg_bad1',       'error handling for auto change address transaction (bad ID FFFFFFFF:C)'),
+		('bob_auto_chg_bad2',       'error handling for auto change address transaction (bad ID 00000000:C)'),
+		('bob_auto_chg_bad3',       'error handling for auto change address transaction (no unused addresses)'),
+		('bob_auto_chg_bad4',       'error handling for auto change address transaction by addrtype '
+									'(no unused addresses)'),
 		('carol_twimport2',          'recreating Carol’s tracking wallet from JSON dump'),
 		('carol_rescan_blockchain',  'rescanning the blockchain (full rescan)'),
 		('carol_auto_chg1',          'creating an automatic change address transaction (C)'),
@@ -427,7 +430,8 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		('carol_auto_chg_addrtype2', 'creating an automatic change address transaction by addrtype (B)'),
 		('carol_auto_chg_addrtype3', 'creating an automatic change address transaction by addrtype (S)'),
 		('carol_auto_chg_bad1',      'error handling for auto change address transaction (no unused addresses)'),
-		('carol_auto_chg_bad2',      'error handling for auto change address transaction by addrtype (no unused addresses)'),
+		('carol_auto_chg_bad2',      'error handling for auto change address transaction by addrtype '
+									'(no unused addresses)'),
 		('carol_delete_wallet',      'unloading and deleting Carol’s tracking wallet'),
 	),
 	}
@@ -467,7 +471,8 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 			if use_comments:
 				a.set_comment(idx,get_comment())
 			else:
-				if n % 2: a.set_comment(idx,f'Test address {n}')
+				if n % 2:
+					a.set_comment(idx,f'Test address {n}')
 		a.file.format(add_comments=True)
 		from mmgen.fileutil import write_data_to_file
 		write_data_to_file(
@@ -482,8 +487,10 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 	def setup(self):
 		stop_test_daemons(self.proto.network_id,force=True,remove_datadir=True)
 		from shutil import rmtree
-		try: rmtree(joinpath(self.tr.data_dir,'regtest'))
-		except: pass
+		try:
+			rmtree(joinpath(self.tr.data_dir,'regtest'))
+		except:
+			pass
 		t = self.spawn('mmgen-regtest',['-n','setup'])
 		for s in ('Starting','Creating','Creating','Creating','Mined','Setup complete'):
 			t.expect(s)
@@ -507,8 +514,10 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		t.written_to_file(capfirst(dfl_wcls.desc))
 		return t
 
-	def walletgen_bob(self):   return self.walletgen('bob')
-	def walletgen_alice(self): return self.walletgen('alice')
+	def walletgen_bob(self):
+		return self.walletgen('bob')
+	def walletgen_alice(self):
+		return self.walletgen('alice')
 
 	def _user_dir(self,user,coin=None):
 		return joinpath(self.tr.data_dir,'regtest',coin or self.proto.coin.lower(),user)
@@ -527,27 +536,45 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		end_silence()
 		return w.seed.subseed(subseed_idx).sid
 
-	def addrgen(self,user,wf=None,addr_range='1-5',subseed_idx=None,mmtypes=[]):
+	def addrgen(
+			self,
+			user,
+			wf          = None,
+			addr_range  = '1-5',
+			subseed_idx = None,
+			mmtypes     = []):
 		from mmgen.addr import MMGenAddrType
 		for mmtype in mmtypes or self.proto.mmtypes:
-			t = self.spawn('mmgen-addrgen',
+			t = self.spawn(
+				'mmgen-addrgen',
 				['--quiet','--'+user,'--type='+mmtype,f'--outdir={self._user_dir(user)}'] +
 				([wf] if wf else []) +
 				(['--subwallet='+subseed_idx] if subseed_idx else []) +
 				[addr_range],
-				extra_desc='({})'.format( MMGenAddrType.mmtypes[mmtype].name ))
+				extra_desc = '({})'.format( MMGenAddrType.mmtypes[mmtype].name ))
 			t.passphrase(dfl_wcls.desc,rt_pw)
 			t.written_to_file('Addresses')
 			ok_msg()
 		t.skip_ok = True
 		return t
 
-	def addrgen_bob(self):   return self.addrgen('bob')
-	def addrgen_alice(self): return self.addrgen('alice')
+	def addrgen_bob(self):
+		return self.addrgen('bob')
+	def addrgen_alice(self):
+		return self.addrgen('alice')
 
-	def addrimport(self,user,sid=None,addr_range='1-5',num_addrs=5,mmtypes=[],batch=True,quiet=True):
+	def addrimport(
+			self,
+			user,
+			sid        = None,
+			addr_range = '1-5',
+			num_addrs  = 5,
+			mmtypes    = [],
+			batch      = True,
+			quiet      = True):
 		id_strs = { 'legacy':'', 'compressed':'-C', 'segwit':'-S', 'bech32':'-B' }
-		if not sid: sid = self._user_sid(user)
+		if not sid:
+			sid = self._user_sid(user)
 		from mmgen.addr import MMGenAddrType
 		for mmtype in mmtypes or self.proto.mmtypes:
 			desc = MMGenAddrType.mmtypes[mmtype].name
@@ -577,8 +604,10 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		t.skip_ok = True
 		return t
 
-	def addrimport_bob(self):   return self.addrimport('bob')
-	def addrimport_alice(self): return self.addrimport('alice',batch=False,quiet=False)
+	def addrimport_bob(self):
+		return self.addrimport('bob')
+	def addrimport_alice(self):
+		return self.addrimport('alice',batch=False,quiet=False)
 
 	def bob_import_miner_addr(self):
 		if not self.deterministic:
@@ -663,7 +692,8 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 			t.expect(r'{}\b.*\D{}\b'.format(*chk),regex=True)
 		return t
 
-	def bob_twview1(self): return self.user_twview('bob', chk = ('1',rtAmts[0]) )
+	def bob_twview1(self):
+		return self.user_twview('bob', chk = ('1',rtAmts[0]) )
 
 	def user_bal(self,user,bal,args=['showempty=1'],skip_check=False):
 		t = self.spawn('mmgen-tool',['--'+user,'listaddresses'] + args)
@@ -723,8 +753,10 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		sid = self._get_user_subsid(user,subseed_idx)
 		return self.addrimport(user,sid=sid,mmtypes=['C'])
 
-	def bob_subwallet_addrimport1(self): return self.subwallet_addrimport('bob','29L')
-	def bob_subwallet_addrimport2(self): return self.subwallet_addrimport('bob','127S')
+	def bob_subwallet_addrimport1(self):
+		return self.subwallet_addrimport('bob','29L')
+	def bob_subwallet_addrimport2(self):
+		return self.subwallet_addrimport('bob','127S')
 
 	def bob_subwallet_fund(self):
 		sid1 = self._get_user_subsid('bob','29L')
@@ -840,10 +872,14 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 			)
 		return t
 
-	def bob_0conf0_getbalance(self): return self.bob_getbalance(rtBals_gb['0conf0'],confs=0)
-	def bob_0conf1_getbalance(self): return self.bob_getbalance(rtBals_gb['0conf1'],confs=1)
-	def bob_1conf1_getbalance(self): return self.bob_getbalance(rtBals_gb['1conf1'],confs=1)
-	def bob_1conf2_getbalance(self): return self.bob_getbalance(rtBals_gb['1conf2'],confs=2)
+	def bob_0conf0_getbalance(self):
+		return self.bob_getbalance(rtBals_gb['0conf0'],confs=0)
+	def bob_0conf1_getbalance(self):
+		return self.bob_getbalance(rtBals_gb['0conf1'],confs=1)
+	def bob_1conf1_getbalance(self):
+		return self.bob_getbalance(rtBals_gb['1conf1'],confs=1)
+	def bob_1conf2_getbalance(self):
+		return self.bob_getbalance(rtBals_gb['1conf2'],confs=2)
 
 	def bob_nochg_burn(self):
 		return self.user_txdo('bob',
@@ -863,35 +899,42 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 
 	def user_txsend_status(self,user,tx_file,exp1='',exp2='',extra_args=[]):
 		t = self.spawn('mmgen-txsend',['-d',self.tmpdir,'--'+user,'--status'] + extra_args + [tx_file])
-		if exp1: t.expect(exp1,regex=True)
-		if exp2: t.expect(exp2,regex=True)
+		if exp1:
+			t.expect(exp1,regex=True)
+		if exp2:
+			t.expect(exp2,regex=True)
 		return t
 
-	def user_txdo(  self, user, fee, outputs_cl, outputs_list,
-			extra_args   = [],
-			wf           = None,
-			do_label     = False,
-			bad_locktime = False,
-			full_tx_view = False,
-			menu         = ['M'],
-			skip_passphrase = False,
-			used_chg_addr_resp = None ):
+	def user_txdo(
+			self,
+			user,
+			fee,
+			outputs_cl,
+			outputs_list,
+			extra_args         = [],
+			wf                 = None,
+			bad_locktime       = False,
+			full_tx_view       = False,
+			menu               = ['M'],
+			skip_passphrase    = False,
+			used_chg_addr_resp = None):
 
 		t = self.spawn('mmgen-txdo',
 			['-d',self.tmpdir,'-B','--'+user] +
 			(['--fee='+fee] if fee else []) +
 			extra_args + ([],[wf])[bool(wf)] + outputs_cl)
 
-		self.txcreate_ui_common(t,
-			caller          = 'txdo',
-			menu            = menu,
-			inputs          = outputs_list,
-			file_desc       = 'Signed transaction',
-			interactive_fee = (tx_fee,'')[bool(fee)],
-			add_comment     = tx_comment_jp,
-			view            = 't',
-			save            = True,
-			used_chg_addr_resp = used_chg_addr_resp )
+		self.txcreate_ui_common(
+				t,
+				caller             = 'txdo',
+				menu               = menu,
+				inputs             = outputs_list,
+				file_desc          = 'Signed transaction',
+				interactive_fee    = (tx_fee,'')[bool(fee)],
+				add_comment        = tx_comment_jp,
+				view               = 't',
+				save               = True,
+				used_chg_addr_resp = used_chg_addr_resp)
 
 		if not skip_passphrase:
 			t.passphrase(dfl_wcls.desc,rt_pw)
@@ -962,7 +1005,16 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		outputs_cl = self._create_tx_outputs('bob',(('L',1,''),)) # bob_sid:L:1
 		return self.user_txdo('alice',None,outputs_cl,'1') # fee=None
 
-	def user_txbump(self,user,outdir,txfile,fee,add_args=[],has_label=True,signed_tx=True,one_output=False):
+	def user_txbump(
+			self,
+			user,
+			outdir,
+			txfile,
+			fee,
+			add_args   = [],
+			has_label  = True,
+			signed_tx  = True,
+			one_output = False):
 		if not self.proto.cap('rbf'):
 			return 'skip'
 		t = self.spawn('mmgen-txbump',
@@ -1163,7 +1215,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 			expect        = (),
 			expect2       = (),
 			warn_used     = False,
-			non_segwit_ok = False ):
+			non_segwit_ok = False):
 
 		if not (non_segwit_ok or self.proto.cap('segwit')):
 			return 'skip'
@@ -1301,7 +1353,12 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		self.write_to_tmpfile( fn, json.dumps(text,indent=4) )
 		return 'ok'
 
-	def carol_twimport(self,rpc_backend='http',add_parms=[],expect_str=None,expect_str2='Found 1 unspent output'):
+	def carol_twimport(
+			self,
+			rpc_backend = 'http',
+			add_parms   = [],
+			expect_str  = None,
+			expect_str2 = 'Found 1 unspent output'):
 		from mmgen.tw.json import TwJSON
 		fn = joinpath( self.tmpdir, TwJSON.Base(cfg,self.proto).dump_fn )
 		t = self.spawn(
@@ -1433,8 +1490,10 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		sid = self._user_sid('alice')
 		return self._user_chk_comment('alice',sid+':C:1','Replacement Label',extra_args=['age_fmt=block'])
 
-	def alice_edit_comment1(self): return self.user_edit_comment('alice','4',tw_comment_lat_cyr_gr)
-	def alice_edit_comment2(self): return self.user_edit_comment('alice','3',tw_comment_zh)
+	def alice_edit_comment1(self):
+		return self.user_edit_comment('alice','4',tw_comment_lat_cyr_gr)
+	def alice_edit_comment2(self):
+		return self.user_edit_comment('alice','3',tw_comment_zh)
 
 	def alice_chk_comment3(self):
 		sid = self._user_sid('alice')
@@ -1706,7 +1765,15 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 			return 'skip'
 		return self.generate()
 
-	def _usr_auto_chg(self,user,mmtype,idx,by_mmtype=False,include_dest=True,by_addrtype=False,ignore_labels=False):
+	def _usr_auto_chg(
+			self,
+			user,
+			mmtype,
+			idx,
+			by_mmtype     = False,
+			include_dest  = True,
+			by_addrtype   = False,
+			ignore_labels = False):
 		if mmtype in ('S','B') and not self.proto.cap('segwit'):
 			return 'skip'
 		sid = self._user_sid('bob')

+ 48 - 21
test/test_py_d/ts_seedsplit.py

@@ -96,8 +96,10 @@ class TestSuiteSeedSplit(TestSuiteBase):
 		return t
 
 	def ss_splt(self,tdir,ofmt,spec,add_args=[],wf=None,master=None):
-		try: os.mkdir(self.get_tmp_subdir(tdir))
-		except: pass
+		try:
+			os.mkdir(self.get_tmp_subdir(tdir))
+		except:
+			pass
 		t = self.spawn('mmgen-seedsplit',
 				['-q','-d',self.get_tmp_subdir(tdir),'-r0','-o',ofmt]
 				+ (['-L',(spec or 'label')] if ofmt == 'w' else [])
@@ -123,7 +125,16 @@ class TestSuiteSeedSplit(TestSuiteBase):
 		t.written_to_file(capfirst(ocls.desc))
 		return t
 
-	def ss_join(self,tdir,ofmt,in_exts,add_args=[],sid=None,bad_invocation=False,master=None,id_str=None):
+	def ss_join(
+			self,
+			tdir,
+			ofmt,
+			in_exts,
+			add_args       = [],
+			sid            = None,
+			bad_invocation = False,
+			master         = None,
+			id_str         = None):
 		td = self.get_tmp_subdir(tdir)
 		shares = [get_file_with_ext(td,f) for f in in_exts]
 		if not sid:
@@ -166,30 +177,46 @@ class TestSuiteSeedSplit(TestSuiteBase):
 		sid = self.read_from_tmpfile('dfl.sid')
 		return os.path.join(self.tmpdir,tdir,sid+suf+'.hincog') + ',123'
 
-	def ss_2way_A_dfl1(self):    return self.ss_splt('2way_dfl1','w','1:2')
-	def ss_2way_B_dfl1(self):    return self.ss_splt('2way_dfl1','bip39','2:2')
-	def ss_2way_join_dfl1(self): return self.ss_join('2way_dfl1','w',['mmdat','bip39'])
+	def ss_2way_A_dfl1(self):
+		return self.ss_splt('2way_dfl1','w','1:2')
+	def ss_2way_B_dfl1(self):
+		return self.ss_splt('2way_dfl1','bip39','2:2')
+	def ss_2way_join_dfl1(self):
+		return self.ss_join('2way_dfl1','w',['mmdat','bip39'])
 
-	def ss_2way_A_dfl2(self):    return self.ss_splt('2way_dfl2','seed','default:1:2')
+	def ss_2way_A_dfl2(self):
+		return self.ss_splt('2way_dfl2','seed','default:1:2')
 	def ss_2way_B_dfl2(self):
 		return self.ss_splt('2way_dfl2','hincog','default:2:2',['-J',self.get_hincog_arg('2way_dfl2')])
 	def ss_2way_join_dfl2(self):
 		return self.ss_join('2way_dfl2','mmhex',['mmseed'],['-H',self.get_hincog_arg('2way_dfl2')])
 
-	def ss_2way_A_alice(self):        return self.ss_splt('2way_alice','w','alice:1:2')
-	def ss_2way_B_alice(self):        return self.ss_splt('2way_alice','mmhex','alice:2:2')
-	def ss_2way_join_alice(self):     return self.ss_join('2way_alice','seed',['mmdat','mmhex'])
-	def ss_2way_join_alice_mix(self): return self.ss_join('2way_alice','seed',['mmhex','mmdat'])
-
-	def ss_2way_A_dfl_usw(self):    return self.ss_splt('2way_dfl_usw','words','1:2',[],wf=ref_wf)
-	def ss_2way_B_dfl_usw(self):    return self.ss_splt('2way_dfl_usw','incog','2:2',[],wf=ref_wf)
-	def ss_2way_join_dfl_usw(self): return self.ss_join('2way_dfl_usw','mmhex',['mmwords','mmincog'],sid=ref_sid)
-
-	def ss_3way_A_dfl(self):        return self.ss_splt('3way_dfl','words','1:3')
-	def ss_3way_B_dfl(self):        return self.ss_splt('3way_dfl','incog_hex','2:3')
-	def ss_3way_C_dfl(self):        return self.ss_splt('3way_dfl','bip39','3:3')
-	def ss_3way_join_dfl(self):     return self.ss_join('3way_dfl','mmhex',['mmwords','mmincox','bip39'])
-	def ss_3way_join_dfl_mix(self): return self.ss_join('3way_dfl','mmhex',['bip39','mmwords','mmincox'])
+	def ss_2way_A_alice(self):
+		return self.ss_splt('2way_alice','w','alice:1:2')
+	def ss_2way_B_alice(self):
+		return self.ss_splt('2way_alice','mmhex','alice:2:2')
+	def ss_2way_join_alice(self):
+		return self.ss_join('2way_alice','seed',['mmdat','mmhex'])
+	def ss_2way_join_alice_mix(self):
+		return self.ss_join('2way_alice','seed',['mmhex','mmdat'])
+
+	def ss_2way_A_dfl_usw(self):
+		return self.ss_splt('2way_dfl_usw','words','1:2',[],wf=ref_wf)
+	def ss_2way_B_dfl_usw(self):
+		return self.ss_splt('2way_dfl_usw','incog','2:2',[],wf=ref_wf)
+	def ss_2way_join_dfl_usw(self):
+		return self.ss_join('2way_dfl_usw','mmhex',['mmwords','mmincog'],sid=ref_sid)
+
+	def ss_3way_A_dfl(self):
+		return self.ss_splt('3way_dfl','words','1:3')
+	def ss_3way_B_dfl(self):
+		return self.ss_splt('3way_dfl','incog_hex','2:3')
+	def ss_3way_C_dfl(self):
+		return self.ss_splt('3way_dfl','bip39','3:3')
+	def ss_3way_join_dfl(self):
+		return self.ss_join('3way_dfl','mmhex',['mmwords','mmincox','bip39'])
+	def ss_3way_join_dfl_mix(self):
+		return self.ss_join('3way_dfl','mmhex',['bip39','mmwords','mmincox'])
 
 	def ss_2way_A_dfl_master3(self):
 		return self.ss_splt('2way_dfl_master3','w','',master=3)

+ 49 - 28
test/test_py_d/ts_shared.py

@@ -31,22 +31,24 @@ from .common import ref_bw_file,ref_bw_hash_preset,ref_dir
 class TestSuiteShared(object):
 	'shared methods for the test.py test suite'
 
-	def txcreate_ui_common(self,t,
-			caller            = None,
-			menu              = [],
-			inputs            = '1',
-			file_desc         = 'Unsigned transaction',
-			input_sels_prompt = 'to spend',
-			bad_input_sels    = False,
-			interactive_fee   = '',
-			fee_desc          = 'transaction fee',
-			fee_info_pat      = None,
-			add_comment       = '',
-			view              = 't',
-			save              = True,
-			tweaks            = [],
+	def txcreate_ui_common(
+			self,
+			t,
+			caller             = None,
+			menu               = [],
+			inputs             = '1',
+			file_desc          = 'Unsigned transaction',
+			input_sels_prompt  = 'to spend',
+			bad_input_sels     = False,
+			interactive_fee    = '',
+			fee_desc           = 'transaction fee',
+			fee_info_pat       = None,
+			add_comment        = '',
+			view               = 't',
+			save               = True,
+			tweaks             = [],
 			used_chg_addr_resp = None,
-			auto_chg_addr     = None ):
+			auto_chg_addr      = None):
 
 		txdo = (caller or self.test_name)[:4] == 'txdo'
 
@@ -106,7 +108,9 @@ class TestSuiteShared(object):
 
 		return t
 
-	def txsign_ui_common(self,t,
+	def txsign_ui_common(
+			self,
+			t,
 			caller      = None,
 			view        = 't',
 			add_comment = '',
@@ -114,7 +118,7 @@ class TestSuiteShared(object):
 			ni          = False,
 			save        = True,
 			do_passwd   = False,
-			has_label   = False ):
+			has_label   = False):
 
 		txdo = (caller or self.test_name)[:4] == 'txdo'
 
@@ -130,7 +134,9 @@ class TestSuiteShared(object):
 
 		return t
 
-	def txsend_ui_common(self,t,
+	def txsend_ui_common(
+			self,
+			t,
 			caller       = None,
 			view         = 'n',
 			add_comment  = '',
@@ -138,7 +144,7 @@ class TestSuiteShared(object):
 			confirm_send = True,
 			bogus_send   = True,
 			quiet        = False,
-			has_label    = False ):
+			has_label    = False):
 
 		txdo = (caller or self.test_name)[:4] == 'txdo'
 
@@ -167,7 +173,10 @@ class TestSuiteShared(object):
 		t.written_to_file('Signed transaction' + (' #' + tnum if tnum else ''), oo=True)
 		return t
 
-	def txsign(self,wf,txfile,
+	def txsign(
+			self,
+			wf,
+			txfile,
 			pf         = '',
 			bumpf      = '',
 			save       = True,
@@ -175,7 +184,7 @@ class TestSuiteShared(object):
 			extra_opts = [],
 			extra_desc = '',
 			view       = 'n',
-			dfl_wallet = False ):
+			dfl_wallet = False):
 		opts = extra_opts + ['-d',self.tmpdir,txfile] + ([wf] if wf else [])
 		t = self.spawn('mmgen-txsign', opts, extra_desc)
 		t.license()
@@ -197,7 +206,15 @@ class TestSuiteShared(object):
 		add_args = [f'-l{self.seed_len}', f'-p{ref_bw_hash_preset}']
 		return self.walletchk(wf,pf=None,add_args=add_args,sid=self.ref_bw_seed_id)
 
-	def walletchk(self,wf,pf,wcls=None,add_args=[],sid=None,extra_desc='',dfl_wallet=False):
+	def walletchk(
+			self,
+			wf,
+			pf,
+			wcls       = None,
+			add_args   = [],
+			sid        = None,
+			extra_desc = '',
+			dfl_wallet = False):
 		hp = self.hash_preset if hasattr(self,'hash_preset') else '1'
 		wcls = wcls or get_wallet_cls(ext=get_extension(wf))
 		t = self.spawn('mmgen-walletchk',
@@ -215,20 +232,23 @@ class TestSuiteShared(object):
 			cmp_or_die(chk,sid)
 		return t
 
-	def addrgen(self,wf,
-			pf         = None,
+	def addrgen(
+			self,
+			wf,
+			pf = None,
 			check_ref  = False,
 			ftype      = 'addr',
 			id_str     = None,
 			extra_args = [],
 			mmtype     = None,
 			stdout     = False,
-			dfl_wallet = False ):
+			dfl_wallet = False):
 		passgen = ftype[:4] == 'pass'
 		if not mmtype and not passgen:
 			mmtype = self.segwit_mmtype
 		cmd_pfx = (ftype,'pass')[passgen]
-		t = self.spawn(f'mmgen-{cmd_pfx}gen',
+		t = self.spawn(
+				f'mmgen-{cmd_pfx}gen',
 				['-d',self.tmpdir] + extra_args +
 				([],['--type='+str(mmtype)])[bool(mmtype)] +
 				([],['--stdout'])[stdout] +
@@ -246,8 +266,9 @@ class TestSuiteShared(object):
 			t.expect('Encrypt password list? (y/N): ','N')
 		t.read() if stdout else t.written_to_file(('Addresses','Password list')[passgen])
 		if check_ref:
-			chk_ref = (self.chk_data[self.test_name] if passgen else
-						self.chk_data[self.test_name][self.fork][self.proto.testnet])
+			chk_ref = (
+				self.chk_data[self.test_name] if passgen else
+				self.chk_data[self.test_name][self.fork][self.proto.testnet])
 			cmp_or_die(chk,chk_ref,desc=f'{ftype}list data checksum')
 		return t
 

+ 1 - 3
test/test_py_d/ts_tool.py

@@ -53,9 +53,7 @@ class TestSuiteTool(TestSuiteMain,TestSuiteBase):
 			t = self.spawn(
 				'mmgen-tool',
 				['-d',self.tmpdir,'-r0','rand2file','rand2file.out',nbytes],
-				extra_desc='({} byte{})'.format(
-					nbytes,
-					suf(parse_bytespec(nbytes)) )
+				extra_desc='({} byte{})'.format( nbytes, suf(parse_bytespec(nbytes)) )
 			)
 			t.expect('random data written to file')
 			t.read()

+ 42 - 26
test/test_py_d/ts_wallet.py

@@ -100,13 +100,18 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 
 	def ref_mn_conv(self,ext='mmwords'):
 		wf = joinpath(ref_dir,self.seed_id+'.'+ext)
-		return self.walletconv_in(wf,oo=True)
-
-	def ref_bip39_conv(self):    return self.ref_mn_conv(ext='bip39')
-	def ref_seed_conv(self):     return self.ref_mn_conv(ext='mmseed')
-	def ref_hex_conv(self):      return self.ref_mn_conv(ext='mmhex')
-	def ref_plainhex_conv(self): return self.ref_mn_conv(ext='hex')
-	def ref_dieroll_conv(self):  return self.ref_mn_conv(ext='b6d')
+		return self.walletconv_in(wf)
+
+	def ref_bip39_conv(self):
+		return self.ref_mn_conv(ext='bip39')
+	def ref_seed_conv(self):
+		return self.ref_mn_conv(ext='mmseed')
+	def ref_hex_conv(self):
+		return self.ref_mn_conv(ext='mmhex')
+	def ref_plainhex_conv(self):
+		return self.ref_mn_conv(ext='hex')
+	def ref_dieroll_conv(self):
+		return self.ref_mn_conv(ext='b6d')
 
 	def ref_brain_conv(self):
 		uopts = ['-i','bw','-p','1','-l',str(self.seed_len)]
@@ -133,15 +138,24 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 	def ref_hincog_conv_old(self):
 		return self.ref_hincog_conv(wfk='hic_wallet_old',add_uopts=['-O'])
 
-	def ref_wallet_conv_out(self):   return self.walletconv_out('w')
-	def ref_mn_conv_out(self):       return self.walletconv_out('mn')
-	def ref_bip39_conv_out(self):    return self.walletconv_out('bip39')
-	def ref_seed_conv_out(self):     return self.walletconv_out('seed')
-	def ref_hex_conv_out(self):      return self.walletconv_out('hexseed')
-	def ref_plainhex_conv_out(self): return self.walletconv_out('hex')
-	def ref_dieroll_conv_out(self):  return self.walletconv_out('dieroll')
-	def ref_incog_conv_out(self):    return self.walletconv_out('i')
-	def ref_incox_conv_out(self):    return self.walletconv_out('xi')
+	def ref_wallet_conv_out(self):
+		return self.walletconv_out('w')
+	def ref_mn_conv_out(self):
+		return self.walletconv_out('mn')
+	def ref_bip39_conv_out(self):
+		return self.walletconv_out('bip39')
+	def ref_seed_conv_out(self):
+		return self.walletconv_out('seed')
+	def ref_hex_conv_out(self):
+		return self.walletconv_out('hexseed')
+	def ref_plainhex_conv_out(self):
+		return self.walletconv_out('hex')
+	def ref_dieroll_conv_out(self):
+		return self.walletconv_out('dieroll')
+	def ref_incog_conv_out(self):
+		return self.walletconv_out('i')
+	def ref_incox_conv_out(self):
+		return self.walletconv_out('xi')
 
 	def ref_hincog_conv_out(self,ic_f=None):
 		if not ic_f:
@@ -196,10 +210,11 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 		t.p.wait()
 		# back check of result
 		msg('' if cfg.profile else ' OK')
-		return self.walletchk(  wf,
-								pf         = None,
-								extra_desc = '(check)',
-								sid        = self.seed_id )
+		return self.walletchk(
+				wf,
+				pf         = None,
+				extra_desc = '(check)',
+				sid        = self.seed_id)
 
 	def walletconv_out(self,out_fmt='w',uopts=[],uopts_chk=[]):
 		wcls = get_wallet_cls(fmt_code=out_fmt)
@@ -226,9 +241,10 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 			add_args += uopts_chk
 			wf = None
 		msg('' if cfg.profile else ' OK')
-		return self.walletchk(  wf,
-								pf         = pf,
-								wcls       = wcls,
-								extra_desc = '(check)',
-								sid        = self.seed_id,
-								add_args   = add_args )
+		return self.walletchk(
+				wf,
+				pf         = pf,
+				wcls       = wcls,
+				extra_desc = '(check)',
+				sid        = self.seed_id,
+				add_args   = add_args)

+ 13 - 2
test/test_py_d/ts_xmr_autosign.py

@@ -277,7 +277,15 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
 		get_file_with_ext(self.asi.xmr_tx_dir,'sigtx',delete_all=True)
 		return self._create_transfer_tx('0.257')
 
-	def _xmr_autosign_op(self,op,desc=None,dtype=None,ext=None,wallet_arg=None,add_opts=[],wait_signed=False):
+	def _xmr_autosign_op(
+			self,
+			op,
+			desc        = None,
+			dtype       = None,
+			ext         = None,
+			wallet_arg  = None,
+			add_opts    = [],
+			wait_signed = False):
 		if wait_signed:
 			oqmsg_r(gray(f'→ offline wallet{"s" if dtype.endswith("s") else ""} signing {dtype}'))
 			while True:
@@ -330,7 +338,10 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
 		return self._submit_transfer_tx( ext='sigtx' )
 
 	def resubmit_transfer_tx1(self):
-		return self._submit_transfer_tx( relay_parm=self.tx_relay_daemon_proxy_parm, op='resubmit', check_bal=False )
+		return self._submit_transfer_tx(
+				relay_parm = self.tx_relay_daemon_proxy_parm,
+				op         = 'resubmit',
+				check_bal  = False)
 
 	def submit_transfer_tx2(self):
 		return self._submit_transfer_tx( relay_parm=self.tx_relay_daemon_parm )

+ 21 - 9
test/test_py_d/ts_xmrwallet.py

@@ -160,9 +160,12 @@ class TestSuiteXMRWallet(TestSuiteBase):
 
 		def port_in_use(port):
 			import socket
-			try: socket.create_connection(('localhost',port)).close()
-			except: return False
-			else: return True
+			try:
+				socket.create_connection(('localhost',port)).close()
+			except:
+				return False
+			else:
+				return True
 
 		def start_proxy():
 			if external_call or not cfg.no_daemon_autostart:
@@ -355,8 +358,10 @@ class TestSuiteXMRWallet(TestSuiteBase):
 		t.skip_ok = True
 		return t
 
-	def create_wallets_miner(self): return self.create_wallets('miner')
-	def create_wallets_alice(self): return self.create_wallets('alice')
+	def create_wallets_miner(self):
+		return self.create_wallets('miner')
+	def create_wallets_alice(self):
+		return self.create_wallets('alice')
 
 	def create_wallets(self,user,wallet=None,add_opts=[],op='create'):
 		assert wallet is None or is_int(wallet), 'wallet arg'
@@ -510,13 +515,17 @@ class TestSuiteXMRWallet(TestSuiteBase):
 				assert bal_chk_func(n,*amts), f'balance check for wallet {n} failed!'
 		return t
 
-	def do_op(self, op, user, arg2,
+	def do_op(
+			self,
+			op,
+			user,
+			arg2,
 			tx_relay_parm = None,
 			no_relay      = False,
 			return_amt    = False,
 			reuse_acct    = False,
 			add_desc      = None,
-			do_ret        = False ):
+			do_ret        = False):
 
 		data = self.users[user]
 		cmd_opts = list_gen(
@@ -635,7 +644,8 @@ class TestSuiteXMRWallet(TestSuiteBase):
 		min_bal = XMRAmt('0.9')
 
 		for i in range(4):
-			if i: ok()
+			if i:
+				ok()
 			get_file_with_ext(self.users['alice'].udir,'sigtx',delete_all=True)
 			send_amt = self.do_op(
 				'sweep','alice','2:1,3', # '2:1,3'
@@ -834,7 +844,9 @@ class TestSuiteXMRWallet(TestSuiteBase):
 
 		for count in range(max_iterations):
 			bal_info = await get_balance(dest,count)
-			if h > height_threshold and (dest.test(bal_info) is True or ( chk_bal_chg and bal_info.ub != bal_info_start.ub )):
+			if h > height_threshold and (
+						dest.test(bal_info) is True or (chk_bal_chg and bal_info.ub != bal_info_start.ub)
+					):
 				imsg('')
 				oqmsg_r('+')
 				print_balance(dest,bal_info)

+ 38 - 21
test/tooltest.py

@@ -239,7 +239,8 @@ class MMGenToolTestUtils(object):
 			tool_args +
 			kwargs.split()
 		)
-		if extra_msg: extra_msg = f'({extra_msg})'
+		if extra_msg:
+			extra_msg = f'({extra_msg})'
 		full_name = ' '.join([name.lower()]+add_opts+kwargs.split()+extra_msg.split())
 		if not silent:
 			if cfg.verbose:
@@ -252,8 +253,11 @@ class MMGenToolTestUtils(object):
 		out = cp.stdout
 		err = cp.stderr
 		if cfg.debug:
-			try: dmsg(err.decode())
-			except: dmsg(repr(err))
+			from test.include.common import dmsg
+			try:
+				dmsg(err.decode())
+			except:
+				dmsg(repr(err))
 		if not binary:
 			out = out.decode()
 		if cp.returncode != 0:
@@ -272,7 +276,8 @@ class MMGenToolTestUtils(object):
 		vmsg('Out:  ' + repr(ret))
 		def cmp_equal(a,b):
 			return (a.lstrip('0') == b.lstrip('0')) if strip_hex else (a == b)
-		if cmp_equal(ret,idata): ok()
+		if cmp_equal(ret,idata):
+			ok()
 		else:
 			die(4, "Error: values don't match:\nIn:  {!r}\nOut: {!r}".format(idata,ret))
 		return ret
@@ -298,9 +303,11 @@ class MMGenToolTestUtils(object):
 			if chkdata:
 				cmp_or_die(ret,chkdata)
 				return
-			if Return: return ret
+			if Return:
+				return ret
 			else:
-				if not hush: ok()
+				if not hush:
+					ok()
 		else:
 			die(4,f'Error for command {name!r}')
 
@@ -317,10 +324,13 @@ class MMGenToolTestUtils(object):
 tu = MMGenToolTestUtils()
 
 def ok_or_die(val,chk_func,s,skip_ok=False):
-	try: ret = chk_func(val)
-	except: ret = False
+	try:
+		ret = chk_func(val)
+	except:
+		ret = False
 	if ret:
-		if not skip_ok: ok()
+		if not skip_ok:
+			ok()
 	else:
 		die(4,f'Returned value {val!r} is not a {s}')
 
@@ -367,22 +377,24 @@ class MMGenToolTestCmds(object):
 			cmp_or_die(iaddr,ret)
 			ok()
 	def hex2wif(self,name,f1,f2,f3,f4):
-		for n,fi,fo,k in ((1,f1,f2,''),(2,f3,f4,compressed)):
+		for fi,fo,k in (
+				(f1,f2,''),
+				(f3,f4,compressed)):
 			ao = ['--type='+k] if k else []
 			ret = tu.run_cmd_chk(name,fi,fo,add_opts=ao)
 	def addr2pubhash(self,name,f1,f2,f3,f4):
 		for n,f,m,ao in (
-			(1,f1,'',[]),
-			(2,f2,'from {}'.format( compressed or 'uncompressed' ),[]),
-			(4,f4,'',type_bech32_arg),
+				(1,f1,'',[]),
+				(2,f2,'from {}'.format( compressed or 'uncompressed' ),[]),
+				(4,f4,'',type_bech32_arg),
 			):
 			addr = read_from_file(f).split()[-1]
 			tu.run_cmd_out(name,addr,fn_idx=n,add_opts=ao,extra_msg=m)
 	def pubhash2addr(self,name,f1,f2,f3,f4,f5,f6,f7,f8):
 		for n,fi,fo,m,ao in (
-			(1,f1,f2,'',[]),
-			(2,f3,f4,'from {}'.format( compressed or 'uncompressed' ),[]),
-			(4,f7,f8,'',type_bech32_arg)
+				(1,f1,f2,'',[]),
+				(2,f3,f4,'from {}'.format( compressed or 'uncompressed' ),[]),
+				(4,f7,f8,'',type_bech32_arg)
 			):
 			tu.run_cmd_chk(name,fi,fo,add_opts=ao,extra_msg=m)
 	def privhex2pubhex(self,name,f1,f2,f3): # from Hex2wif
@@ -435,10 +447,14 @@ class MMGenToolTestCmds(object):
 	def mn2hex(self,name,f1,f2,f3,f4,f5,f6):
 		for f_i,f_o,m in ((f1,f2,'128-bit'),(f3,f4,'192-bit'),(f5,f6,'256-bit')):
 			tu.run_cmd_chk(name,f_i,f_o,extra_msg=m,strip_hex=True)
-	def mn_rand128(self,name): tu.run_cmd_out(name)
-	def mn_rand192(self,name): tu.run_cmd_out(name)
-	def mn_rand256(self,name): tu.run_cmd_out(name)
-	def mn_stats(self,name):   tu.run_cmd_out(name)
+	def mn_rand128(self,name):
+		tu.run_cmd_out(name)
+	def mn_rand192(self,name):
+		tu.run_cmd_out(name)
+	def mn_rand256(self,name):
+		tu.run_cmd_out(name)
+	def mn_stats(self,name):
+		tu.run_cmd_out(name)
 	def mn_printlist(self,name):
 		tu.run_cmd(name,[])
 		ok()
@@ -488,7 +504,8 @@ try:
 		for cmd in cmd_data:
 			msg('Running tests for {}:'.format( cmd_data[cmd]['desc'] ))
 			do_cmds(cmd)
-			if cmd is not list(cmd_data.keys())[-1]: msg('')
+			if cmd is not list(cmd_data.keys())[-1]:
+				msg('')
 except KeyboardInterrupt:
 	die(1,green('\nExiting at user request'))
 

+ 8 - 3
test/tooltest2.py

@@ -341,7 +341,10 @@ tests = {
 		],
 		'hash256': [
 			( ['deadbeef'], 'e107944e77a688feae4c2d4db5951923812dd0f72026a11168104ee1b248f8a9' ),
-			( ['000000000000000000000000000000000000000000'], 'fd5181fcd097a334ab340569e5edcd09f702fef7994abab01f4b66e86b32ebbe' ),
+			(
+				['000000000000000000000000000000000000000000'],
+				'fd5181fcd097a334ab340569e5edcd09f702fef7994abab01f4b66e86b32ebbe'
+			),
 			( [''], '5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456' ),
 			( ['ffffffffffffffff'], '57b2d2c3455e0f76c61c5237ff04fc9fc0f3fe691e587ea9c951949e1a5e0fed' ),
 		],
@@ -824,8 +827,10 @@ def check_output(out,chk):
 	if isinstance(out,str):
 		out = out.encode()
 	err_fs = "Output ({!r}) doesn't match expected output ({!r})"
-	try: outd = out.decode()
-	except: outd = None
+	try:
+		outd = out.decode()
+	except:
+		outd = None
 
 	if type(chk).__name__ == 'function':
 		assert chk(outd), f'{chk.__name__}({outd}) failed!'

+ 8 - 1
test/unit_tests_d/ut_addrlist.py

@@ -14,7 +14,14 @@ from mmgen.passwdlist import PasswordList
 from mmgen.protocol import init_proto
 from ..include.common import cfg,qmsg,vmsg
 
-def do_test(list_type,chksum,idx_spec=None,pw_id_str=None,add_kwargs=None,coin=None,addrtype=None):
+def do_test(
+		list_type,
+		chksum,
+		idx_spec   = None,
+		pw_id_str  = None,
+		add_kwargs = None,
+		coin       = None,
+		addrtype   = None):
 
 	qmsg(blue(f'Testing {list_type.__name__}'))
 	proto = init_proto( cfg, coin or 'btc' )

+ 1 - 4
test/unit_tests_d/ut_addrparse.py

@@ -59,10 +59,7 @@ def test_network(proto,addrs):
 		return pp_fmt({k:(v.hex() if isinstance(v,bytes) else v) for k,v in addr.parsed._asdict().items()})
 
 	def print_info(addr):
-		vmsg('\n{}\n{}\n{}'.format(
-			yellow(addr.addr_fmt),
-			cyan(addr),
-			fmt_addr_data(addr)))
+		vmsg('\n{}\n{}\n{}'.format(yellow(addr.addr_fmt), cyan(addr), fmt_addr_data(addr)))
 
 	msg_r(f'Testing {proto.coin} address parsing...')
 	vmsg('')

+ 20 - 13
test/unit_tests_d/ut_indexed_dict.py

@@ -11,12 +11,13 @@ from ..include.common import vmsg
 class unit_test(object):
 
 	def run_test(self,name,ut):
-		bad_msg = ( 'initializing values via constructor',
-					'reassignment to existing key',
-					'item deletion',
-					'item moving',
-					'clearing',
-					'updating' )
+		bad_msg = (
+			'initializing values via constructor',
+			'reassignment to existing key',
+			'item deletion',
+			'item moving',
+			'clearing',
+			'updating')
 		def bad0(): IndexedDict(arg)
 		def bad1(): d['a'] = 2
 		def bad2(): del d['a']
@@ -41,13 +42,19 @@ class unit_test(object):
 		dict(arg)
 
 		for i in range(6):
-			try: locals()['bad'+str(i)]()
-			except NotImplementedError as e: omsg(e)
-			else: odie(i)
-
-		try: d.key(2)
-		except Exception as e: omsg(e)
-		else: odie('list index out of range')
+			try:
+				locals()['bad'+str(i)]()
+			except NotImplementedError as e:
+				omsg(e)
+			else:
+				odie(i)
+
+		try:
+			d.key(2)
+		except Exception as e:
+			omsg(e)
+		else:
+			odie('list index out of range')
 
 		d['c'] = 3
 

+ 3 - 1
test/unit_tests_d/ut_lockable.py

@@ -24,7 +24,9 @@ class unit_test(object):
 		ac.foo = 'new fooval'
 		ac.foo = 'new fooval2'
 
-		class MyAttrCtrlAutolock(AttrCtrl): pass
+		class MyAttrCtrlAutolock(AttrCtrl):
+			pass
+
 		aca = MyAttrCtrlAutolock()
 
 		class MyAttrCtrlClsCheck(AttrCtrl):

+ 2 - 1
test/unit_tests_d/ut_tx_deserialize.py

@@ -39,7 +39,8 @@ async def test_tx(tx_proto,tx_hex,desc,n):
 	rpc = await rpc_init( cfg, proto=tx_proto, ignore_wallet=True )
 	d = await rpc.call('decoderawtransaction',tx_hex)
 
-	if has_nonstandard_outputs(d['vout']): return False
+	if has_nonstandard_outputs(d['vout']):
+		return False
 
 	dt = DeserializeTX(tx_proto,tx_hex)