mmgen-regtest: final implementation; additional test suite tests

This commit is contained in:
The MMGen Project 2017-09-26 15:41:11 +03:00
commit 12ea12e4e2
Signed by: mmgen
GPG key ID: 62DBE9E5212F05BE
7 changed files with 228 additions and 181 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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()

View file

@ -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

View file

@ -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?

View file

@ -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"

View file

@ -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'])