Browse Source

use relative imports throughout

The MMGen Project 5 years ago
parent
commit
701e7a77e5

+ 26 - 26
mmgen/addr.py

@@ -21,9 +21,9 @@ addr.py:  Address generation/display routines for the MMGen suite
 """
 
 from hashlib import sha256,sha512
-from mmgen.common import *
-from mmgen.obj import *
-from mmgen.baseconv import *
+from .common import *
+from .obj import *
+from .baseconv import *
 
 pnm = g.proj_name
 
@@ -53,7 +53,7 @@ class AddrGenerator(MMGenObject):
 
 class AddrGeneratorP2PKH(AddrGenerator):
 	def to_addr(self,pubhex):
-		from mmgen.protocol import hash160
+		from .protocol import hash160
 		assert type(pubhex) == PubKey
 		return CoinAddr(g.proto.pubhash2addr(hash160(pubhex),p2sh=False))
 
@@ -72,7 +72,7 @@ class AddrGeneratorSegwit(AddrGenerator):
 class AddrGeneratorBech32(AddrGenerator):
 	def to_addr(self,pubhex):
 		assert pubhex.compressed,'Uncompressed public keys incompatible with Segwit'
-		from mmgen.protocol import hash160
+		from .protocol import hash160
 		return CoinAddr(g.proto.pubhash2bech32addr(hash160(pubhex)))
 
 	def to_segwit_redeem_script(self,pubhex):
@@ -86,10 +86,10 @@ class AddrGeneratorEthereum(AddrGenerator):
 			assert not g.use_internal_keccak_module
 			from sha3 import keccak_256
 		except:
-			from mmgen.keccak import keccak_256
+			from .keccak import keccak_256
 		self.keccak_256 = keccak_256
 
-		from mmgen.protocol import hash256
+		from .protocol import hash256
 		self.hash256 = hash256
 
 		return AddrGenerator.__init__(addr_type)
@@ -111,7 +111,7 @@ class AddrGeneratorZcashZ(AddrGenerator):
 		s = bytearray(s + bytes(32))
 		s[0] |= 0xc0
 		s[32] = t
-		from mmgen.sha2 import Sha256
+		from .sha2 import Sha256
 		return Sha256(s,preprocess=False).digest()
 
 	def to_addr(self,pubhex): # pubhex is really privhex
@@ -119,7 +119,7 @@ class AddrGeneratorZcashZ(AddrGenerator):
 		assert len(key) == 32,'{}: incorrect privkey length'.format(len(key))
 		from nacl.bindings import crypto_scalarmult_base
 		p2 = crypto_scalarmult_base(self.zhash256(key,1))
-		from mmgen.protocol import _b58chk_encode
+		from .protocol import _b58chk_encode
 		ver_bytes = g.proto.addr_fmt_to_ver_bytes('zcash_z')
 		ret = _b58chk_encode(ver_bytes + self.zhash256(key,0) + p2)
 		return CoinAddr(ret)
@@ -131,7 +131,7 @@ class AddrGeneratorZcashZ(AddrGenerator):
 		vk[32] &= 0xf8
 		vk[63] &= 0x7f
 		vk[63] |= 0x40
-		from mmgen.protocol import _b58chk_encode
+		from .protocol import _b58chk_encode
 		ver_bytes = g.proto.addr_fmt_to_ver_bytes('viewkey')
 		ret = _b58chk_encode(ver_bytes + vk)
 		return ZcashViewKey(ret)
@@ -147,17 +147,17 @@ class AddrGeneratorMonero(AddrGenerator):
 			assert not g.use_internal_keccak_module
 			from sha3 import keccak_256
 		except:
-			from mmgen.keccak import keccak_256
+			from .keccak import keccak_256
 		self.keccak_256 = keccak_256
 
-		from mmgen.protocol import hash256
+		from .protocol import hash256
 		self.hash256 = hash256
 
 		if opt.use_old_ed25519:
-			from mmgen.ed25519 import edwards,encodepoint,B,scalarmult
+			from .ed25519 import edwards,encodepoint,B,scalarmult
 		else:
-			from mmgen.ed25519ll_djbec import scalarmult
-			from mmgen.ed25519 import edwards,encodepoint,B
+			from .ed25519ll_djbec import scalarmult
+			from .ed25519 import edwards,encodepoint,B
 
 		self.edwards     = edwards
 		self.encodepoint = encodepoint
@@ -233,7 +233,7 @@ class KeyGenerator(MMGenObject):
 	@classmethod
 	def test_for_secp256k1(self,silent=False):
 		try:
-			from mmgen.secp256k1 import priv2pub
+			from .secp256k1 import priv2pub
 			m = 'Unable to execute priv2pub() from secp256k1 extension module'
 			assert priv2pub(bytes.fromhex('deadbeef'*8),1),m
 			return True
@@ -280,7 +280,7 @@ class KeyGeneratorSecp256k1(KeyGenerator):
 	desc = 'mmgen-secp256k1'
 	def to_pubhex(self,privhex):
 		assert type(privhex) == PrivKey
-		from mmgen.secp256k1 import priv2pub
+		from .secp256k1 import priv2pub
 		return PubKey(priv2pub(bytes.fromhex(privhex),int(privhex.compressed)).hex(),compressed=privhex.compressed)
 
 class KeyGeneratorDummy(KeyGenerator):
@@ -494,14 +494,14 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 			scramble_key = g.coin.lower()
 		else:
 			scramble_key = (g.coin.lower()+':','')[is_btcfork] + self.al_id.mmtype.name
-		from mmgen.crypto import scramble_seed
+		from .crypto import scramble_seed
 		if g.proto.is_testnet():
 			scramble_key += ':testnet'
 		dmsg_sc('str',scramble_key)
 		return scramble_seed(seed,scramble_key.encode())
 
 	def encrypt(self,desc='new key list'):
-		from mmgen.crypto import mmgen_encrypt
+		from .crypto import mmgen_encrypt
 		self.fmt_data = mmgen_encrypt(self.fmt_data.encode(),desc,'')
 		self.ext += '.'+g.mmenc_ext
 
@@ -697,7 +697,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 			else:
 				mmtype = MMGenAddrType(al_mmtype,on_fail='raise')
 
-			from mmgen.protocol import CoinProtocol
+			from .protocol import CoinProtocol
 			base_coin = CoinProtocol(al_coin or 'BTC',testnet=False).base_coin
 			return base_coin,mmtype,tn
 
@@ -780,7 +780,7 @@ class KeyList(AddrList):
 	chksum_rec_f = lambda foo,e: (str(e.idx), e.addr, e.sec.wif)
 
 def is_bip39_str(s):
-	from mmgen.bip39 import bip39
+	from .bip39 import bip39
 	return bool(bip39.tohex(s.split(),wl_id='bip39'))
 
 def is_xmrseed(s):
@@ -918,7 +918,7 @@ Record this checksum: it will be used to verify the password file in the future
 			pw_bytes = self.pw_len // 2
 			good_pw_len = seed.byte_len * 2
 		elif pf == 'bip39':
-			from mmgen.bip39 import bip39
+			from .bip39 import bip39
 			pw_bytes = bip39.nwords2seedlen(self.pw_len,in_bytes=True)
 			good_pw_len = bip39.seedlen2nwords(seed.byte_len,in_bytes=True)
 		elif pf == 'xmrseed':
@@ -952,7 +952,7 @@ Record this checksum: it will be used to verify the password file in the future
 			# take most significant part
 			return hex_sec[:self.pw_len]
 		elif self.pw_fmt == 'bip39':
-			from mmgen.bip39 import bip39
+			from .bip39 import bip39
 			pw_len_hex = bip39.nwords2seedlen(self.pw_len,in_hex=True)
 			# take most significant part
 			return ' '.join(bip39.fromhex(hex_sec[:pw_len_hex],wl_id='bip39'))
@@ -960,7 +960,7 @@ Record this checksum: it will be used to verify the password file in the future
 			pw_len_hex = baseconv.seedlen_map_rev['xmrseed'][self.pw_len] * 2
 			# take most significant part
 			bytes_trunc = bytes.fromhex(hex_sec[:pw_len_hex])
-			from mmgen.protocol import MoneroProtocol
+			from .protocol import MoneroProtocol
 			bytes_preproc = MoneroProtocol.preprocess_key(bytes_trunc,None)
 			return ' '.join(baseconv.frombytes(bytes_preproc,wl_id='xmrseed'))
 		else:
@@ -982,11 +982,11 @@ Record this checksum: it will be used to verify the password file in the future
 		scramble_key = '{}:{}:{}'.format(self.pw_fmt,self.pw_len,self.pw_id_str)
 
 		if self.hex2bip39:
-			from mmgen.bip39 import bip39
+			from .bip39 import bip39
 			pwlen = bip39.nwords2seedlen(self.pw_len,in_hex=True)
 			scramble_key = '{}:{}:{}'.format('hex',pwlen,self.pw_id_str)
 
-		from mmgen.crypto import scramble_seed
+		from .crypto import scramble_seed
 		dmsg_sc('str',scramble_key)
 		return scramble_seed(seed,scramble_key.encode())
 

+ 7 - 7
mmgen/baseconv.py

@@ -21,8 +21,8 @@ baseconv.py:  base conversion class for the MMGen suite
 """
 
 from hashlib import sha256
-from mmgen.exception import *
-from mmgen.util import die
+from .exception import *
+from .util import die
 
 def is_b58_str(s): return set(list(s)) <= set(baseconv.digits['b58'])
 def is_b32_str(s): return set(list(s)) <= set(baseconv.digits['b32'])
@@ -76,13 +76,13 @@ class baseconv(object):
 		if mn_id in cls.digits:
 			return
 		if mn_id == 'mmgen':
-			from mmgen.mn_electrum import words
+			from .mn_electrum import words
 			cls.digits[mn_id] = words
 		elif mn_id == 'xmrseed':
-			from mmgen.mn_monero import words
+			from .mn_monero import words
 			cls.digits[mn_id] = words
 		elif mn_id == 'tirosh':
-			from mmgen.mn_tirosh import words
+			from .mn_tirosh import words
 			cls.digits[mn_id] = words[:cls.mn_base]
 		else:
 			raise ValueError('{}: unrecognized mnemonic ID'.format(mn_id))
@@ -109,7 +109,7 @@ class baseconv(object):
 		cls.init_mn(wl_id)
 
 		wl = cls.digits[wl_id]
-		from mmgen.util import qmsg,compare_chksums
+		from .util import qmsg,compare_chksums
 		ret = 'Wordlist: {}\nLength: {} words'.format(wl_id,len(wl))
 		new_chksum = cls.get_wordlist_chksum(wl_id)
 
@@ -202,7 +202,7 @@ class baseconv(object):
 	def fromhex(cls,hexstr,wl_id,pad=None,tostr=False):
 		"convert hex string to list or string data of base 'wl_id'"
 
-		from mmgen.util import is_hex_str
+		from .util import is_hex_str
 		if not is_hex_str(hexstr):
 			m = ('{h!r}:','seed data')[pad=='seed'] + ' not a hexadecimal string'
 			raise HexadecimalStringError(m.format(h=hexstr))

+ 3 - 3
mmgen/bip39.py

@@ -22,9 +22,9 @@ bip39.py - Data and routines for BIP39 mnemonic seed phrases
 
 from hashlib import sha256
 
-from mmgen.exception import *
-from mmgen.baseconv import *
-from mmgen.util import is_hex_str
+from .exception import *
+from .baseconv import *
+from .util import is_hex_str
 
 # implements a subset of the baseconv API
 class bip39(baseconv):

+ 2 - 2
mmgen/cfg.py

@@ -27,8 +27,8 @@ cfg.py: API for the MMGen runtime configuration file and related files
 import sys,os,re,hashlib
 from collections import namedtuple
 
-from mmgen.globalvars import *
-from mmgen.util import *
+from .globalvars import *
+from .util import *
 
 def cfg_file(id_str):
 	return CfgFile.get_cls_by_id(id_str)()

+ 2 - 2
mmgen/color.py

@@ -93,12 +93,12 @@ def init_color(num_colors='auto'):
 
 def start_mscolor():
 	import sys
-	from mmgen.globalvars import g
+	from .globalvars import g
 	try:
 		import colorama
 		colorama.init(strip=True,convert=True)
 	except:
-		from mmgen.util import msg
+		from .util import msg
 		msg('Import of colorama module failed')
 	else:
 		g.stdout = sys.stdout

+ 6 - 6
mmgen/common.py

@@ -21,16 +21,16 @@ common.py:  Common imports for all MMGen scripts
 """
 
 import sys,os
-from mmgen.exception import *
-from mmgen.globalvars import *
+from .exception import *
+from .globalvars import *
 import mmgen.opts as opts
-from mmgen.opts import opt
-from mmgen.util import *
+from .opts import opt
+from .util import *
 
 def help_notes(k):
-	from mmgen.obj import SubSeedIdxRange,SeedShareIdx,SeedShareCount,MasterShareIdx
+	from .obj import SubSeedIdxRange,SeedShareIdx,SeedShareCount,MasterShareIdx
 	from .wallet import Wallet
-	from mmgen.tx import MMGenTX
+	from .tx import MMGenTX
 	def fee_spec_letters(use_quotes=False):
 		cu = g.proto.coin_amt.units
 		sep,conj = ((',',' or '),("','","' or '"))[use_quotes]

+ 2 - 2
mmgen/crypto.py

@@ -23,7 +23,7 @@ crypto.py:  Cryptographic and related routines for the MMGen suite
 from cryptography.hazmat.primitives.ciphers import Cipher,algorithms,modes
 from cryptography.hazmat.backends import default_backend
 from hashlib import sha256
-from mmgen.common import *
+from .common import *
 
 crmsg = {
 	'usr_rand_notice': """
@@ -158,7 +158,7 @@ def _get_random_data_from_user(uchars,desc,test_suite=False):
 	prompt = 'You may begin typing.  {} symbols left: '
 
 	import time
-	from mmgen.term import get_char_raw
+	from .term import get_char_raw
 	key_data,time_data = '',[]
 
 	for i in range(uchars):

+ 5 - 5
mmgen/daemon.py

@@ -23,8 +23,8 @@ daemon.py:  Daemon control interface for the MMGen suite
 import shutil
 from subprocess import run,PIPE
 from collections import namedtuple
-from mmgen.exception import *
-from mmgen.common import *
+from .exception import *
+from .common import *
 
 class Daemon(MMGenObject):
 
@@ -253,7 +253,7 @@ class MoneroWalletDaemon(Daemon):
 	def state(self):
 		if not self.test_socket(g.monero_wallet_rpc_host,self.rpc_port):
 			return 'stopped'
-		from mmgen.rpc import MoneroWalletRPCConnection
+		from .rpc import MoneroWalletRPCConnection
 		try:
 			MoneroWalletRPCConnection(
 				g.monero_wallet_rpc_host,
@@ -337,7 +337,7 @@ class CoinDaemon(Daemon):
 			me.desc = 'test suite daemon'
 			rel_datadir = os.path.join('test','daemons',daemon_id)
 		else:
-			from mmgen.protocol import CoinProtocol
+			from .protocol import CoinProtocol
 			me.datadir = CoinProtocol(daemon_id,False).daemon_data_dir
 
 		if test_suite:
@@ -523,7 +523,7 @@ class EthereumDaemon(CoinDaemon):
 
 	@property
 	def state(self):
-		from mmgen.rpc import EthereumRPCConnection
+		from .rpc import EthereumRPCConnection
 		try:
 			conn = EthereumRPCConnection('localhost',self.rpc_port,socket_timeout=0.2)
 		except:

+ 2 - 2
mmgen/devtools.py

@@ -102,9 +102,9 @@ if os.getenv('MMGEN_DEBUG') or os.getenv('MMGEN_TEST_SUITE') or os.getenv('MMGEN
 
 		# Check that all immutables have been initialized.  Expensive, so do only when testing.
 		def immutable_attr_init_check(self):
-			from mmgen.globalvars import g
+			from .globalvars import g
 			if g.test_suite:
-				from mmgen.util import rdie
+				from .util import rdie
 				cls = type(self)
 				for attrname in sorted({a for a in self.valid_attrs if a[0] != '_'}):
 					for o in (cls,cls.__bases__[0]): # assume there's only one base class

+ 5 - 5
mmgen/filename.py

@@ -22,10 +22,10 @@ filename.py:  Filename class and methods for the MMGen suite
 
 import sys,os
 
-from mmgen.exception import BadFileExtension,FileNotFound
-from mmgen.obj import *
-from mmgen.util import die,get_extension
-from mmgen.seed import *
+from .exception import BadFileExtension,FileNotFound
+from .obj import *
+from .util import die,get_extension
+from .seed import *
 
 class Filename(MMGenObject):
 
@@ -40,7 +40,7 @@ class Filename(MMGenObject):
 		self.atime    = None
 
 		from .wallet import Wallet
-		from mmgen.tx import MMGenTX
+		from .tx import MMGenTX
 		if ftype:
 			if isinstance(ftype,type):
 				if issubclass(ftype,(Wallet,MMGenTX)):

+ 1 - 1
mmgen/globalvars.py

@@ -23,7 +23,7 @@ globalvars.py:  Constants and configuration options for the MMGen suite
 import sys,os
 from decimal import Decimal
 from collections import namedtuple
-from mmgen.devtools import *
+from .devtools import *
 
 # Global vars are set to dfl values in class g.
 # They're overridden in this order:

+ 1 - 1
mmgen/license.py

@@ -20,7 +20,7 @@
 license.py:  Copyright notice and text of GPLv3
 """
 
-from mmgen.globalvars import g
+from .globalvars import g
 
 warning = """
   {pnm} Copyright (C) {g.Cdates} by {g.author} {g.email}.  This

+ 2 - 2
mmgen/main.py

@@ -27,7 +27,7 @@ def launch(mod):
 	if mod == 'keygen': mod = 'addrgen'
 
 	import sys,os
-	from mmgen.globalvars import g
+	from .globalvars import g
 
 	if g.platform == 'linux' and sys.stdin.isatty():
 		import termios,atexit
@@ -49,7 +49,7 @@ def launch(mod):
 			try: m = '{}'.format(e.args[0])
 			except: m = repr(e.args[0])
 
-			from mmgen.util import die,ydie,rdie
+			from .util import die,ydie,rdie
 			d = [   (ydie,2,'\nMMGen Unhandled Exception ({n}): {m}'),
 					(die, 1,'{m}'),
 					(ydie,2,'{m}'),

+ 3 - 3
mmgen/main_addrgen.py

@@ -21,9 +21,9 @@ mmgen-addrgen: Generate a series or range of addresses from an MMGen
                deterministic wallet
 """
 
-from mmgen.common import *
-from mmgen.crypto import *
-from mmgen.addr import *
+from .common import *
+from .crypto import *
+from .addr import *
 from .wallet import Wallet
 
 if g.prog_name == 'mmgen-keygen':

+ 5 - 5
mmgen/main_addrimport.py

@@ -22,9 +22,9 @@ mmgen-addrimport: Import addresses into a MMGen coin daemon tracking wallet
 
 import time
 
-from mmgen.common import *
-from mmgen.addr import AddrList,KeyAddrList
-from mmgen.obj import TwLabel,is_coin_addr
+from .common import *
+from .addr import AddrList,KeyAddrList
+from .obj import TwLabel,is_coin_addr
 
 ai_msgs = lambda k: {
 	'rescan': """
@@ -76,7 +76,7 @@ cmd_args = opts.init(opts_data)
 def import_mmgen_list(infile):
 	al = (AddrList,KeyAddrList)[bool(opt.keyaddr_file)](infile)
 	if al.al_id.mmtype in ('S','B'):
-		from mmgen.tx import segwit_is_active
+		from .tx import segwit_is_active
 		if not segwit_is_active():
 			rdie(2,'Segwit is not active on this chain. Cannot import Segwit addresses')
 	return al
@@ -102,7 +102,7 @@ qmsg('OK. {} addresses{}'.format(al.num_addrs,m))
 
 err_msg = None
 
-from mmgen.tw import TrackingWallet
+from .tw import TrackingWallet
 tw = TrackingWallet(mode='w')
 
 if g.token:

+ 5 - 5
mmgen/main_autosign.py

@@ -30,7 +30,7 @@ part_label   = 'MMGEN_TX'
 wallet_dir   = '/dev/shm/autosign'
 key_fn       = 'autosign.key'
 
-from mmgen.common import *
+from .common import *
 prog_name = os.path.basename(sys.argv[0])
 opts_data = {
 	'text': {
@@ -111,10 +111,10 @@ exit_if_mswin('autosigning')
 
 import mmgen.tx
 import mmgen.altcoins.eth.tx
-from mmgen.txsign import txsign
-from mmgen.protocol import CoinProtocol,init_coin
+from .txsign import txsign
+from .protocol import CoinProtocol,init_coin
 if g.test_suite:
-	from mmgen.daemon import CoinDaemon
+	from .daemon import CoinDaemon
 
 if opt.stealth_led: opt.led = True
 
@@ -362,7 +362,7 @@ def setup():
 	opt.hash_preset = '1'
 	opt.set_by_user = ['hash_preset']
 	opt.passwd_file = os.path.join(tx_dir,key_fn)
-	from mmgen.obj import MMGenWalletLabel
+	from .obj import MMGenWalletLabel
 	opt.label = MMGenWalletLabel('Autosign Wallet')
 	ss_out = Wallet(ss=ss_in)
 	ss_out.write_to_file(desc='autosign wallet',outdir=wallet_dir)

+ 4 - 4
mmgen/main_passgen.py

@@ -21,11 +21,11 @@ mmgen-passgen: Generate a series or range of passwords from an MMGen
                deterministic wallet
 """
 
-from mmgen.common import *
-from mmgen.crypto import *
-from mmgen.addr import PasswordList,AddrIdxList
+from .common import *
+from .crypto import *
+from .addr import PasswordList,AddrIdxList
 from .wallet import Wallet
-from mmgen.obj import MMGenPWIDString
+from .obj import MMGenPWIDString
 
 pwi = PasswordList.pw_info
 pwi_fs = '{:8} {:1} {:26} {:<7}  {:<7}  {}'

+ 2 - 2
mmgen/main_regtest.py

@@ -21,7 +21,7 @@ mmgen-regtest: Coin daemon regression test mode setup and operations for the MMG
                suite
 """
 
-from mmgen.common import *
+from .common import *
 
 opts_data = {
 	'sets': [('yes', True, 'quiet', True)],
@@ -58,7 +58,7 @@ opts_data = {
 
 cmd_args = opts.init(opts_data)
 
-from mmgen.regtest import MMGenRegtest
+from .regtest import MMGenRegtest
 
 def check_num_args():
 	m = getattr(MMGenRegtest,cmd_args[0])

+ 2 - 2
mmgen/main_seedjoin.py

@@ -21,8 +21,8 @@ mmgen/main_seedjoin: Regenerate an MMGen deterministic wallet from seed shares
                      created by 'mmgen-seedsplit'
 """
 
-from mmgen.common import *
-from mmgen.obj import MasterShareIdx,SeedSplitIDString,MMGenWalletLabel
+from .common import *
+from .obj import MasterShareIdx,SeedSplitIDString,MMGenWalletLabel
 from .seed import Seed,SeedShareMasterJoining
 from .wallet import Wallet
 

+ 4 - 4
mmgen/main_split.py

@@ -24,7 +24,7 @@ mmgen-split: Split funds after a replayable chain fork using a timelocked transa
 
 import time
 
-from mmgen.common import *
+from .common import *
 
 opts_data = {
 	'text': {
@@ -97,7 +97,7 @@ if len(cmd_args) != 2:
 	fs = 'This command requires exactly two {} addresses as arguments'
 	die(1,fs.format(g.proj_name))
 
-from mmgen.obj import MMGenID
+from .obj import MMGenID
 try:
 	mmids = [MMGenID(a,on_fail='die') for a in cmd_args]
 except:
@@ -106,8 +106,8 @@ except:
 if mmids[0] == mmids[1]:
 	die(2,'Both transactions have the same output! ({})'.format(mmids[0]))
 
-from mmgen.tx import MMGenSplitTX
-from mmgen.protocol import init_coin
+from .tx import MMGenSplitTX
+from .protocol import init_coin
 
 if opt.tx_fees:
 	for idx,g_coin in ((1,opt.other_coin),(0,g.coin)):

+ 1 - 1
mmgen/main_tool.py

@@ -21,7 +21,7 @@ mmgen-tool:  Perform various MMGen- and cryptocoin-related operations.
              Part of the MMGen suite
 """
 
-from mmgen.common import *
+from .common import *
 
 def make_cmd_help():
 	import mmgen.tool

+ 4 - 4
mmgen/main_txbump.py

@@ -21,7 +21,7 @@ mmgen-txbump: Increase the fee on a replaceable (replace-by-fee) MMGen
               transaction, and optionally sign and send it
 """
 
-from mmgen.common import *
+from .common import *
 from .wallet import Wallet
 
 opts_data = {
@@ -101,8 +101,8 @@ rpc_init()
 tx_file = cmd_args.pop(0)
 check_infile(tx_file)
 
-from mmgen.tx import *
-from mmgen.txsign import *
+from .tx import *
+from .txsign import *
 
 seed_files = get_seed_files(opt,cmd_args) if (cmd_args or opt.send) else None
 
@@ -143,7 +143,7 @@ if g.proto.base_proto == 'Bitcoin':
 if not opt.yes:
 	tx.add_comment()   # edits an existing comment
 
-from mmgen.tw import TwUnspentOutputs
+from .tw import TwUnspentOutputs
 tx.twuo = TwUnspentOutputs(minconf=opt.minconf)
 
 tx.create_raw()        # creates tx.hex, tx.txid

+ 2 - 2
mmgen/main_txcreate.py

@@ -21,7 +21,7 @@ mmgen-txcreate: Create a cryptocoin transaction with MMGen- and/or non-MMGen
                 inputs and outputs
 """
 
-from mmgen.common import *
+from .common import *
 
 opts_data = {
 	'sets': [('yes', True, 'quiet', True)],
@@ -79,7 +79,7 @@ g.use_cached_balances = opt.cached_balances
 
 rpc_init()
 
-from mmgen.tx import MMGenTX
+from .tx import MMGenTX
 tx = MMGenTX()
 tx.create(cmd_args,int(opt.locktime or 0),do_info=opt.info)
 tx.write_to_file(ask_write=not opt.yes,ask_overwrite=not opt.yes,ask_write_default_yes=False)

+ 4 - 4
mmgen/main_txdo.py

@@ -20,9 +20,9 @@
 mmgen-txdo: Create, sign and broadcast an online MMGen transaction
 """
 
-from mmgen.common import *
+from .common import *
 from .wallet import Wallet
-from mmgen.obj import SubSeedIdxRange
+from .obj import SubSeedIdxRange
 
 opts_data = {
 	'sets': [('yes', True, 'quiet', True)],
@@ -116,8 +116,8 @@ g.use_cached_balances = opt.cached_balances
 
 rpc_init()
 
-from mmgen.tx import *
-from mmgen.txsign import *
+from .tx import *
+from .txsign import *
 
 seed_files = get_seed_files(opt,cmd_args)
 

+ 2 - 2
mmgen/main_txsend.py

@@ -20,7 +20,7 @@
 mmgen-txsend: Broadcast a transaction signed by 'mmgen-txsign' to the network
 """
 
-from mmgen.common import *
+from .common import *
 
 opts_data = {
 	'sets': [('yes', True, 'quiet', True)],
@@ -48,7 +48,7 @@ else: opts.usage()
 
 if not opt.status: do_license_msg()
 
-from mmgen.tx import *
+from .tx import *
 
 tx = MMGenTX(infile,quiet_open=True) # sig check performed here
 vmsg("Signed transaction file '{}' is valid".format(infile))

+ 3 - 3
mmgen/main_txsign.py

@@ -20,8 +20,8 @@
 mmgen-txsign: Sign a transaction generated by 'mmgen-txcreate'
 """
 
-from mmgen.common import *
-from mmgen.obj import SubSeedIdxRange
+from .common import *
+from .obj import SubSeedIdxRange
 from .wallet import Wallet
 
 # -w, --use-wallet-dat (keys from running coin daemon) removed: use walletdump rpc instead
@@ -100,7 +100,7 @@ if g.proto.sign_mode == 'daemon':
 if not opt.info and not opt.terse_info:
 	do_license_msg(immed=True)
 
-from mmgen.txsign import *
+from .txsign import *
 
 tx_files   = get_tx_files(opt,infiles)
 seed_files = get_seed_files(opt,infiles)

+ 5 - 5
mmgen/main_wallet.py

@@ -21,10 +21,10 @@ mmgen/main_wallet:  Entry point for MMGen wallet-related scripts
 """
 
 import os
-from mmgen.common import *
+from .common import *
 from .wallet import Wallet,MMGenWallet
-from mmgen.filename import find_file_in_dir
-from mmgen.obj import MMGenWalletLabel,MasterShareIdx
+from .filename import find_file_in_dir
+from .obj import MMGenWalletLabel,MasterShareIdx
 
 usage = '[opts] [infile]'
 nargs = 1
@@ -148,10 +148,10 @@ if opt.label:
 	opt.label = MMGenWalletLabel(opt.label,msg="Error in option '--label'")
 
 if invoked_as == 'subgen':
-	from mmgen.obj import SubSeedIdx
+	from .obj import SubSeedIdx
 	ss_idx = SubSeedIdx(cmd_args.pop())
 elif invoked_as == 'seedsplit':
-	from mmgen.obj import SeedSplitSpecifier
+	from .obj import SeedSplitSpecifier
 	master_share = MasterShareIdx(opt.master_share) if opt.master_share else None
 	if cmd_args:
 		sss = SeedSplitSpecifier(cmd_args.pop(),on_fail='silent')

+ 4 - 4
mmgen/mn_entry.py

@@ -22,10 +22,10 @@ mn_entry.py - Mnemonic user entry methods for the MMGen suite
 
 import time
 
-from mmgen.globalvars import *
-from mmgen.util import msg,msg_r,qmsg,fmt,fmt_list,capfirst,die
-from mmgen.term import get_char,get_char_raw
-from mmgen.color import cyan
+from .globalvars import *
+from .util import msg,msg_r,qmsg,fmt,fmt_list,capfirst,die
+from .term import get_char,get_char_raw
+from .color import cyan
 
 from string import ascii_lowercase as _word_chars
 _return_chars = '\n\r '

+ 17 - 17
mmgen/obj.py

@@ -24,9 +24,9 @@ import sys,os,unicodedata
 from decimal import *
 from string import hexdigits,ascii_letters,digits
 
-from mmgen.exception import *
-from mmgen.color import *
-from mmgen.devtools import *
+from .exception import *
+from .color import *
+from .devtools import *
 
 def is_mmgen_seed_id(s): return SeedID(sid=s,on_fail='silent')
 def is_mmgen_idx(s):     return AddrIdx(s,on_fail='silent')
@@ -105,8 +105,8 @@ class InitErrors(object):
 
 		if m2: errmsg = '{!r}\n{}'.format(m2,errmsg)
 
-		from mmgen.globalvars import g
-		from mmgen.util import die,msg
+		from .globalvars import g
+		from .util import die,msg
 		if cls.on_fail == 'silent':
 			return None # TODO: return False instead?
 		elif cls.on_fail == 'return':
@@ -495,7 +495,7 @@ class XMRAmt(BTCAmt):
 	min_coin_unit = Decimal('0.000000000001')
 	units = ('min_coin_unit',)
 
-from mmgen.altcoins.eth.obj import ETHAmt,ETHNonce
+from .altcoins.eth.obj import ETHAmt,ETHNonce
 
 class CoinAddr(str,Hilite,InitErrors,MMGenObject):
 	color = 'cyan'
@@ -505,7 +505,7 @@ class CoinAddr(str,Hilite,InitErrors,MMGenObject):
 	def __new__(cls,s,on_fail='die'):
 		if type(s) == cls: return s
 		cls.arg_chk(on_fail)
-		from mmgen.globalvars import g
+		from .globalvars import g
 		try:
 			assert set(s) <= set(ascii_letters+digits),'contains non-alphanumeric characters'
 			me = str.__new__(cls,s)
@@ -529,7 +529,7 @@ class CoinAddr(str,Hilite,InitErrors,MMGenObject):
 
 	def is_for_chain(self,chain):
 
-		from mmgen.globalvars import g
+		from .globalvars import g
 		if g.proto.__name__[:8] == 'Ethereum':
 			return True
 
@@ -545,7 +545,7 @@ class TokenAddr(CoinAddr):
 
 class ViewKey(object):
 	def __new__(cls,s,on_fail='die'):
-		from mmgen.globalvars import g
+		from .globalvars import g
 		if g.proto.name == 'zcash':
 			return ZcashViewKey.__new__(ZcashViewKey,s,on_fail)
 		elif g.proto.name == 'monero':
@@ -564,9 +564,9 @@ class SeedID(str,Hilite,InitErrors):
 		cls.arg_chk(on_fail)
 		try:
 			if seed:
-				from mmgen.seed import SeedBase
+				from .seed import SeedBase
 				assert isinstance(seed,SeedBase),'not a subclass of SeedBase'
-				from mmgen.util import make_chksum_8
+				from .util import make_chksum_8
 				return str.__new__(cls,make_chksum_8(seed.data))
 			elif sid:
 				assert set(sid) <= set(hexdigits.upper()),'not uppercase hex digits'
@@ -585,7 +585,7 @@ class SubSeedIdx(str,Hilite,InitErrors):
 		try:
 			assert isinstance(s,str),'not a string or string subclass'
 			idx = s[:-1] if s[-1] in 'SsLl' else s
-			from mmgen.util import is_int
+			from .util import is_int
 			assert is_int(idx),"valid format: an integer, plus optional letter 'S','s','L' or 'l'"
 			idx = int(idx)
 			assert idx >= SubSeedIdxRange.min_idx, 'subseed index < {:,}'.format(SubSeedIdxRange.min_idx)
@@ -605,7 +605,7 @@ class MMGenID(str,Hilite,InitErrors,MMGenObject):
 	trunc_ok = False
 	def __new__(cls,s,on_fail='die'):
 		cls.arg_chk(on_fail)
-		from mmgen.globalvars import g
+		from .globalvars import g
 		try:
 			ss = str(s).split(':')
 			assert len(ss) in (2,3),'not 2 or 3 colon-separated items'
@@ -634,7 +634,7 @@ class TwMMGenID(str,Hilite,InitErrors,MMGenObject):
 			sort_key,idtype = ret.sort_key,'mmgen'
 		except Exception as e:
 			try:
-				from mmgen.globalvars import g
+				from .globalvars import g
 				assert s.split(':',1)[0] == g.proto.base_coin.lower(),(
 					"not a string beginning with the prefix '{}:'".format(g.proto.base_coin.lower()))
 				assert set(s[4:]) <= set(ascii_letters+digits),'contains non-alphanumeric characters'
@@ -703,7 +703,7 @@ class WifKey(str,Hilite,InitErrors):
 		cls.arg_chk(on_fail)
 		try:
 			assert set(s) <= set(ascii_letters+digits),'not an ascii alphanumeric string'
-			from mmgen.globalvars import g
+			from .globalvars import g
 			g.proto.parse_wif(s) # raises exception on error
 			return str.__new__(cls,s)
 		except Exception as e:
@@ -736,7 +736,7 @@ class PrivKey(str,Hilite,InitErrors,MMGenObject):
 
 	# initialize with (priv_bin,compressed), WIF or self
 	def __new__(cls,s=None,compressed=None,wif=None,pubkey_type=None,on_fail='die'):
-		from mmgen.globalvars import g
+		from .globalvars import g
 
 		if type(s) == cls: return s
 		cls.arg_chk(on_fail)
@@ -904,7 +904,7 @@ class MMGenAddrType(str,Hilite,InitErrors,MMGenObject):
 	def __new__(cls,s,on_fail='die',errmsg=None):
 		if type(s) == cls: return s
 		cls.arg_chk(on_fail)
-		from mmgen.globalvars import g
+		from .globalvars import g
 		try:
 			for k,v in list(cls.mmtypes.items()):
 				if s in (k,v.name):

+ 13 - 13
mmgen/opts.py

@@ -25,10 +25,10 @@ class opt_cls(object):
 	pass
 opt = opt_cls()
 
-from mmgen.exception import UserOptError
-from mmgen.globalvars import g
+from .exception import UserOptError
+from .globalvars import g
 import mmgen.share.Opts
-from mmgen.util import *
+from .util import *
 
 def usage():
 	Die(1,'USAGE: {} {}'.format(g.prog_name,usage_txt))
@@ -78,17 +78,17 @@ def opt_postproc_debug():
 	Msg('\n=== end opts.py debug ===\n')
 
 def init_term_and_color():
-	from mmgen.term import init_term
+	from .term import init_term
 	init_term()
 
 	if g.color: # MMGEN_DISABLE_COLOR sets this to False
-		from mmgen.color import start_mscolor,init_color
+		from .color import start_mscolor,init_color
 		if g.platform == 'win':
 			start_mscolor()
 		init_color(num_colors=('auto',256)[bool(g.force_256_color)])
 
 def override_globals_from_cfg_file(ucfg):
-	from mmgen.protocol import CoinProtocol
+	from .protocol import CoinProtocol
 	for d in ucfg.parse():
 		val = d.value
 		if d.name in g.cfg_file_opts:
@@ -121,7 +121,7 @@ def override_globals_from_env():
 			setattr(g,gname,set_for_type(val,getattr(g,gname),name,disable))
 
 def common_opts_code(s):
-	from mmgen.protocol import CoinProtocol
+	from .protocol import CoinProtocol
 	return s.format(
 		pnm=g.proj_name,pn=g.proto.name,dn=g.proto.daemon_name,
 		cu_dfl=g.coin,
@@ -228,7 +228,7 @@ def init(opts_data,add_opts=[],opt_filter=None,parse_only=False):
 	init_term_and_color()
 
 	if not opt.skip_cfg_file:
-		from mmgen.cfg import cfg_file
+		from .cfg import cfg_file
 		cfg_file('sample') # check for changes in system template file
 		override_globals_from_cfg_file(cfg_file('usr'))
 
@@ -251,7 +251,7 @@ def init(opts_data,add_opts=[],opt_filter=None,parse_only=False):
 
 	g.network = 'testnet' if g.testnet else 'mainnet'
 
-	from mmgen.protocol import init_genonly_altcoins,CoinProtocol
+	from .protocol import init_genonly_altcoins,CoinProtocol
 	altcoin_trust_level = init_genonly_altcoins(g.coin)
 
 	# g.testnet is finalized, so we can set g.proto
@@ -288,7 +288,7 @@ def init(opts_data,add_opts=[],opt_filter=None,parse_only=False):
 		g.proto = CoinProtocol(g.coin,g.testnet)
 		g.rpc_host = 'localhost'
 		g.data_dir = os.path.join(g.data_dir_root,'regtest',g.coin.lower(),('alice','bob')[g.bob])
-		from mmgen.regtest import MMGenRegtest
+		from .regtest import MMGenRegtest
 		g.rpc_user = MMGenRegtest.rpc_user
 		g.rpc_password = MMGenRegtest.rpc_password
 		g.rpc_port = MMGenRegtest(g.coin).d.rpc_port
@@ -335,7 +335,7 @@ def opt_is_tx_fee(key,val,desc): # 'key' must remain a placeholder
 	if hasattr(opt,'tx_gas') and opt.tx_gas:
 		return
 
-	from mmgen.tx import MMGenTX
+	from .tx import MMGenTX
 	tx = MMGenTX(offline=True)
 	# Size of 224 is just a ball-park figure to eliminate the most extreme cases at startup
 	# This check will be performed again once we know the true size
@@ -480,7 +480,7 @@ def check_usr_opts(usr_opts): # Raises an exception if any check fails
 		opt_compares(val,'>',0,desc)
 
 	def chk_coin(key,val,desc):
-		from mmgen.protocol import CoinProtocol
+		from .protocol import CoinProtocol
 		opt_is_in_list(val.lower(),list(CoinProtocol.coins.keys()),'coin')
 
 	def chk_rbf(key,val,desc):
@@ -490,7 +490,7 @@ def check_usr_opts(usr_opts): # Raises an exception if any check fails
 
 	def chk_bob(key,val,desc):
 		m = "Regtest (Bob and Alice) mode not set up yet.  Run '{}-regtest setup' to initialize."
-		from mmgen.regtest import MMGenRegtest
+		from .regtest import MMGenRegtest
 		try:
 			os.stat(os.path.join(MMGenRegtest(g.coin).d.datadir,'regtest','debug.log'))
 		except:

+ 9 - 9
mmgen/protocol.py

@@ -23,10 +23,10 @@ protocol.py: Coin protocol functions, classes and methods
 import sys,os,hashlib
 from collections import namedtuple,OrderedDict
 
-from mmgen.util import msg,ymsg,Msg,ydie
-from mmgen.devtools import *
-from mmgen.obj import BTCAmt,LTCAmt,BCHAmt,B2XAmt,ETHAmt
-from mmgen.globalvars import g
+from .util import msg,ymsg,Msg,ydie
+from .devtools import *
+from .obj import BTCAmt,LTCAmt,BCHAmt,B2XAmt,ETHAmt
+from .globalvars import g
 import mmgen.bech32 as bech32
 
 parsed_wif = namedtuple('parsed_wif',['sec','pubkey_type','compressed'])
@@ -343,7 +343,7 @@ class EthereumProtocol(DummyWIF,BitcoinProtocol):
 
 	@classmethod
 	def parse_addr(cls,addr):
-		from mmgen.util import is_hex_str_lc
+		from .util import is_hex_str_lc
 		if is_hex_str_lc(addr) and len(addr) == cls.addr_len * 2:
 			return parsed_addr( bytes.fromhex(addr), 'ethereum' )
 		if g.debug: Msg("Invalid address '{}'".format(addr))
@@ -416,14 +416,14 @@ class MoneroProtocol(DummyWIF,BitcoinProtocolAddrgen):
 
 	@classmethod
 	def preprocess_key(cls,sec,pubkey_type): # reduce key
-		from mmgen.ed25519 import l
+		from .ed25519 import l
 		n = int.from_bytes(sec[::-1],'big') % l
 		return int.to_bytes(n,cls.privkey_len,'big')[::-1]
 
 	@classmethod
 	def parse_addr(cls,addr):
 
-		from mmgen.baseconv import baseconv,is_b58_str
+		from .baseconv import baseconv,is_b58_str
 
 		def b58dec(addr_str):
 			l = len(addr_str)
@@ -437,7 +437,7 @@ class MoneroProtocol(DummyWIF,BitcoinProtocolAddrgen):
 			assert not g.use_internal_keccak_module
 			from sha3 import keccak_256
 		except:
-			from mmgen.keccak import keccak_256
+			from .keccak import keccak_256
 
 		chk = keccak_256(ret[:-4]).digest()[:4]
 		assert ret[-4:] == chk,'{}: incorrect checksum.  Correct value: {}'.format(ret[-4:].hex(),chk.hex())
@@ -489,7 +489,7 @@ def init_genonly_altcoins(usr_coin=None):
 	If usr_coin is None, initializes all coins for current network with trust level >-1.
 	Returns trust_level of usr_coin, or 0 (untrusted) if usr_coin is None.
 	"""
-	from mmgen.altcoin import CoinInfo as ci
+	from .altcoin import CoinInfo as ci
 	data = { 'mainnet': (), 'testnet': () }
 	networks = ['mainnet'] + (['testnet'] if g.testnet else [])
 

+ 3 - 3
mmgen/regtest.py

@@ -22,8 +22,8 @@ regtest: Coin daemon regression test mode setup and operations for the MMGen sui
 
 import os,time,shutil,re,json
 from subprocess import run,PIPE
-from mmgen.common import *
-from mmgen.daemon import CoinDaemon
+from .common import *
+from .daemon import CoinDaemon
 
 def create_data_dir(data_dir):
 	try: os.stat(os.path.join(data_dir,'regtest'))
@@ -269,7 +269,7 @@ class MMGenRegtest(MMGenObject):
 
 	def fork(self,coin): # currently disabled
 
-		from mmgen.protocol import CoinProtocol
+		from .protocol import CoinProtocol
 		forks = CoinProtocol(coin,False).forks
 		if not [f for f in forks if f[2] == g.coin.lower() and f[3] == True]:
 			die(1,"Coin {} is not a replayable fork of coin {}".format(g.coin,coin))

+ 6 - 6
mmgen/rpc.py

@@ -23,7 +23,7 @@ rpc.py:  Cryptocoin RPC library for the MMGen suite
 import http.client,base64,json
 from decimal import Decimal
 
-from mmgen.common import *
+from .common import *
 
 def dmsg_rpc(fs,data=None,is_json=False):
 	if g.debug_rpc:
@@ -113,7 +113,7 @@ class RPCConnection(MMGenObject):
 		dmsg_rpc('    RPC POST data ==>\n{}\n',p)
 
 		ca_type = self.coin_amt_type if hasattr(self,'coin_amt_type') else str
-		from mmgen.obj import HexStr
+		from .obj import HexStr
 		class MyJSONEncoder(json.JSONEncoder):
 			def default(self,obj):
 				if isinstance(obj,g.proto.coin_amt):
@@ -385,9 +385,9 @@ def rpc_errmsg(ret):
 def init_daemon_parity():
 
 	def resolve_token_arg(token_arg):
-		from mmgen.obj import CoinAddr
-		from mmgen.altcoins.eth.tw import EthereumTrackingWallet
-		from mmgen.altcoins.eth.contract import Token
+		from .obj import CoinAddr
+		from .altcoins.eth.tw import EthereumTrackingWallet
+		from .altcoins.eth.contract import Token
 
 		tw = EthereumTrackingWallet(no_rpc=True)
 
@@ -458,7 +458,7 @@ def init_daemon_bitcoind():
 				auth_cookie=get_coin_daemon_auth_cookie())
 
 	if g.bob or g.alice:
-		from mmgen.regtest import MMGenRegtest
+		from .regtest import MMGenRegtest
 		MMGenRegtest(g.coin).switch_user(('alice','bob')[g.bob],quiet=True)
 	conn.daemon_version = int(conn.getnetworkinfo()['version'])
 	conn.blockcount = conn.getblockcount()

+ 2 - 2
mmgen/seed.py

@@ -20,8 +20,8 @@
 seed.py:  Seed-related classes and methods for the MMGen suite
 """
 
-from mmgen.common import *
-from mmgen.obj import *
+from .common import *
+from .obj import *
 from .crypto import get_random,scramble_seed
 
 class SeedBase(MMGenObject):

+ 1 - 1
mmgen/term.py

@@ -22,7 +22,7 @@ term.py:  Terminal classes for the MMGen suite
 
 import sys,os,time
 from collections import namedtuple
-from mmgen.common import *
+from .common import *
 
 try:
 	import tty,termios

+ 33 - 33
mmgen/tool.py

@@ -20,10 +20,10 @@
 tool.py:  Routines for the 'mmgen-tool' utility
 """
 
-from mmgen.protocol import hash160
-from mmgen.common import *
-from mmgen.crypto import *
-from mmgen.addr import *
+from .protocol import hash160
+from .common import *
+from .crypto import *
+from .addr import *
 
 NL = ('\n','\r\n')[g.platform=='win']
 
@@ -215,7 +215,7 @@ def _process_result(ret,pager=False,print_result=False):
 	else:
 		ydie(1,"tool.py: can't handle return value of type '{}'".format(type(ret).__name__))
 
-from mmgen.obj import MMGenAddrType
+from .obj import MMGenAddrType
 
 def init_generators(arg=None):
 	global at,kg,ag
@@ -225,7 +225,7 @@ def init_generators(arg=None):
 		ag = AddrGenerator(at)
 
 def conv_cls_bip39():
-	from mmgen.bip39 import bip39
+	from .bip39 import bip39
 	return bip39
 
 dfl_mnemonic_fmt = 'mmgen'
@@ -369,12 +369,12 @@ class MMGenToolCmdUtil(MMGenToolCmds):
 
 	def hextob58chk(self,hexstr:'sstr'):
 		"convert a hexadecimal number to base58-check encoding"
-		from mmgen.protocol import _b58chk_encode
+		from .protocol import _b58chk_encode
 		return _b58chk_encode(bytes.fromhex(hexstr))
 
 	def b58chktohex(self,b58chk_num:'sstr'):
 		"convert a base58-check encoded number to hexadecimal"
-		from mmgen.protocol import _b58chk_decode
+		from .protocol import _b58chk_decode
 		return _b58chk_decode(b58chk_num).hex()
 
 	def hextob32(self,hexstr:'sstr',pad=0):
@@ -488,17 +488,17 @@ class MMGenToolCmdCoin(MMGenToolCmds):
 
 	def addr2pubhash(self,addr:'sstr'):
 		"convert coin address to public key hash"
-		from mmgen.tx import addr2pubhash
+		from .tx import addr2pubhash
 		return addr2pubhash(CoinAddr(addr))
 
 	def addr2scriptpubkey(self,addr:'sstr'):
 		"convert coin address to scriptPubKey"
-		from mmgen.tx import addr2scriptPubKey
+		from .tx import addr2scriptPubKey
 		return addr2scriptPubKey(CoinAddr(addr))
 
 	def scriptpubkey2addr(self,hexstr:'sstr'):
 		"convert scriptPubKey to coin address"
-		from mmgen.tx import scriptPubKey2addr
+		from .tx import scriptPubKey2addr
 		return scriptPubKey2addr(hexstr)[0]
 
 class MMGenToolCmdMnemonic(MMGenToolCmds):
@@ -524,7 +524,7 @@ class MMGenToolCmdMnemonic(MMGenToolCmds):
 
 	@staticmethod
 	def _xmr_reduce(bytestr):
-		from mmgen.protocol import MoneroProtocol as mp
+		from .protocol import MoneroProtocol as mp
 		if len(bytestr) != mp.privkey_len:
 			m = '{!r}: invalid bit length for Monero private key (must be {})'
 			die(1,m.format(len(bytestr*8),mp.privkey_len*8))
@@ -560,7 +560,7 @@ class MMGenToolCmdMnemonic(MMGenToolCmds):
 	def hex2mn( self, hexstr:'sstr', fmt:mn_opts_disp = dfl_mnemonic_fmt ):
 		"convert a 16, 24 or 32-byte hexadecimal number to a mnemonic seed phrase"
 		if fmt == 'bip39':
-			from mmgen.bip39 import bip39
+			from .bip39 import bip39
 			return ' '.join(bip39.fromhex(hexstr,fmt))
 		else:
 			bytestr = bytes.fromhex(hexstr)
@@ -571,14 +571,14 @@ class MMGenToolCmdMnemonic(MMGenToolCmds):
 	def mn2hex( self, seed_mnemonic:'sstr', fmt:mn_opts_disp = dfl_mnemonic_fmt ):
 		"convert a mnemonic seed phrase to a hexadecimal number"
 		if fmt == 'bip39':
-			from mmgen.bip39 import bip39
+			from .bip39 import bip39
 			return bip39.tohex(seed_mnemonic.split(),fmt)
 		else:
 			return baseconv.tohex(seed_mnemonic.split(),fmt,'seed')
 
 	def mn2hex_interactive( self, fmt:mn_opts_disp=dfl_mnemonic_fmt, mn_len=24, print_mn=False ):
 		"convert an interactively supplied mnemonic seed phrase to a hexadecimal number"
-		from mmgen.mn_entry import mn_entry
+		from .mn_entry import mn_entry
 		mn = mn_entry(fmt).get_mnemonic_from_user(25 if fmt == 'xmrseed' else mn_len,validate=False)
 		if print_mn:
 			msg(mn)
@@ -603,7 +603,7 @@ class MMGenToolCmdFile(MMGenToolCmds):
 	def _file_chksum(self,mmgen_addrfile,objname):
 		opt.yes = True
 		opt.quiet = True
-		from mmgen.addr import AddrList,KeyAddrList,PasswordList
+		from .addr import AddrList,KeyAddrList,PasswordList
 		ret = locals()[objname](mmgen_addrfile)
 		if opt.verbose:
 			if ret.al_id.mmtype.name == 'password':
@@ -647,8 +647,8 @@ class MMGenToolCmdFile(MMGenToolCmds):
 		tx_sort = kwargs.get('sort') or 'addr'
 		file_sort = kwargs.get('filesort') or 'mtime'
 
-		from mmgen.filename import MMGenFileList
-		from mmgen.tx import MMGenTX
+		from .filename import MMGenFileList
+		from .tx import MMGenTX
 		flist = MMGenFileList(infiles,ftype=MMGenTX)
 		flist.sort_by_age(key=file_sort) # in-place sort
 
@@ -834,14 +834,14 @@ class MMGenToolCmdWallet(MMGenToolCmds):
 		ret = d.sec.wif if target=='wif' else d.addr
 		return ret
 
-from mmgen.tw import TwAddrList,TwUnspentOutputs
+from .tw import TwAddrList,TwUnspentOutputs
 
 class MMGenToolCmdRPC(MMGenToolCmds):
 	"tracking wallet commands using the JSON-RPC interface"
 
 	def getbalance(self,minconf=1,quiet=False,pager=False):
 		"list confirmed/unconfirmed, spendable/unspendable balances in tracking wallet"
-		from mmgen.tw import TwGetBalance
+		from .tw import TwGetBalance
 		return TwGetBalance(minconf,quiet).format()
 
 	def listaddress(self,
@@ -921,7 +921,7 @@ class MMGenToolCmdRPC(MMGenToolCmds):
 	def add_label(self,mmgen_or_coin_addr:str,label:str):
 		"add descriptive label for address in tracking wallet"
 		rpc_init()
-		from mmgen.tw import TrackingWallet
+		from .tw import TrackingWallet
 		TrackingWallet(mode='w').add_label(mmgen_or_coin_addr,label,on_fail='raise')
 		return True
 
@@ -932,7 +932,7 @@ class MMGenToolCmdRPC(MMGenToolCmds):
 
 	def remove_address(self,mmgen_or_coin_addr:str):
 		"remove an address from tracking wallet"
-		from mmgen.tw import TrackingWallet
+		from .tw import TrackingWallet
 		tw = TrackingWallet(mode='w')
 		ret = tw.remove_address(mmgen_or_coin_addr) # returns None on failure
 		if ret:
@@ -954,7 +954,7 @@ class MMGenToolCmdMonero(MMGenToolCmds):
 	@property
 	def monero_chain_height(self):
 		if self._monero_chain_height == None:
-			from mmgen.daemon import CoinDaemon
+			from .daemon import CoinDaemon
 			port = CoinDaemon('xmr',test_suite=g.test_suite).rpc_port
 			cmd = ['monerod','--rpc-bind-port={}'.format(port)] + self.monerod_args + ['status']
 
@@ -996,7 +996,7 @@ class MMGenToolCmdMonero(MMGenToolCmds):
 				return False
 			gmsg(m)
 
-			from mmgen.baseconv import baseconv
+			from .baseconv import baseconv
 			ret = c.restore_deterministic_wallet(
 				filename  = os.path.basename(fn),
 				password  = d.wallet_passwd,
@@ -1045,7 +1045,7 @@ class MMGenToolCmdMonero(MMGenToolCmds):
 
 			ret = c.get_balance() # account_index=0, address_indices=[0,1]
 
-			from mmgen.obj import XMRAmt
+			from .obj import XMRAmt
 			bals[fn] = tuple([XMRAmt(ret[k],from_unit='min_coin_unit') for k in ('balance','unlocked_balance')])
 
 			if opt.verbose:
@@ -1063,20 +1063,20 @@ class MMGenToolCmdMonero(MMGenToolCmds):
 			m =   { 'create': ('Creat','Generat',create,False),
 					'sync':   ('Sync', 'Sync',   sync,  True) }
 			opt.accept_defaults = opt.accept_defaults or m[op][3]
-			from mmgen.protocol import init_coin
+			from .protocol import init_coin
 			init_coin('xmr')
-			from mmgen.addr import AddrList
+			from .addr import AddrList
 			al = KeyAddrList(infile)
 			data = [d for d in al.data if addrs == '' or d.idx in AddrIdxList(addrs)]
 			dl = len(data)
 			assert dl,"No addresses in addrfile within range '{}'".format(addrs)
 			gmsg('\n{}ing {} wallet{}'.format(m[op][0],dl,suf(dl)))
 
-			from mmgen.daemon import MoneroWalletDaemon
+			from .daemon import MoneroWalletDaemon
 			wd = MoneroWalletDaemon(opt.outdir or '.',test_suite=g.test_suite)
 			wd.restart()
 
-			from mmgen.rpc import MoneroWalletRPCConnection
+			from .rpc import MoneroWalletRPCConnection
 			c = MoneroWalletRPCConnection(
 				g.monero_wallet_rpc_host,
 				wd.rpc_port,
@@ -1101,7 +1101,7 @@ class MMGenToolCmdMonero(MMGenToolCmds):
 				col1_w = max(map(len,bals)) + 1
 				fs = '{:%s} {} {}' % col1_w
 				msg('\n'+fs.format('Wallet','Balance           ','Unlocked Balance  '))
-				from mmgen.obj import XMRAmt
+				from .obj import XMRAmt
 				tbals = [XMRAmt('0'),XMRAmt('0')]
 				for bal in bals:
 					for i in (0,1): tbals[i] += bals[bal][i]
@@ -1179,7 +1179,7 @@ class tool_api(
 		Valid choices for coins: one of the symbols returned by the 'coins' attribute
 		Valid choices for network: 'mainnet','testnet','regtest'
 		"""
-		from mmgen.protocol import init_coin,init_genonly_altcoins
+		from .protocol import init_coin,init_genonly_altcoins
 		altcoin_trust_level = init_genonly_altcoins(coinsym)
 		warn_altcoins(coinsym,altcoin_trust_level)
 		if network == 'regtest':
@@ -1189,8 +1189,8 @@ class tool_api(
 	@property
 	def coins(self):
 		"""The available coins"""
-		from mmgen.protocol import CoinProtocol
-		from mmgen.altcoin import CoinInfo
+		from .protocol import CoinProtocol
+		from .altcoin import CoinInfo
 		return sorted(set(CoinProtocol.list_coins() + [c.symbol for c in CoinInfo.get_supported_coins(g.network)]))
 
 	@property

+ 10 - 10
mmgen/tw.py

@@ -21,10 +21,10 @@ tw: Tracking wallet methods for the MMGen suite
 """
 
 import json
-from mmgen.exception import *
-from mmgen.common import *
-from mmgen.obj import *
-from mmgen.tx import is_mmgen_id
+from .exception import *
+from .common import *
+from .obj import *
+from .tx import is_mmgen_id
 
 CUR_HOME,ERASE_ALL = '\033[H','\033[0J'
 def CUR_RIGHT(n): return '\033[{}C'.format(n)
@@ -217,7 +217,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 		return ret
 
 	def set_term_columns(self):
-		from mmgen.term import get_terminal_size
+		from .term import get_terminal_size
 		while True:
 			self.cols = g.terminal_width or get_terminal_size().width
 			if self.cols >= g.min_screen_width: break
@@ -383,7 +383,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 						return n
 
 	def view_and_sort(self,tx):
-		from mmgen.term import get_char
+		from .term import get_char
 		prompt = self.prompt.strip() + '\b'
 		no_output,oneshot_msg = False,None
 		while True:
@@ -819,7 +819,7 @@ class TrackingWallet(MMGenObject):
 	# returns on failure
 	@write_mode
 	def add_label(self,arg1,label='',addr=None,silent=False,on_fail='return'):
-		from mmgen.tx import is_mmgen_id,is_coin_addr
+		from .tx import is_mmgen_id,is_coin_addr
 		mmaddr,coinaddr = None,None
 		if is_coin_addr(addr or arg1):
 			coinaddr = CoinAddr(addr or arg1,on_fail='return')
@@ -827,7 +827,7 @@ class TrackingWallet(MMGenObject):
 			mmaddr = TwMMGenID(arg1)
 
 		if mmaddr and not coinaddr:
-			from mmgen.addr import AddrData
+			from .addr import AddrData
 			coinaddr = AddrData(source='tw').mmaddr2coinaddr(mmaddr)
 
 		try:
@@ -842,7 +842,7 @@ class TrackingWallet(MMGenObject):
 		# Allow for the possibility that BTC addr of MMGen addr was entered.
 		# Do reverse lookup, so that MMGen addr will not be marked as non-MMGen.
 		if not mmaddr:
-			from mmgen.addr import AddrData
+			from .addr import AddrData
 			mmaddr = AddrData(source='tw').coinaddr2mmaddr(coinaddr)
 
 		if not mmaddr: mmaddr = '{}:{}'.format(g.proto.base_coin.lower(),coinaddr)
@@ -856,7 +856,7 @@ class TrackingWallet(MMGenObject):
 
 		ret = self.set_label(coinaddr,lbl)
 
-		from mmgen.rpc import rpc_error,rpc_errmsg
+		from .rpc import rpc_error,rpc_errmsg
 		if rpc_error(ret):
 			msg('From {}: {}'.format(g.proto.daemon_name,rpc_errmsg(ret)))
 			if not silent:

+ 11 - 11
mmgen/tx.py

@@ -22,8 +22,8 @@ tx.py:  Transaction routines for the MMGen suite
 
 import sys,os,json
 from stat import *
-from mmgen.common import *
-from mmgen.obj import *
+from .common import *
+from .obj import *
 
 wmsg = lambda k: {
 	'addr_in_addrfile_only': """
@@ -700,7 +700,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 			repr([amt_to_str(e.__dict__) for e in self.outputs])
 		]
 		if self.label:
-			from mmgen.baseconv import baseconv
+			from .baseconv import baseconv
 			lines.append(baseconv.frombytes(self.label.encode(),'b58',tostr=True))
 		if self.coin_txid:
 			if not self.label: lines.append('-') # keep old tx files backwards compatible
@@ -732,7 +732,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 		qmsg('Passing {} key{} to {}'.format(len(keys),suf(keys),g.proto.daemon_name))
 
 		if self.has_segwit_inputs():
-			from mmgen.addr import KeyGenerator,AddrGenerator
+			from .addr import KeyGenerator,AddrGenerator
 			kg = KeyGenerator('std')
 			ag = AddrGenerator('segwit')
 			keydict = MMGenDict([(d.addr,d.sec) for d in keys])
@@ -963,7 +963,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 
 		ret = None if g.bogus_send else g.rpch.sendrawtransaction(self.hex,on_fail='return')
 
-		from mmgen.rpc import rpc_error,rpc_errmsg
+		from .rpc import rpc_error,rpc_errmsg
 		if rpc_error(ret):
 			errmsg = rpc_errmsg(ret)
 			if 'Signature must use SIGHASH_FORKID' in errmsg:
@@ -1032,7 +1032,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 
 	def view_with_prompt(self,prompt='',pause=True):
 		prompt += ' (y)es, (N)o, pager (v)iew, (t)erse view: '
-		from mmgen.term import get_char
+		from .term import get_char
 		ok_chars = 'YyNnVvTt'
 		while True:
 			reply = get_char(prompt,immed_chars=ok_chars).strip('\n\r')
@@ -1050,7 +1050,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 		if pager: do_pager(o)
 		else:
 			msg_r(o)
-			from mmgen.term import get_char
+			from .term import get_char
 			if pause:
 				get_char('Press any key to continue: ')
 				msg('')
@@ -1226,7 +1226,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 				c = tx_data.pop(-1)
 				if c != '-':
 					desc = 'encoded comment (not base58)'
-					from mmgen.baseconv import baseconv
+					from .baseconv import baseconv
 					comment = baseconv.tobytes(c,'b58').decode()
 					assert comment != False,'invalid comment'
 					desc = 'comment'
@@ -1316,7 +1316,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 			die(2,'At least one output must be specified on the command line')
 
 	def get_outputs_from_cmdline(self,cmd_args):
-		from mmgen.addr import AddrList,AddrData
+		from .addr import AddrList,AddrData
 		addrfiles = [a for a in cmd_args if get_extension(a) == AddrList.ext]
 		cmd_args = set(cmd_args) - set(addrfiles)
 
@@ -1441,7 +1441,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 
 		twuo_addrs = self.get_cmdline_input_addrs()
 
-		from mmgen.tw import TwUnspentOutputs
+		from .tw import TwUnspentOutputs
 		self.twuo = TwUnspentOutputs(minconf=opt.minconf,addrs=twuo_addrs)
 
 		if not do_info:
@@ -1593,7 +1593,7 @@ class MMGenSplitTX(MMGenTX):
 
 	def get_outputs_from_cmdline(self,mmid): # TODO: check that addr is empty
 
-		from mmgen.addr import AddrData
+		from .addr import AddrData
 		ad_w = AddrData(source='tw')
 
 		if is_mmgen_id(mmid):

+ 5 - 5
mmgen/txsign.py

@@ -20,10 +20,10 @@
 txsign: Sign a transaction generated by 'mmgen-txcreate'
 """
 
-from mmgen.common import *
+from .common import *
 from .wallet import *
-from mmgen.tx import *
-from mmgen.addr import *
+from .tx import *
+from .addr import *
 
 pnm = g.proj_name
 
@@ -72,7 +72,7 @@ def generate_kals_for_mmgen_addrs(need_keys,infiles,saved_seeds):
 	sids = {i.sid for i in mmids}
 	vmsg('Need seed{}: {}'.format(suf(sids),' '.join(sids)))
 	d = MMGenList()
-	from mmgen.addr import KeyAddrList
+	from .addr import KeyAddrList
 	for sid in sids:
 		# Returns only if seed is found
 		seed = get_seed_for_seed_id(sid,infiles,saved_seeds)
@@ -119,7 +119,7 @@ def get_seed_files(opt,args):
 	# favor unencrypted seed sources first, as they don't require passwords
 	u,e = WalletUnenc,WalletEnc
 	ret = _pop_and_return(args,u.get_extensions())
-	from mmgen.filename import find_file_in_dir
+	from .filename import find_file_in_dir
 	wf = find_file_in_dir(MMGenWallet,g.data_dir) # Make this the first encrypted ss in the list
 	if wf: ret.append(wf)
 	ret += _pop_and_return(args,e.get_extensions())

+ 12 - 12
mmgen/util.py

@@ -23,9 +23,9 @@ util.py:  Low-level routines imported by other modules in the MMGen suite
 import sys,os,time,stat,re
 from hashlib import sha256
 from string import hexdigits,digits
-from mmgen.color import *
-from mmgen.exception import *
-from mmgen.globalvars import *
+from .color import *
+from .exception import *
+from .globalvars import *
 
 if g.platform == 'win':
 	def msg_r(s):
@@ -201,7 +201,7 @@ def check_or_create_dir(path):
 		except:
 			die(2,"ERROR: unable to read or create path '{}'".format(path))
 
-from mmgen.opts import opt
+from .opts import opt
 
 def qmsg(s,alt=None):
 	if opt.quiet:
@@ -264,11 +264,11 @@ def make_chksum_N(s,nchars,sep=False):
 	return sep.join([s[i*4:i*4+4] for i in range(nchars//4)])
 
 def make_chksum_8(s,sep=False):
-	from mmgen.obj import HexStr
+	from .obj import HexStr
 	s = HexStr(sha256(sha256(s).digest()).hexdigest()[:8].upper(),case='upper')
 	return '{} {}'.format(s[:4],s[4:]) if sep else s
 def make_chksum_6(s):
-	from mmgen.obj import HexStr
+	from .obj import HexStr
 	if isinstance(s,str): s = s.encode()
 	return HexStr(sha256(s).hexdigest()[:6])
 def is_chksum_6(s): return len(s) == 6 and is_hex_str_lc(s)
@@ -477,7 +477,7 @@ def make_full_path(outdir,outfile):
 	return os.path.normpath(os.path.join(outdir, os.path.basename(outfile)))
 
 def get_seed_file(cmd_args,nargs,invoked_as=None):
-	from mmgen.filename import find_file_in_dir
+	from .filename import find_file_in_dir
 	from .wallet import MMGenWallet
 
 	wf = find_file_in_dir(MMGenWallet,g.data_dir)
@@ -658,7 +658,7 @@ def mmgen_decrypt_file_maybe(fn,desc='',quiet=False,silent=False):
 	if have_enc_ext or not is_utf8(d):
 		m = ('Attempting to decrypt','Decrypting')[have_enc_ext]
 		qmsg("{} {} '{}'".format(m,desc,fn))
-		from mmgen.crypto import mmgen_decrypt_retry
+		from .crypto import mmgen_decrypt_retry
 		d = mmgen_decrypt_retry(d,desc)
 	return d
 
@@ -720,7 +720,7 @@ def my_raw_input(prompt,echo=True,insert_txt='',use_readline=True):
 		msg_r(prompt)
 		prompt = ''
 
-	from mmgen.term import kb_hold_protect
+	from .term import kb_hold_protect
 	kb_hold_protect()
 
 	if g.test_suite_popen_spawn:
@@ -756,7 +756,7 @@ def keypress_confirm(prompt,default_yes=False,verbose=False,no_nl=False,complete
 		msg(p)
 		return default_yes
 
-	from mmgen.term import get_char
+	from .term import get_char
 	while True:
 		reply = get_char(p,immed_chars='yYnN').strip('\n\r')
 		if not reply:
@@ -802,7 +802,7 @@ def do_license_msg(immed=False):
 	msg(gpl.warning)
 	prompt = '{} '.format(p.strip())
 
-	from mmgen.term import get_char
+	from .term import get_char
 	while True:
 		reply = get_char(prompt, immed_chars=('','wc')[bool(immed)])
 		if reply == 'w':
@@ -840,7 +840,7 @@ def rpc_init(reinit=False):
 	if not 'rpc' in g.proto.mmcaps:
 		die(1,'Coin daemon operations not supported for coin {}!'.format(g.coin))
 	if g.rpch != None and not reinit: return g.rpch
-	from mmgen.rpc import init_daemon
+	from .rpc import init_daemon
 	g.rpch = init_daemon(g.proto.daemon_family)
 	return g.rpch