Browse Source

import cleanups throughout

The MMGen Project 3 years ago
parent
commit
ad569cbeb7

+ 0 - 2
mmgen/amt.py

@@ -23,8 +23,6 @@ amt.py: MMGen CoinAmt and related classes
 from decimal import Decimal
 from .objmethods import Hilite,InitErrors
 
-class UnknownCoinAmt(Decimal): pass
-
 class DecimalNegateResult(Decimal): pass
 
 class CoinAmt(Decimal,Hilite,InitErrors): # abstract class

+ 3 - 2
mmgen/baseconv.py

@@ -21,10 +21,11 @@ baseconv.py:  base conversion class for the MMGen suite
 """
 
 from hashlib import sha256
-from .exception import *
-from .util import die
 from collections import namedtuple
 
+from .exception import BaseConversionError,BaseConversionPadError,HexadecimalStringError,SeedLengthError
+from .util import die
+
 def is_b58_str(s):
 	return set(list(s)) <= set(baseconv('b58').digits)
 

+ 1 - 1
mmgen/bip39.py

@@ -22,7 +22,7 @@ bip39.py - Data and routines for BIP39 mnemonic seed phrases
 
 from hashlib import sha256
 
-from .exception import *
+from .exception import MnemonicError
 from .baseconv import baseconv
 from .util import is_hex_str
 

+ 6 - 3
mmgen/daemon.py

@@ -20,11 +20,13 @@
 daemon.py:  Daemon control interface for the MMGen suite
 """
 
-import shutil
+import os,shutil,time
 from subprocess import run,PIPE,CompletedProcess
 from collections import namedtuple
-from .exception import *
-from .common import *
+
+from .globalvars import g
+from .opts import opt
+from .util import msg,die,list_gen,get_subclasses
 from .flags import *
 
 _dd = namedtuple('daemon_data',['coind_name','coind_version','coind_version_str']) # latest tested version
@@ -78,6 +80,7 @@ class Daemon(Lockable):
 		try:
 			cp = run(cmd,check=False,stdout=out,stderr=out)
 		except Exception as e:
+			from .exception import MMGenCalledProcessError
 			raise MMGenCalledProcessError(f'Error starting executable: {type(e).__name__} [Errno {e.errno}]')
 		if self.debug:
 			print(cp)

+ 2 - 1
mmgen/fileutil.py

@@ -23,7 +23,6 @@ fileutil.py: Routines that read, write, execute or stat files
 import sys,os
 
 from .globalvars import g
-from .exception import FileNotFound,MaxInputSizeExceeded
 from .util import (
 	msg,
 	qmsg,
@@ -90,6 +89,7 @@ def _check_file_type_and_access(fname,ftype,blkdev_ok=False):
 	try:
 		mode = os.stat(fname).st_mode
 	except:
+		from .exception import FileNotFound
 		raise FileNotFound(f'Requested {ftype} {fname!r} not found')
 
 	for t in ok_types:
@@ -289,6 +289,7 @@ def get_data_from_file(infile,desc='data',dash=False,silent=False,binary=False,q
 		data = data.decode()
 
 	if len(data) == g.max_input_size + 1:
+		from .exception import MaxInputSizeExceeded
 		raise MaxInputSizeExceeded(f'Too much input data!  Max input data size: {f.max_input_size} bytes')
 
 	return data

+ 4 - 8
mmgen/main_autosign.py

@@ -24,6 +24,8 @@ import sys,os,time,signal,shutil
 from subprocess import run,PIPE,DEVNULL
 from stat import *
 
+from .common import *
+
 mountpoint   = '/mnt/tx'
 tx_dir       = '/mnt/tx/tx'
 part_label   = 'MMGEN_TX'
@@ -35,10 +37,8 @@ mn_fmts      = {
 }
 mn_fmt_dfl   = 'mmgen'
 
-from .common import *
 opts.UserOpts._set_ok += ('outdir','passwd_file')
 
-prog_name = os.path.basename(sys.argv[0])
 opts_data = {
 	'sets': [('stealth_led', True, 'led', True)],
 	'text': {
@@ -118,7 +118,7 @@ This command is currently available only on Linux-based platforms.
 
 cmd_args = opts.init(
 	opts_data,
-	add_opts = ['outdir','passwd_file'], # required, because in _set_ok
+	add_opts = ['outdir','passwd_file'], # in _set_ok, so must be set
 	init_opts = {
 		'quiet': True,
 		'out_fmt': 'wallet',
@@ -135,15 +135,12 @@ if opt.mnemonic_fmt:
 			opt.mnemonic_fmt,
 			fmt_list(mn_fmts,fmt='no_spc') ))
 
-import mmgen.tx
 from .wallet import Wallet
+from .tx import MMGenTX
 from .txsign import txsign
 from .protocol import init_proto
 from .rpc import rpc_init
 
-if g.test_suite:
-	from .daemon import CoinDaemon
-
 if opt.mountpoint:
 	mountpoint = opt.mountpoint
 
@@ -198,7 +195,6 @@ def do_umount():
 		run(['umount',mountpoint],check=True)
 
 async def sign_tx_file(txfile):
-	from .tx import MMGenTX
 	try:
 		tx1 = MMGenTX.Unsigned(filename=txfile)
 		if tx1.proto.sign_mode == 'daemon':

+ 1 - 1
mmgen/passwdlist.py

@@ -22,7 +22,6 @@ passwdlist.py: Password list class for the MMGen suite
 
 from collections import namedtuple
 
-from .exception import InvalidPasswdFormat
 from .util import ymsg,is_hex_str,is_int,keypress_confirm
 from .obj import ImmutableAttr,ListItemAttr,MMGenPWIDString
 from .baseconv import baseconv,is_b32_str,is_b58_str
@@ -115,6 +114,7 @@ class PasswordList(AddrList):
 			self.pw_fmt = pw_fmt
 			self.pw_fmt_disp = pw_fmt
 		if self.pw_fmt not in self.pw_info:
+			from .exception import InvalidPasswdFormat
 			raise InvalidPasswdFormat(
 				'{!r}: invalid password format.  Valid formats: {}'.format(
 					self.pw_fmt,

+ 3 - 1
mmgen/seedsplit.py

@@ -22,7 +22,6 @@ seedsplit.py: Seed split classes and methods for the MMGen suite
 
 from .globalvars import g
 from .color import yellow
-from .exception import RangeError
 from .obj import MMGenPWIDString,MMGenIdx
 from .subseed import *
 
@@ -81,6 +80,7 @@ class SeedShareList(SubSeedList):
 						msg(f'master_share seed ID collision with parent seed, incrementing nonce to {nonce+1}')
 				else:
 					return ms
+			from .exception import SubSeedNonceRangeExceeded
 			raise SubSeedNonceRangeExceeded('nonce range exceeded')
 
 		def last_share_debug(last_share):
@@ -109,6 +109,7 @@ class SeedShareList(SubSeedList):
 				self.data['long'][ls.sid] = (count,nonce)
 				break
 		else:
+			from .exception import SubSeedNonceRangeExceeded
 			raise SubSeedNonceRangeExceeded('nonce range exceeded')
 
 		if g.debug_subseed:
@@ -118,6 +119,7 @@ class SeedShareList(SubSeedList):
 
 	def get_share_by_idx(self,idx,base_seed=False):
 		if idx < 1 or idx > self.count:
+			from .exception import RangeError
 			raise RangeError(f'{idx}: share index out of range')
 		elif idx == self.count:
 			return self.last_share

+ 1 - 1
mmgen/subseed.py

@@ -22,7 +22,6 @@ subseed.py:  Subseed classes and methods for the MMGen suite
 
 from .color import green
 from .util import msg_r,msg,qmsg
-from .exception import SubSeedNonceRangeExceeded
 from .obj import MMGenRange,IndexedDict
 from .seed import *
 from .crypto import scramble_seed
@@ -192,6 +191,7 @@ class SubSeedList(MMGenObject):
 					self.data[length][sid] = (idx,nonce)
 					return last_sid == sid
 			else: # must exit here, as this could leave self.data in inconsistent state
+				from .exception import SubSeedNonceRangeExceeded
 				raise SubSeedNonceRangeExceeded('add_subseed(): nonce range exceeded')
 
 		for idx in SubSeedIdxRange(first_idx,last_idx).iterate():

+ 4 - 9
mmgen/tool.py

@@ -20,19 +20,20 @@
 tool.py:  Routines for the 'mmgen-tool' utility
 """
 
-from .protocol import hash160
 from .common import *
+from .protocol import hash160
+from .fileutil import get_seed_file,get_data_from_file,write_data_to_file
 from .crypto import get_random
 from .key import PrivKey
 from .subseed import SubSeedList
 from .seedsplit import MasterShareIdx
 from .addr import *
-from .addrlist import AddrList,KeyAddrList
+from .addrlist import AddrList,KeyAddrList,AddrIdxList
 from .passwdlist import PasswordList
 from .baseconv import baseconv
 from .xmrseed import xmrseed
 from .bip39 import bip39
-from .fileutil import get_seed_file,get_data_from_file,write_data_to_file
+from .tw import TwCommon
 
 NL = ('\n','\r\n')[g.platform=='win']
 
@@ -234,8 +235,6 @@ def _process_result(ret,pager=False,print_result=False):
 	else:
 		ydie(1,f'tool.py: can’t handle return value of type {type(ret).__name__!r}')
 
-from .addr import MMGenAddrType
-
 dfl_mnemonic_fmt = 'mmgen'
 mft = namedtuple('mnemonic_format',['fmt','pad','conv_cls'])
 mnemonic_fmts = {
@@ -895,7 +894,6 @@ class MMGenToolCmdWallet(MMGenToolCmds):
 		ss = Wallet(sf)
 		if ss.seed.sid != addr.sid:
 			die(1,f'Seed ID of requested address ({addr.sid}) does not match wallet ({ss.seed.sid})')
-		from .addrlist import AddrList,AddrIdxList
 		al = AddrList(
 			proto     = self.proto,
 			seed      = ss.seed,
@@ -905,8 +903,6 @@ class MMGenToolCmdWallet(MMGenToolCmds):
 		ret = d.sec.wif if target=='wif' else d.addr
 		return ret
 
-from .tw import TwCommon
-
 class MMGenToolCmdRPC(MMGenToolCmds):
 	"tracking wallet commands using the JSON-RPC interface"
 
@@ -964,7 +960,6 @@ class MMGenToolCmdRPC(MMGenToolCmds):
 				die(1,
 					f'{mmgen_addrs}: invalid address list argument ' +
 					'(must be in form <seed ID>:[<type>:]<idx list>)' )
-			from .addrlist import AddrIdxList
 			usr_addr_list = [MMGenID(self.proto,f'{a[0]}:{i}') for i in AddrIdxList(a[1])]
 
 		from .twaddrs import TwAddrList

+ 1 - 1
mmgen/twaddrs.py

@@ -21,7 +21,6 @@ twaddrs: Tracking wallet listaddresses class for the MMGen suite
 """
 
 from .color import green
-from .exception import BadAgeFormat
 from .util import msg,die,altcoin_subclass
 from .base_obj import AsyncInit
 from .obj import MMGenList,MMGenDict,TwComment
@@ -125,6 +124,7 @@ class TwAddrList(MMGenDict,TwCommon,metaclass=AsyncInit):
 		if not self.has_age:
 			show_age = False
 		if age_fmt not in self.age_fmts:
+			from .exception import BadAgeFormat
 			raise BadAgeFormat(f'{age_fmt!r}: invalid age format (must be one of {self.age_fmts!r})')
 		fs = '{mid}' + ('',' {addr}')[showbtcaddrs] + ' {cmt} {amt}' + ('',' {age}')[show_age]
 		mmaddrs = [k for k in self.keys() if k.type == 'mmgen']

+ 2 - 1
mmgen/twctl.py

@@ -21,7 +21,6 @@ twctl: Tracking wallet control class for the MMGen suite
 """
 
 from .globalvars import g
-from .exception import WalletFileError
 from .util import msg,dmsg,write_mode,altcoin_subclass
 from .base_obj import AsyncInit
 from .objmethods import MMGenObject
@@ -62,6 +61,7 @@ class TrackingWallet(MMGenObject,metaclass=AsyncInit):
 			self.init_empty()
 
 		if self.data['coin'] != self.proto.coin: # TODO remove?
+			from .exception import WalletFileError
 			raise WalletFileError(
 				'Tracking wallet coin ({}) does not match current coin ({})!'.format(
 					self.data['coin'],
@@ -98,6 +98,7 @@ class TrackingWallet(MMGenObject,metaclass=AsyncInit):
 				self.init_empty()
 				self.force_write()
 			else:
+				from .exception import WalletFileError
 				raise WalletFileError(f'File {self.tw_fn!r} exists but does not contain valid json data')
 		else:
 			self.upgrade_wallet_maybe()

+ 1 - 1
mmgen/twuo.py

@@ -25,7 +25,6 @@ from collections import namedtuple
 
 from .globalvars import g
 from .color import red,yellow,green
-from .exception import BadAgeFormat
 from .util import (
 	msg,
 	msg_r,
@@ -129,6 +128,7 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view, add [l]abel:
 	@age_fmt.setter
 	def age_fmt(self,val):
 		if val not in self.age_fmts:
+			from .exception import BadAgeFormat
 			raise BadAgeFormat(f'{val!r}: invalid age format (must be one of {self.age_fmts!r})')
 		self._age_fmt = val
 

+ 41 - 4
mmgen/tx.py

@@ -20,10 +20,45 @@
 tx.py:  Transaction routines for the MMGen suite
 """
 
-import sys,os,json
-from stat import *
-from .common import *
-from .obj import *
+import sys,time
+from .globalvars import g
+from .opts import opt
+from .color import *
+from .util import (
+	msg,
+	ymsg,
+	dmsg,
+	vmsg,
+	qmsg,
+	msg_r,
+	die,
+	is_int,
+	fmt,
+	suf,
+	altcoin_subclass,
+	confirm_or_raise,
+	remove_dups,
+	get_extension,
+	keypress_confirm,
+	do_license_msg,
+	line_input,
+	make_chksum_6,
+	make_timestamp,
+	secs_to_dhms,
+)
+from .objmethods import MMGenObject
+from .obj import (
+	ImmutableAttr,
+	ListItemAttr,
+	MMGenList,
+	MMGenListItem,
+	MMGenTxLabel,
+	HexStr,
+	MMGenTxID,
+	MMGenDict,
+	CoinTxID,
+	get_obj,
+)
 from .addr import MMGenID,CoinAddr,is_mmgen_id,is_coin_addr
 
 wmsg = lambda k: {
@@ -148,6 +183,7 @@ class DeserializedTX(dict,MMGenObject):
 				return int(vbytes[::-1].hex(),16)
 
 		def make_txid(tx_bytes):
+			from hashlib import sha256
 			return sha256(sha256(tx_bytes).digest()).digest()[::-1].hex()
 
 		self.idx = 0
@@ -1356,6 +1392,7 @@ class MMGenTX:
 			vmsg(f'\nVsize: {vsize} (true) {est_vsize} (estimated)')
 			ratio = float(est_vsize) / vsize
 			if not (0.95 < ratio < 1.05): # allow for 5% error
+				from .exception import BadTxSizeEstimate
 				raise BadTxSizeEstimate(fmt(f"""
 					Estimated transaction vsize is {ratio:1.2f} times the true vsize
 					Your transaction fee estimates will be inaccurate

+ 2 - 2
mmgen/txfile.py

@@ -23,8 +23,6 @@ txfile.py:  Transaction file operations for the MMGen suite
 from .common import *
 from .obj import HexStr,MMGenTxID,CoinTxID,MMGenTxLabel
 from .tx import MMGenTxOutput,MMGenTxOutputList,MMGenTxInput,MMGenTxInputList
-from .amt import UnknownCoinAmt
-from .exception import MaxFileSizeExceeded
 
 class MMGenTxFile:
 
@@ -63,6 +61,7 @@ class MMGenTxFile:
 		try:
 			desc = 'data'
 			if len(tx_data) > g.max_tx_file_size:
+				from .exception import MaxFileSizeExceeded
 				raise MaxFileSizeExceeded(f'Transaction file size exceeds limit ({g.max_tx_file_size} bytes)')
 			tx_data = tx_data.splitlines()
 			assert len(tx_data) >= 5,'number of lines less than 5'
@@ -188,6 +187,7 @@ class MMGenTxFile:
 		self.chksum = make_chksum_6(' '.join(lines))
 		fmt_data = '\n'.join([self.chksum] + lines) + '\n'
 		if len(fmt_data) > g.max_tx_file_size:
+			from .exception import MaxFileSizeExceeded
 			raise MaxFileSizeExceeded(f'Transaction file size exceeds limit ({g.max_tx_file_size} bytes)')
 		return fmt_data
 

+ 21 - 22
mmgen/util.py

@@ -25,8 +25,8 @@ from hashlib import sha256
 from string import hexdigits,digits
 
 from .color import *
-from .exception import BadFileExtension,UserNonConfirmation
 from .globalvars import g
+from .opts import opt
 
 CUR_HIDE = '\033[?25l'
 CUR_SHOW = '\033[?25h'
@@ -65,6 +65,24 @@ def gmsg(s):   msg(green(s))
 def gmsg_r(s): msg_r(green(s))
 def bmsg(s):   msg(blue(s))
 def bmsg_r(s): msg_r(blue(s))
+def qmsg(s,alt=None):
+	if opt.quiet:
+		if alt != None: msg(alt)
+	else: msg(s)
+def qmsg_r(s,alt=None):
+	if opt.quiet:
+		if alt != None: msg_r(alt)
+	else: msg_r(s)
+def vmsg(s,force=False):
+	if opt.verbose or force: msg(s)
+def vmsg_r(s,force=False):
+	if opt.verbose or force: msg_r(s)
+def Vmsg(s,force=False):
+	if opt.verbose or force: Msg(s)
+def Vmsg_r(s,force=False):
+	if opt.verbose or force: Msg_r(s)
+def dmsg(s):
+	if opt.debug: msg(s)
 
 def mmsg(*args):
 	for d in args: Msg(repr(d))
@@ -239,27 +257,6 @@ def parse_bytespec(nbytes):
 
 	die(1,f'{nbytes!r}: invalid byte specifier')
 
-from .opts import opt
-
-def qmsg(s,alt=None):
-	if opt.quiet:
-		if alt != None: msg(alt)
-	else: msg(s)
-def qmsg_r(s,alt=None):
-	if opt.quiet:
-		if alt != None: msg_r(alt)
-	else: msg_r(s)
-def vmsg(s,force=False):
-	if opt.verbose or force: msg(s)
-def vmsg_r(s,force=False):
-	if opt.verbose or force: msg_r(s)
-def Vmsg(s,force=False):
-	if opt.verbose or force: Msg(s)
-def Vmsg_r(s,force=False):
-	if opt.verbose or force: Msg_r(s)
-def dmsg(s):
-	if opt.debug: msg(s)
-
 def suf(arg,suf_type='s',verb='none'):
 	suf_types = {
 		'none': {
@@ -449,6 +446,7 @@ def compare_or_die(val1, desc1, val2, desc2, e='Error'):
 def check_wallet_extension(fn):
 	from .wallet import Wallet
 	if not Wallet.ext_to_type(get_extension(fn)):
+		from .exception import BadFileExtension
 		raise BadFileExtension(f'{fn!r}: unrecognized seed source file extension')
 
 def make_full_path(outdir,outfile):
@@ -460,6 +458,7 @@ def confirm_or_raise(message,q,expect='YES',exit_msg='Exiting at user request'):
 	a = f'{q}  ' if q[0].isupper() else f'Are you sure you want to {q}?\n'
 	b = f'Type uppercase {expect!r} to confirm: '
 	if line_input(a+b).strip() != expect:
+		from .exception import UserNonConfirmation
 		raise UserNonConfirmation(exit_msg)
 
 def get_words_from_user(prompt):

+ 4 - 1
mmgen/xmrseed.py

@@ -20,7 +20,6 @@
 xmrseed.py: Monero mnemonic conversion class for the MMGen suite
 """
 
-from .exception import *
 from .baseconv import baseconv
 from .util import die
 
@@ -55,6 +54,8 @@ class xmrseed(baseconv):
 		wl = self.digits
 		base = len(wl)
 
+		from .exception import MnemonicError
+
 		if not set(words) <= set(wl):
 			raise MnemonicError( f'{words!r}: not in {desc} format' )
 
@@ -64,6 +65,7 @@ class xmrseed(baseconv):
 		z = self.monero_mn_checksum(words[:-1])
 		if z != words[-1]:
 			raise MnemonicError(f'invalid {desc} checksum')
+
 		words = tuple(words[:-1])
 
 		def gen():
@@ -82,6 +84,7 @@ class xmrseed(baseconv):
 		base = len(wl)
 
 		if len(bytestr) not in self.seedlen_map:
+			from .exception import SeedLengthError
 			raise SeedLengthError(f'{len(bytestr)}: invalid seed byte length for {desc}')
 
 		def num2base_monero(num):

+ 1 - 0
test/objattrtest.py

@@ -31,6 +31,7 @@ os.environ['MMGEN_TEST_SUITE'] = '1'
 
 # Import these _after_ local path's been added to sys.path
 from test.objattrtest_py_d.oat_common import *
+from mmgen.common import *
 from mmgen.addrlist import *
 from mmgen.passwdlist import *