Browse Source

various cleanups and fixes

MMGen 5 years ago
parent
commit
2a880e7a93
8 changed files with 90 additions and 61 deletions
  1. 0 6
      mmgen/common.py
  2. 5 10
      mmgen/main_addrgen.py
  3. 10 2
      mmgen/main_txsign.py
  4. 6 1
      mmgen/rpc.py
  5. 27 7
      mmgen/seed.py
  6. 5 5
      mmgen/txsign.py
  7. 36 29
      test/test_py_d/ts_regtest.py
  8. 1 1
      test/unit_tests_d/ut_subseed.py

+ 0 - 6
mmgen/common.py

@@ -141,13 +141,7 @@ address mappings, all outputs to {pnm} addresses are verified with a seed
 source.  Therefore, seed files or a key-address file for all {pnm} outputs
 must also be supplied on the command line if the data can't be found in the
 default wallet.
-
-Seed source files must have the canonical extensions listed in the 'FileExt'
-column below:
-
-  {n_fmt}
 """.format( dn=g.proto.daemon_name,
-			n_fmt='\n  '.join(SeedSource.format_fmt_codes().splitlines()),
 			pnm=g.proj_name,
 			pnu=g.proto.name.capitalize(),
 			pnl=g.proj_name.lower())

+ 5 - 10
mmgen/main_addrgen.py

@@ -25,9 +25,8 @@ from mmgen.common import *
 from mmgen.crypto import *
 from mmgen.addr import *
 from mmgen.seed import SeedSource
-MAT = MMGenAddrType
 
-if sys.argv[0].split('-')[-1] == 'keygen':
+if g.prog_name == 'mmgen-keygen':
 	gen_what = 'keys'
 	gen_desc = 'secret keys'
 	opt_filter = None
@@ -37,9 +36,6 @@ else:
 	gen_desc = 'addresses'
 	opt_filter = 'hbcdeEiHOkKlpzPqrStUv-'
 	note_addrkey = ''
-note_secp256k1 = """
-If available, the secp256k1 library will be used for address generation.
-""".strip()
 
 opts_data = {
 	'sets': [('print_checksum',True,'quiet',True)],
@@ -90,7 +86,7 @@ opts_data = {
 Address indexes are given as a comma-separated list and/or hyphen-separated
 range(s).
 
-{n_addrkey}{n_secp}
+{n_addrkey}If available, the secp256k1 library will be used for address generation.
 
 ADDRESS TYPES:
   {n_at}
@@ -108,7 +104,7 @@ FMT CODES:
 	'code': {
 		'options': lambda s: s.format(
 			seed_lens=', '.join(map(str,g.seed_lens)),
-			dmat="'{}' or '{}'".format(g.proto.dfl_mmtype,MAT.mmtypes[g.proto.dfl_mmtype]['name']),
+			dmat="'{}' or '{}'".format(g.proto.dfl_mmtype,MMGenAddrType.mmtypes[g.proto.dfl_mmtype]['name']),
 			kgs=' '.join(['{}:{}'.format(n,k) for n,k in enumerate(g.key_generators,1)]),
 			kg=g.key_generator,
 			pnm=g.proj_name,
@@ -116,14 +112,13 @@ FMT CODES:
 			g=g,
 		),
 		'notes': lambda s: s.format(
-			n_secp=note_secp256k1,
 			n_addrkey=note_addrkey,
 			n_sw=help_notes('subwallet')+'\n\n',
 			n_pw=help_notes('passwd')+'\n\n',
 			n_bw=help_notes('brainwallet'),
 			n_fmt='\n  '.join(SeedSource.format_fmt_codes().splitlines()),
 			n_at='\n  '.join(["'{}','{:<12} - {}".format(
-				k,v['name']+"'",v['desc']) for k,v in list(MAT.mmtypes.items())])
+				k,v['name']+"'",v['desc']) for k,v in list(MMGenAddrType.mmtypes.items())])
 		)
 	}
 }
@@ -131,7 +126,7 @@ FMT CODES:
 cmd_args = opts.init(opts_data,add_opts=['b16'],opt_filter=opt_filter)
 
 errmsg = "'{}': invalid parameter for --type option".format(opt.type)
-addr_type = MAT(opt.type or g.proto.dfl_mmtype,errmsg=errmsg)
+addr_type = MMGenAddrType(opt.type or g.proto.dfl_mmtype,errmsg=errmsg)
 
 if len(cmd_args) < 1: opts.usage()
 

+ 10 - 2
mmgen/main_txsign.py

@@ -21,6 +21,7 @@ mmgen-txsign: Sign a transaction generated by 'mmgen-txcreate'
 """
 
 from mmgen.common import *
+from mmgen.seed import SeedSource
 
 # -w, --use-wallet-dat (keys from running coin daemon) removed: use walletdump rpc instead
 opts_data = {
@@ -63,7 +64,13 @@ opts_data = {
 -V, --vsize-adj=   f  Adjust transaction's estimated vsize by factor 'f'
 -y, --yes             Answer 'yes' to prompts, suppress non-essential output
 """,
-	'notes': '\n{}'
+	'notes': """
+{}
+Seed source files must have the canonical extensions listed in the 'FileExt'
+column below:
+
+  {f}
+"""
 	},
 	'code': {
 		'options': lambda s: s.format(
@@ -72,7 +79,8 @@ opts_data = {
 			kg=g.key_generator,
 			cu=g.coin),
 		'notes': lambda s: s.format(
-			help_notes('txsign'))
+			help_notes('txsign'),
+			f='\n  '.join(SeedSource.format_fmt_codes().splitlines()))
 	}
 }
 

+ 6 - 1
mmgen/rpc.py

@@ -98,12 +98,17 @@ class CoinDaemonRPCConnection(object):
 		else:
 			p = {'method':cmd,'params':args,'id':1,'jsonrpc':'2.0'}
 
-		def do_fail(*args):
+		def do_fail(*args): # args[0] is either None or HTTPResponse object
 			if cf['on_fail'] in ('return','silent'): return 'rpcfail',args
 
 			try:    s = '{}'.format(args[2])
 			except: s = repr(args[2])
 
+			if s == '' and args[0] != None:
+				from http import HTTPStatus
+				hs = HTTPStatus(args[0].code)
+				s = '{} {}'.format(hs.value,hs.name)
+
 			raise RPCFailure(s)
 
 		dmsg_rpc('=== request() debug ===')

+ 27 - 7
mmgen/seed.py

@@ -94,19 +94,39 @@ class Seed(SeedBase):
 				idx,nonce = self.subseeds[k][sid]
 				return SubSeed(self,idx,nonce,length=k)
 
-	def subseed_by_seed_id(self,sid,last_idx=g.subseeds):
+	def subseed_by_seed_id(self,sid,last_idx=None,print_msg=False):
+
+		def do_msg(seed):
+			if print_msg:
+				qmsg('{} {} ({}:{})'.format(
+					green('Found subseed'),
+					seed.sid.hl(),
+					self.sid.hl(),
+					seed.ss_idx.hl(),
+				))
+
+		if last_idx == None:
+			last_idx = g.subseeds
 
 		seed = self.existing_subseed_by_seed_id(sid)
-		if seed: return seed
+		if seed:
+			do_msg(seed)
+			return seed
 
 		if len(self.subseeds['long']) >= last_idx:
 			return None
 
 		self.gen_subseeds(last_idx,last_sid=sid)
 
-		return self.existing_subseed_by_seed_id(sid)
+		seed = self.existing_subseed_by_seed_id(sid)
+		if seed:
+			do_msg(seed)
+			return seed
+
+	def gen_subseeds(self,last_idx=None,last_sid=None):
 
-	def gen_subseeds(self,last_idx=g.subseeds,last_sid=None):
+		if last_idx == None:
+			last_idx = g.subseeds
 
 		first_idx = len(self.subseeds['long']) + 1
 
@@ -134,7 +154,7 @@ class Seed(SeedBase):
 			if add_subseed(idx,'long') + add_subseed(idx,'short'):
 				break
 
-	def fmt_subseeds(self,first_idx=1,last_idx=g.subseeds):
+	def fmt_subseeds(self,first_idx,last_idx):
 
 		r = SubSeedIdxRange(first_idx,last_idx)
 
@@ -172,12 +192,12 @@ class SubSeed(SeedBase,SubSeedBase):
 
 	idx    = MMGenImmutableAttr('idx',int,typeconv=False)
 	nonce  = MMGenImmutableAttr('nonce',int,typeconv=False)
-	ss_idx = MMGenImmutableAttr('ss_idx',str,typeconv=False)
+	ss_idx = MMGenImmutableAttr('ss_idx',SubSeedIdx,typeconv=False)
 
 	def __init__(self,parent,idx,nonce,length):
 		self.idx = idx
 		self.nonce = nonce
-		self.ss_idx = str(idx) + { 'long': 'L', 'short': 'S' }[length]
+		self.ss_idx = SubSeedIdx(str(idx) + { 'long': 'L', 'short': 'S' }[length])
 		SeedBase.__init__(self,seed_bin=SubSeedBase.make_subseed_bin(parent,idx,nonce,length))
 
 class SeedSource(MMGenObject):

+ 5 - 5
mmgen/txsign.py

@@ -47,16 +47,16 @@ def get_seed_for_seed_id(sid,infiles,saved_seeds):
 
 	while True:
 		if infiles:
-			ss = SeedSource(infiles.pop(0),ignore_in_fmt=True)
+			seed = SeedSource(infiles.pop(0),ignore_in_fmt=True).seed
 		elif opt.in_fmt:
 			qmsg('Need seed data for Seed ID {}'.format(sid))
-			ss = SeedSource()
-			msg('User input produced Seed ID {}'.format(ss.seed.sid))
+			seed = SeedSource().seed
+			msg('User input produced Seed ID {}'.format(seed.sid))
 		else:
 			die(2,'ERROR: No seed source found for Seed ID: {}'.format(sid))
 
-		saved_seeds[ss.seed.sid] = ss.seed
-		if ss.seed.sid == sid: return ss.seed
+		saved_seeds[seed.sid] = seed
+		if seed.sid == sid: return seed
 
 def generate_kals_for_mmgen_addrs(need_keys,infiles,saved_seeds):
 	mmids = [e.mmid for e in need_keys]

+ 36 - 29
test/test_py_d/ts_regtest.py

@@ -83,7 +83,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		('fund_alice',               "funding Alice's wallet"),
 		('bob_bal1',                 "Bob's balance"),
 		('bob_add_label',            "adding a 40-character UTF-8 encoded label"),
-		('bob_twview',               "viewing Bob's tracking wallet"),
+		('bob_twview1',              "viewing Bob's tracking wallet"),
 		('bob_split1',               "splitting Bob's funds"),
 		('generate',                 'mining a block'),
 		('bob_bal2',                 "Bob's balance"),
@@ -110,6 +110,13 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		('bob_bal5_getbalance',      "Bob's balance"),
 		('bob_send_non_mmgen',       'sending funds to Alice (from non-MMGen addrs)'),
 		('generate',                 'mining a block'),
+		('alice_bal_rpcfail',        'RPC failure code'),
+		('alice_send_estimatefee',   'tx creation with no fee on command line'),
+		('generate',                 'mining a block'),
+		('bob_bal6',                 "Bob's balance"),
+		('bob_alice_bal',            "Bob and Alice's balances"),
+		('alice_bal2',               "Alice's balance"),
+
 		('alice_add_label1',         'adding a label'),
 		('alice_chk_label1',         'the label'),
 		('alice_add_label2',         'adding a label'),
@@ -124,12 +131,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		('alice_add_label_badaddr2', 'adding a label with invalid address for this chain'),
 		('alice_add_label_badaddr3', 'adding a label with wrong MMGen address'),
 		('alice_add_label_badaddr4', 'adding a label with wrong coin address'),
-		('alice_bal_rpcfail',        'RPC failure code'),
-		('alice_send_estimatefee',   'tx creation with no fee on command line'),
-		('generate',                 'mining a block'),
-		('bob_bal6',                 "Bob's balance"),
-		('bob_alice_bal',            "Bob and Alice's balances"),
-		('alice_bal2',               "Alice's balance"),
+
 		('stop',                     'stopping regtest daemon'),
 	)
 
@@ -182,12 +184,13 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 	def _user_sid(self,user):
 		return os.path.basename(get_file_with_ext(self._user_dir(user),'mmdat'))[:8]
 
-	def addrgen(self,user,wf=None,addr_range='1-5'):
+	def addrgen(self,user,wf=None,addr_range='1-5',mmtypes=[]):
 		from mmgen.addr import MMGenAddrType
-		for mmtype in g.proto.mmtypes:
+		for mmtype in mmtypes or g.proto.mmtypes:
 			t = self.spawn('mmgen-addrgen',
 				['--quiet','--'+user,'--type='+mmtype,'--outdir={}'.format(self._user_dir(user))] +
-				([],[wf])[bool(wf)] + [addr_range],
+				([wf] if wf else []) +
+				[addr_range],
 				extra_desc='({})'.format(MMGenAddrType.mmtypes[mmtype]['name']))
 			t.passphrase('MMGen wallet',rt_pw)
 			t.written_to_file('Addresses')
@@ -198,11 +201,11 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 	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):
+	def addrimport(self,user,sid=None,addr_range='1-5',num_addrs=5,mmtypes=[]):
 		id_strs = { 'legacy':'', 'compressed':'-C', 'segwit':'-S', 'bech32':'-B' }
 		if not sid: sid = self._user_sid(user)
 		from mmgen.addr import MMGenAddrType
-		for mmtype in g.proto.mmtypes:
+		for mmtype in mmtypes or g.proto.mmtypes:
 			desc = MMGenAddrType.mmtypes[mmtype]['name']
 			addrfile = joinpath(self._user_dir(user),
 				'{}{}{}[{}]{x}.testnet.addrs'.format(
@@ -239,14 +242,13 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 	def fund_bob(self):   return self.fund_wallet('bob','C',rtFundAmt)
 	def fund_alice(self): return self.fund_wallet('alice',('L','S')[g.proto.cap('segwit')],rtFundAmt)
 
-	def user_twview(self,user):
-		t = self.spawn('mmgen-tool',['--'+user,'twview'])
-		t.expect(r'1\).*\b{}\b'.format(rtAmts[0]),regex=True)
+	def user_twview(self,user,chk=None,sort='age'):
+		t = self.spawn('mmgen-tool',['--'+user,'twview','sort='+sort])
+		if chk: t.expect(chk,regex=True)
 		t.read()
 		return t
 
-	def bob_twview(self):
-		return self.user_twview('bob')
+	def bob_twview1(self): return self.user_twview('bob',chk=r'1\).*\b{}\b'.format(rtAmts[0]))
 
 	def user_bal(self,user,bal,args=['showempty=1'],skip_check=False,exit_val=0):
 		t = self.spawn('mmgen-tool',['--'+user,'listaddresses'] + args)
@@ -326,8 +328,10 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 					wf           = None,
 					do_label     = False,
 					bad_locktime = False,
-					full_tx_view = False ):
-		os.environ['MMGEN_BOGUS_SEND'] = ''
+					full_tx_view = False,
+					menu         = ['M'],
+					bogus_send   = False):
+		os.environ['MMGEN_BOGUS_SEND'] = ('','1')[bool(bogus_send)]
 		t = self.spawn('mmgen-txdo',
 			['-d',self.tmpdir,'-B','--'+user] +
 			(['--tx-fee='+fee] if fee else []) +
@@ -336,7 +340,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 
 		self.txcreate_ui_common(t,
 								caller          = 'txdo',
-								menu            = ['M'],
+								menu            = menu,
 								inputs          = outputs_list,
 								file_desc       = 'Signed transaction',
 								interactive_fee = (tx_fee,'')[bool(fee)],
@@ -512,14 +516,14 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		return self.user_add_label('alice',sid+':C:1','Replacement Label')
 
 	def alice_add_label_coinaddr(self):
-		mmaddr = self._user_sid('alice') + ':C:2'
-		t = self.spawn('mmgen-tool',['--alice','listaddress',mmaddr],no_msg=True)
-		btcaddr = [i for i in t.read().splitlines() if i.lstrip()[0:len(mmaddr)] == mmaddr][0].split()[1]
+		mmid = self._user_sid('alice') + (':S:1',':L:1')[g.coin=='BCH']
+		t = self.spawn('mmgen-tool',['--alice','listaddress',mmid],no_msg=True)
+		btcaddr = [i for i in t.read().splitlines() if i.lstrip()[0:len(mmid)] == mmid][0].split()[1]
 		return self.user_add_label('alice',btcaddr,'Label added using coin address')
 
 	def alice_chk_label_coinaddr(self):
-		sid = self._user_sid('alice')
-		return self.user_chk_label('alice',sid+':C:2','Label added using coin address')
+		mmid = self._user_sid('alice') + (':S:1',':L:1')[g.coin=='BCH']
+		return self.user_chk_label('alice',mmid,'Label added using coin address')
 
 	def alice_add_label_badaddr(self,addr,reply):
 		t = self.spawn('mmgen-tool',['--alice','add_label',addr,'(none)'])
@@ -555,7 +559,8 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 
 	def alice_remove_label1(self):
 		sid = self._user_sid('alice')
-		return self.user_remove_label('alice',sid+':C:1')
+		mmid = sid + (':S:3',':L:3')[g.coin=='BCH']
+		return self.user_remove_label('alice',mmid)
 
 	def user_chk_label(self,user,addr,label,label_pat=None):
 		t = self.spawn('mmgen-tool',['--'+user,'listaddresses','all_labels=1'])
@@ -571,15 +576,17 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		return self.user_chk_label('alice',sid+':C:1','Replacement Label')
 
 	def alice_edit_label1(self):
-		return self.user_edit_label('alice','1',utf8_label)
+		return self.user_edit_label('alice','4',utf8_label)
 
 	def alice_chk_label3(self):
 		sid = self._user_sid('alice')
-		return self.user_chk_label('alice',sid+':C:1',utf8_label,label_pat=utf8_label_pat)
+		mmid = sid + (':S:3',':L:3')[g.coin=='BCH']
+		return self.user_chk_label('alice',mmid,utf8_label,label_pat=utf8_label_pat)
 
 	def alice_chk_label4(self):
 		sid = self._user_sid('alice')
-		return self.user_chk_label('alice',sid+':C:1','-')
+		mmid = sid + (':S:3',':L:3')[g.coin=='BCH']
+		return self.user_chk_label('alice',mmid,'-')
 
 	def user_edit_label(self,user,output,label):
 		t = self.spawn('mmgen-txcreate',['-B','--'+user,'-i'])

+ 1 - 1
test/unit_tests_d/ut_subseed.py

@@ -56,7 +56,7 @@ class subseed(object):
 
 				assert seed.pformat() == seed2.pformat()
 
-				s = seed.fmt_subseeds()
+				s = seed.fmt_subseeds(1,g.subseeds)
 				s_lines = s.strip().split('\n')
 				assert len(s_lines) == g.subseeds + 4, s