From 50f55b9790306adebea9b27c7ce6c9358c3edadd Mon Sep 17 00:00:00 2001 From: philemon Date: Tue, 19 Sep 2017 22:14:00 +0300 Subject: [PATCH] mmgen-regtest: test suite support, mswin bugfixes tx.view(): refactor, bugfixes new script: test-release.sh --- mmgen/main_regtest.py | 3 +- mmgen/obj.py | 18 ++- mmgen/opts.py | 28 ++-- mmgen/regtest.py | 67 +++++---- mmgen/rpc.py | 7 +- mmgen/test.py | 2 +- mmgen/tool.py | 4 +- mmgen/tx.py | 110 +++++++------- mmgen/txsign.py | 2 +- mmgen/util.py | 13 +- scripts/test-release.sh | 68 +++++++++ scripts/traceback.py | 4 +- test/mmgen_pexpect.py | 17 ++- test/ref/btcwallet-testnet.dump | 109 ++++++++++++++ test/ref/btcwallet.dump | 109 ++++++++++++++ test/test.py | 253 ++++++++++++++++++++++++++++---- 16 files changed, 652 insertions(+), 162 deletions(-) create mode 100755 scripts/test-release.sh create mode 100644 test/ref/btcwallet-testnet.dump create mode 100644 test/ref/btcwallet.dump diff --git a/mmgen/main_regtest.py b/mmgen/main_regtest.py index 1cd62196..3b7f02a7 100755 --- a/mmgen/main_regtest.py +++ b/mmgen/main_regtest.py @@ -47,6 +47,7 @@ opts_data = lambda: { generate - mine a block test_daemon - test whether daemon is running get_balances - get balances of Bob and Alice + show_mempool - show transaction IDs in mempool """ } @@ -56,7 +57,7 @@ if len(cmd_args) != 1: opts.usage() cmds = ('setup','stop','generate','test_daemon','create_data_dir','bob','alice','user', - 'wait_for_daemon','wait_for_exit','get_current_user','get_balances') + 'wait_for_daemon','wait_for_exit','get_current_user','get_balances','show_mempool') if cmd_args[0] not in cmds: opts.usage() diff --git a/mmgen/obj.py b/mmgen/obj.py index bda19ad8..4af957cf 100755 --- a/mmgen/obj.py +++ b/mmgen/obj.py @@ -661,9 +661,21 @@ class MMGenAddrType(str,Hilite,InitErrors,MMGenObject): trunc_ok = False color = 'blue' mmtypes = { # since 'name' is used to cook the seed, it must never change! -'L': {'name':'legacy','comp':False,'gen':'p2pkh', 'fmt':'p2pkh','desc':'Legacy uncompressed Bitcoin address'}, -'S': {'name':'segwit','comp':True, 'gen':'segwit','fmt':'p2sh', 'desc':'Bitcoin Segwit P2SH-P2WPK address' }, -'C': {'name':'compressed','comp':True,'gen':'p2pkh','fmt':'p2pkh','desc':'Compressed Bitcoin P2PKH address'} + 'L': { 'name':'legacy', + 'comp':False, + 'gen':'p2pkh', + 'fmt':'p2pkh', + 'desc':'Legacy uncompressed Bitcoin address'}, + 'S': { 'name':'segwit', + 'comp':True, + 'gen':'segwit', + 'fmt':'p2sh', + 'desc':'Bitcoin Segwit P2SH-P2WPK address' }, + 'C': { 'name':'compressed', + 'comp':True, + 'gen':'p2pkh', + 'fmt':'p2pkh', + 'desc':'Compressed Bitcoin P2PKH address'} # 'l': 'litecoin', # 'e': 'ethereum', # 'E': 'ethereum_classic', diff --git a/mmgen/opts.py b/mmgen/opts.py index 4fa6fdba..48dcb5d2 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -227,10 +227,6 @@ def init(opts_f,add_opts=[],opt_filter=None): else: setattr(opt,k,g.__dict__[k]) - # Check user-set opts without modifying them - if not check_opts(uopts): - sys.exit(1) - if opt.show_hash_presets: _show_hash_presets() sys.exit(0) @@ -246,24 +242,27 @@ def init(opts_f,add_opts=[],opt_filter=None): opts_data['long_options'] = common_opts_data mmgen.share.Opts.parse_opts(sys.argv,opts_data,opt_filter=opt_filter) - # We don't need this data anymore - del mmgen.share.Opts - del opts_f - for k in ('prog_name','desc','usage','options','notes'): - if k in opts_data: del opts_data[k] - if g.bob or g.alice: + g.data_dir = os.path.join(g.data_dir_root,'regtest') import regtest as rt - rt.user(('alice','bob')[g.bob],quiet=True) g.testnet = True g.rpc_host = 'localhost' g.rpc_port = rt.rpc_port g.rpc_user = rt.rpc_user g.rpc_password = rt.rpc_password - g.data_dir = os.path.join(g.home_dir,'.'+g.proj_name.lower(),'regtest') + + # Check user-set opts without modifying them + if not check_opts(uopts): + sys.exit(1) if g.debug: opt_postproc_debug() + # We don't need this data anymore + del mmgen.share.Opts + del opts_f + for k in ('prog_name','desc','usage','options','notes'): + if k in opts_data: del opts_data[k] + return args def check_opts(usr_opts): # Returns false if any check fails @@ -414,6 +413,11 @@ def check_opts(usr_opts): # Returns false if any check fails if not opt_compares(val,'>',0,desc): return False elif key == 'coin': if not opt_is_in_list(val.upper(),g.coins,'coin'): return False + elif key in ('bob','alice'): + from mmgen.regtest import regtest_dir + m = "{}'s wallet doesn't exist yet. Run '{}-regtest setup' to initialize." + try: os.stat(regtest_dir) + except: die(1,m.format(key.capitalize(),g.proj_name.lower())) else: if g.debug: Msg("check_opts(): No test for opt '%s'" % key) diff --git a/mmgen/regtest.py b/mmgen/regtest.py index c46dc898..ef671ce0 100755 --- a/mmgen/regtest.py +++ b/mmgen/regtest.py @@ -22,26 +22,20 @@ regtest: Bitcoind regression test mode setup and operations for the MMGen suite import os,subprocess,time,shutil from mmgen.common import * +PIPE = subprocess.PIPE -data_dir = os.path.join(g.data_dir,'regtest') -regtest_dir = os.path.join(data_dir,'regtest') -rpc_port = 8552 -rpc_user = 'bobandalice' +data_dir = os.path.join(g.data_dir_root,'regtest') +regtest_dir = os.path.join(data_dir,'regtest') +rpc_port = 8552 +rpc_user = 'bobandalice' rpc_password = 'hodltothemoon' -init_amt = 500 -tr_wallet = { - 'orig': os.path.join(regtest_dir,'wallet.dat.orig'), - 'bob': os.path.join(regtest_dir,'wallet.dat.bob'), - 'alice': os.path.join(regtest_dir,'wallet.dat.alice') -} -mmwords = { - 'bob': os.path.join(data_dir,'1163DDF1[128].mmwords'), - 'alice': os.path.join(data_dir,'9304C211[128].mmwords') -} -mmaddrs = { - 'bob': os.path.join(data_dir,'1163DDF1{}[1-10].addrs'), - 'alice': os.path.join(data_dir,'9304C211{}[1-10].addrs') -} +init_amt = 500 +sids = { 'bob':'1163DDF1', 'alice':'9304C211' } + +tr_wallet = lambda user: os.path.join(regtest_dir,'wallet.dat.'+user) +mmwallet = lambda user: os.path.join(data_dir,'{}[128].mmwords'.format(sids[user])) +mmaddrs = lambda user: os.path.join(data_dir,'{}{{}}[1-5].addrs'.format(sids[user])) + mnemonic = { 'bob': 'ignore bubble ignore crash stay long stay patient await glorious destination moon', 'alice': 'stay long guard secret await price rise destination moon enjoy rich future' @@ -54,6 +48,7 @@ send_addr = { common_args = ( '-rpcuser={}'.format(rpc_user), '-rpcpassword={}'.format(rpc_password), + '-rpcport={}'.format(rpc_port), '-regtest', '-datadir={}'.format(data_dir)) @@ -61,13 +56,11 @@ def start_daemon(user,quiet=False,daemon=True): cmd = ( 'bitcoind', '-keypool=1', - '-rpcbind=localhost:{}'.format(rpc_port), - '-rpcallowip=::1', - '-wallet={}'.format(os.path.basename(tr_wallet[user])) + '-wallet={}'.format(os.path.basename(tr_wallet(user))) ) + common_args if daemon: cmd += ('-daemon',) if not g.debug or quiet: vmsg('{}'.format(' '.join(cmd))) - p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + p = subprocess.Popen(cmd,stdout=PIPE,stderr=PIPE) err = process_output(p,silent=False)[1] if err: rdie(1,'Error starting the Bitcoin daemon:\n{}'.format(err)) @@ -82,10 +75,11 @@ def start_daemon_mswin(user,quiet=False): def start_cmd(*args,**kwargs): cmd = args if args[0] == 'cli': - cmd = ('bitcoin-cli','-rpcconnect=localhost','-rpcport={}'.format(rpc_port)) + common_args + args[1:] + cmd = ('bitcoin-cli',) + common_args + args[1:] if g.debug or not 'quiet' in kwargs: vmsg('{}'.format(' '.join(cmd))) - return subprocess.Popen(cmd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + io=(PIPE,None)['no_pipe' in kwargs and kwargs['no_pipe']] + return subprocess.Popen(cmd,stdin=io,stdout=io,stderr=io) def test_daemon(): p = start_cmd('cli','getblockcount',quiet=True) @@ -113,7 +107,9 @@ def get_balances(): tbal = 0 from mmgen.obj import BTCAmt for user in (user1,user2): - p = start_cmd('python','mmgen-tool','--{}'.format(user),'getbalance','quiet=1') + p = start_cmd('python','mmgen-tool', + '--{}'.format(user),'--data-dir='+g.data_dir, + 'getbalance','quiet=1') bal = BTCAmt(p.stdout.read()) ustr = "{}'s balance:".format(user.capitalize()) msg('{:<16} {:12}'.format(ustr,bal)) @@ -122,7 +118,6 @@ def get_balances(): msg('{:<16} {:12}'.format('Miner fees:',1000-tbal)) def create_data_dir(): -#def keypress_confirm(prompt,default_yes=False,verbose=False,no_nl=False): try: os.stat(regtest_dir) except: pass else: @@ -136,6 +131,7 @@ def create_data_dir(): def process_output(p,silent=False): out = p.stdout.read() + if not opt.verbose: Msg_r(' \b') err = p.stderr.read() if g.debug or not silent: vmsg('stdout: [{}]'.format(out.strip())) @@ -155,9 +151,11 @@ def create_mmgen_wallet(user): def create_mmgen_addrs(user,addr_type): gmsg('Creating MMGen addresses for user {} (type: {})'.format(user.capitalize(),addr_type)) suf = ('-'+addr_type,'')[addr_type=='L'] - try: os.unlink(mmaddrs[user].format(suf)) + try: os.unlink(mmaddrs(user).format(suf)) except: pass - p = start_cmd('python','mmgen-addrgen','--{}'.format(user),'-d',data_dir,'--type',addr_type,mmwords[user],'1-10') + p = start_cmd('python','mmgen-addrgen', + '--{}'.format(user),'--data-dir='+g.data_dir, + '-d',data_dir,'--type',addr_type,mmwallet(user),'1-5') p.stdin.write(mnemonic[user]+'\n') p.stdin.close() err = process_output(p)[1] @@ -168,9 +166,9 @@ def create_mmgen_addrs(user,addr_type): def import_mmgen_addrs(user,addr_type): gmsg_r('Importing MMGen addresses for user {} (type: {})'.format(user.capitalize(),addr_type)) suf = ('-'+addr_type,'')[addr_type=='L'] - p = start_cmd('python','mmgen-addrimport','--{}'.format(user),'-q','--batch',mmaddrs[user].format(suf)) - p.stdin.write(mnemonic[user]+'\n') - p.stdin.close() + p = start_cmd('python','mmgen-addrimport', + '--{}'.format(user),'--data-dir='+g.data_dir, + '-q','--batch',mmaddrs(user).format(suf)) err = process_output(p)[1] if not 'addresses imported' in err: rdie(1,'Error importing MMGen addresses') @@ -211,6 +209,11 @@ def fund_wallet(user,amt): process_output(p) p.wait() +def show_mempool(): + p = start_cmd('cli','getrawmempool') + msg_r(p.stdout.read()) + p.wait() + def setup(): try: os.mkdir(data_dir) except: pass @@ -245,7 +248,7 @@ def setup(): def get_current_user_win(quiet=False): if test_daemon() == 'stopped': return None - p = start_cmd('grep','Using wallet',os.path.join(regtest_dir,'debug.log')) + p = start_cmd('grep','Using wallet',os.path.join(regtest_dir,'debug.log'),quiet=True) try: wallet_fn = p.stdout.readlines()[-1].split()[-1] except: return None for k in ('orig','bob','alice'): diff --git a/mmgen/rpc.py b/mmgen/rpc.py index 9025c2dc..22fd577b 100755 --- a/mmgen/rpc.py +++ b/mmgen/rpc.py @@ -75,7 +75,9 @@ class BitcoinRPCConnection(object): if cf['on_fail'] in ('return','silent'): return 'rpcfail',args else: - die(args[1],yellow(args[2])) + try: s = u'{}'.format(args[2]) + except: s = repr(args[2]) + die(args[1],yellow(s)) dmsg('=== request() debug ===') dmsg(' RPC POST data ==> %s\n' % p) @@ -91,7 +93,8 @@ class BitcoinRPCConnection(object): # dump = json.dumps(p,cls=MyJSONEncoder,ensure_ascii=False) # print(dump) - dmsg(' RPC AUTHORIZATION data ==> [Basic {}]\n'.format(base64.b64encode(self.auth_str))) + dmsg(' RPC AUTHORIZATION data ==> raw: [{}]\n{}enc: [Basic {}]\n'.format( + self.auth_str,' '*31,base64.b64encode(self.auth_str))) try: hc.request('POST', '/', json.dumps(p,cls=MyJSONEncoder), { 'Host': self.host, diff --git a/mmgen/test.py b/mmgen/test.py index 8e5a348d..b0d9bb92 100755 --- a/mmgen/test.py +++ b/mmgen/test.py @@ -49,7 +49,7 @@ def mk_tmpdir(d): except OSError as e: if e.errno != 17: raise else: - qmsg("Created directory '%s'" % d) + vmsg("Created directory '%s'" % d) def mk_tmpdir_path(path,cfg): try: diff --git a/mmgen/tool.py b/mmgen/tool.py index 836e7594..a9ec37db 100755 --- a/mmgen/tool.py +++ b/mmgen/tool.py @@ -78,7 +78,7 @@ cmd_data = OrderedDict([ ('Mn_printlist', ["wordlist [str='electrum']"]), ('Listaddress',['<{} address> [str]'.format(pnm),'minconf [int=1]','pager [bool=False]','showempty [bool=True]''showbtcaddr [bool=True]']), - ('Listaddresses',["addrs [str='']",'minconf [int=1]','showempty [bool=False]','pager [bool=False]','showbtcaddrs [bool=False]','all_labels [bool=False]']), + ('Listaddresses',["addrs [str='']",'minconf [int=1]','showempty [bool=False]','pager [bool=False]','showbtcaddrs [bool=True]','all_labels [bool=False]']), ('Getbalance', ['minconf [int=1]','quiet [bool=False]']), ('Txview', ['<{} TX file(s)> [str]'.format(pnm),'pager [bool=False]','terse [bool=False]',"sort [str='mtime'] (options: 'ctime','atime')",'MARGS']), ('Twview', ["sort [str='age']",'reverse [bool=False]','show_days [bool=True]','show_mmid [bool=True]','minconf [int=1]','wide [bool=False]','pager [bool=False]']), @@ -354,7 +354,7 @@ def Listaddress(addr,minconf=1,pager=False,showempty=True,showbtcaddr=True): return Listaddresses(addrs=addr,minconf=minconf,pager=pager,showempty=showempty,showbtcaddrs=showbtcaddr) # List MMGen addresses and their balances. TODO: move this code to AddrList -def Listaddresses(addrs='',minconf=1,showempty=False,pager=False,showbtcaddrs=False,all_labels=False): +def Listaddresses(addrs='',minconf=1,showempty=False,pager=False,showbtcaddrs=True,all_labels=False): c = rpc_connection() diff --git a/mmgen/tx.py b/mmgen/tx.py index d072d64a..f655bf9b 100755 --- a/mmgen/tx.py +++ b/mmgen/tx.py @@ -134,7 +134,7 @@ class MMGenTX(MMGenObject): class MMGenTxInput(MMGenListItem): for k in txio_attrs: locals()[k] = txio_attrs[k] # in lieu of inheritance scriptPubKey = MMGenListItemAttr('scriptPubKey','HexStr') - sequence = MMGenListItemAttr('sequence',int,typeconv=False) + sequence = MMGenListItemAttr('sequence',(int,long)[g.platform=='win'],typeconv=False) class MMGenTxOutput(MMGenListItem): for k in txio_attrs: locals()[k] = txio_attrs[k] @@ -632,7 +632,7 @@ class MMGenTX(MMGenObject): o = self.format_view(terse=terse).encode('utf8') if pager: do_pager(o) else: - Msg_r(o) + msg_r(o) from mmgen.term import get_char if pause: get_char('Press any key to continue: ') @@ -663,76 +663,65 @@ class MMGenTX(MMGenObject): 'TRANSACTION DATA\n\n[ID:{}] [{} {}] [{} UTC] [RBF:{}] [Signed:{}]\n', 'Transaction {} {} {} ({} UTC) RBF={} Signed={}\n' )[bool(terse)] + nonmm_str = '(non-{pnm} address)'.format(pnm=g.proj_name) + + def get_max_mmwid(io): + if io == self.inputs: + sel_f = lambda o: len(o.mmid) + 2 # len('()') + else: + sel_f = lambda o: len(o.mmid) + (2,8)[bool(o.is_chg)] # + len(' (chg)') + return max(max([sel_f(o) for o in io if o.mmid] or [0]),len(nonmm_str)) + + max_mmwid = max(get_max_mmwid(self.inputs),get_max_mmwid(self.outputs)) + + def format_io(io): + ip = io == self.inputs + io_out = '' + for n,e in enumerate(sorted(io,key=lambda o: o.mmid.sort_key if o.mmid else o.addr)): + if ip and blockcount: + confs = e.confs + blockcount - self.blockcount + days = int(confs * g.mins_per_block / (60*24)) + if e.mmid: + app=('',' (chg)')[bool(not ip and e.is_chg and terse)] + mmid_fmt = e.mmid.fmt(width=max_mmwid,encl='()',color=True,app=app,appcolor='green') + else: + mmid_fmt = MMGenID.fmtc(nonmm_str,width=max_mmwid) + if terse: + io_out += '{:3} {} {} {} {}\n'.format(n+1,e.addr.fmt(color=True),mmid_fmt,e.amt.hl(),g.coin) + else: + icommon = [ + ((n+1,'')[ip], 'address:', e.addr.fmt(color=True) + ' ' + mmid_fmt), + ('', 'comment:', e.label.hl() if e.label else ''), + ('', 'amount:', '{} {}'.format(e.amt.hl(),g.coin))] + items = [(n+1, 'tx,vout:', '%s,%s' % (e.txid, e.vout))] + icommon + [ + ('', 'confirmations:', '%s (around %s days)' % (confs,days) if blockcount else '') + ] if ip else icommon + [ + ('', 'change:', green('True') if e.is_chg else '')] + io_out += '\n'.join([('%3s %-8s %s' % d) for d in items if d[2]]) + '\n\n' + return io_out out = hdr_fs.format(self.txid.hl(),self.send_amt.hl(),g.coin,self.timestamp, self.is_rbf(color=True),self.marked_signed(color=True)) - + if self.chain in ('testnet','regtest'): + out += green('Chain: {}\n'.format(self.chain.upper())) + if self.btc_txid: + out += '{} TxID: {}\n'.format(g.coin,self.btc_txid.hl()) enl = ('\n','')[bool(terse)] - if self.chain in ('testnet','regtest'): out += green('Chain: {}\n'.format(self.chain.upper())) - if self.btc_txid: out += '{} TxID: {}\n'.format(g.coin,self.btc_txid.hl()) out += enl - if self.label: out += 'Comment: %s\n%s' % (self.label.hl(),enl) - out += 'Inputs:\n' + enl - - nonmm_str = '(non-{pnm} address)'.format(pnm=g.proj_name) - max_mmwid = max(max([len(i.mmid) for i in self.inputs if i.mmid] or [0])+len('()'),len(nonmm_str)) - for n,e in enumerate(sorted(self.inputs,key=lambda o: o.mmid.sort_key if o.mmid else o.addr)): - if blockcount: - confs = e.confs + blockcount - self.blockcount - days = int(confs * g.mins_per_block / (60*24)) - mmid_fmt = e.mmid.fmt(width=max_mmwid,encl='()',color=True) if e.mmid else MMGenID.hlc(nonmm_str) - if terse: - out += '{:3} {} {} {} {}'.format(n+1,e.addr.fmt(color=True),mmid_fmt,e.amt.hl(),g.coin) - else: - for d in ( - (n+1, 'tx,vout:', '%s,%s' % (e.txid, e.vout)), - ('', 'address:', e.addr.fmt(color=True) + ' ' + mmid_fmt), - ('', 'comment:', e.label.hl() if e.label else ''), - ('', 'amount:', '{} {}'.format(e.amt.hl(),g.coin)), - ('', 'confirmations:', '%s (around %s days)' % (confs,days) if blockcount else '') - ): - if d[2]: out += ('%3s %-8s %s\n' % d) - out += '\n' - - out += 'Outputs:\n' + enl - sel_f = lambda o: (len(o.mmid),len(o.mmid)+len(' (chg)'))[bool(o.is_chg)] - max_mmwid = max([sel_f(o) for o in self.outputs if o.mmid] or [0]) - max_mmwid = max(max_mmwid+len('()'),len(nonmm_str)) - for n,e in enumerate(sorted(self.outputs,key=lambda o: o.mmid.sort_key if o.mmid else o.addr)): - if e.mmid: - app=('',' (chg)')[bool(e.is_chg and terse)] - mmid_fmt = e.mmid.fmt(width=max_mmwid,encl='()',color=True, - app=app,appcolor='green') - else: - mmid_fmt = MMGenID.hlc(nonmm_str) - if terse: - out += '{:3} {} {} {} {}'.format(n+1,e.addr.fmt(color=True),mmid_fmt,e.amt.hl(),g.coin) - else: - for d in ( - (n+1, 'address:', e.addr.fmt(color=True) + ' ' + mmid_fmt), - ('', 'comment:', e.label.hl() if e.label else ''), - ('', 'amount:', '{} {}'.format(e.amt.hl(),g.coin)), - ('', 'change:', green('True') if e.is_chg else '') - ): - if d[2]: out += ('%3s %-8s %s\n' % d) - out += '\n' + out += 'Inputs:\n' + enl + format_io(self.inputs) + out += 'Outputs:\n' + enl + format_io(self.outputs) fs = ( 'Total input: {} {c}\nTotal output: {} {c}\nTX fee: {} {c} ({} satoshis per byte)\n', 'In {} {c} - Out {} {c} - Fee {} {c} ({} satoshis/byte)\n' )[bool(terse)] - total_in = self.sum_inputs() - total_out = self.sum_outputs() - out += fs.format( - total_in.hl(), - total_out.hl(), - (total_in-total_out).hl(), - pink(str(self.btc2spb(total_in-total_out))), - c=g.coin - ) + t_in,t_out = self.sum_inputs(),self.sum_outputs() + fee = t_in-t_out + out += fs.format(t_in.hl(),t_out.hl(),fee.hl(),pink(str(self.btc2spb(fee))),c=g.coin) + if opt.verbose: ts = len(self.hex)/2 if self.hex else 'unknown' out += 'Transaction size: Vsize={} Actual={}'.format(self.estimate_size(),ts) @@ -741,8 +730,7 @@ class MMGenTX(MMGenObject): out += ' Base={} Witness={}'.format(ts-ws,ws) out += '\n' - # TX label might contain non-ascii chars - return out + return out # TX label might contain non-ascii chars def parse_tx_file(self,infile): diff --git a/mmgen/txsign.py b/mmgen/txsign.py index 4e4caf4f..634bce34 100755 --- a/mmgen/txsign.py +++ b/mmgen/txsign.py @@ -141,7 +141,7 @@ def get_seed_files(opt,args): from mmgen.filename import find_file_in_dir,find_files_in_dir if g.bob or g.alice: import regtest as rt - wf = rt.mmwords[('alice','bob')[g.bob]] + wf = rt.mmwallet(('alice','bob')[g.bob]) else: wf = find_file_in_dir(Wallet,g.data_dir) # Make this the first encrypted ss in the list if wf: ret.append(wf) diff --git a/mmgen/util.py b/mmgen/util.py index 881b45dc..6c768f2b 100755 --- a/mmgen/util.py +++ b/mmgen/util.py @@ -470,7 +470,7 @@ def get_seed_file(cmd_args,nargs,invoked_as=None): from mmgen.seed import Wallet if g.bob or g.alice: import regtest as rt - wf = rt.mmwords[('alice','bob')[g.bob]] + wf = rt.mmwallet(('alice','bob')[g.bob]) else: wf = find_file_in_dir(Wallet,g.data_dir) @@ -610,7 +610,6 @@ def write_data_to_file( else: do_file(outfile,ask_write_prompt) - def get_words_from_user(prompt): # split() also strips words = my_raw_input(prompt, echo=opt.echo_passphrase).split() @@ -797,13 +796,8 @@ def get_bitcoind_cfg_options(cfg_keys): return cfg def get_bitcoind_auth_cookie(): - f = os.path.join(g.bitcoin_data_dir,('',g.testnet_name)[g.testnet],'.cookie') - - if file_is_readable(f): - return get_lines_from_file(f,'')[0] - else: - return '' + return get_lines_from_file(f,'')[0] if file_is_readable(f) else '' def rpc_connection(): @@ -840,6 +834,9 @@ def rpc_connection(): auth_cookie=get_bitcoind_auth_cookie()) if not g.bitcoind_version: # First call + if g.bob or g.alice: + import regtest as rt + rt.user(('alice','bob')[g.bob],quiet=True) g.bitcoind_version = int(c.getnetworkinfo()['version']) g.chain = c.getblockchaininfo()['chain'] if g.chain != 'regtest': diff --git a/scripts/test-release.sh b/scripts/test-release.sh new file mode 100755 index 00000000..d19f220f --- /dev/null +++ b/scripts/test-release.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# Tested on Linux, MinGW-64 + +set -e +GREEN="\e[32;1m" YELLOW="\e[33;1m" RESET="\e[0m" BRANCH=$1 +REFDIR=test/ref +if uname -a | grep -qi mingw; then SUDO='' MINGW=1; else SUDO='sudo' MINGW=''; fi + +function check { + [ "$BRANCH" ] || { echo 'No branch specified. Exiting'; exit; } + [ "$(git diff $BRANCH)" == "" ] || { + echo "Unmerged changes from branch '$BRANCH'. Exiting" + exit + } + git diff $BRANCH >/dev/null 2>&1 || exit +} + +function install { + set -x + eval "$SUDO rm -rf .test-release" + git clone --branch $BRANCH --single-branch . .test-release + cd .test-release + ./setup.py sdist + mkdir pydist && cd pydist + if [ "$MINGW" ]; then unzip ../dist/mmgen-*.zip; else tar zxvf ../dist/mmgen-*gz; fi + cd mmgen-* + scripts/deinstall.sh + + [ "$MINGW" ] && ./setup.py build --compiler=mingw32 + eval "$SUDO ./setup.py install" +} + +function do_test { + set +x + for i in "${CMDS[@]}"; do + echo -e "\n${GREEN}Running:$RESET $YELLOW$i$RESET" + eval "$i" + done +} + +check +(install) + +eval "cd .test-release/pydist/mmgen-*" + +CMDS=( + 'test/test.py -On' + 'test/test.py -On --segwit dfl_wallet main ref ref_other' + 'test/test.py -On --segwit-random dfl_wallet main' +) +do_test + +CMDS=('test/test.py -On regtest') +do_test + +# tooltest tests both segwit and non-segwit +CMDS=( + 'test/tooltest.py' + "test/gentest.py -q 2 $REFDIR/btcwallet.dump" + "test/gentest.py -q --testnet=1 2 $REFDIR/btcwallet-testnet.dump" + 'test/gentest.py -q 1:2 10' + 'test/gentest.py -q --segwit 1:2 10' +# "scripts/tx-old2new.py -S $REFDIR/tx_*raw >/dev/null 2>&1" + "scripts/compute-file-chksum.py $REFDIR/*testnet.rawtx >/dev/null 2>&1" +) +do_test + +echo -e "\n${GREEN}All OK$RESET" diff --git a/scripts/traceback.py b/scripts/traceback.py index b751eae5..8c845a4a 100755 --- a/scripts/traceback.py +++ b/scripts/traceback.py @@ -10,7 +10,8 @@ try: sys.argv.pop(0) execfile(sys.argv[0]) except SystemExit: - sys.exit(int(str(sys.exc_info()[1]))) + e = sys.exc_info() + sys.exit(int(str(e[1]))) except: l = traceback.format_exception(*sys.exc_info()) exc = l.pop() @@ -18,3 +19,4 @@ except: def yellow(s): return '{e}[33;1m{}{e}[0m'.format(s,e='\033') sys.stdout.write('{}{}'.format(yellow(''.join(l)),red(exc))) traceback.print_exc(file=f) + diff --git a/test/mmgen_pexpect.py b/test/mmgen_pexpect.py index 980a1450..85fd7f5b 100755 --- a/test/mmgen_pexpect.py +++ b/test/mmgen_pexpect.py @@ -35,6 +35,10 @@ else: send_delay = 0 os.environ['MMGEN_DISABLE_HOLD_PROTECT'] = '1' +stderr_save = sys.stderr +def errmsg(s): stderr_save.write(s+'\n') +def errmsg_r(s): stderr_save.write(s) + def my_send(p,t,delay=send_delay,s=False): if delay: time.sleep(delay) ret = p.send(t) # returns num bytes written @@ -45,11 +49,12 @@ def my_send(p,t,delay=send_delay,s=False): msg('%sSEND %s%s' % (ls,es,yellow("'%s'"%t.replace('\n',r'\n')))) return ret -def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False): +def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False,silent=False): quo = ('',"'")[type(s) == str] - if opt.verbose: msg_r('EXPECT %s' % yellow(quo+str(s)+quo)) - else: msg_r('+') + if not silent: + if opt.verbose: msg_r('EXPECT %s' % yellow(quo+str(s)+quo)) + elif not opt.exact_output: msg_r('+') try: if s == '': ret = 0 @@ -69,7 +74,7 @@ def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False): sys.exit(1) else: if t == '': - if not nonl: vmsg('') + if not nonl and not silent: vmsg('') else: my_send(p,t,delay,s) return ret @@ -233,14 +238,14 @@ class MMGenPexpect(object): debug_pexpect_msg(self.p) # end = self.readline().strip() # readline() of partial lines doesn't work with PopenSpawn, so do this instead: - self.expect(self.NL,nonl=True) + self.expect(self.NL,nonl=True,silent=True) debug_pexpect_msg(self.p) end = self.p.before vmsg(' ==> %s' % cyan(end)) return end def interactive(self): - return self.p.interact() + return self.p.interact() # interact() not available with popen_spawn def logfile(self,arg): self.p.logfile = arg diff --git a/test/ref/btcwallet-testnet.dump b/test/ref/btcwallet-testnet.dump new file mode 100644 index 00000000..f788b1d3 --- /dev/null +++ b/test/ref/btcwallet-testnet.dump @@ -0,0 +1,109 @@ +# Wallet dump created by Bitcoin v0.15.0 +# * Created on 2017-09-18T19:13:26Z +# * Best block at time of backup was 0 (000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943), +# mined on 2011-02-02T23:16:42Z + +# extended private masterkey: tprv8ZgxMBicQKsPdiu5xpPn3bx1GCYK7sMSgcF8WGUoZgFxkXvQiX1nowCK4FqcRqVGKNrPGqdGUvQaWGvhoBQGZTXARyNSVaa1ZN4hPizUCK8 + +cUEusQd9JM1yAs2PfZ6g5SMdjSxWnmr1MwGA2JhUxtiSTypkqH4Y 2017-09-18T19:12:26Z reserve=1 # addr=mfX7cEamwkYkRbUJrrXXvoatWbAoGZj199 hdkeypath=m/0'/1'/30' +cPRnb6khn1kgQjsQDqsqUUoqcsfMhYBRstXyAL1GbXv4mCJ6i7qn 2017-09-18T19:12:26Z reserve=1 # addr=mfXTxzK38HGtyFYXQfLkUxPCqHyJQvPGZL hdkeypath=m/0'/0'/845' +cTcfhngLaH21pbhBNGoBBAZ9VUMtnidg2soESoTRUtcs1gPRDCLZ 2017-09-18T19:12:26Z reserve=1 # addr=mfY2NMWSumDYrS9qUAHWd6yVpX58P7cYqy hdkeypath=m/0'/0'/725' +cQv25Qu3CdbMv8WBNwcNWAmzgeRHkyuvhkhxjVwoyYkL8wFDdK8K 2017-09-18T19:12:26Z reserve=1 # addr=mfYXm11FhF4BrxBMLzBXoviA4dmA6s4ao2 hdkeypath=m/0'/0'/195' +cRuFFcZ7Bh9RKJFjVYsRnFfPeoHmU1g9po2jiAFV4b99oSQawXo3 2017-09-18T19:12:26Z reserve=1 # addr=mfaNEGCWTUSTjV74csgU48M28XeHxuKVMZ hdkeypath=m/0'/1'/60' +cTDgAs627gcpYGmDqTFgdMCZFqHHgdx4uvGMBQvo4bLJdLGV7apk 2017-09-18T19:12:26Z reserve=1 # addr=mfafQVAcuDD7zrek7V2hXH9tpQVkRyWreG hdkeypath=m/0'/0'/460' +cVVuidrFg911sww3f8JaAqGacQQUyq3LcqTbpAo6rzR3hmKkmdZV 2017-09-18T19:12:26Z reserve=1 # addr=mfcY5a9q2TX2K8QgjS1uerraSp28JAJqDo hdkeypath=m/0'/1'/116' +cMoZ8voCBxkWTKSLJV5NoN1gcJ7SA9sh3RbMnLPmtMcUY4B5ZCaL 2017-09-18T19:12:26Z reserve=1 # addr=mfdJh6gnZin9iWA8wwZWcJhwPgdEoAEHdG hdkeypath=m/0'/0'/635' +cRwQpvfsgHL1YfP32QCLZp1rZiJCDg7tTwYy14xoPttNJ8W4mjJo 2017-09-18T19:12:26Z reserve=1 # addr=mfeCBSvj9oAmdGMG2phoXNfHSg4dVavk1h hdkeypath=m/0'/0'/325' +cNHFKMBXzbKp65ytTJBiF9E4cu4qpScDotNQL6r9yG4Uw6ipadim 2017-09-18T19:12:26Z reserve=1 # addr=mfftEQuszis2f7yKcCJuRC2JkF7jPQR4Wq hdkeypath=m/0'/0'/783' +cPVbgWezdXVijdzjAMayFtQWepzVrYTVX3Wk949gk7vZDaNpNMvj 2017-09-18T19:12:26Z reserve=1 # addr=mfgmonsaJzLFS1rPZRvAF1UNCEURsqGhut hdkeypath=m/0'/0'/870' +cVjHGeShf8qGH5yu1vMu357hCjz6ToHmgHUbdKkTTxLucZzW3s6Q 2017-09-18T19:12:26Z reserve=1 # addr=mfja4BQr7tBoJRhVFzFLTPEPkhwWuTk2Ma hdkeypath=m/0'/1'/5' +cPd4rtRPXBFPorMa395Jaz43kYkWdKBEL14qEgZnnKTqsd9uCGSK 2017-09-18T19:12:26Z reserve=1 # addr=mfmcBLvT4btK41jF4q78FhHqJuXVEPvCpB hdkeypath=m/0'/0'/20' +cUy7KrF3ngkHWcs3h5DPVRKJw74HzUG5H4mUHHDfp5NKqYftb9ob 2017-09-18T19:12:26Z reserve=1 # addr=mfo2braQsYCHiv9TSZDTMpRGo5jUNGV6tF hdkeypath=m/0'/1'/128' +cUDfnjK92pvR4GW5sALwkJr8Do9qJ3hPUWTtsLQrbZG4UGQF8Kzp 2017-09-18T19:12:26Z reserve=1 # addr=mfoWT5kXtHNo9NxKoCCjRJf2tfJ3iRju7s hdkeypath=m/0'/0'/788' +cVAcUB3FKDH8qRmu26S1Xn3dHPbVSWbE5u48QmQzNxYnkZBFgSv6 2017-09-18T19:12:26Z reserve=1 # addr=mfomDSHg7Dkvxr4DkELRFVd9jjGeLhBGFj hdkeypath=m/0'/0'/750' +cSMp98cCCdkpNF8Xvnqg4XCT77a1RhPLZZ6fSMMSLRMWkyFo4Mrf 2017-09-18T19:12:26Z reserve=1 # addr=mfp6J6m4H7XjKnP2ypqRYcmpR1zBSn4AZj hdkeypath=m/0'/0'/875' +cQ9oJ1zCFzAq1HrMMZJ8vAP9FDeQ5PhsUP6vHsJfPa4faxo8L7XC 2017-09-18T19:12:26Z reserve=1 # addr=mfqMqsiFJ6NerkhRJuGoxqJ6vTsrJytobc hdkeypath=m/0'/0'/521' +cMhZjftGBWaxRWuK6SeVb5u5xdX35YpcAh19zFKuBKuprjVAHCuw 2017-09-18T19:12:26Z reserve=1 # addr=mfsxPH6zuw32xmr5dhX3kzFcrqUayXrGoK hdkeypath=m/0'/0'/198' +cV3bwqAR8LdxgRaXBV4vAhHTMUHwpNLCBuuAn7dgyJBhEwpdAu88 2017-09-18T19:12:26Z reserve=1 # addr=mfvn5bzozCoSgz9Bz3AVd6AGCAMKos1wdE hdkeypath=m/0'/0'/166' +cUgZr68qTJQ8wNFVTCReMpfv28VHVMsKLCfTeocfNCMSXaHtGEkM 2017-09-18T19:12:26Z reserve=1 # addr=mfwe3oEA13AtNAFYTeNVeHfDBRe8Y7pfXk hdkeypath=m/0'/1'/189' +cNBaTKHUZJtXQgrBQFpVcVu1ftXnfXH8iEXTjPwiqMKNjcXUUb4o 2017-09-18T19:12:26Z reserve=1 # addr=mfyYF66eFMZZEW1YNU8ko3AEc1NxPDpwQa hdkeypath=m/0'/0'/100' +cMdKZvGmNygfKGR1qYSxaSLnjvdVxLpVwNEvLsXdAdx8GBTG4xy5 2017-09-18T19:12:26Z reserve=1 # addr=mfyc28cLaBNU5eagreMbhE7ZJBy331q7ud hdkeypath=m/0'/1'/103' +cQkQd9vxFGhY83NhiWcTvsT98VvJV332LN5k9rAJzfdqbWspXTcB 2017-09-18T19:12:26Z reserve=1 # addr=mfyhcaQVVdhtnkxk73VAdSKJbRDmD8zsvS hdkeypath=m/0'/1'/181' +cU3U3JXz3Nmr6yar9viqqSmMf81DQeaogbZN9LDwBaA7LK4CiJmY 2017-09-18T19:12:26Z reserve=1 # addr=mfymvVPDE34qmBo5CpbsHHkTM78WCVcdeS hdkeypath=m/0'/1'/198' +cQEF1CVs2KT3WTJ5Djk6ndQUazqhUphtHHsrrR2GyAyWwbf8TgfR 2017-09-18T19:12:26Z reserve=1 # addr=mfzML9isnEGuRZNxspkMN6PquGaKbUbApm hdkeypath=m/0'/1'/6' +cUe51W5TH3qyYwdwUb3fSn3qZJPfpUrUP5CRFQXx9bdcQCNeXtQi 2017-09-18T19:12:26Z reserve=1 # addr=mfzYpdTDEoP1ZDQFGFLzCH4dNXuP5496wg hdkeypath=m/0'/0'/524' +cUKeW7Lgog8EJnaVvCTHM2VJt9y4LScpoUhhjiXCkVjZrpja8Lxf 2017-09-18T19:12:26Z reserve=1 # addr=mfzqd1SazPjMmFEtgcpnDtwcNuoCNkS5Ns hdkeypath=m/0'/0'/963' +cVgy2ciTigtCsxSP8xWJww8e3i5HJnvvQs2AQR7pyrao6472jrw4 2017-09-18T19:12:26Z reserve=1 # addr=mfzy1bZ9KS5TVpYp6hhxU2KdXTn5NfqEGc hdkeypath=m/0'/0'/363' +cUGrwHz1hKn2RE9QPQePsnUDa8Hr1JzsNq6naA62NQ5tv6AMq9Ed 2017-09-18T19:12:26Z reserve=1 # addr=mg24nppTicboNBREawhno4h7oYrn5Ehzca hdkeypath=m/0'/1'/301' +cUVrcE74icmrtCUAuUNvnbWrthv4uptojywg82By8JyfGBnj5Jjk 2017-09-18T19:12:26Z reserve=1 # addr=mg5dgtgL48jcyvKaWKEoSzuiTYL3np3432 hdkeypath=m/0'/0'/435' +cS74qVN1ae87rFWs8zTaoSzoLEKoacCMHgBkohztkzmLfETHbRmf 2017-09-18T19:12:26Z reserve=1 # addr=mg66ivjMqTawMGErboBVk6YRpAoJ22FZmb hdkeypath=m/0'/0'/693' +cUMGyiiGH7QH9dYfo5bKhNAj9maMWScXd9uPKNrTwxAnnaE5ptK1 2017-09-18T19:12:26Z reserve=1 # addr=mg7vjMKssY9PLzATH1bmVg9GZYSozSNp9q hdkeypath=m/0'/0'/653' +cRVAyqcZJsk3Kmo59e3Dqsu3BMFC4roJA9zFyRtjXqnEd5gmuPE4 2017-09-18T19:12:26Z reserve=1 # addr=mg9owk3CG996DLLXekkFdMno8JjjiT7ZZ3 hdkeypath=m/0'/1'/144' +cMtiz9a9EethEytbyCCTiKabiDM2gPeiaxN6QTP3SUGKJ8ZcnodD 2017-09-18T19:12:26Z reserve=1 # addr=mgBJRBCeFRWZQfx8WCBBfXdbeDnZvNkLXH hdkeypath=m/0'/0'/22' +cPwtj9HiYkMRxWpRy7NxBoBtwLeoBZDwy42MoKDk9RSCs5vYAwSb 2017-09-18T19:12:26Z reserve=1 # addr=mgEJhby7hjZpdwwyEjaGx2XJnkDy3prVqT hdkeypath=m/0'/0'/247' +cRkUgMf21JGtsKdd8K1FYnnT39PZC1aAW3fob6okP9SxpSqaEHGQ 2017-09-18T19:12:26Z reserve=1 # addr=mgGp46ihVqEdmNsVntFfURqzkuTYCMLX6h hdkeypath=m/0'/0'/849' +cP86ro7xPC56vcDeiE8VfASCVfRAySSWXiBG2LQWFntGgBNM2XBD 2017-09-18T19:12:26Z reserve=1 # addr=mgHhjD5PFQZJNQcArwXsFZSgPoRA2q5Xgd hdkeypath=m/0'/0'/968' +cP5oSH7Vmryjx5f4ZawC8pDuwZf13ppZuQixQ9iyKk4UvVqxvNYo 2017-09-18T19:12:26Z reserve=1 # addr=mgJdTEGRJjgamgboWQQouxAkG68XMKNAth hdkeypath=m/0'/1'/156' +cP36EPnWCX17rDC6eEDKAvABU54NJRBiPaYfGdjLxSYBjJV16XYF 2017-09-18T19:12:26Z reserve=1 # addr=mgLYtXM2o362mqgnu1L98GUD4BKNJMGZwH hdkeypath=m/0'/0'/625' +cVhQcb83xJEjhUKsopmjSa7qGuLhWJEJUH8ohM4gwQg8x6WnxwMy 2017-09-18T19:12:26Z reserve=1 # addr=mgMST1dNEKbdpUL89JuJ7tucNLfbPDj4s6 hdkeypath=m/0'/0'/588' +cSn5pZaz6GEqDXeiXyWiQHDvEd8i3rroNyRAJqBrWfhpq7eCqK4i 2017-09-18T19:12:26Z reserve=1 # addr=mgMwxCPC6ihG5YSysEPD1ZSbppuyA96MWJ hdkeypath=m/0'/0'/662' +cRkjmnG3576D72kiyemsRD63zwVEiYQNCkorrGSUiE26ktXAanac 2017-09-18T19:12:26Z reserve=1 # addr=mgPRxzaNqXWBukmM5kd3hTia8Td1brng2o hdkeypath=m/0'/0'/380' +cPb8emkLsQFgZ65Znf8tQ7jEKo6EikKFPb3LskJXUBQWGRcZAHhJ 2017-09-18T19:12:26Z reserve=1 # addr=mgUY817xR7aWq1N38nvrkJCQ5NL9iKFTfR hdkeypath=m/0'/0'/41' +cMxBC4eGzBsdk7d2iMx2Vq4y4Nf5eLNsLbyh3DwG271TwikG6hhM 2017-09-18T19:12:26Z reserve=1 # addr=mgXMPYuhyuXYmyR42BYGca6XxwD1mGqv7p hdkeypath=m/0'/1'/153' +cNqCVFqcxW5uqDvQ1hVfxSoQxdEjW6tZD5FoBbP2wLyVs9W6G5vn 2017-09-18T19:12:26Z reserve=1 # addr=mgYHWWh7okm2JVevMjztTaNHn4Rfsuc6rq hdkeypath=m/0'/0'/478' +cUuAELbXdzPGuk5oxauQyZLoZvSTqVMbmhbJ8uHtPtExyze5ixzv 2017-09-18T19:12:26Z reserve=1 # addr=mgZnTfhTDE8ET6Gv837DMvv6mBPpTLZha6 hdkeypath=m/0'/0'/237' +cSkABPcFdcNE5kVoeFhRUQczt61HaQFU5Eo162BXraHLyK9jtuzL 2017-09-18T19:12:26Z reserve=1 # addr=mgcnM7S3WST5DJxYEwh53RAHpZnXoxZBLJ hdkeypath=m/0'/0'/497' +cQxRV2DziyuLoqy9TL3S7gyaafMyyfp21HTMrMkD7WsotKFtbHef 2017-09-18T19:12:26Z reserve=1 # addr=mgdcQj1CJX6Qi6F5C8Rec6D6FarM6y8M9a hdkeypath=m/0'/0'/261' +cNt3pNZSBKFzKukxqWx5J2WAYs1jmE2yasiww8n3ry7QQ5FFiVGg 2017-09-18T19:12:26Z reserve=1 # addr=mggjpuKGAqPndHvqUhXdrGP8R22CrfvAZV hdkeypath=m/0'/0'/357' +cN8iNvSqDgRgsZ6TCb3kJWiSdDq8WtM5Jj8zWS4seUehRsVtfg1f 2017-09-18T19:12:26Z reserve=1 # addr=mghQ9DYfth9wf1dyouwYdxP39zYMr9gp39 hdkeypath=m/0'/0'/611' +cUR11zG7QB3nUZ1LRfarivSxPz7q8g3pak2W887rifVeE54JJgdE 2017-09-18T19:12:26Z reserve=1 # addr=mghYouw6KQyndkr4p15EMC7qE8YjvgUzdC hdkeypath=m/0'/0'/95' +cPZZsqBsdn1cxMfr8a7bCqfChSP1SiWkK9MiC9Tgm9EMQBzMEaPV 2017-09-18T19:12:26Z reserve=1 # addr=mgiaATPDAjuuhiia1WgtefgKCcJk4MHhnw hdkeypath=m/0'/0'/359' +cTZw76RGDARXZKdvaaQ7a54fg8FS6PkF2qTwsi4qWnZLitsvC1rZ 2017-09-18T19:12:26Z reserve=1 # addr=mgjGN46xC1xn5XPxoSzu66goMUZHBHLRsD hdkeypath=m/0'/0'/712' +cVinRphzVCdV3PNX6zyecjj7DRTX6voUUaDUiqYmyTt9whhV53ZY 2017-09-18T19:12:26Z reserve=1 # addr=mgkakhnfWh6bXyJ8s6KHw4GEJqebASzE3g hdkeypath=m/0'/0'/150' +cUWq9LEUq8uQjZdDgwSTFNkvHdRGpSFWH2Arz8oZnSvzKMVDiRBG 2017-09-18T19:12:26Z reserve=1 # addr=mgmCjiVVqzhNjwJZ8uTHwmiJpD3KaJiMxY hdkeypath=m/0'/0'/931' +cRzPwRyxm7Lsdfb1tit6zAGMHPZxHD5pNgFn9VaHBisMgcx1kN79 2017-09-18T19:12:26Z reserve=1 # addr=mgmETogWwFfN3Q5MLxCnypt1HGDjNWzeK5 hdkeypath=m/0'/0'/418' +cTwtS31QNgvwLyW4GjzWNDnzXKUXXDJ7suUkLAokSG66kLgTA3qJ 2017-09-18T19:12:26Z reserve=1 # addr=mgmQZd8n6r8yfiuxvrHEQbPc5cu1VX8Rjk hdkeypath=m/0'/1'/248' +cSgbxaxtcvPP9KmY7hTRxtJC54nvVL22XQytTofdstTNCHB7odkF 2017-09-18T19:12:26Z reserve=1 # addr=mgojwBbnCmcy6h6aEUxkqQvq3LGNWw3QfE hdkeypath=m/0'/1'/240' +cPK4C5rXbBpjyzwZwg285URb3AwUeNUwG2LPMVaewdjpRAJBnLkE 2017-09-18T19:12:26Z reserve=1 # addr=mgqBL6VNo4JDdUiXpbSrbqeyMLgKh7eVAT hdkeypath=m/0'/0'/111' +cVzkdVL55VQS1ZtZheUG3BJHF5STtqjQG1wxogxYbXmSxKbZx1Mo 2017-09-18T19:12:26Z reserve=1 # addr=mgrFMXnHpZYFsrNnv5RFvzZUb3z6Xgs1Q7 hdkeypath=m/0'/0'/879' +cUtCRTwfNUwRtRZ4tb2MePoK1hW8mdbrYnmJAoa2Lu3NcR2NL99o 2017-09-18T19:12:26Z reserve=1 # addr=mgrxNJXe4kcrmfxXfvZT1ju2GNqJsWDP3P hdkeypath=m/0'/0'/165' +cTXju6oD74QJCAB8uDKhgB3WNUBXGuPvk3wXU9oT45tfiGp4rsfn 2017-09-18T19:12:26Z reserve=1 # addr=mgtRpaaDbYg1nFtLj1e7ArYbGkc2VH3mmw hdkeypath=m/0'/1'/124' +cS6fMWZCs4D7FJthikDr3kgN7zvjUSG6WZHsV7aMbXfd6isBjuT7 2017-09-18T19:12:26Z reserve=1 # addr=mguHHUWELMJWvvaudfdJYf3nuCWGCx2A5w hdkeypath=m/0'/0'/952' +cRsZUuoHMDVxFCoBqsJaVN4q1xjb9Qen7brkqHyRJgUqSw2hKueJ 2017-09-18T19:12:26Z reserve=1 # addr=mgun8z5o5KyFnPJKyVcENKU8iaFCBiDibt hdkeypath=m/0'/0'/83' +cRNVw8Lv9NfvbLbbmoqN7YjXW21jnqMgdJ5xfhi78zLYzfwGpwfz 2017-09-18T19:12:26Z reserve=1 # addr=mgvwYbA3QJAU4JMDui3yVdviLv98SiHUZB hdkeypath=m/0'/0'/139' +cPJ5CLyxkbeRLHCUUcA5AFCbo1R8W1kStU1p6H3NHVZwYEJR8CCP 2017-09-18T19:12:26Z reserve=1 # addr=mgvzrhhFuKmRNsrwVv8yPGVUFzJjDfeqvf hdkeypath=m/0'/0'/844' +cRhtQYF3zhzjSuRM1mhZFPLZgoNUHtDNren39WnVai32CsfhDLRS 2017-09-18T19:12:26Z reserve=1 # addr=mgy28x85PnY49QZoimF3HMLJBoLqmre9JB hdkeypath=m/0'/0'/577' +cTkUtTZBQTzBphoVkNBx1WgnJ8Z6LvfiJsmyATKDHw9Hv8j7guXi 2017-09-18T19:12:26Z reserve=1 # addr=mgygzo4CmednkXqruhcxG19yJqVbg3BXFz hdkeypath=m/0'/1'/54' +cUiEZUtqJ1n3ora9u3miFtjJH7KgVZxtPnSotPT88PUZVj538vJ4 2017-09-18T19:12:26Z reserve=1 # addr=mgz4mgyfX4TUVBeYGqLLNAsSkFVur1qaL1 hdkeypath=m/0'/0'/991' +cPMUx7whzrCAaKmDcUm3Uw87XxGMmSujrFgjPm1ShUjdz1G41Ssp 2017-09-18T19:12:26Z reserve=1 # addr=mgzhexcGPnxu7kdcxVpaqzYPVNZnrWPEVE hdkeypath=m/0'/0'/432' +cPtkoZmZTqRKPE5a7w7xFHmXkXsF4ZReytLA45ss6hZJDJsiJyF1 2017-09-18T19:12:26Z reserve=1 # addr=mh2TyYXZMosidMHj3UCKJbynkVLA9k88hZ hdkeypath=m/0'/0'/702' +cNDeMQXduT1773V7tANE65kW8hTHdaqXLPxfZQv8VQzUD1jRHhmq 2017-09-18T19:12:26Z reserve=1 # addr=mh4VoC7FxTPyzLLE2hCMB9qjnYjUccAtjL hdkeypath=m/0'/1'/97' +cTAkLCTj8d1ZKG4k2c222SGKmDu6MxuCzZcEuUBvJ1EvgB3AeSuY 2017-09-18T19:12:26Z reserve=1 # addr=mh5Fs7qQ5hVVHBV95CTd7TiL6R6xKDCtmZ hdkeypath=m/0'/1'/7' +cSCR2oEupHhrBj7wxYp6rt5vho9KZrW4TFokj3Ta9AyZJ4xPfEVj 2017-09-18T19:12:26Z reserve=1 # addr=mh6W5iiDmApTbzoWWbX5oz74sqAKS8mboS hdkeypath=m/0'/0'/956' +cUFfbDFCetV6dyenFxMamsD69YFSxAMfjRMns55frjw1j4zNVSAB 2017-09-18T19:12:26Z reserve=1 # addr=mh7Qbvv13b7Ej9Qk3yhbV6SCmXdL6QGs8Z hdkeypath=m/0'/0'/542' +cQHJAxkPzshvHEJr6DDpZTpQtpsgdxAXS6Sq5Wm6Z151Trt4jeeW 2017-09-18T19:12:26Z reserve=1 # addr=mh8LuZEZkmjDiT54mhkAQZZdNMoWGoQQ6n hdkeypath=m/0'/0'/458' +cTWm6AYc5a6txkkyinv3LzDbXUgwwpXbc7KctH1grQ8ehYPR1Kzh 2017-09-18T19:12:26Z reserve=1 # addr=mh8XtNtizKKTbJm8M53vcMnGccchkW1xqT hdkeypath=m/0'/0'/690' +cV4GF3MrngdszfuMYcPeXvEA2MD8eJ6tJ859VX6UPct7PSwfBkZq 2017-09-18T19:12:26Z reserve=1 # addr=mh9bHKZaUwvpZA91gCZCyqMsWz4GSj9gCG hdkeypath=m/0'/0'/379' +cVT46Quvai57PtVThyWGsYuDKdpP6meEdVUdEqkJYjp2RNrwWmxG 2017-09-18T19:12:26Z reserve=1 # addr=mh9t7dKSRLxRWbihfssoT1XGFJCDs5FsrR hdkeypath=m/0'/1'/221' +cQcfMPiaZAvxuTCoxRWFvqDNQqNcUYhfu3kNbAd13bXpx3KnAZvt 2017-09-18T19:12:26Z reserve=1 # addr=mhAsFXqHTqZCHCz984ezCzTZ1ouSa85iCW hdkeypath=m/0'/0'/957' +cSV9iw52bDtnKauFT99tPokaFsATJH6wTmA7y5wU7L1W1HbYjPfq 2017-09-18T19:12:26Z reserve=1 # addr=mhD5aMUvvBidi51aPtGX5qut6vrJNewMee hdkeypath=m/0'/0'/876' +cPpTAoez3UFBs7Ss87XwLpATK7YfUVKjJF85VHpkWBnvTKWG1xvR 2017-09-18T19:12:26Z reserve=1 # addr=mhD7kSbqambret4VykN31hUkgCqvKw7D3H hdkeypath=m/0'/1'/257' +cRiGkRMKjzEP2LMT15z4BunT5X8ByrZUZgaEpXbRNAwESkDDQVay 2017-09-18T19:12:26Z reserve=1 # addr=mhDBJfHZ4zeA1w2AxsChfW45so6v2DJzAq hdkeypath=m/0'/0'/107' +cPQDVwnnEQWcd9FDbbdMi6iZBg46BcEKJVZzYxeui4bbnBHbffrt 2017-09-18T19:12:26Z reserve=1 # addr=mhDTTNW8Cjuqamw69MhaVnpmqh98sVThZU hdkeypath=m/0'/0'/973' +cTPzU3FsrwYhtDmwceNjmGgrGFq8zpaMwrQAz85iHw3PYAaHkG8D 2017-09-18T19:12:26Z reserve=1 # addr=mhDcJUuV1ZxYbV5xWjYP7zz99TXJYwEeTX hdkeypath=m/0'/0'/246' +cPYTA7xxPEkGV4NL8gFmSCe6R4eu69SLCLDmQM816JuiJnUjp5ao 2017-09-18T19:12:26Z reserve=1 # addr=mhEpZkVypE67XGxM8Aemh1x1ZDKzew5U2q hdkeypath=m/0'/0'/490' +cS95FLFX9vCK9joVhZEArmN7gtHAHDRNLvxj5f5rtWER4hPBu4Zw 2017-09-18T19:12:26Z reserve=1 # addr=mhFM3JHBJFx9scEU6ruErv8puj6cJfyC3y hdkeypath=m/0'/0'/556' +cTVTztRBrW3LqwtxfnKg1zou4Y194h2HcQdzSeNiAmUHDw1cX5mS 2017-09-18T19:12:26Z reserve=1 # addr=mhHCVRyyNiwTzTNLzVBXrbJMzoZ57uGX8M hdkeypath=m/0'/0'/60' +cRUrrM8eDyAmA4dmhc6rRyk1nwAA1BHmKkLa9N5P7qP68hUK96PY 2017-09-18T19:12:26Z reserve=1 # addr=mhHEFFqRY2yinZgvrzj1QVnGTEgZRreKY4 hdkeypath=m/0'/1'/53' +cSrqGuJeguaiSMcXsJh3ucGffDGsawATM1boex8CcMJRRFHjW15G 2017-09-18T19:12:26Z reserve=1 # addr=mhHu5fHf4GUof9s2TF9dkM5H23A9kE8qYa hdkeypath=m/0'/0'/574' +cRtRWMDFSK2ptwjdWSZhYppWn8i85UJMgSZkkoTsVoyc5bhLksYA 2017-09-18T19:12:26Z reserve=1 # addr=mhJm8kuu8tLUz4gZJiRKceWY9rsxx6XDwC hdkeypath=m/0'/0'/26' +cUqoD1fKbbmiynJn1CE4Mudua9aXCBobojRVvQFYUJbiXke4F2pF 2017-09-18T19:12:26Z reserve=1 # addr=mhL7NSncF4nx8zvyqptWrp6nGVKyaSrNJ6 hdkeypath=m/0'/0'/865' +cPUboeZpUxcDgQZq9E5Cgf4P5sXvKh7PbKQn6tDQKUjo8dnW2hja 2017-09-18T19:12:26Z reserve=1 # addr=mhLRN4micxcLs8BcLNxfNauakVZHGFytSd hdkeypath=m/0'/0'/446' +cRYzbeAzJej1hVjQt4GkAyzxhVrfExty8ozTfRNyKVQPpD99FCAA 2017-09-18T19:12:26Z reserve=1 # addr=mhMRk21dfTQbAyE7azEzkWH27qoLrMysEN hdkeypath=m/0'/0'/121' +cPvc5bBm14Y3CXNqXwdvjaQEMrVVz7wvpZ3gs1ShwzU2oJPsZeXn 2017-09-18T19:12:26Z reserve=1 # addr=mhMw17TSYgE4jzoJHiayhqn8Sc9ViMYzyT hdkeypath=m/0'/0'/241' +cVF6hweqSccJn7Vfoi5dx3dJnq3nNawQAuNedPLJvJWnghwJGh7k 2017-09-18T19:12:26Z reserve=1 # addr=mhNq4Xi1vWuT7CHME9XU8QBpA23TjuTS8j hdkeypath=m/0'/0'/216' +cU9p4ZV2JUjGoSh6KoXEQGuNASy4JtP8MD2ntV2mLSauZG3W6e2W 2017-09-18T19:12:26Z reserve=1 # addr=mhPsQVgPqoaw6bZ32jMckskYotgun7SLgD hdkeypath=m/0'/1'/159' +cW9Q5J49iCqXUwv22wc4ss3NxxdqVopCUDvdeD2V2TZhTv2UjoCd 2017-09-18T19:12:26Z reserve=1 # addr=mhQvmLiUUMrxi3j9ci2RmXvCtNiCvdztdY hdkeypath=m/0'/1'/170' +cNcbni84FPTzqv7sDHXtGiXpWZLdXTB36Z2JFFFYVz3UGM9Ygobh 2017-09-18T19:12:26Z reserve=1 # addr=mhSSb6xfyEF4MobdGzurSkcYH5zduniwWf hdkeypath=m/0'/1'/280' + +# End of dump diff --git a/test/ref/btcwallet.dump b/test/ref/btcwallet.dump new file mode 100644 index 00000000..f6fac4ec --- /dev/null +++ b/test/ref/btcwallet.dump @@ -0,0 +1,109 @@ +# Wallet dump created by Bitcoin v0.15.0 +# * Created on 2017-09-18T19:09:18Z +# * Best block at time of backup was 0 (000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f), +# mined on 2009-01-03T18:15:05Z + +# extended private masterkey: xprv9s21ZrQH143K354NmfyK5jphFPnQrgpbN7q8gB9ybaFhvJB7KXbDsRywFp9pxZAK94DW7mFJ86F2qD6oYYLTwuNJ6DSbzRKaf9NM9gjKTo1 + +L5LUujY27o8vP719sKccwRr3XmdC1adSfAf6xhZFa8Gv6dmgY6BG 2017-09-18T19:07:26Z hdmaster=1 # addr=16DKtHYwdUQ4bvTfVk4ztsGaee55c4q92u hdkeypath=m +L1x2Fesucugt9HVTVdkUjanj36ecsx26Ab8fhkQuuK41tY6TgnHe 2017-09-18T19:07:27Z reserve=1 # addr=113dkRcsZF8oubiFvt9hy9D22zgk3pjmVT hdkeypath=m/0'/0'/336' +L4yrXL47zC9kpm7ziShPNMAAtjMZnHZMNBWaBwa7SgKqgTsBH6W2 2017-09-18T19:07:27Z reserve=1 # addr=113pS8xCuWnhUKRBw22LFEnBxTXnK6poDb hdkeypath=m/0'/0'/679' +L1yU69qpjdV51R4381J25QYus1kJx9ruxwqAEgVHRBT7a35bZ6g7 2017-09-18T19:07:27Z reserve=1 # addr=114Lpo71r2iHoPuths1oQkh8kFSxu6BCer hdkeypath=m/0'/0'/287' +L27BH682oja5y3RmNf2TtoJwAZ3kEQCiL3YLsZGFdWNVUXwjK9Dq 2017-09-18T19:07:27Z reserve=1 # addr=18aiMArDWheSKw3CZ9sNo5YaXyUwEimTZ hdkeypath=m/0'/0'/381' +KwFqLv7eAY8juMYrNXS8Pq4wxq343uksWk6JP2w26UbTpddZ8odp 2017-09-18T19:07:27Z reserve=1 # addr=1APUKkXm2c7a8cxGvQqXNu1Xpm8gTXXsD hdkeypath=m/0'/1'/384' +L4FpgfDg3Woo9fN3ZcfX5LY6VFQYrzBgFYWAAFnYcgkRRVCnNe3T 2017-09-18T19:07:27Z reserve=1 # addr=1BpQS3NHZbRhgW3cDmJZUSm6THmHKTe5e hdkeypath=m/0'/0'/184' +L5iYZMCdEUXruDsxLmFfhbCLUZJxLquJf1STVNq9XWGydQTSV9or 2017-09-18T19:07:27Z reserve=1 # addr=1C5bSNmBHhPykTMQ6uvKnpmkgyURkj6iF hdkeypath=m/0'/0'/668' +L5U4tDLoVZf8bxRG7DdYp6QRcPD9FqNqX4zNhnW2wKK1MXLTXwtT 2017-09-18T19:07:27Z reserve=1 # addr=1CbV3RYCf8esKdvNpDDahyYVLvG3etjt5 hdkeypath=m/0'/1'/135' +KzXLu5rU4mZLwxF9qqdSmjF1ZBV1tQter5R9nXBAtrWZymkyfztc 2017-09-18T19:07:27Z reserve=1 # addr=1CtKBXTHhF4cUUdEMCdJVFs9jwn9cDRJx hdkeypath=m/0'/0'/460' +L3yRscb2sCE6jTgCiVWLByPLUxvUHbN2SUUjH3RxP6GEgQaxtajt 2017-09-18T19:07:27Z reserve=1 # addr=1E5icionAv42fy8CKfwW5RckZZytsznua hdkeypath=m/0'/0'/278' +Kx8Jhn21p8gPqmLZjWwSPSPei4wDATADAsXQEm4Nogqy8W6SvzBs 2017-09-18T19:07:27Z reserve=1 # addr=1FfTDTzp3AJiWytPLk9PdXRNE3sfVghPN hdkeypath=m/0'/0'/681' +L4dxASzxJSk7jcjW6qpwFXpmdBqQudbcA8xjo7q1qd9E1DADVakn 2017-09-18T19:07:27Z label= # addr=1FmABfe81aZ2aikRaxSyFFAT9y6bHb627 hdkeypath=m/0'/0'/0' +L3Twqq7LmXhf5boqxxrguJPt9exvAqVV7KjdRVGpGhkJ3R25jrbb 2017-09-18T19:07:27Z reserve=1 # addr=1FqESrZPXGNRda2CTVt2AocNJ1QbVQgh7 hdkeypath=m/0'/0'/546' +KyGs5ZaXzpfJbkx46UDehGjEjHSNHSSKWMXwkgDW2cgNXERkMGU3 2017-09-18T19:07:27Z reserve=1 # addr=1GiJttRW18rVVGrT5y6R38Hyhfw8tnurt hdkeypath=m/0'/0'/417' +KxJ3agJDYe2qnd9ZNSenxjAhzFnoC776ptJdWC1cRC6sxf1MfD68 2017-09-18T19:07:27Z reserve=1 # addr=1GrUMXM5yEcXLWgegqqnPAHTJJ2NHbgms hdkeypath=m/0'/0'/8' +L3aZ2jfMJ9YBWSfG5LQ7owZgnLJkDuBanuB7dpn5b7TCoqHpbnZe 2017-09-18T19:07:27Z reserve=1 # addr=1K5eBDNPXNLH8FJKNtWm11B86LgusXMBH hdkeypath=m/0'/0'/449' +L5WwGbDYfBGsdP1ptTbhRUb4vxNzbJ6j5SA1py33doAcG3zqgmpN 2017-09-18T19:07:27Z reserve=1 # addr=1KuuABVjF3YeBssdagXP9nGATaGg571D5 hdkeypath=m/0'/1'/228' +L5J4jJjdDv8uQ2LMxr19HHXixyDMps8B4fWdJ99v3MyadgY2ekia 2017-09-18T19:07:27Z reserve=1 # addr=1LmvAqEE215Vy4zi7Qywcjagp893JrvYU hdkeypath=m/0'/1'/481' +L4fw5jvacrg1ZgULLabaDN6RPoHkv8V46QTahms7T2mC7rttjk2t 2017-09-18T19:07:27Z reserve=1 # addr=1MSx2SQZVfgo5bt3kD2nMhjuvXgMjZgno hdkeypath=m/0'/0'/784' +KyAxJbSbHnNLQr11e91J4SNPfynS3tAkMeh888FMAJZhyseEwa9b 2017-09-18T19:07:27Z reserve=1 # addr=1PnJpTMpyMhg2Hd88vm9JemJ6AmzPHUNx hdkeypath=m/0'/0'/740' +L1YWjG83Pbegm8fNKEu3g2JM6jQuYcfvAFFhFo21yVGJksW3kDw3 2017-09-18T19:07:27Z reserve=1 # addr=1QMKxPV1xmqsLvpjLGYdRVhsk1r2WwMuo hdkeypath=m/0'/1'/256' +L4zp65kGkCbWaHWbFu1LqGjs7kYgYeKWapKxQtuc1BAmGS2qwKrX 2017-09-18T19:07:27Z reserve=1 # addr=1QnZD4EQVCv7NUQdwCNstw5CAQ5aFa3UF hdkeypath=m/0'/1'/425' +L2SzJD8DqasrVpLvZhzm11pJ1UYhDDBKFNoCwpWNTZUuJSjxoY3n 2017-09-18T19:07:27Z reserve=1 # addr=1RAZnDTjUntih19Cv67YHCpxJXoMtQWQK hdkeypath=m/0'/0'/137' +KxoyRUoDQoqcqpHSKwY9JpNaM7hSvkBn8WwwCvNQA79gH6jYynAT 2017-09-18T19:07:27Z reserve=1 # addr=1RyxjcAbMxDApAWhLGiw2E6K27mW6PTgm hdkeypath=m/0'/1'/213' +L411UbAd5dHVVHEkS7BtLXSQvRhB69aL2H57bzzAAEn6dP413Xhu 2017-09-18T19:07:27Z reserve=1 # addr=1S8fDdBWnu8xMw3fPDqMGBfvzGFcPTGXs hdkeypath=m/0'/1'/433' +L3VsCkFJavPZuGB7uLDSYDDbHJh3f5x68xb37zZt35oQTrAadtNe 2017-09-18T19:07:27Z reserve=1 # addr=1ScMi71DJ5KqtyZLkHLkNqMKB915tJf67 hdkeypath=m/0'/1'/448' +L3AVSiPVrewmkV1TKnpLWAgTxDb9VQp2gxGxP7K2AJXANfqqPGW4 2017-09-18T19:07:27Z reserve=1 # addr=1SizkyFfRsTP4jNWpZBff2Z9HzfeuBxta hdkeypath=m/0'/1'/294' +KxA9ZwF4gYdqTDrR5YBAJo9SwqWnyTn9VpbLFNenQ11nfUrq82Tk 2017-09-18T19:07:27Z reserve=1 # addr=1TuVu4VC6KRiay6Z5hapW9qXXYj5TTWCT hdkeypath=m/0'/0'/52' +L42jH2MdBvPxUwTcnokrvKHFnygwkee47pJ6ESQEAF24KLsYQYJy 2017-09-18T19:07:27Z reserve=1 # addr=1V73irXxmr8LyK2s4w1vPfBPSeq85md5M hdkeypath=m/0'/1'/194' +L1vAFgS3X6zYTkGNq4EybZRxvnkq4vu9NLLFqm3QznEVu6XuDQEC 2017-09-18T19:07:27Z reserve=1 # addr=1VVAzE5m1rwBUyaWbpbwHEM13SptJDGkm hdkeypath=m/0'/0'/202' +L4pUrVxupTRQeU2SzM8sGJ1ZvUkaJT7oKFtS3Wkot2yo1CcYeeKG 2017-09-18T19:07:27Z reserve=1 # addr=1WNJAZboJJJ9mQ4bw6bo9VaiqRnWfdNEV hdkeypath=m/0'/0'/803' +L2WVZ5PoTmpDaGfSyHykJ1DxKa3GyNqX9Lhf3ZEw1zKHEMFZHRwU 2017-09-18T19:07:27Z reserve=1 # addr=1WcgqbW92nsvbrxkJ6ZnKphTNwzbz7NW2 hdkeypath=m/0'/1'/159' +Kyk9Kik13wFdMJWbbFqWHVxEJeWVjqXERWECx3vH9yAS1LzNcbBy 2017-09-18T19:07:27Z reserve=1 # addr=1WrsK2Wbt7JLC76xvRKcDsbjt81Z8ytNW hdkeypath=m/0'/0'/228' +L3S7bt5qqSkW72yjc75wU8LChNdRD9amZgZegrc5UCRrKe1apugG 2017-09-18T19:07:27Z reserve=1 # addr=1WwzHnRGAUqpaw6PCQcXV761uchpArajZ hdkeypath=m/0'/0'/430' +KwNQqjWrbDpsQGJQsWcgk56Kc2kbryF6289YcW2Fe83VdwCiJHcB 2017-09-18T19:07:27Z reserve=1 # addr=1XNwBbZLbau3a9a3aDF3A8SQrX6bgpFMB hdkeypath=m/0'/0'/126' +L1t9fwEWmnL6WJbNaP8kMbHVMhwSwBvn5WipH1kexb5zMUru9ydL 2017-09-18T19:07:27Z reserve=1 # addr=1XPBFJypcpFdxGYybE1rrvqNC27XtfKQB hdkeypath=m/0'/0'/132' +L3AtB99RYL9gnp85Yf6PXmL5D19SefFHqn4WUxfDy4ZEAn7u6ASR 2017-09-18T19:07:27Z reserve=1 # addr=1YAVDkpVPNeyoG11jRDp6tB2GQgAoZuWb hdkeypath=m/0'/0'/869' +KyNMmHu2sqPYo2LTXRS2FNiJ2mJGpXSLp3XFuEZNuKKJ2hcukAdB 2017-09-18T19:07:27Z reserve=1 # addr=1YHqhhg32w2BYc3oHUVkbWLiHdiiKPU8K hdkeypath=m/0'/0'/484' +KyCf7Reuf4QgLXjAqaVzjorSsyfmNLmFYuU2RhuQy1kpTzb1raRZ 2017-09-18T19:07:27Z reserve=1 # addr=1YMCcHgEJvTBhDhCUHTzvGVvPM949gvjd hdkeypath=m/0'/1'/83' +L47bETaCU1aTwqcpHovqcyGABNLGFTK2FctcWP5p2wMLa4cMtYs5 2017-09-18T19:07:27Z reserve=1 # addr=1a2u23iCFefbSszBfme4gv9fBHJ776xaw hdkeypath=m/0'/1'/148' +L2zjRo6EUeyzgw9nH3cCTB2zKH5rQy6xV51gZTowJWGbkrWBQt2L 2017-09-18T19:07:27Z reserve=1 # addr=1aJiMdsDbsaL9cEsXnRFsnvLevFj72NZs hdkeypath=m/0'/1'/466' +L2VnhKdSrU43zbxdFbgBf4qVhCabjA84MtVazF5GE5QXMgBeHk6D 2017-09-18T19:07:27Z reserve=1 # addr=1aN8Uj5jbJ7iFpYXNDoW4kiWCmSmKB3wU hdkeypath=m/0'/0'/520' +L5ic4PBs8sExopkP6KUcRJNpxSzjdsX1Zzrd7c97WhqZkaKpd2qE 2017-09-18T19:07:27Z reserve=1 # addr=1ateLA5VY2PcnUeGNAdbiN3UrF1iUUmMo hdkeypath=m/0'/0'/671' +KwL84Ni5ErcS4FwFVNCR84JPonMZ68TsAi1n7HhYv5Zvei87UDHH 2017-09-18T19:07:27Z reserve=1 # addr=1bYvPtsEyNQPQ3j4fdiRzSGg7682sMGeU hdkeypath=m/0'/0'/149' +KyEfXPW34fjrMND4xrDxBDNArXwZf7vi94zzoXjdX2jwwC3ArtR5 2017-09-18T19:07:27Z reserve=1 # addr=1eztp2sRfJ8xmpFGAEfT5y5JNqtuDTyzY hdkeypath=m/0'/1'/74' +KxJCF2wz7H6y6M5nUbRVg5LHDPq3UUZPEp5nYDaPFtK8rrPyUxwa 2017-09-18T19:07:27Z reserve=1 # addr=1fS8XPt2Rq2vqtgr7Ag5rPiXFxR4Y7Avv hdkeypath=m/0'/0'/486' +Ky2qZAt5bNMj29Sc8xTL5iXw3CJTHPavvJv6r1oBHDiAJ94hx76V 2017-09-18T19:07:27Z reserve=1 # addr=1hdoi7LTQPEKVnX9UAvDJJa5X3nhZaReq hdkeypath=m/0'/0'/161' +L3UdsWgTqP5ptzzepwr8rB7dWiJdsfqQYhpHioNgu7bKSXat74UF 2017-09-18T19:07:27Z reserve=1 # addr=1huWRtuss4wFiU4jsMhwPS4mMZDEhhkEv hdkeypath=m/0'/1'/55' +L12Hj3c8Jf9m4k4uhGJ4na2yJkwr5Nz951jHCcYbQqVKYFp2VuwH 2017-09-18T19:07:27Z reserve=1 # addr=1kVs2qc7qbVHDWydM8zDD6SZbX3geCmZn hdkeypath=m/0'/0'/243' +KxGFokkLAR3ChbHYF7A1dhgqm2zg2AtEF7rqKeA8eUCAKFEU9qfy 2017-09-18T19:07:27Z reserve=1 # addr=1mAPwUHuHFC55m99vjW8HGjBDcXHpFoRG hdkeypath=m/0'/1'/338' +L1sD7D5FgQfWXHucPYmSfoVysVkF9y5n9Ra3R3Xk2grEDDCFqUf4 2017-09-18T19:07:27Z reserve=1 # addr=1mSKeNhNryewnjEFRfXYAosY9N4JMRKYi hdkeypath=m/0'/0'/394' +L4iNbbeUUZMqkteAcgv4Mt5nTtnwnCKZxARvbkeamgrYut7DCFvZ 2017-09-18T19:07:27Z reserve=1 # addr=1na9m5Lf7PXLw147SGbmM5S9CqzvvmCdv hdkeypath=m/0'/0'/840' +L5TNqp59BKW3kiMdNEQy6Yy4uRxzy9vYgJ8DMYBPv2Hf3q5eQ134 2017-09-18T19:07:27Z reserve=1 # addr=1njSR5CtSZAjzYWsQofmU2DvwpcCGKBA2 hdkeypath=m/0'/1'/151' +L3K1PXVicWZu2M1WjojZ5LRFNJzGZt9YH8b8RsfeKH91VBSCtUvu 2017-09-18T19:07:27Z reserve=1 # addr=1oyce6ctVtzu7mHSieMR1boyupeEbxCYY hdkeypath=m/0'/1'/38' +L2MMwuFDfqLsUQBBJwYPX8RBN1u3XozzVLzTAuuVPJz9PBsdEkDp 2017-09-18T19:07:27Z reserve=1 # addr=1qFybRffWdNrRKA5t5HykBzGfB3yDoqd6 hdkeypath=m/0'/0'/985' +L3ZtdKSjKBsTn81nyUBay7mVYQ3wHmqdz4GKpX4oeytQGAKDPDQS 2017-09-18T19:07:27Z reserve=1 # addr=1s8K5CVkGNqLV14QvRPqYEhJVDsGwjtoe hdkeypath=m/0'/0'/518' +KzzDhtHdDU2ZnHW6ZNYLjoZC1Y5Yc65EoHK2deWWiygWdd7PABtG 2017-09-18T19:07:27Z reserve=1 # addr=1sJeE5EM4rKZm9eocsFV99K2wWxCGFuAW hdkeypath=m/0'/0'/167' +L3cWnxWhBNX1SPexR6qDU3Zhxo63eYsUWMrLXNHA7j3KD4MUfQAF 2017-09-18T19:07:27Z reserve=1 # addr=1smSBaXcZZ2W6iaNXTT7CdxwnqZrQmPjq hdkeypath=m/0'/1'/121' +KwS6fT5VB2KQv2txK2dvGMBpZVADg3uYKYABzCisgSAFoHsavezu 2017-09-18T19:07:27Z reserve=1 # addr=1ttvzcWJuS7bWMVEX9tLXhcNTAwhsxYfg hdkeypath=m/0'/1'/200' +KzKPeGCmFb4DLnZQFvGqLs1zCRq8NnCDkdpfn86nJyPBnuQMtvqP 2017-09-18T19:07:27Z reserve=1 # addr=1w98cTmKX6SfhYybTGniCtEb6c5JMxwZU hdkeypath=m/0'/1'/365' +L3XWYmoZnK7pJcDYAFi9K8rSRLPPuj3puqsxRBkWh5dDvodTL55U 2017-09-18T19:07:27Z reserve=1 # addr=1wadqSYW14di7zmdxad8buiuy69WCQpr8 hdkeypath=m/0'/0'/941' +L2eTpDCZSTGAtQh5vSMvfrETSUQY5tXhvjkXPUDFX4CAH25cii28 2017-09-18T19:07:27Z reserve=1 # addr=1y5ZbqPBomrpMvinhCQhUj1vu5FZUP3C8 hdkeypath=m/0'/1'/93' +L3HXmcTnhqxprC86dahcxQN5aZT825jp7831NKbyNvDqzekciuad 2017-09-18T19:07:27Z reserve=1 # addr=1yMhG2ac9cKpave8198HnVB52bT76oMCV hdkeypath=m/0'/0'/198' +L3ATcSGuZotRwcs1AyyEgyCk8f1GAPof2dtLWF1myb1Ag5RSMTwf 2017-09-18T19:07:27Z reserve=1 # addr=1yghmi4bY8MictksXCrYC4fBuZeKfGYPo hdkeypath=m/0'/0'/223' +L1jDMrcjep9PyivZFqnDWbZ1w2dU7Un3UJyLdjqUsofsMGmaw9Pk 2017-09-18T19:07:27Z reserve=1 # addr=1222f2BYuV2i24qAC7pnzesvWZvr9yfJ61 hdkeypath=m/0'/1'/142' +L2BcBHkpgauyEJVtGB3VrK9FthdHSv85xyoS6j6CBvCa9wNLjYgU 2017-09-18T19:07:27Z reserve=1 # addr=123q3BXwTR84fKceHEgypj9nLNY6r6URQL hdkeypath=m/0'/0'/276' +KzyiQE6hysH1FgtXVs9xBUPNipEoAoJ5ouZAfsbGZ17CDS6x587u 2017-09-18T19:07:27Z reserve=1 # addr=124EWXxBgVFiLAZihD4fwWBADn9Hn7srPk hdkeypath=m/0'/0'/217' +L1xM4m7nLXZaqfRmyWWiWLcKkCXcqKbXz6t4S8DVd37fTvCxCmA7 2017-09-18T19:07:27Z reserve=1 # addr=126HaZCXCBjdxb6mEEZz5q6SCeHjdspGoW hdkeypath=m/0'/1'/231' +L2Kwksa8c4h8e1NsWA7LVXNnNTXPpxivqCsPXjCG5Qg7LdJd8sxw 2017-09-18T19:07:27Z reserve=1 # addr=126NinSEzkey9VoNNfHcJpYaN43Bse4HnP hdkeypath=m/0'/1'/255' +KxGp54hzb61WAcXLhpMw51MXCrQf8pkwUB7PWxZyQfcLbEppS5ki 2017-09-18T19:07:27Z reserve=1 # addr=126oMQPf2SqStNtai78HHjBq1pD3MbPhdY hdkeypath=m/0'/0'/900' +KxE3xagi1xBAPwLEU4KfKGJrB4EP8xWcQkNc4nJebYC8MQ433ZFq 2017-09-18T19:07:27Z reserve=1 # addr=127z4EXPBfb3WjxcTafrG9nTaWyRsXj2eN hdkeypath=m/0'/0'/277' +L2KgsusgBr4b6akZnmTMKDHAEM88246zURbGRj8vQfSF8EukFYFC 2017-09-18T19:07:27Z reserve=1 # addr=128rEXMhruANwihRd9fyWio3pDV42qnPCR hdkeypath=m/0'/0'/295' +KyHaLBKZscV3GeBVc1znAC6DbnrW1XeJtVmMnJhttC1fyK3if1aD 2017-09-18T19:07:27Z reserve=1 # addr=129fx9Gn3Vw7ALJANiCee7qiGhjih5Gcx4 hdkeypath=m/0'/1'/250' +L3e6tGJkVg7wJGgcW1ZBvgk1d4HB4g28VMhhXp8WJD9PGiXNAnB5 2017-09-18T19:07:27Z reserve=1 # addr=12AiV2mp4PsjTagfieLZJYUSvJ9wP2TNNm hdkeypath=m/0'/0'/662' +L1jA9JekAdMh7fBtddTjTyh1TGsXuWttc1g9LBn22qmpLMyFn8nr 2017-09-18T19:07:27Z reserve=1 # addr=12CtM6k7EsYFoYQFgKjiCECYuvaxVjE2Uc hdkeypath=m/0'/0'/790' +KzFdNVfg1Tzeh6CcaED94g5W3AsW6f81bDGKySzeTFStoq4WvFyJ 2017-09-18T19:07:27Z reserve=1 # addr=12D4i8v7ij52hvso3woAPbm2KPA7ucQX7h hdkeypath=m/0'/0'/128' +KyZskTR6nmW1kydh9f5g9eyXnXRwnJDX1NiU4JLkd8ptseBDoeWN 2017-09-18T19:07:27Z reserve=1 # addr=12D8X4qLZ7tVHFMzwdFdXYdmZ55X3qD5DX hdkeypath=m/0'/0'/319' +KwFDGuCnShh9BTZV22FyjTfrRNeVwRHTAZCgsF7i9xeqLRJrg6QM 2017-09-18T19:07:27Z reserve=1 # addr=12Dr1yMBpNeampwYsEEScMiZSiE6vC9ooY hdkeypath=m/0'/0'/72' +KzMLxb5XgZtgSGY64T9ekTe6aTnNPt1oYzoPa2F3dCgkMmPvuSiY 2017-09-18T19:07:27Z reserve=1 # addr=12EGgUN3xEZwXcipz41TEyVcm5X2u1Lzf1 hdkeypath=m/0'/0'/636' +KyQ645daANAfhYv1c2ya37wg8WRmGe4Pgbt5bkcYeKnu3xXkUrCt 2017-09-18T19:07:27Z reserve=1 # addr=12FB9PR8oP58KoPSAWicyjgv2PK6qtkpX8 hdkeypath=m/0'/0'/346' +KzA6B9uu6eUgytq69F2WLjvLHea34Xy5DUcpRG32Cr2zWoLw3fqh 2017-09-18T19:07:27Z reserve=1 # addr=12Fznbw763E6VqGTFK4oXXjDDKQnnDWwVG hdkeypath=m/0'/0'/928' +KzLhYhBZwrbcHFmZnuGniN7Xn88u1zHuhEoUj8zVViMuNKeETXdG 2017-09-18T19:07:27Z reserve=1 # addr=12G9f4aFiobRY5nDTN6aR7zWZpR8KYR6im hdkeypath=m/0'/0'/7' +KydySFGfowWh74Tx6aXPzS1a9WkoRnoWLM2p5QY2FjQW8ufvBmr6 2017-09-18T19:07:27Z reserve=1 # addr=12GdJv9KVvoBaQhZuTxnFRChtEoTLMyf9Q hdkeypath=m/0'/0'/830' +L3TTZVZKd7obbkBPgY7fEzoKhQJpZqNnLJz1pqESiQn2Uo6JHNuj 2017-09-18T19:07:27Z reserve=1 # addr=12HcLKceVsqxcTGX3dWAk9qJ3KaofZES2Y hdkeypath=m/0'/1'/352' +KzauKVLNW2ZRornVzaFB5WGbipZjvLAb9UjD8HrqkiVhuZabfrdY 2017-09-18T19:07:27Z reserve=1 # addr=12JvNdkfQmMhrXFiTaPLBRQaGmj47v54Cs hdkeypath=m/0'/0'/547' +L2jYNEHVsSmDd3Dr68hiRZdbGoTNtyqymzNmjLdER8YkscKBumic 2017-09-18T19:07:27Z reserve=1 # addr=12KJW1CRbAbESzZD6oxcDCTg9Ac6NDdb9C hdkeypath=m/0'/0'/914' +Kz1U26YUceKUDj6rw6TtSEUbVxqxDxMsAioeAkQQs8RttSE1nmYa 2017-09-18T19:07:27Z reserve=1 # addr=12LZZ6xC7X3gXGY3t9e128YdePhjDjPrSa hdkeypath=m/0'/0'/125' +L1yKAoC6irDo83KiXFzLh6af9sE7YjmKN375E4b3nX97bRTSfG3g 2017-09-18T19:07:27Z reserve=1 # addr=12M6yokHDBEJ15aAyFS7euRggf8CUwsko2 hdkeypath=m/0'/1'/432' +KzTC5PAZQ5LfnFGz683pM9UZemkTJ2dahb6Mdat4TEJr12zofoqU 2017-09-18T19:07:27Z reserve=1 # addr=12MpKkHPZNQaEG6fLAkHc4vbr1KyXvJPp1 hdkeypath=m/0'/1'/309' +KwWe1KDu6tQ122p54rZEN5qegPDHgPUp86258GkdW2mBRALSyk43 2017-09-18T19:07:27Z reserve=1 # addr=12NPB1tYPtPaEuxBdHcVQfdP3eNotpHyzF hdkeypath=m/0'/1'/66' +KypmNhq9ptrvkz1rCWSszcEMcnruL1Hdm9LiGwroQMHESbp5FsBa 2017-09-18T19:07:27Z reserve=1 # addr=12QaWB8EhG8wFAgQ4rbJzq1KpWgHFzDb2W hdkeypath=m/0'/0'/79' +L5iNfXhyF1ZYP9WrM6hyWZSEPHiTKA1cnwfHKzK1rkQZEgRFJx5P 2017-09-18T19:07:27Z reserve=1 # addr=12R7bNadKXfqbCXA6P7efNDWz81a1F3E9d hdkeypath=m/0'/0'/372' +L2MJYNGatcetU5LdcWKo6fu8My54jQYpDdkyfQVyugawu7SSguAc 2017-09-18T19:07:27Z reserve=1 # addr=12RQfKkwfyVkMNpRG7FnxNK7ZNun52BTvD hdkeypath=m/0'/0'/455' +KwypYV7K3emewSJ9bCT4uTa2xSBD7ZHCAK8aSnqQLdLmpWnW9eje 2017-09-18T19:07:27Z reserve=1 # addr=12SzoA4sow2eyCspHaSHzGcLv3jVLKVK8R hdkeypath=m/0'/1'/6' +KzCABRNQXJCMrScYxLXVipVaNV1puY6SVPoCZY979FMmNjps1tVF 2017-09-18T19:07:27Z reserve=1 # addr=12VWSvvzqT6CLFC6qHA9C5LBxEVqrSHRih hdkeypath=m/0'/0'/799' +KyaN2XahbkmL4Nua1vedpoehvuvmTmqA9BJksYiZGkV2NX9h5Cx1 2017-09-18T19:07:27Z reserve=1 # addr=12WBprMrLCAphMsBGopTdBAjfqzfbqKikN hdkeypath=m/0'/0'/454' +L3wfGdGiD1FazmVq3onXKZfKJeZQUPgxKxBjLp9d47GVX4x4oxJS 2017-09-18T19:07:27Z reserve=1 # addr=12Wb3qFBpNMmCv3q587qAMX59ADwGBDCYJ hdkeypath=m/0'/1'/465' +L112v3tnDrYmWVwcPsim3aMFsUdcuDDo3siCo7V3WDTqfifXA5Ku 2017-09-18T19:07:27Z reserve=1 # addr=12Xb5nGyU14UeJEdkfo1B1dPucA6ULpAHt hdkeypath=m/0'/0'/758' +L3b4N8pobwj3daPFTxcaRxoDYYcj6yaJJpZK9McK5MsGLXnbMNsr 2017-09-18T19:07:27Z reserve=1 # addr=12ZTexE3VGRJn1qk51UdGnA7T9RoYtGEKe hdkeypath=m/0'/0'/144' + +# End of dump diff --git a/test/test.py b/test/test.py index 00fc5465..954332d4 100755 --- a/test/test.py +++ b/test/test.py @@ -20,7 +20,7 @@ test/test.py: Test suite for the MMGen suite """ -import sys,os +import sys,os,subprocess,shutil,time,re pn = os.path.dirname(sys.argv[0]) os.chdir(os.path.join(pn,os.pardir)) @@ -80,13 +80,17 @@ if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts try: os.listdir(data_dir) except: pass else: - import shutil - shutil.rmtree(data_dir) + try: shutil.rmtree(data_dir) + except: # we couldn't remove data dir - perhaps regtest daemon is running + try: subprocess.call(['python','mmgen-regtest','stop']) + except: rdie(1,'Unable to remove data dir!') + else: + time.sleep(2) + shutil.rmtree(data_dir) os.mkdir(data_dir,0755) else: d,pfx = '/dev/shm','mmgen-test-' try: - import subprocess subprocess.call('rm -rf %s/%s*'%(d,pfx),shell=True) except Exception as e: die(2,'Unable to delete directory tree %s/%s* (%s)'%(d,pfx,e)) @@ -119,7 +123,7 @@ opts_data = lambda: { -l, --list-cmds List and describe the commands in the test suite -L, --log Log commands to file {lf} -n, --names Display command names instead of descriptions --O, --popen-spawn Use pexpect's popen_spawn instead of popen +-O, --popen-spawn Use pexpect's popen_spawn instead of popen (always true, so ignored) -p, --pause Pause between tests, resuming on keypress -P, --profile Record the execution time of each script -q, --quiet Produce minimal output. Suppress dependency info @@ -141,6 +145,7 @@ If no command is given, the whole suite of tests is run. sys.argv = [sys.argv[0]] + ['--data-dir',data_dir] + sys.argv[1:] cmd_args = opts.init(opts_data) +opt.popen_spawn = True # popen has issues, so use popen_spawn always tn_desc = ('','.testnet')[g.testnet] @@ -174,6 +179,9 @@ cfgs = { }, 'segwit': get_segwit_val() }, + '17': { + 'tmpdir': os.path.join('test','tmp17'), + }, '1': { 'tmpdir': os.path.join('test','tmp1'), 'wpasswd': 'Dorian', @@ -268,8 +276,12 @@ cfgs = { 'seed_len': 128, 'seed_id': 'FE3C6545', 'ref_bw_seed_id': '33F10310', -'addrfile_chk': ('B230 7526 638F 38CB','B64D 7327 EF2A 60FE','9914 6D10 2307 F348','7DBF 441F E188 8B37'), -'keyaddrfile_chk':('CF83 32FB 8A8B 08E2','FEBF 7878 97BB CC35','C13B F717 D4E8 CF59','4DB5 BAF0 45B7 6E81'), + 'addrfile_chk': ('B230 7526 638F 38CB','B64D 7327 EF2A 60FE'), + 'addrfile_segwit_chk': ('9914 6D10 2307 F348','7DBF 441F E188 8B37'), + 'addrfile_compressed_chk': ('95EB 8CC0 7B3B 7856','629D FDE4 CDC0 F276'), + 'keyaddrfile_chk': ('CF83 32FB 8A8B 08E2','FEBF 7878 97BB CC35'), + 'keyaddrfile_segwit_chk': ('C13B F717 D4E8 CF59','4DB5 BAF0 45B7 6E81'), + 'keyaddrfile_compressed_chk': ('E43A FA46 5751 720A','B995 A6CF D1CD FAD0'), 'passfile_chk': 'EB29 DC4F 924B 289F', 'passfile32_chk': '37B6 C218 2ABC 7508', 'wpasswd': 'reference password', @@ -297,8 +309,12 @@ cfgs = { 'seed_len': 192, 'seed_id': '1378FC64', 'ref_bw_seed_id': 'CE918388', -'addrfile_chk': ('8C17 A5FA 0470 6E89','0A59 C8CD 9439 8B81','91C4 0414 89E4 2089','3BA6 7494 8E2B 858D'), -'keyaddrfile_chk': ('9648 5132 B98E 3AD9','2F72 C83F 44C5 0FAC','C98B DF08 A3D5 204B','25F2 AEB6 AAAC 8BBE'), + 'addrfile_chk': ('8C17 A5FA 0470 6E89','0A59 C8CD 9439 8B81'), + 'addrfile_segwit_chk': ('91C4 0414 89E4 2089','3BA6 7494 8E2B 858D'), + 'addrfile_compressed_chk': ('2615 8401 2E98 7ECA','DF38 22AB AAB0 124E'), + 'keyaddrfile_chk': ('9648 5132 B98E 3AD9','2F72 C83F 44C5 0FAC'), + 'keyaddrfile_segwit_chk': ('C98B DF08 A3D5 204B','25F2 AEB6 AAAC 8BBE'), + 'keyaddrfile_compressed_chk': ('6D6D 3D35 04FD B9C3','B345 9CD8 9EAE 5489'), 'passfile_chk': 'ADEA 0083 094D 489A', 'passfile32_chk': '2A28 C5C7 36EC 217A', 'wpasswd': 'reference password', @@ -326,8 +342,12 @@ cfgs = { 'seed_len': 256, 'seed_id': '98831F3A', 'ref_bw_seed_id': 'B48CD7FC', -'addrfile_chk': ('6FEF 6FB9 7B13 5D91','3C2C 8558 BB54 079E','06C1 9C87 F25C 4EE6','58D1 7B6C E9F9 9C14'), -'keyaddrfile_chk': ('9F2D D781 1812 8BAD','7410 8F95 4B33 B4B2','A447 12C2 DD14 5A9B','0690 460D A600 D315'), + 'addrfile_chk': ('6FEF 6FB9 7B13 5D91','3C2C 8558 BB54 079E'), + 'addrfile_segwit_chk': ('06C1 9C87 F25C 4EE6','58D1 7B6C E9F9 9C14'), + 'addrfile_compressed_chk': ('A33C 4FDE F515 F5BC','5186 02C2 535E B7D5'), + 'keyaddrfile_chk': ('9F2D D781 1812 8BAD','7410 8F95 4B33 B4B2'), + 'keyaddrfile_segwit_chk': ('A447 12C2 DD14 5A9B','0690 460D A600 D315'), + 'keyaddrfile_compressed_chk': ('420A 8EB5 A9E2 7814','3243 DD92 809E FE8D'), 'passfile_chk': '2D6D 8FBA 422E 1315', 'passfile32_chk': 'F6C1 CDFB 97D9 FCAE', 'wpasswd': 'reference password', @@ -475,6 +495,8 @@ cmd_group['ref'] = ( ('refwalletgen', ([],'gen new refwallet')), ('refaddrgen', (['mmdat',pwfile],'new refwallet addr chksum')), ('refkeyaddrgen', (['mmdat',pwfile],'new refwallet key-addr chksum')), + ('refaddrgen_compressed', (['mmdat',pwfile],'new refwallet addr chksum (compressed)')), + ('refkeyaddrgen_compressed', (['mmdat',pwfile],'new refwallet key-addr chksum (compressed)')), ('refpasswdgen', (['mmdat',pwfile],'new refwallet passwd file chksum')), ('ref_b32passwdgen',(['mmdat',pwfile],'new refwallet passwd file chksum (base32)')), ) @@ -515,6 +537,23 @@ cmd_group['conv_out'] = ( # writing ('ref_hincog_conv_out', 'ref seed conversion to hidden incog data') ) +cmd_group['regtest'] = ( + ('regtest_setup', 'regtest (Bob and Alice) mode setup'), + ('regtest_alice_bal1', "Alice's balance"), + ('regtest_bob_bal1', "Bob's balance"), + ('regtest_bob_split', "splitting Bob's funds"), + ('regtest_generate', 'mining a block'), + ('regtest_bob_bal2', "Bob's balance"), + ('regtest_bob_rbf_send','sending funds to Alice (RBF)'), + ('regtest_get_mempool1','mempool (before RBF bump)'), + ('regtest_bob_rbf_bump1','bumping RBF transaction'), + ('regtest_get_mempool2','mempool (after RBF bump)'), + ('regtest_generate', 'mining a block'), + ('regtest_bob_bal3', "Bob's balance"), + ('regtest_alice_bal2', "Alice's balance"), + ('regtest_stop', 'stopping regtest daemon'), +) + cmd_list = OrderedDict() for k in cmd_group: cmd_list[k] = [] @@ -556,6 +595,11 @@ for a,b in cmd_group['conv_out']: cmd_list['conv_out'].append(k) cmd_data[k] = (10+i,'%s (%s-bit)' % (b,j),[[[],10+i]]) +cmd_data['info_regtest'] = 'regtest mode',[17] +for a,b in cmd_group['regtest']: + cmd_list['regtest'].append(a) + cmd_data[a] = (17,b,[[[],17]]) + utils = { 'check_deps': 'check dependencies for specified command', 'clean': 'clean specified tmp dir(s) 1,2,3,4,5 or 6 (no arg = all dirs)', @@ -596,6 +640,8 @@ meta_cmds = OrderedDict([ ['saved_ref_conv_out1', [c[0]+'1' for c in cmd_group['conv_out']]], ['saved_ref_conv_out2', [c[0]+'2' for c in cmd_group['conv_out']]], ['saved_ref_conv_out3', [c[0]+'3' for c in cmd_group['conv_out']]], + + ['regtest', dict(cmd_group['regtest']).keys()], ]) del cmd_group @@ -677,7 +723,6 @@ if opt.list_cmds: Msg(fs.format(cmd,utils[cmd],w=w)) sys.exit(0) -import time,re NL = ('\r\n','\n')[g.platform=='linux' and bool(opt.popen_spawn)] def get_file_with_ext(ext,mydir,delete=True,no_dot=False): @@ -1136,20 +1181,27 @@ class MMGenTestSuite(object): have_dfl_wallet = False ok() - def addrgen(self,name,wf,pf=None,check_ref=False,ftype='addr',id_str=None,extra_args=[]): - ftype,chkfile = ((ftype,'{}file_chk'.format(ftype)),('pass','passfile32_chk'))[ftype=='pass32'] - add_args = extra_args + (get_segwit_arg(cfg),[])[ftype[:4]=='pass'] - dlist = [id_str] if id_str else [] - t = MMGenExpect(name,'mmgen-{}gen'.format(ftype), add_args + - ['-d',cfg['tmpdir']] + ([],[wf])[bool(wf)] + dlist + [cfg['{}_idx_list'.format(ftype)]]) + def addrgen(self,name,wf,pf=None,check_ref=False,ftype='addr',id_str=None,extra_args=[],mmtype=None): + if cfg['segwit'] and ftype[:4] != 'pass' and not mmtype: mmtype = 'segwit' + cmd_pfx = (ftype,'pass')[ftype[:4]=='pass'] + t = MMGenExpect(name,'mmgen-{}gen'.format(cmd_pfx), + ['-d',cfg['tmpdir']] + + extra_args + + ([],['--type='+str(mmtype)])[bool(mmtype)] + + ([],[wf])[bool(wf)] + + ([],[id_str])[bool(id_str)] + + [cfg['{}_idx_list'.format(cmd_pfx)]]) t.license() t.passphrase('MMGen wallet',cfg['wpasswd']) t.expect('Passphrase is OK') - desc = ('address','password')[ftype=='pass'] + desc = ('address','password')[ftype[:4]=='pass'] chk = t.expect_getend(r'Checksum for {} data .*?: '.format(desc),regex=True) if check_ref: - c = (cfg[chkfile][g.testnet + 2*cfg['segwit']],cfg[chkfile])[ftype=='pass'] - refcheck('address data checksum',chk,c) + k = 'passfile32_chk' if ftype == 'pass32' \ + else 'passfile_chk' if ftype == 'pass' \ + else '{}file{}_chk'.format(ftype,'_'+mmtype if mmtype else '') + chk_ref = cfg[k] if ftype[:4] == 'pass' else cfg[k][g.testnet] + refcheck('address data checksum',chk,chk_ref) return t.written_to_file('Addresses',oo=True) t.ok() @@ -1158,9 +1210,11 @@ class MMGenTestSuite(object): return self.addrgen(name,wf=None,pf=pf,check_ref=check_ref) def refaddrgen(self,name,wf,pf): - d = ' (%s-bit seed)' % cfg['seed_len'] self.addrgen(name,wf,pf=pf,check_ref=True) + def refaddrgen_compressed(self,name,wf,pf): + self.addrgen(name,wf,pf=pf,check_ref=True,mmtype='compressed') + def addrimport(self,name,addrfile): outfile = os.path.join(cfg['tmpdir'],'addrfile_w_comments') add_comments_to_addr_file(addrfile,outfile) @@ -1210,8 +1264,7 @@ class MMGenTestSuite(object): t.expect(r"'q'=quit view, .*?:.",'q', regex=True) outputs_list = [(addrs_per_wallet+1)*i + 1 for i in range(len(tx_data))] if non_mmgen_input: outputs_list.append(len(tx_data)*(addrs_per_wallet+1) + 1) - t.expect('Enter a range or space-separated list of outputs to spend: ', - ' '.join([str(i) for i in outputs_list])+'\n') + t.expect('outputs to spend: ',' '.join([str(i) for i in outputs_list])+'\n') if non_mmgen_input and not txdo_args: t.expect('Accept? (y/N): ','y') t.expect('OK? (Y/n): ','y') # fee OK? t.expect('OK? (Y/n): ','y') # change OK? @@ -1408,14 +1461,17 @@ class MMGenTestSuite(object): self.addrgen_incog(name,[],'',in_fmt='hi',desc='hidden incognito data', args=['-H','%s,%s'%(rf,hincog_offset),'-l',str(hincog_seedlen)]) - def keyaddrgen(self,name,wf,pf=None,check_ref=False): - args = get_segwit_arg(cfg) + ['-d',cfg['tmpdir'],usr_rand_arg,wf,cfg['addr_idx_list']] - t = MMGenExpect(name,'mmgen-keygen', args) + def keyaddrgen(self,name,wf,pf=None,check_ref=False,mmtype=None): + if cfg['segwit'] and not mmtype: mmtype = 'segwit' + args = ['-d',cfg['tmpdir'],usr_rand_arg,wf,cfg['addr_idx_list']] + t = MMGenExpect(name,'mmgen-keygen', + ([],['--type='+str(mmtype)])[bool(mmtype)] + args) t.license() t.passphrase('MMGen wallet',cfg['wpasswd']) chk = t.expect_getend(r'Checksum for key-address data .*?: ',regex=True) if check_ref: - refcheck('key-address data checksum',chk,cfg['keyaddrfile_chk'][g.testnet + 2*cfg['segwit']]) + k = 'keyaddrfile{}_chk'.format('_'+mmtype if mmtype else '') + refcheck('key-address data checksum',chk,cfg[k][g.testnet]) return t.expect('Encrypt key list? (y/N): ','y') t.usr_rand(usr_rand_chars) @@ -1428,6 +1484,9 @@ class MMGenTestSuite(object): def refkeyaddrgen(self,name,wf,pf): self.keyaddrgen(name,wf,pf,check_ref=True) + def refkeyaddrgen_compressed(self,name,wf,pf): + self.keyaddrgen(name,wf,pf,check_ref=True,mmtype='compressed') + def refpasswdgen(self,name,wf,pf): self.addrgen(name,wf,pf,check_ref=True,ftype='pass',id_str='alice@crypto.org') @@ -1724,10 +1783,9 @@ class MMGenTestSuite(object): def ref_tool_decrypt(self,name): f = os.path.join(ref_dir,ref_enc_fn) - aa = [] - t = MMGenExpect(name,'mmgen-tool', - aa + ['-q','decrypt',f,'outfile=-','hash_preset=1']) + t = MMGenExpect(name,'mmgen-tool', ['-q','decrypt',f,'outfile=-','hash_preset=1']) t.passphrase('user data',tool_enc_passwd) +# t.expect("Type uppercase 'YES' to confirm: ",'YES\n') # comment out with popen_spawn t.expect(NL,nonl=True) import re o = re.sub('\r\n','\n',t.read()) @@ -1794,6 +1852,134 @@ class MMGenTestSuite(object): add_args=add_args, extra_desc='(check)') + def regtest_setup(self,name): + try: shutil.rmtree(os.path.join(data_dir,'regtest')) + except: pass + os.environ['MMGEN_TEST_SUITE'] = '' # mnemonic is piped to stdin, so stop being a terminal + t = MMGenExpect(name,'mmgen-regtest',['-m','--data-dir='+data_dir,'setup']) + os.environ['MMGEN_TEST_SUITE'] = '1' + t.expect('Mined') + t.expect('Setting up') + t.expect('Creating') + t.expect('Creating') + t.expect('Importing') + t.expect('Importing') + t.expect('Importing') + t.expect('Setting up') + t.expect('Creating') + t.expect('Creating') + t.expect('Importing') + t.expect('Importing') + t.expect('Importing') + t.expect('Sending') + t.expect('Sending') + t.expect('Mined') + t.expect('Setup complete') + t.ok() + + def regtest_user_bal(self,name,user,bal): + t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','showempty=1']) + total = t.expect_getend('TOTAL: ') + cmp_or_die(total,'{} BTC'.format(bal)) + + def regtest_alice_bal1(self,name): + return self.regtest_user_bal(name,'alice','500') + + def regtest_alice_bal2(self,name): + return self.regtest_user_bal(name,'alice','600') + + def regtest_bob_bal1(self,name): + return self.regtest_user_bal(name,'bob','500') + + def regtest_bob_bal2(self,name): + return self.regtest_user_bal(name,'bob','499.999942') + + def regtest_bob_bal3(self,name): + return self.regtest_user_bal(name,'bob','399.9998214') + + def regtest_user_txdo(self,name,user,fee,outputs_cl,outputs_prompt,extra_args=[],no_send=False): + os.environ['MMGEN_BOGUS_SEND'] = '' + t = MMGenExpect(name,'mmgen-txdo', + ['-d',cfg['tmpdir'],'-B','--'+user,'--tx-fee='+fee] + extra_args + outputs_cl) + os.environ['MMGEN_BOGUS_SEND'] = '1' + + t.expect(r"'q'=quit view, .*?:.",'M',regex=True) # sort by mmid + t.expect(r"'q'=quit view, .*?:.",'q',regex=True) + t.expect('outputs to spend: ',outputs_prompt+'\n') + t.expect('OK? (Y/n): ','y') # fee OK? + t.expect('OK? (Y/n): ','y') # change OK? + t.expect('Add a comment to transaction? (y/N): ','\n') + t.expect('View decoded transaction\? .*?: ','t',regex=True) + t.expect('to continue: ','\n') + t.written_to_file('Signed transaction') + if not no_send: + t.expect('to confirm: ','YES, I REALLY WANT TO DO THIS\n') + t.expect('Transaction sent') + t.read() + t.ok() + + def regtest_bob_split(self,name): + from mmgen.regtest import sids + outputs_cl = [sids['bob']+':C:1,100', sids['bob']+':L:2,200',sids['bob']+':S:2'] + return self.regtest_user_txdo(name,'bob','20s',outputs_cl,'1') + + def regtest_bob_rbf_send(self,name): + from mmgen.regtest import sids + outputs_cl = [ + 'n2XovQAmdtRBS7H1PUnRFk1FR5n8wDAsXB,60', # sids['alice']:L:1 + 'mn67MDDa16eV2H6yDtPi3mKTAqqDxoWpJ3,40', # sids['alice']:C:1 + sids['bob']+':S:2'] + return self.regtest_user_txdo(name,'bob','10s',outputs_cl,'3',extra_args=['--rbf']) + + def regtest_user_txbump(self,name,user,txfile,fee,red_op,no_send=False): + os.environ['MMGEN_BOGUS_SEND'] = '' + t = MMGenExpect(name,'mmgen-txbump', + ['-d',cfg['tmpdir'],'--send','--'+user,'--tx-fee='+fee,'--output-to-reduce='+red_op] + [txfile]) + os.environ['MMGEN_BOGUS_SEND'] = '1' + t.expect('OK? (Y/n): ','y') # output OK? + t.expect('OK? (Y/n): ','y') # fee OK? + t.expect('Add a comment to transaction? (y/N): ','n') + t.written_to_file('Signed transaction') + if not no_send: + t.expect('to confirm: ','YES, I REALLY WANT TO DO THIS\n') + t.expect('Transaction sent') + t.written_to_file('Signed transaction') + t.read() + t.ok() + + def regtest_bob_rbf_bump1(self,name): + txfile = get_file_with_ext(',10].sigtx',cfg['tmpdir'],delete=False,no_dot=True) + return self.regtest_user_txbump(name,'bob',txfile,'60s','c') + + def regtest_generate(self,name): + t = MMGenExpect(name,'mmgen-regtest',['generate']) + t.expect('Mined 1 block') + t.ok() + + def regtest_get_mempool(self,name): + t = MMGenExpect(name,'mmgen-regtest',['show_mempool']) + ret = eval(t.read()) + return ret + + def regtest_get_mempool1(self,name): + mp = self.regtest_get_mempool(name) + if len(mp) != 1: + rdie(2,'Mempool has more or less than one TX!') + write_to_tmpfile(cfg,'rbf_txid',mp[0]+'\n') + ok() + + def regtest_get_mempool2(self,name): + mp = self.regtest_get_mempool(name) + if len(mp) != 1: + rdie(2,'Mempool has more or less than one TX!') + chk = read_from_tmpfile(cfg,'rbf_txid') + if chk.strip() == mp[0]: + rdie(2,'TX in mempool has not changed! RBF bump failed') + ok() + + def regtest_stop(self,name): + t = MMGenExpect(name,'mmgen-regtest',['stop']) + t.ok() # END methods for k in ( @@ -1815,13 +2001,15 @@ class MMGenTestSuite(object): 'ref_hincog_conv_out', 'ref_wallet_chk', 'refwalletgen', - 'refaddrgen', 'ref_seed_chk', 'ref_hex_chk', 'ref_mn_chk', 'ref_brain_chk', 'ref_hincog_chk', + 'refaddrgen', 'refkeyaddrgen', + 'refaddrgen_compressed', + 'refkeyaddrgen_compressed', 'refpasswdgen', 'ref_b32passwdgen' ): @@ -1887,6 +2075,7 @@ try: else: clean() for cmd in cmd_data: + if cmd == 'info_regtest': break # don't run these by default if cmd[:5] == 'info_': msg(green('%sTesting %s' % (('\n','')[bool(opt.resume)],cmd_data[cmd][0]))) continue