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
 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
 must also be supplied on the command line if the data can't be found in the
 default wallet.
 default wallet.
-
-Seed source files must have the canonical extensions listed in the 'FileExt'
-column below:
-
-  {n_fmt}
 """.format( dn=g.proto.daemon_name,
 """.format( dn=g.proto.daemon_name,
-			n_fmt='\n  '.join(SeedSource.format_fmt_codes().splitlines()),
 			pnm=g.proj_name,
 			pnm=g.proj_name,
 			pnu=g.proto.name.capitalize(),
 			pnu=g.proto.name.capitalize(),
 			pnl=g.proj_name.lower())
 			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.crypto import *
 from mmgen.addr import *
 from mmgen.addr import *
 from mmgen.seed import SeedSource
 from mmgen.seed import SeedSource
-MAT = MMGenAddrType
 
 
-if sys.argv[0].split('-')[-1] == 'keygen':
+if g.prog_name == 'mmgen-keygen':
 	gen_what = 'keys'
 	gen_what = 'keys'
 	gen_desc = 'secret keys'
 	gen_desc = 'secret keys'
 	opt_filter = None
 	opt_filter = None
@@ -37,9 +36,6 @@ else:
 	gen_desc = 'addresses'
 	gen_desc = 'addresses'
 	opt_filter = 'hbcdeEiHOkKlpzPqrStUv-'
 	opt_filter = 'hbcdeEiHOkKlpzPqrStUv-'
 	note_addrkey = ''
 	note_addrkey = ''
-note_secp256k1 = """
-If available, the secp256k1 library will be used for address generation.
-""".strip()
 
 
 opts_data = {
 opts_data = {
 	'sets': [('print_checksum',True,'quiet',True)],
 	'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
 Address indexes are given as a comma-separated list and/or hyphen-separated
 range(s).
 range(s).
 
 
-{n_addrkey}{n_secp}
+{n_addrkey}If available, the secp256k1 library will be used for address generation.
 
 
 ADDRESS TYPES:
 ADDRESS TYPES:
   {n_at}
   {n_at}
@@ -108,7 +104,7 @@ FMT CODES:
 	'code': {
 	'code': {
 		'options': lambda s: s.format(
 		'options': lambda s: s.format(
 			seed_lens=', '.join(map(str,g.seed_lens)),
 			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)]),
 			kgs=' '.join(['{}:{}'.format(n,k) for n,k in enumerate(g.key_generators,1)]),
 			kg=g.key_generator,
 			kg=g.key_generator,
 			pnm=g.proj_name,
 			pnm=g.proj_name,
@@ -116,14 +112,13 @@ FMT CODES:
 			g=g,
 			g=g,
 		),
 		),
 		'notes': lambda s: s.format(
 		'notes': lambda s: s.format(
-			n_secp=note_secp256k1,
 			n_addrkey=note_addrkey,
 			n_addrkey=note_addrkey,
 			n_sw=help_notes('subwallet')+'\n\n',
 			n_sw=help_notes('subwallet')+'\n\n',
 			n_pw=help_notes('passwd')+'\n\n',
 			n_pw=help_notes('passwd')+'\n\n',
 			n_bw=help_notes('brainwallet'),
 			n_bw=help_notes('brainwallet'),
 			n_fmt='\n  '.join(SeedSource.format_fmt_codes().splitlines()),
 			n_fmt='\n  '.join(SeedSource.format_fmt_codes().splitlines()),
 			n_at='\n  '.join(["'{}','{:<12} - {}".format(
 			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)
 cmd_args = opts.init(opts_data,add_opts=['b16'],opt_filter=opt_filter)
 
 
 errmsg = "'{}': invalid parameter for --type option".format(opt.type)
 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()
 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.common import *
+from mmgen.seed import SeedSource
 
 
 # -w, --use-wallet-dat (keys from running coin daemon) removed: use walletdump rpc instead
 # -w, --use-wallet-dat (keys from running coin daemon) removed: use walletdump rpc instead
 opts_data = {
 opts_data = {
@@ -63,7 +64,13 @@ opts_data = {
 -V, --vsize-adj=   f  Adjust transaction's estimated vsize by factor 'f'
 -V, --vsize-adj=   f  Adjust transaction's estimated vsize by factor 'f'
 -y, --yes             Answer 'yes' to prompts, suppress non-essential output
 -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': {
 	'code': {
 		'options': lambda s: s.format(
 		'options': lambda s: s.format(
@@ -72,7 +79,8 @@ opts_data = {
 			kg=g.key_generator,
 			kg=g.key_generator,
 			cu=g.coin),
 			cu=g.coin),
 		'notes': lambda s: s.format(
 		'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:
 		else:
 			p = {'method':cmd,'params':args,'id':1,'jsonrpc':'2.0'}
 			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
 			if cf['on_fail'] in ('return','silent'): return 'rpcfail',args
 
 
 			try:    s = '{}'.format(args[2])
 			try:    s = '{}'.format(args[2])
 			except: s = repr(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)
 			raise RPCFailure(s)
 
 
 		dmsg_rpc('=== request() debug ===')
 		dmsg_rpc('=== request() debug ===')

+ 27 - 7
mmgen/seed.py

@@ -94,19 +94,39 @@ class Seed(SeedBase):
 				idx,nonce = self.subseeds[k][sid]
 				idx,nonce = self.subseeds[k][sid]
 				return SubSeed(self,idx,nonce,length=k)
 				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)
 		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:
 		if len(self.subseeds['long']) >= last_idx:
 			return None
 			return None
 
 
 		self.gen_subseeds(last_idx,last_sid=sid)
 		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
 		first_idx = len(self.subseeds['long']) + 1
 
 
@@ -134,7 +154,7 @@ class Seed(SeedBase):
 			if add_subseed(idx,'long') + add_subseed(idx,'short'):
 			if add_subseed(idx,'long') + add_subseed(idx,'short'):
 				break
 				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)
 		r = SubSeedIdxRange(first_idx,last_idx)
 
 
@@ -172,12 +192,12 @@ class SubSeed(SeedBase,SubSeedBase):
 
 
 	idx    = MMGenImmutableAttr('idx',int,typeconv=False)
 	idx    = MMGenImmutableAttr('idx',int,typeconv=False)
 	nonce  = MMGenImmutableAttr('nonce',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):
 	def __init__(self,parent,idx,nonce,length):
 		self.idx = idx
 		self.idx = idx
 		self.nonce = nonce
 		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))
 		SeedBase.__init__(self,seed_bin=SubSeedBase.make_subseed_bin(parent,idx,nonce,length))
 
 
 class SeedSource(MMGenObject):
 class SeedSource(MMGenObject):

+ 5 - 5
mmgen/txsign.py

@@ -47,16 +47,16 @@ def get_seed_for_seed_id(sid,infiles,saved_seeds):
 
 
 	while True:
 	while True:
 		if infiles:
 		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:
 		elif opt.in_fmt:
 			qmsg('Need seed data for Seed ID {}'.format(sid))
 			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:
 		else:
 			die(2,'ERROR: No seed source found for Seed ID: {}'.format(sid))
 			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):
 def generate_kals_for_mmgen_addrs(need_keys,infiles,saved_seeds):
 	mmids = [e.mmid for e in need_keys]
 	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"),
 		('fund_alice',               "funding Alice's wallet"),
 		('bob_bal1',                 "Bob's balance"),
 		('bob_bal1',                 "Bob's balance"),
 		('bob_add_label',            "adding a 40-character UTF-8 encoded label"),
 		('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"),
 		('bob_split1',               "splitting Bob's funds"),
 		('generate',                 'mining a block'),
 		('generate',                 'mining a block'),
 		('bob_bal2',                 "Bob's balance"),
 		('bob_bal2',                 "Bob's balance"),
@@ -110,6 +110,13 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 		('bob_bal5_getbalance',      "Bob's balance"),
 		('bob_bal5_getbalance',      "Bob's balance"),
 		('bob_send_non_mmgen',       'sending funds to Alice (from non-MMGen addrs)'),
 		('bob_send_non_mmgen',       'sending funds to Alice (from non-MMGen addrs)'),
 		('generate',                 'mining a block'),
 		('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_add_label1',         'adding a label'),
 		('alice_chk_label1',         'the label'),
 		('alice_chk_label1',         'the label'),
 		('alice_add_label2',         'adding a 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_badaddr2', 'adding a label with invalid address for this chain'),
 		('alice_add_label_badaddr3', 'adding a label with wrong MMGen address'),
 		('alice_add_label_badaddr3', 'adding a label with wrong MMGen address'),
 		('alice_add_label_badaddr4', 'adding a label with wrong coin 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'),
 		('stop',                     'stopping regtest daemon'),
 	)
 	)
 
 
@@ -182,12 +184,13 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 	def _user_sid(self,user):
 	def _user_sid(self,user):
 		return os.path.basename(get_file_with_ext(self._user_dir(user),'mmdat'))[:8]
 		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
 		from mmgen.addr import MMGenAddrType
-		for mmtype in g.proto.mmtypes:
+		for mmtype in mmtypes or g.proto.mmtypes:
 			t = self.spawn('mmgen-addrgen',
 			t = self.spawn('mmgen-addrgen',
 				['--quiet','--'+user,'--type='+mmtype,'--outdir={}'.format(self._user_dir(user))] +
 				['--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']))
 				extra_desc='({})'.format(MMGenAddrType.mmtypes[mmtype]['name']))
 			t.passphrase('MMGen wallet',rt_pw)
 			t.passphrase('MMGen wallet',rt_pw)
 			t.written_to_file('Addresses')
 			t.written_to_file('Addresses')
@@ -198,11 +201,11 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 	def addrgen_bob(self):   return self.addrgen('bob')
 	def addrgen_bob(self):   return self.addrgen('bob')
 	def addrgen_alice(self): return self.addrgen('alice')
 	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' }
 		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
 		from mmgen.addr import MMGenAddrType
-		for mmtype in g.proto.mmtypes:
+		for mmtype in mmtypes or g.proto.mmtypes:
 			desc = MMGenAddrType.mmtypes[mmtype]['name']
 			desc = MMGenAddrType.mmtypes[mmtype]['name']
 			addrfile = joinpath(self._user_dir(user),
 			addrfile = joinpath(self._user_dir(user),
 				'{}{}{}[{}]{x}.testnet.addrs'.format(
 				'{}{}{}[{}]{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_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 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()
 		t.read()
 		return t
 		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):
 	def user_bal(self,user,bal,args=['showempty=1'],skip_check=False,exit_val=0):
 		t = self.spawn('mmgen-tool',['--'+user,'listaddresses'] + args)
 		t = self.spawn('mmgen-tool',['--'+user,'listaddresses'] + args)
@@ -326,8 +328,10 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 					wf           = None,
 					wf           = None,
 					do_label     = False,
 					do_label     = False,
 					bad_locktime = 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',
 		t = self.spawn('mmgen-txdo',
 			['-d',self.tmpdir,'-B','--'+user] +
 			['-d',self.tmpdir,'-B','--'+user] +
 			(['--tx-fee='+fee] if fee else []) +
 			(['--tx-fee='+fee] if fee else []) +
@@ -336,7 +340,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 
 
 		self.txcreate_ui_common(t,
 		self.txcreate_ui_common(t,
 								caller          = 'txdo',
 								caller          = 'txdo',
-								menu            = ['M'],
+								menu            = menu,
 								inputs          = outputs_list,
 								inputs          = outputs_list,
 								file_desc       = 'Signed transaction',
 								file_desc       = 'Signed transaction',
 								interactive_fee = (tx_fee,'')[bool(fee)],
 								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')
 		return self.user_add_label('alice',sid+':C:1','Replacement Label')
 
 
 	def alice_add_label_coinaddr(self):
 	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')
 		return self.user_add_label('alice',btcaddr,'Label added using coin address')
 
 
 	def alice_chk_label_coinaddr(self):
 	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):
 	def alice_add_label_badaddr(self,addr,reply):
 		t = self.spawn('mmgen-tool',['--alice','add_label',addr,'(none)'])
 		t = self.spawn('mmgen-tool',['--alice','add_label',addr,'(none)'])
@@ -555,7 +559,8 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
 
 
 	def alice_remove_label1(self):
 	def alice_remove_label1(self):
 		sid = self._user_sid('alice')
 		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):
 	def user_chk_label(self,user,addr,label,label_pat=None):
 		t = self.spawn('mmgen-tool',['--'+user,'listaddresses','all_labels=1'])
 		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')
 		return self.user_chk_label('alice',sid+':C:1','Replacement Label')
 
 
 	def alice_edit_label1(self):
 	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):
 	def alice_chk_label3(self):
 		sid = self._user_sid('alice')
 		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):
 	def alice_chk_label4(self):
 		sid = self._user_sid('alice')
 		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):
 	def user_edit_label(self,user,output,label):
 		t = self.spawn('mmgen-txcreate',['-B','--'+user,'-i'])
 		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()
 				assert seed.pformat() == seed2.pformat()
 
 
-				s = seed.fmt_subseeds()
+				s = seed.fmt_subseeds(1,g.subseeds)
 				s_lines = s.strip().split('\n')
 				s_lines = s.strip().split('\n')
 				assert len(s_lines) == g.subseeds + 4, s
 				assert len(s_lines) == g.subseeds + 4, s