mmgen-regtest: final implementation; additional test suite tests
This commit is contained in:
parent
49e1acfb74
commit
12ea12e4e2
7 changed files with 228 additions and 181 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
126
mmgen/regtest.py
126
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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
163
test/test.py
163
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'])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue