From 2a880e7a93888fce8beab5068294e3869cfedb38 Mon Sep 17 00:00:00 2001 From: MMGen Date: Thu, 16 May 2019 09:43:33 +0000 Subject: [PATCH] various cleanups and fixes --- mmgen/common.py | 6 --- mmgen/main_addrgen.py | 15 +++----- mmgen/main_txsign.py | 12 +++++- mmgen/rpc.py | 7 +++- mmgen/seed.py | 34 +++++++++++++---- mmgen/txsign.py | 10 ++--- test/test_py_d/ts_regtest.py | 65 ++++++++++++++++++--------------- test/unit_tests_d/ut_subseed.py | 2 +- 8 files changed, 90 insertions(+), 61 deletions(-) diff --git a/mmgen/common.py b/mmgen/common.py index 08f42ec0..8215f847 100755 --- a/mmgen/common.py +++ b/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()) diff --git a/mmgen/main_addrgen.py b/mmgen/main_addrgen.py index 74ffbdb0..5543563d 100755 --- a/mmgen/main_addrgen.py +++ b/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() diff --git a/mmgen/main_txsign.py b/mmgen/main_txsign.py index 93cc8b31..aa3bab80 100755 --- a/mmgen/main_txsign.py +++ b/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())) } } diff --git a/mmgen/rpc.py b/mmgen/rpc.py index dfd0174c..6d7c6a5c 100755 --- a/mmgen/rpc.py +++ b/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 ===') diff --git a/mmgen/seed.py b/mmgen/seed.py index d248927c..d5e7d42d 100755 --- a/mmgen/seed.py +++ b/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=g.subseeds,last_sid=None): + def gen_subseeds(self,last_idx=None,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): diff --git a/mmgen/txsign.py b/mmgen/txsign.py index 9f7bef7f..2f9a9525 100755 --- a/mmgen/txsign.py +++ b/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] diff --git a/test/test_py_d/ts_regtest.py b/test/test_py_d/ts_regtest.py index 18a92c58..7ffdb5a4 100755 --- a/test/test_py_d/ts_regtest.py +++ b/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']) diff --git a/test/unit_tests_d/ut_subseed.py b/test/unit_tests_d/ut_subseed.py index c9ed421c..9d598c52 100755 --- a/test/unit_tests_d/ut_subseed.py +++ b/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