From 12ea12e4e281f4d72f6536587f6ad530c8b22583 Mon Sep 17 00:00:00 2001 From: philemon Date: Tue, 26 Sep 2017 15:41:11 +0300 Subject: [PATCH] mmgen-regtest: final implementation; additional test suite tests --- mmgen/main_regtest.py | 43 ++++++----- mmgen/opts.py | 11 +-- mmgen/regtest.py | 126 +++++++++---------------------- mmgen/txsign.py | 8 +- mmgen/util.py | 6 +- scripts/test-release.sh | 56 ++++++++++---- test/test.py | 163 +++++++++++++++++++++++++++++----------- 7 files changed, 230 insertions(+), 183 deletions(-) diff --git a/mmgen/main_regtest.py b/mmgen/main_regtest.py index 1eb8e4b2..ff5753a4 100755 --- a/mmgen/main_regtest.py +++ b/mmgen/main_regtest.py @@ -30,38 +30,41 @@ opts_data = lambda: { -h, --help Print this help message --, --longhelp Print help message for long options (common options) -e, --empty Don't fund Bob and Alice's wallets on setup --m, --mixed Create Bob and Alice's wallets with mixed address types +-n, --setup-no-stop-daemon Don't stop daemon after setup is finished -q, --quiet Produce quieter output -v, --verbose Produce more verbose output """, 'notes': """ - AVAILABLE COMMANDS + AVAILABLE COMMANDS - setup - setup up system for regtest operation with MMGen - stop - stop the regtest bitcoind - bob - switch to Bob's wallet, starting daemon if necessary - alice - switch to Alice's wallet, starting daemon if necessary - user - show current user - 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 + setup - setup up system for regtest operation with MMGen + stop - stop the regtest bitcoind + bob - switch to Bob's wallet, starting daemon if necessary + alice - switch to Alice's wallet, starting daemon if necessary + user - show current user + generate - mine a block + send ADDR AMT - send amount AMT to address ADDR + test_daemon - test whether daemon is running + get_balances - get balances of Bob and Alice + show_mempool - show transaction IDs in mempool """ } cmd_args = opts.init(opts_data) -if len(cmd_args) != 1: - opts.usage() - -cmds = ('setup','stop','generate','test_daemon','create_data_dir','bob','alice','user', +cmds = ('setup','stop','generate','test_daemon','create_data_dir','bob','alice','miner','user','send', 'wait_for_daemon','wait_for_exit','get_current_user','get_balances','show_mempool') -if cmd_args[0] not in cmds: +try: + if cmd_args[0] == 'send': + assert len(cmd_args) == 3 + else: + assert cmd_args[0] in cmds and len(cmd_args) == 1 +except: opts.usage() - -from mmgen.regtest import * - -globals()[cmd_args[0]]() +else: + args = cmd_args[1:] + from mmgen.regtest import * + globals()[cmd_args[0]](*args) diff --git a/mmgen/opts.py b/mmgen/opts.py index 48dcb5d2..3c71f896 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -243,7 +243,8 @@ def init(opts_f,add_opts=[],opt_filter=None): mmgen.share.Opts.parse_opts(sys.argv,opts_data,opt_filter=opt_filter) if g.bob or g.alice: - g.data_dir = os.path.join(g.data_dir_root,'regtest') + g.data_dir = os.path.join(g.data_dir_root,'regtest',('alice','bob')[g.bob]) + check_or_create_dir(g.data_dir) import regtest as rt g.testnet = True g.rpc_host = 'localhost' @@ -414,10 +415,10 @@ def check_opts(usr_opts): # Returns false if any check fails 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())) + from mmgen.regtest import daemon_dir + m = "Regtest (Bob and Alice) mode not set up yet. Run '{}-regtest setup' to initialize." + try: os.stat(daemon_dir) + except: die(1,m.format(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 5cbe2a3b..63fbcdaa 100755 --- a/mmgen/regtest.py +++ b/mmgen/regtest.py @@ -25,25 +25,13 @@ from mmgen.common import * PIPE = subprocess.PIPE data_dir = os.path.join(g.data_dir_root,'regtest') -regtest_dir = os.path.join(data_dir,'regtest') +daemon_dir = os.path.join(data_dir,'regtest') rpc_port = 8552 rpc_user = 'bobandalice' rpc_password = 'hodltothemoon' 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' -} -send_addr = { - 'bob': 'mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ', - 'alice': '2N3HhxasbRvrJyHg72JNVCCPi9EUGrEbFnu', -} +tr_wallet = lambda user: os.path.join(daemon_dir,'wallet.dat.'+user) common_args = ( '-rpcuser={}'.format(rpc_user), @@ -78,8 +66,9 @@ def start_cmd(*args,**kwargs): cmd = ('bitcoin-cli',) + common_args + args[1:] if g.debug or not 'quiet' in kwargs: vmsg('{}'.format(' '.join(cmd))) - io=(PIPE,None)['no_pipe' in kwargs and kwargs['no_pipe']] - return subprocess.Popen(cmd,stdin=io,stdout=io,stderr=io) + ip = op = ep = (PIPE,None)['no_pipe' in kwargs and kwargs['no_pipe']] + if 'pipe_stdout_only' in kwargs and kwargs['pipe_stdout_only']: ip = ep = None + return subprocess.Popen(cmd,stdin=ip,stdout=op,stderr=ep) def test_daemon(): p = start_cmd('cli','getblockcount',quiet=True) @@ -103,22 +92,25 @@ def wait_for_daemon(state,silent=False,nonl=False): def get_balances(): user1 = get_current_user(quiet=True) + if user1 == None: + die(1,'Regtest daemon not running') user2 = ('bob','alice')[user1=='bob'] tbal = 0 from mmgen.obj import BTCAmt - for user in (user1,user2): + for u in (user1,user2): p = start_cmd('python','mmgen-tool', - '--{}'.format(user),'--data-dir='+g.data_dir, + '--{}'.format(u),'--data-dir='+g.data_dir, 'getbalance','quiet=1') - bal = BTCAmt(p.stdout.read()) - ustr = "{}'s balance:".format(user.capitalize()) + bal = p.stdout.read().replace(' \b','') # hack + if u == user1: user(user2) + bal = BTCAmt(bal) + ustr = "{}'s balance:".format(u.capitalize()) msg('{:<16} {:12}'.format(ustr,bal)) tbal += bal msg('{:<16} {:12}'.format('Total balance:',tbal)) - msg('{:<16} {:12}'.format('Miner fees:',1000-tbal)) def create_data_dir(): - try: os.stat(regtest_dir) + try: os.stat(daemon_dir) except: pass else: if keypress_confirm('Delete your existing MMGen regtest setup and create a new one?'): @@ -131,48 +123,13 @@ def create_data_dir(): def process_output(p,silent=False): out = p.stdout.read() - if not opt.verbose: Msg_r(' \b') + if g.platform == 'win' and not opt.verbose: Msg_r(' \b') err = p.stderr.read() if g.debug or not silent: vmsg('stdout: [{}]'.format(out.strip())) vmsg('stderr: [{}]'.format(err.strip())) return out,err -def create_mmgen_wallet(user): - gmsg("Creating {}'s MMGen wallet".format(user.capitalize())) - p = start_cmd('python','mmgen-walletconv','-d',data_dir,'-i','words','-o','words') - p.stdin.write(mnemonic[user]+'\n') - p.stdin.close() - err = process_output(p)[1] - if not 'written to file' in err: - rdie(1,'Error creating MMGen wallet') - p.wait() - -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)) - except: pass - 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] - if not 'written to file' in err: - rdie(1,'Error creating MMGen addresses') - p.wait() - -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','-q','--batch', - '--{}'.format(user),'--data-dir='+g.data_dir,mmaddrs(user).format(suf)) - err = process_output(p)[1] - if not 'addresses imported' in err: - rdie(1,'Error importing MMGen addresses') - p.wait() - def start_and_wait(user,silent=False,nonl=False): vmsg('Starting bitcoin regtest daemon') (start_daemon_mswin,start_daemon)[g.platform=='linux'](user) @@ -182,27 +139,18 @@ def stop_and_wait(silent=False,nonl=False,stop_silent=False,ignore_noconnect_err stop(silent=stop_silent,ignore_noconnect_error=ignore_noconnect_error) wait_for_daemon('stopped',silent=silent,nonl=nonl) -def setup_wallet(user,funded,stop=True): - gmsg_r("Setting up {}'s tracking wallet".format(user.capitalize())) - start_and_wait(user) - create_mmgen_wallet(user) - mmtypes = ([funded],['L','C','S'])[bool(opt.mixed)] - for mmtype in mmtypes: - create_mmgen_addrs(user,mmtype) - for mmtype in mmtypes: - import_mmgen_addrs(user,mmtype); msg('') - if stop: - stop_and_wait(silent=True,stop_silent=True) - -def fund_wallet(user,amt): - gmsg('Sending {} BTC to {}'.format(amt,user.capitalize())) - p = start_cmd('cli','sendtoaddress',send_addr[user],str(amt)) +def send(addr,amt): + user('miner') + gmsg('Sending {} BTC to address {}'.format(amt,addr)) + p = start_cmd('cli','sendtoaddress',addr,str(amt)) process_output(p) p.wait() + generate(1) def show_mempool(): p = start_cmd('cli','getrawmempool') - msg_r(p.stdout.read()) + from pprint import pformat + msg(pformat(eval(p.stdout.read()))) p.wait() def setup(): @@ -214,28 +162,27 @@ def setup(): gmsg('Starting setup') - setup_wallet('alice','S') - setup_wallet('bob','C') + gmsg_r('Creating miner wallet') + start_and_wait('miner') + generate(432,silent=True) + stop_and_wait(silent=True,stop_silent=True) - if opt.empty: - ymsg("'--empty' selected: skipping funding of wallets") - else: - gmsg_r('Funding wallets') - start_and_wait('orig') - generate(432,silent=True) - fund_wallet('bob',init_amt) - fund_wallet('alice',init_amt) - generate(1) - stop_and_wait(silent=True,stop_silent=True) + for user in ('alice','bob'): + gmsg_r("Creating {}'s tracking wallet".format(user.capitalize())) + start_and_wait(user) + if user == 'bob' and opt.setup_no_stop_daemon: + msg('Leaving daemon running with Bob as current user') + else: + stop_and_wait(silent=True,stop_silent=True) gmsg('Setup complete') 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'),quiet=True) + p = start_cmd('grep','Using wallet',os.path.join(daemon_dir,'debug.log'),quiet=True) try: wallet_fn = p.stdout.readlines()[-1].split()[-1] except: return None - for k in ('orig','bob','alice'): + for k in ('miner','bob','alice'): if wallet_fn == 'wallet.dat.'+k: if not quiet: msg('Current user is {}'.format(k.capitalize())) return k @@ -245,7 +192,7 @@ def get_current_user_unix(quiet=False): p = start_cmd('pgrep','-af', 'bitcoind.*-rpcuser={}.*'.format(rpc_user)) cmdline = p.stdout.read() if not cmdline: return None - for k in ('orig','bob','alice'): + for k in ('miner','bob','alice'): if 'wallet.dat.'+k in cmdline: if not quiet: msg('Current user is {}'.format(k.capitalize())) return k @@ -255,6 +202,7 @@ get_current_user = (get_current_user_win,get_current_user_unix)[g.platform=='lin def bob(): return user('bob',quiet=False) def alice(): return user('alice',quiet=False) +def miner(): return user('miner',quiet=False) def user(user=None,quiet=False): if user==None: get_current_user() diff --git a/mmgen/txsign.py b/mmgen/txsign.py index 634bce34..be7327cc 100755 --- a/mmgen/txsign.py +++ b/mmgen/txsign.py @@ -138,12 +138,8 @@ def get_seed_files(opt,args): # favor unencrypted seed sources first, as they don't require passwords u,e = SeedSourceUnenc,SeedSourceEnc ret = _pop_and_return(args,u.get_extensions()) - from mmgen.filename import find_file_in_dir,find_files_in_dir - if g.bob or g.alice: - import regtest as rt - 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 + from mmgen.filename import find_file_in_dir + wf = find_file_in_dir(Wallet,g.data_dir) # Make this the first encrypted ss in the list if wf: ret.append(wf) ret += _pop_and_return(args,e.get_extensions()) if not (ret or opt.mmgen_keys_from_file or opt.keys_from_file): # or opt.use_wallet_dat diff --git a/mmgen/util.py b/mmgen/util.py index 6c768f2b..ccb391ef 100755 --- a/mmgen/util.py +++ b/mmgen/util.py @@ -468,11 +468,7 @@ def make_full_path(outdir,outfile): def get_seed_file(cmd_args,nargs,invoked_as=None): from mmgen.filename import find_file_in_dir from mmgen.seed import Wallet - if g.bob or g.alice: - import regtest as rt - wf = rt.mmwallet(('alice','bob')[g.bob]) - else: - wf = find_file_in_dir(Wallet,g.data_dir) + wf = find_file_in_dir(Wallet,g.data_dir) wd_from_opt = bool(opt.hidden_incog_input_params or opt.in_fmt) # have wallet data from opt? diff --git a/scripts/test-release.sh b/scripts/test-release.sh index 6bcb50bb..4ab00114 100755 --- a/scripts/test-release.sh +++ b/scripts/test-release.sh @@ -1,8 +1,35 @@ #!/bin/bash # Tested on Linux, MinGW-64 +PROGNAME=$(basename $0) +while getopts hint OPT +do + case "$OPT" in + h) printf " %-16s Test MMGen release\n" "${PROGNAME^^}:" + echo " USAGE: $PROGNAME [options] branch [tests]" + echo " OPTIONS: '-h' Print this help message" + echo " '-i' Install only; don't run tests" + echo " '-n' Don't install; test in place" + echo " '-t' Print the tests without running them" + echo " AVAILABLE TESTS:" + echo " 1 - main" + echo " 2 - regtest" + echo " 3 - tool" + echo " 4 - gen" + echo " By default, all tests are run" + exit ;; + i) INSTALL_ONLY=1 ;; + n) NO_INSTALL=1 ;; + t) TESTING=1 ;; + *) exit ;; + esac +done + +shift $((OPTIND-1)) + set -e -GREEN="\e[32;1m" YELLOW="\e[33;1m" RESET="\e[0m" BRANCH=$1 +GREEN="\e[32;1m" YELLOW="\e[33;1m" RESET="\e[0m" +BRANCH=$1; shift REFDIR=test/ref if uname -a | grep -qi mingw; then SUDO='' MINGW=1; else SUDO='sudo' MINGW=''; fi @@ -29,12 +56,12 @@ function install { [ "$MINGW" ] && ./setup.py build --compiler=mingw32 eval "$SUDO ./setup.py install" } - +[ -z "$TESTING" ] && LS='\n' function do_test { set +x for i in "$@"; do - echo -e "\n${GREEN}Running:$RESET $YELLOW$i$RESET" - eval "$i" + echo -e "$LS${GREEN}Running:$RESET $YELLOW$i$RESET" + [ "$TESTING" ] || eval "$i" done } @@ -50,13 +77,16 @@ T4=("test/gentest.py -q 2 $REFDIR/btcwallet.dump" # "scripts/tx-old2new.py -S $REFDIR/tx_*raw >/dev/null 2>&1" "scripts/compute-file-chksum.py $REFDIR/*testnet.rawtx >/dev/null 2>&1") -check -(install) -eval "cd .test-release/pydist/mmgen-*" +[ -d .git -a -z "$NO_INSTALL" -a -z "$TESTING" ] && { + check + (install) + eval "cd .test-release/pydist/mmgen-*" +} +[ "$INSTALL_ONLY" ] && exit -do_test "${T1[@]}" -do_test "${T2[@]}" -do_test "${T3[@]}" -do_test "${T4[@]}" - -echo -e "\n${GREEN}All OK$RESET" +if [ "$*" ]; then TESTS=$@; else TESTS='1 2 3 4'; fi +for t in $TESTS; do + [ $t == 4 ] && LS='' + eval "do_test \"\${T$t[@]}\"" +done +echo -e "$LS${GREEN}All OK$RESET" diff --git a/test/test.py b/test/test.py index 1c6dd64d..b747b490 100755 --- a/test/test.py +++ b/test/test.py @@ -539,6 +539,14 @@ cmd_group['conv_out'] = ( # writing cmd_group['regtest'] = ( ('regtest_setup', 'regtest (Bob and Alice) mode setup'), + ('regtest_walletgen_bob', 'wallet generation (Bob)'), + ('regtest_walletgen_alice', 'wallet generation (Alice)'), + ('regtest_addrgen_bob', 'address generation (Bob)'), + ('regtest_addrgen_alice', 'address generation (Alice)'), + ('regtest_addrimport_bob', "importing Bob's addresses"), + ('regtest_addrimport_alice', "importing Alice's addresses"), + ('regtest_fund_bob', "funding Bob's wallet"), + ('regtest_fund_alice', "funding Alice's wallet"), ('regtest_bob_bal1', "Bob's balance"), ('regtest_bob_split1', "splitting Bob's funds"), ('regtest_generate', 'mining a block'), @@ -559,8 +567,7 @@ cmd_group['regtest'] = ( ('regtest_bob_bal5', "Bob's balance"), ('regtest_bob_send_non_mmgen', 'sending funds to Alice (from non-MMGen addrs)'), ('regtest_generate', 'mining a block'), - ('regtest_bob_bal6', "Bob's balance"), - ('regtest_alice_bal2', "Alice's balance"), + ('regtest_bob_alice_bal', "Bob and Alice's balances"), ('regtest_alice_add_label1', 'adding a label'), ('regtest_alice_chk_label1', 'the label'), ('regtest_alice_add_label2', 'adding a label'), @@ -743,13 +750,14 @@ if opt.list_cmds: NL = ('\r\n','\n')[g.platform=='linux' and bool(opt.popen_spawn)] -def get_file_with_ext(ext,mydir,delete=True,no_dot=False): +def get_file_with_ext(ext,mydir,delete=True,no_dot=False,return_list=False): dot = ('.','')[bool(no_dot)] flist = [os.path.join(mydir,f) for f in os.listdir(mydir) if f == ext or f[-len(dot+ext):] == dot+ext] if not flist: return False + if return_list: return flist if len(flist) > 1: if delete: @@ -1874,20 +1882,69 @@ class MMGenTestSuite(object): 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']) + t = MMGenExpect(name,'mmgen-regtest',['-n','setup']) os.environ['MMGEN_TEST_SUITE'] = '1' - t.expect('Starting setup') - - for user in ('alice','bob'): - t.expect('Setting up') - for i in range(4): t.expect('Creating') - for i in range(3): t.expect('Importing') - - for s in ('Funding','Mined','Sending','Sending','Mined','Setup complete'): + for s in 'Starting setup','Creating','Mined','Creating','Creating','Setup complete': t.expect(s) - t.ok() + def regtest_walletgen(self,name,user): + t = MMGenExpect(name,'mmgen-walletgen',['-q','-r0','-p1','--'+user]) + t.passphrase_new('new MMGen wallet','abc') + t.label() + t.expect('move it to the data directory? (Y/n): ','y') + t.written_to_file('MMGen wallet') + t.ok() + + def regtest_walletgen_bob(self,name): return self.regtest_walletgen(name,'bob') + def regtest_walletgen_alice(self,name): return self.regtest_walletgen(name,'alice') + + @staticmethod + def regtest_user_dir(user): + return os.path.join(data_dir,'regtest',user) + + def regtest_user_sid(self,user): + return os.path.basename(get_file_with_ext('mmdat',self.regtest_user_dir(user)))[:8] + + def regtest_addrgen(self,name,user): + for mmtype in ('legacy','compressed','segwit'): + t = MMGenExpect(name,'mmgen-addrgen', + ['--quiet','--'+user,'--type='+mmtype, + '--outdir={}'.format(self.regtest_user_dir(user)), + '1-5'],extra_desc='({})'.format(mmtype)) + t.passphrase('MMGen wallet','abc') + t.written_to_file('Addresses') + t.ok() + + def regtest_addrgen_bob(self,name): self.regtest_addrgen(name,'bob') + def regtest_addrgen_alice(self,name): self.regtest_addrgen(name,'alice') + + def regtest_addrimport(self,name,user): + id_strs = { 'legacy':'', 'compressed':'-C', 'segwit':'-S' } + sid = self.regtest_user_sid(user) + for desc in ('legacy','compressed','segwit'): + fn = os.path.join(self.regtest_user_dir(user),'{}{}[1-5].addrs'.format(sid,id_strs[desc])) + t = MMGenExpect(name,'mmgen-addrimport', ['--quiet','--'+user,'--batch',fn],extra_desc='('+desc+')') + t.expect('Importing') + t.expect('5 addresses imported') + t.ok() + + def regtest_addrimport_bob(self,name): self.regtest_addrimport(name,'bob') + def regtest_addrimport_alice(self,name): self.regtest_addrimport(name,'alice') + + def regtest_fund_wallet(self,name,user,mmtype,amt): + fn = get_file_with_ext('-{}[1-5].addrs'.format(mmtype),self.regtest_user_dir(user),no_dot=True) + silence() + addr = AddrList(fn).data[0].addr + end_silence() + t = MMGenExpect(name,'mmgen-regtest', ['send',str(addr),str(amt)]) + t.expect('Sending {} BTC'.format(amt)) + t.expect('Mined 1 block') + t.ok() + + def regtest_fund_bob(self,name): self.regtest_fund_wallet(name,'bob','C',500) + def regtest_fund_alice(self,name): self.regtest_fund_wallet(name,'alice','S',500) + def regtest_user_bal(self,name,user,bal): t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','showempty=1']) total = t.expect_getend('TOTAL: ') @@ -1896,9 +1953,6 @@ class MMGenTestSuite(object): 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','986.9995799') - def regtest_bob_bal1(self,name): return self.regtest_user_bal(name,'bob','500') @@ -1914,8 +1968,14 @@ class MMGenTestSuite(object): def regtest_bob_bal5(self,name): return self.regtest_user_bal(name,'bob','399.9996799') - def regtest_bob_bal6(self,name): - return self.regtest_user_bal(name,'bob','13') + def regtest_bob_alice_bal(self,name): + t = MMGenExpect(name,'mmgen-regtest',['get_balances']) + t.expect('Switching') + ret = t.expect_getend("Bob's balance:").strip() + cmp_or_die(ret,'13.00000000',skip_ok=True) + ret = t.expect_getend("Alice's balance:").strip() + cmp_or_die(ret,'986.99957990',skip_ok=True) + t.ok() def regtest_user_txdo(self,name,user,fee,outputs_cl,outputs_prompt,extra_args=[],no_send=False): os.environ['MMGEN_BOGUS_SEND'] = '' @@ -1931,6 +1991,7 @@ class MMGenTestSuite(object): t.expect('Add a comment to transaction? (y/N): ','\n') t.expect('View decoded transaction\? .*?: ','t',regex=True) t.expect('to continue: ','\n') + t.passphrase('MMGen wallet','abc') t.written_to_file('Signed transaction') if not no_send: t.expect('to confirm: ','YES, I REALLY WANT TO DO THIS\n') @@ -1939,24 +2000,28 @@ class MMGenTestSuite(object): t.ok() def regtest_bob_split1(self,name): - from mmgen.regtest import sids - outputs_cl = [sids['bob']+':C:1,100', sids['bob']+':L:2,200',sids['bob']+':S:2'] + sid = self.regtest_user_sid('bob') + outputs_cl = [sid+':C:1,100', sid+':L:2,200',sid+':S:2'] return self.regtest_user_txdo(name,'bob','20s',outputs_cl,'1') + def create_tx_outputs(self,user,data): + o,sid = [],self.regtest_user_sid(user) + for id_str,idx,amt_str in data: + fn = get_file_with_ext('{}{}[1-5].addrs'.format(sid,id_str),self.regtest_user_dir(user),no_dot=True) + silence() + addr = AddrList(fn).data[idx-1].addr + end_silence() + o.append(addr+amt_str) + return o + 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'] + outputs_cl = self.create_tx_outputs('alice',(('',1,',60'),('-C',1,',40'))) # alice_sid:L:1, alice_sid:C:1 + outputs_cl += [self.regtest_user_sid('bob')+':S:2'] return self.regtest_user_txdo(name,'bob','10s',outputs_cl,'3',extra_args=['--rbf']) def regtest_bob_send_non_mmgen(self,name): - from mmgen.regtest import sids + outputs_cl = self.create_tx_outputs('alice',(('-S',2,',10'),('-S',3,''))) # alice_sid:S:2, alice_sid:S:3 fn = os.path.join(cfg['tmpdir'],'non-mmgen.keys') - outputs_cl = [ - '2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD,10', # sids['alice']:S:2 - '2NF4y3y4CEjQCcssjX2BDLHT88XHn8z53JS'] # sids['alice']:S:3 return self.regtest_user_txdo(name,'bob','0.0001',outputs_cl,'3-9',extra_args=['--keys-from-file='+fn]) def regtest_user_txbump(self,name,user,txfile,fee,red_op,no_send=False): @@ -1967,6 +2032,7 @@ class MMGenTestSuite(object): 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.passphrase('MMGen wallet','abc') t.written_to_file('Signed transaction') if not no_send: t.expect('to confirm: ','YES, I REALLY WANT TO DO THIS\n') @@ -1986,8 +2052,7 @@ class MMGenTestSuite(object): def regtest_get_mempool(self,name): t = MMGenExpect(name,'mmgen-regtest',['show_mempool']) - ret = eval(t.read()) - return ret + return eval(t.read()) def regtest_get_mempool1(self,name): mp = self.regtest_get_mempool(name) @@ -2005,11 +2070,6 @@ class MMGenTestSuite(object): rdie(2,'TX in mempool has not changed! RBF bump failed') ok() - def regtest_user_import(self,name,user,args): - t = MMGenExpect(name,'mmgen-addrimport',['--quiet','--'+user]+args) - t.read() - t.ok() - @staticmethod def gen_pairs(n): return [subprocess.check_output( @@ -2022,6 +2082,12 @@ class MMGenTestSuite(object): write_to_tmpfile(cfg,'non-mmgen.addrs','\n'.join([a[1] for a in pairs])+'\n') return self.regtest_user_txdo(name,'bob','10s',[pairs[0][1]],'3') + def regtest_user_import(self,name,user,args): + t = MMGenExpect(name,'mmgen-addrimport',['--quiet','--'+user]+args) + t.expect('Importing') + t.expect('OK') + t.ok() + def regtest_bob_import_addr(self,name): addr = read_from_tmpfile(cfg,'non-mmgen.addrs').split()[0] return self.regtest_user_import(name,'bob',['--rescan','--address='+addr]) @@ -2034,8 +2100,8 @@ class MMGenTestSuite(object): addrs = read_from_tmpfile(cfg,'non-mmgen.addrs').split() amts = (a for a in (1.12345678,2.87654321,3.33443344,4.00990099,5.43214321)) outputs1 = ['{},{}'.format(a,amts.next()) for a in addrs] - from mmgen.regtest import sids - outputs2 = [sids['bob']+':C:2,6', sids['bob']+':L:3,7',sids['bob']+':S:3'] + sid = self.regtest_user_sid('bob') + outputs2 = [sid+':C:2,6', sid+':L:3,7',sid+':S:3'] return self.regtest_user_txdo(name,'bob','20s',outputs1+outputs2,'1-2') def regtest_user_add_label(self,name,user,addr,label): @@ -2049,13 +2115,16 @@ class MMGenTestSuite(object): t.ok() def regtest_alice_add_label1(self,name): - return self.regtest_user_add_label(name,'alice','9304C211:S:1','Original Label') + sid = self.regtest_user_sid('alice') + return self.regtest_user_add_label(name,'alice',sid+':S:1','Original Label') def regtest_alice_add_label2(self,name): - return self.regtest_user_add_label(name,'alice','9304C211:S:1','Replacement Label') + sid = self.regtest_user_sid('alice') + return self.regtest_user_add_label(name,'alice',sid+':S:1','Replacement Label') def regtest_alice_remove_label1(self,name): - return self.regtest_user_remove_label(name,'alice','9304C211:S:1') + sid = self.regtest_user_sid('alice') + return self.regtest_user_remove_label(name,'alice',sid+':S:1') def regtest_user_chk_label(self,name,user,addr,label): t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','all_labels=1']) @@ -2063,16 +2132,20 @@ class MMGenTestSuite(object): t.ok() def regtest_alice_chk_label1(self,name): - return self.regtest_user_chk_label(name,'alice','9304C211:S:1','Original Label') + sid = self.regtest_user_sid('alice') + return self.regtest_user_chk_label(name,'alice',sid+':S:1','Original Label') def regtest_alice_chk_label2(self,name): - return self.regtest_user_chk_label(name,'alice','9304C211:S:1','Replacement Label') + sid = self.regtest_user_sid('alice') + return self.regtest_user_chk_label(name,'alice',sid+':S:1','Replacement Label') def regtest_alice_chk_label3(self,name): - return self.regtest_user_chk_label(name,'alice','9304C211:S:1','Edited Label') + sid = self.regtest_user_sid('alice') + return self.regtest_user_chk_label(name,'alice',sid+':S:1','Edited Label') def regtest_alice_chk_label4(self,name): - return self.regtest_user_chk_label(name,'alice','9304C211:S:1','-') + sid = self.regtest_user_sid('alice') + return self.regtest_user_chk_label(name,'alice',sid+':S:1','-') def regtest_user_edit_label(self,name,user,output,label): t = MMGenExpect(name,'mmgen-txcreate',['-B','--'+user,'-i'])