|
@@ -17,86 +17,18 @@
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
"""
|
|
|
-test/test.py: Test suite for the MMGen suite
|
|
|
+test/test.py: Test suite for the MMGen wallet system
|
|
|
"""
|
|
|
|
|
|
-import sys,os,subprocess,shutil,time,re,json
|
|
|
-from decimal import Decimal
|
|
|
+def check_segwit_opts():
|
|
|
+ for k,m in (('segwit','S'),('segwit_random','S'),('bech32','B')):
|
|
|
+ if getattr(opt,k) and m not in g.proto.mmtypes:
|
|
|
+ die(1,'--{} option incompatible with {}'.format(k.replace('_','-'),g.proto.__name__))
|
|
|
|
|
|
-repo_root = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]),os.pardir)))
|
|
|
-os.chdir(repo_root)
|
|
|
-sys.path.__setitem__(0,repo_root)
|
|
|
-
|
|
|
-try: os.unlink(os.path.join(repo_root,'my.err'))
|
|
|
-except: pass
|
|
|
-
|
|
|
-# Import these _after_ local path's been added to sys.path
|
|
|
-from mmgen.common import *
|
|
|
-from mmgen.test import *
|
|
|
-from mmgen.protocol import CoinProtocol,init_coin
|
|
|
-
|
|
|
-def omsg(s): sys.stderr.write(s+'\n')
|
|
|
-def omsg_r(s): sys.stderr.write(s)
|
|
|
-
|
|
|
-class TestSuiteException(Exception): pass
|
|
|
-class TestSuiteFatalException(Exception): pass
|
|
|
-
|
|
|
-set_debug_all()
|
|
|
-
|
|
|
-g.quiet = False # if 'quiet' was set in config file, disable here
|
|
|
-os.environ['MMGEN_QUIET'] = '0' # and for the spawned scripts
|
|
|
-
|
|
|
-log_file = 'test.py_log'
|
|
|
-
|
|
|
-hincog_fn = 'rand_data'
|
|
|
-hincog_bytes = 1024*1024
|
|
|
-hincog_offset = 98765
|
|
|
-hincog_seedlen = 256
|
|
|
-
|
|
|
-incog_id_fn = 'incog_id'
|
|
|
-non_mmgen_fn = 'coinkey'
|
|
|
-pwfile = 'passwd_file'
|
|
|
-
|
|
|
-ref_dir = os.path.join('test','ref')
|
|
|
-
|
|
|
-rt_pw = 'abc-α'
|
|
|
-ref_wallet_brainpass = 'abc'
|
|
|
-ref_wallet_hash_preset = '1'
|
|
|
-ref_wallet_incog_offset = 123
|
|
|
-
|
|
|
-from mmgen.obj import MMGenTXLabel,PrivKey,ETHAmt
|
|
|
-from mmgen.addr import AddrGenerator,KeyGenerator,AddrList,AddrData,AddrIdxList
|
|
|
-
|
|
|
-ref_tx_label_jp = '必要なのは、信用ではなく暗号化された証明に基づく電子取引システムであり、これにより希望する二者が信用できる第三者機関を介さずに直接取引できるよう' # 72 chars ('W'ide)
|
|
|
-ref_tx_label_zh = '所以,我們非常需要這樣一種電子支付系統,它基於密碼學原理而不基於信用,使得任何達成一致的雙方,能夠直接進行支付,從而不需要協力廠商仲介的參與。。' # 72 chars ('F'ull + 'W'ide)
|
|
|
-ref_tx_label_lat_cyr_gr = ''.join(map(chr,
|
|
|
- list(range(65,91)) +
|
|
|
- list(range(1040,1072)) + # cyrillic
|
|
|
- list(range(913,939)) + # greek
|
|
|
- list(range(97,123))))[:MMGenTXLabel.max_len] # 72 chars
|
|
|
-ref_bw_hash_preset = '1'
|
|
|
-ref_bw_file = 'wallet.mmbrain'
|
|
|
-ref_bw_file_spc = 'wallet-spaced.mmbrain'
|
|
|
-
|
|
|
-ref_kafile_pass = 'kafile password'
|
|
|
-ref_kafile_hash_preset = '1'
|
|
|
-
|
|
|
-ref_enc_fn = 'sample-text.mmenc'
|
|
|
-tool_enc_passwd = "Scrypt it, don't hash it!"
|
|
|
-sample_text = \
|
|
|
- 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks\n'
|
|
|
-
|
|
|
-chksum_pat = r'\b[A-F0-9]{4} [A-F0-9]{4} [A-F0-9]{4} [A-F0-9]{4}\b'
|
|
|
-
|
|
|
-# Laggy flash media cause pexpect to crash, so create a temporary directory
|
|
|
-# under '/dev/shm' and put datadir and temp files here.
|
|
|
-shortopts = ''.join([e[1:] for e in sys.argv if len(e) > 1 and e[0] == '-' and e[1] != '-'])
|
|
|
-shortopts = ['-'+e for e in list(shortopts)]
|
|
|
-data_dir_basename = 'data_dir' + ('','-α')[bool(os.getenv('MMGEN_DEBUG_UTF8'))]
|
|
|
-data_dir = os.path.join('test',data_dir_basename)
|
|
|
-trash_dir = os.path.join('test','trash')
|
|
|
-
|
|
|
-if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts):
|
|
|
+def create_shm_dir(data_dir,trash_dir):
|
|
|
+ # Laggy flash media can cause pexpect to fail, so create a temporary directory
|
|
|
+ # under '/dev/shm' and put datadir and tmpdirs here.
|
|
|
+ import shutil
|
|
|
if g.platform == 'win':
|
|
|
for tdir in (data_dir,trash_dir):
|
|
|
try: os.listdir(tdir)
|
|
@@ -111,22 +43,45 @@ if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts
|
|
|
shutil.rmtree(tdir)
|
|
|
os.mkdir(tdir,0o755)
|
|
|
else:
|
|
|
- d,pfx = '/dev/shm','mmgen-test-'
|
|
|
+ tdir,pfx = '/dev/shm','mmgen-test-'
|
|
|
try:
|
|
|
- subprocess.call('rm -rf {}/{}*'.format(d,pfx),shell=True)
|
|
|
+ subprocess.call('rm -rf {}/{}*'.format(tdir,pfx),shell=True)
|
|
|
except Exception as e:
|
|
|
- die(2,'Unable to delete directory tree {}/{}* ({})'.format(d,pfx,e.args[0]))
|
|
|
+ die(2,'Unable to delete directory tree {}/{}* ({})'.format(tdir,pfx,e.args[0]))
|
|
|
try:
|
|
|
import tempfile
|
|
|
- shm_dir = str(tempfile.mkdtemp('',pfx,d))
|
|
|
+ shm_dir = str(tempfile.mkdtemp('',pfx,tdir))
|
|
|
except Exception as e:
|
|
|
- die(2,'Unable to create temporary directory in {} ({})'.format(d,e.args[0]))
|
|
|
- for tdir in (data_dir,trash_dir):
|
|
|
- dd = os.path.join(shm_dir,os.path.basename(tdir))
|
|
|
- os.mkdir(dd,0o755)
|
|
|
- try: os.unlink(tdir)
|
|
|
- except: pass
|
|
|
- os.symlink(dd,tdir)
|
|
|
+ die(2,'Unable to create temporary directory in {} ({})'.format(tdir,e.args[0]))
|
|
|
+
|
|
|
+ dest = os.path.join(shm_dir,os.path.basename(trash_dir))
|
|
|
+ os.mkdir(dest,0o755)
|
|
|
+ try: os.unlink(trash_dir)
|
|
|
+ except: pass
|
|
|
+ os.symlink(dest,trash_dir)
|
|
|
+
|
|
|
+ dest = os.path.join(shm_dir,os.path.basename(data_dir))
|
|
|
+ shutil.move(data_dir,dest) # data_dir was created by opts.init()
|
|
|
+ os.symlink(dest,data_dir)
|
|
|
+
|
|
|
+ return shm_dir
|
|
|
+
|
|
|
+import sys,os,time
|
|
|
+
|
|
|
+repo_root = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]),os.pardir)))
|
|
|
+os.chdir(repo_root)
|
|
|
+sys.path.__setitem__(0,repo_root)
|
|
|
+
|
|
|
+try: os.unlink(os.path.join(repo_root,'my.err'))
|
|
|
+except: pass
|
|
|
+
|
|
|
+# Import these _after_ local path's been added to sys.path
|
|
|
+from mmgen.common import *
|
|
|
+from test.common import *
|
|
|
+from test.test_py_d.common import *
|
|
|
+
|
|
|
+g.quiet = False # if 'quiet' was set in config file, disable here
|
|
|
+os.environ['MMGEN_QUIET'] = '0' # for this script and spawned scripts
|
|
|
|
|
|
opts_data = lambda: {
|
|
|
'desc': 'Test suite for the MMGen suite',
|
|
@@ -144,12 +99,13 @@ opts_data = lambda: {
|
|
|
-E, --direct-exec Bypass pexpect and execute a command directly (for
|
|
|
debugging only)
|
|
|
-e, --exact-output Show the exact output of the MMGen script(s) being run
|
|
|
+-G, --exclude-groups=G Exclude the specified command groups (comma-separated)
|
|
|
-l, --list-cmds List and describe the commands in the test suite
|
|
|
-L, --list-cmd-groups Output a list of command groups, with no descriptions
|
|
|
-n, --names Display command names instead of descriptions
|
|
|
-o, --log Log commands to file {lf}
|
|
|
--O, --popen-spawn Use pexpect's popen_spawn instead of popen (much faster,
|
|
|
- but doesn't emulate terminal)
|
|
|
+-O, --pexpect-spawn Use pexpect.spawn instead of popen_spawn (much slower,
|
|
|
+ kut does real terminal emulation)
|
|
|
-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
|
|
@@ -167,563 +123,204 @@ opts_data = lambda: {
|
|
|
""".format(tbc='scripts/traceback_run.py',lf=log_file),
|
|
|
'notes': """
|
|
|
|
|
|
-If no command is given, the whole suite of tests is run.
|
|
|
+If no command is given, the whole test suite is run.
|
|
|
"""
|
|
|
}
|
|
|
|
|
|
-sys.argv = [sys.argv[0]] + ['--data-dir',data_dir] + sys.argv[1:]
|
|
|
+data_dir = os.path.join('test','data_dir' + ('','-α')[bool(os.getenv('MMGEN_DEBUG_UTF8'))])
|
|
|
|
|
|
-cmd_args = opts.init(opts_data)
|
|
|
+# we need the values of two opts before running opts.init, so parse without initializing:
|
|
|
+uopts = opts.init(opts_data,parse_only=True)[0]
|
|
|
|
|
|
-if opt.popen_spawn: os.environ['MMGEN_TEST_SUITE_POPEN_SPAWN'] = '1'
|
|
|
-if not opt.system: os.environ['PYTHONPATH'] = repo_root
|
|
|
-
|
|
|
-lbl_id = ('account','label')[g.coin=='BTC'] # update as other coins adopt Core's label API
|
|
|
-ref_subdir = '' if g.proto.base_coin == 'BTC' else 'ethereum_classic' if g.coin == 'ETC' else g.proto.name
|
|
|
-altcoin_pfx = '' if g.proto.base_coin == 'BTC' else '-'+g.proto.base_coin
|
|
|
-tn_ext = ('','.testnet')[g.testnet]
|
|
|
+# step 1: delete data_dir symlink in ./test;
|
|
|
+if not ('resume' in uopts or 'skip_deps' in uopts):
|
|
|
+ try: os.unlink(data_dir)
|
|
|
+ except: pass
|
|
|
|
|
|
-coin_sel = g.coin.lower()
|
|
|
-if g.coin.lower() in ('eth','etc'): coin_sel = 'btc'
|
|
|
+sys.argv = [sys.argv[0]] + ['--data-dir='+data_dir] + sys.argv[1:]
|
|
|
|
|
|
-fork = {'bch':'btc','btc':'btc','ltc':'ltc'}[coin_sel]
|
|
|
-tx_fee = {'btc':'0.0001','bch':'0.001','ltc':'0.01'}[coin_sel]
|
|
|
-txbump_fee = {'btc':'123s','bch':'567s','ltc':'12345s'}[coin_sel]
|
|
|
+# step 2: opts.init will create new data_dir in ./test (if not 'resume' or 'skip_deps'):
|
|
|
+usr_args = opts.init(opts_data)
|
|
|
|
|
|
-rtFundAmt = {'btc':'500','bch':'500','ltc':'5500'}[coin_sel]
|
|
|
-rtFee = {
|
|
|
- 'btc': ('20s','10s','60s','31s','10s','20s'),
|
|
|
- 'bch': ('20s','10s','60s','0.0001','10s','20s'),
|
|
|
- 'ltc': ('1000s','500s','1500s','0.05','400s','1000s')
|
|
|
-}[coin_sel]
|
|
|
-rtBals = {
|
|
|
- 'btc': ('499.9999488','399.9998282','399.9998147','399.9996877',
|
|
|
- '52.99990000','946.99933647','999.99923647','52.9999',
|
|
|
- '946.99933647'),
|
|
|
- 'bch': ('499.9999484','399.9999194','399.9998972','399.9997692',
|
|
|
- '46.78900000','953.20966920','999.99866920','46.789',
|
|
|
- '953.2096692'),
|
|
|
- 'ltc': ('5499.99744','5399.994425','5399.993885','5399.987535',
|
|
|
- '52.99000000','10946.93753500','10999.92753500','52.99',
|
|
|
- '10946.937535'),
|
|
|
-}[coin_sel]
|
|
|
-rtBals_gb = {
|
|
|
- 'btc': ('116.77629233','283.22339537'),
|
|
|
- 'bch': ('116.77637483','283.22339437'),
|
|
|
- 'ltc': ('5116.77036263','283.21717237')
|
|
|
-}[coin_sel]
|
|
|
-rtBobOp3 = {'btc':'S:2','bch':'L:3','ltc':'S:2'}[coin_sel]
|
|
|
-rtAmts = {
|
|
|
- 'btc': ('500',),
|
|
|
- 'bch': ('500',),
|
|
|
- 'ltc': ('5500',)
|
|
|
-}[coin_sel]
|
|
|
+# step 3: move data_dir to /dev/shm and symlink it back to ./test:
|
|
|
+trash_dir = os.path.join('test','trash')
|
|
|
+if not ('resume' in uopts or 'skip_deps' in uopts):
|
|
|
+ shm_dir = create_shm_dir(data_dir,trash_dir)
|
|
|
|
|
|
-if opt.segwit and 'S' not in g.proto.mmtypes:
|
|
|
- die(1,'--segwit option incompatible with {}'.format(g.proto.__name__))
|
|
|
-if opt.bech32 and 'B' not in g.proto.mmtypes:
|
|
|
- die(1,'--bech32 option incompatible with {}'.format(g.proto.__name__))
|
|
|
+check_segwit_opts()
|
|
|
|
|
|
-def randbool():
|
|
|
- return hexlify(os.urandom(1))[1] in b'12345678'
|
|
|
-def get_segwit_bool():
|
|
|
- return randbool() if opt.segwit_random else True if opt.segwit or opt.bech32 else False
|
|
|
+if opt.profile: opt.names = True
|
|
|
+if opt.resume: opt.skip_deps = True
|
|
|
|
|
|
-def disable_debug():
|
|
|
- global save_debug
|
|
|
- save_debug = {}
|
|
|
- for k in g.env_opts:
|
|
|
- if k[:11] == 'MMGEN_DEBUG':
|
|
|
- save_debug[k] = os.getenv(k)
|
|
|
- os.environ[k] = ''
|
|
|
-def restore_debug():
|
|
|
- for k in save_debug:
|
|
|
- os.environ[k] = save_debug[k] or ''
|
|
|
+if opt.exact_output:
|
|
|
+ def msg(s): pass
|
|
|
+ qmsg = qmsg_r = vmsg = vmsg_r = msg_r = msg
|
|
|
|
|
|
-cfgs = {
|
|
|
- '15': {
|
|
|
- 'tmpdir': os.path.join('test','tmp15'),
|
|
|
- 'wpasswd': 'Dorian-α',
|
|
|
- 'kapasswd': 'Grok the blockchain',
|
|
|
- 'addr_idx_list': '12,99,5-10,5,12', # 8 addresses
|
|
|
- 'dep_generators': {
|
|
|
- pwfile: 'walletgen_dfl_wallet',
|
|
|
- 'addrs': 'addrgen_dfl_wallet',
|
|
|
- 'rawtx': 'txcreate_dfl_wallet',
|
|
|
- 'sigtx': 'txsign_dfl_wallet',
|
|
|
- 'mmseed': 'export_seed_dfl_wallet',
|
|
|
- 'del_dw_run': 'delete_dfl_wallet',
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+cfgs = { # addr_idx_lists (except 31,32,33,34) must contain exactly 8 addresses
|
|
|
+ '1': { 'wpasswd': 'Dorian-α',
|
|
|
+ 'kapasswd': 'Grok the blockchain',
|
|
|
+ 'addr_idx_list': '12,99,5-10,5,12',
|
|
|
+ 'dep_generators': {
|
|
|
+ pwfile: 'walletgen',
|
|
|
+ 'mmdat': 'walletgen',
|
|
|
+ 'addrs': 'addrgen',
|
|
|
+ 'rawtx': 'txcreate',
|
|
|
+ 'txbump': 'txbump',
|
|
|
+ 'sigtx': 'txsign',
|
|
|
+ 'mmwords': 'export_mnemonic',
|
|
|
+ 'mmseed': 'export_seed',
|
|
|
+ 'mmhex': 'export_hex',
|
|
|
+ 'mmincog': 'export_incog',
|
|
|
+ 'mmincox': 'export_incog_hex',
|
|
|
+ hincog_fn: 'export_incog_hidden',
|
|
|
+ incog_id_fn: 'export_incog_hidden',
|
|
|
+ 'akeys.mmenc': 'keyaddrgen'
|
|
|
+ },
|
|
|
},
|
|
|
- '16': {
|
|
|
- 'tmpdir': os.path.join('test','tmp16'),
|
|
|
- 'wpasswd': 'My changed password',
|
|
|
- 'hash_preset': '2',
|
|
|
- 'dep_generators': {
|
|
|
- pwfile: 'passchg_dfl_wallet',
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '2': { 'wpasswd': 'Hodling away',
|
|
|
+ 'addr_idx_list': '37,45,3-6,22-23',
|
|
|
+ 'seed_len': 128,
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'walletgen2',
|
|
|
+ 'addrs': 'addrgen2',
|
|
|
+ 'rawtx': 'txcreate2',
|
|
|
+ 'sigtx': 'txsign2',
|
|
|
+ 'mmwords': 'export_mnemonic2',
|
|
|
+ },
|
|
|
},
|
|
|
- '17': { 'tmpdir': os.path.join('test','tmp17') },
|
|
|
- '18': { 'tmpdir': os.path.join('test','tmp18') },
|
|
|
-# '19': { 'tmpdir': os.path.join(u'test',u'tmp19'), 'wpasswd':'abc' }, B2X
|
|
|
-
|
|
|
- '31': { 'tmpdir': os.path.join('test','tmp31'), # L
|
|
|
- 'addr_idx_list':'1-2', 'segwit': False,
|
|
|
- 'dep_generators': {'addrs':'ref_tx_addrgen1'} },
|
|
|
- '32': { 'tmpdir': os.path.join('test','tmp32'), # C
|
|
|
- 'addr_idx_list':'1-2', 'segwit': False,
|
|
|
- 'dep_generators': {'addrs':'ref_tx_addrgen2'} },
|
|
|
- '33': { 'tmpdir': os.path.join('test','tmp33'), # S
|
|
|
- 'addr_idx_list':'1-2', 'segwit': True,
|
|
|
- 'dep_generators': {'addrs':'ref_tx_addrgen3'} },
|
|
|
- '34': { 'tmpdir': os.path.join('test','tmp34'), # B
|
|
|
- 'addr_idx_list':'1-2', 'segwit': True,
|
|
|
- 'dep_generators': {'addrs':'ref_tx_addrgen4'} },
|
|
|
-
|
|
|
- '1': {
|
|
|
- 'tmpdir': os.path.join('test','tmp1'),
|
|
|
- 'wpasswd': 'Dorian-α',
|
|
|
- 'kapasswd': 'Grok the blockchain',
|
|
|
- 'addr_idx_list': '12,99,5-10,5,12', # 8 addresses
|
|
|
- 'dep_generators': {
|
|
|
- pwfile: 'walletgen',
|
|
|
- 'mmdat': 'walletgen',
|
|
|
- 'addrs': 'addrgen',
|
|
|
- 'rawtx': 'txcreate',
|
|
|
- 'txbump': 'txbump',
|
|
|
- 'sigtx': 'txsign',
|
|
|
- 'mmwords': 'export_mnemonic',
|
|
|
- 'mmseed': 'export_seed',
|
|
|
- 'mmhex': 'export_hex',
|
|
|
- 'mmincog': 'export_incog',
|
|
|
- 'mmincox': 'export_incog_hex',
|
|
|
- hincog_fn: 'export_incog_hidden',
|
|
|
- incog_id_fn: 'export_incog_hidden',
|
|
|
- 'akeys.mmenc': 'keyaddrgen'
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '3': { 'wpasswd': 'Major miner',
|
|
|
+ 'addr_idx_list': '73,54,1022-1023,2-5',
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'walletgen3',
|
|
|
+ 'addrs': 'addrgen3',
|
|
|
+ 'rawtx': 'txcreate3',
|
|
|
+ 'sigtx': 'txsign3'
|
|
|
+ },
|
|
|
},
|
|
|
- '2': {
|
|
|
- 'tmpdir': os.path.join('test','tmp2'),
|
|
|
- 'wpasswd': 'Hodling away',
|
|
|
- 'addr_idx_list': '37,45,3-6,22-23', # 8 addresses
|
|
|
- 'seed_len': 128,
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'walletgen2',
|
|
|
- 'addrs': 'addrgen2',
|
|
|
- 'rawtx': 'txcreate2',
|
|
|
- 'sigtx': 'txsign2',
|
|
|
- 'mmwords': 'export_mnemonic2',
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '4': { 'wpasswd': 'Hashrate good',
|
|
|
+ 'addr_idx_list': '63,1004,542-544,7-9',
|
|
|
+ 'seed_len': 192,
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'walletgen4',
|
|
|
+ 'mmbrain': 'walletgen4',
|
|
|
+ 'addrs': 'addrgen4',
|
|
|
+ 'rawtx': 'txcreate4',
|
|
|
+ 'sigtx': 'txsign4',
|
|
|
+ 'txdo': 'txdo4',
|
|
|
+ },
|
|
|
+ 'bw_filename': 'brainwallet.mmbrain',
|
|
|
+ 'bw_params': '192,1',
|
|
|
},
|
|
|
- '20': {
|
|
|
- 'tmpdir': os.path.join('test','tmp20'),
|
|
|
- 'wpasswd': 'Vsize it',
|
|
|
- 'addr_idx_list': '1-8', # 8 addresses
|
|
|
- 'seed_len': 256,
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'walletgen5',
|
|
|
- 'addrs': 'addrgen5',
|
|
|
- 'rawtx': 'txcreate5',
|
|
|
- 'sigtx': 'txsign5',
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '5': { 'wpasswd': 'My changed password-α',
|
|
|
+ 'hash_preset': '2',
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'passchg',
|
|
|
+ pwfile: 'passchg',
|
|
|
+ },
|
|
|
},
|
|
|
- '21': {
|
|
|
- 'tmpdir': os.path.join('test','tmp21'),
|
|
|
- 'wpasswd': 'Vsize it',
|
|
|
- 'addr_idx_list': '1-8', # 8 addresses
|
|
|
- 'seed_len': 256,
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'walletgen6',
|
|
|
- 'addrs': 'addrgen6',
|
|
|
- 'rawtx': 'txcreate6',
|
|
|
- 'sigtx': 'txsign6',
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '6': { 'seed_len': 128,
|
|
|
+ 'seed_id': 'FE3C6545',
|
|
|
+ 'ref_bw_seed_id': '33F10310',
|
|
|
+ 'wpasswd': 'reference password',
|
|
|
+ 'kapasswd': '',
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'refwalletgen_1',
|
|
|
+ pwfile: 'refwalletgen_1',
|
|
|
+ 'addrs': 'refaddrgen_1',
|
|
|
+ 'akeys.mmenc': 'refkeyaddrgen_1'
|
|
|
+ },
|
|
|
},
|
|
|
- '22': {
|
|
|
- 'tmpdir': os.path.join('test','tmp22'),
|
|
|
- 'parity_pidfile': 'parity.pid',
|
|
|
- 'parity_keyfile': 'parity.devkey',
|
|
|
- },
|
|
|
- '3': {
|
|
|
- 'tmpdir': os.path.join('test','tmp3'),
|
|
|
- 'wpasswd': 'Major miner',
|
|
|
- 'addr_idx_list': '73,54,1022-1023,2-5', # 8 addresses
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'walletgen3',
|
|
|
- 'addrs': 'addrgen3',
|
|
|
- 'rawtx': 'txcreate3',
|
|
|
- 'sigtx': 'txsign3'
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '7': { 'seed_len': 192,
|
|
|
+ 'seed_id': '1378FC64',
|
|
|
+ 'ref_bw_seed_id': 'CE918388',
|
|
|
+ 'wpasswd': 'reference password',
|
|
|
+ 'kapasswd': '',
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'refwalletgen_2',
|
|
|
+ pwfile: 'refwalletgen_2',
|
|
|
+ 'addrs': 'refaddrgen_2',
|
|
|
+ 'akeys.mmenc': 'refkeyaddrgen_2'
|
|
|
+ },
|
|
|
},
|
|
|
- '4': {
|
|
|
- 'tmpdir': os.path.join('test','tmp4'),
|
|
|
- 'wpasswd': 'Hashrate good',
|
|
|
- 'addr_idx_list': '63,1004,542-544,7-9', # 8 addresses
|
|
|
- 'seed_len': 192,
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'walletgen4',
|
|
|
- 'mmbrain': 'walletgen4',
|
|
|
- 'addrs': 'addrgen4',
|
|
|
- 'rawtx': 'txcreate4',
|
|
|
- 'sigtx': 'txsign4',
|
|
|
- 'txdo': 'txdo4',
|
|
|
- },
|
|
|
- 'bw_filename': 'brainwallet.mmbrain',
|
|
|
- 'bw_params': '192,1',
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '8': { 'seed_len': 256,
|
|
|
+ 'seed_id': '98831F3A',
|
|
|
+ 'ref_bw_seed_id': 'B48CD7FC',
|
|
|
+ 'wpasswd': 'reference password',
|
|
|
+ 'kapasswd': '',
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'refwalletgen_3',
|
|
|
+ pwfile: 'refwalletgen_3',
|
|
|
+ 'addrs': 'refaddrgen_3',
|
|
|
+ 'akeys.mmenc': 'refkeyaddrgen_3'
|
|
|
+ },
|
|
|
},
|
|
|
- '14': {
|
|
|
- 'kapasswd': 'Maxwell',
|
|
|
- 'tmpdir': os.path.join('test','tmp14'),
|
|
|
- 'wpasswd': 'The Halving',
|
|
|
- 'addr_idx_list': '61,998,502-504,7-9', # 8 addresses
|
|
|
- 'seed_len': 256,
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'walletgen14',
|
|
|
- 'addrs': 'addrgen14',
|
|
|
- 'akeys.mmenc': 'keyaddrgen14',
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '9': { 'tool_enc_infn': 'tool_encrypt.in',
|
|
|
+ 'dep_generators': {
|
|
|
+ 'tool_encrypt.in': 'tool_encrypt',
|
|
|
+ 'tool_encrypt.in.mmenc': 'tool_encrypt',
|
|
|
+ },
|
|
|
},
|
|
|
- '5': {
|
|
|
- 'tmpdir': os.path.join('test','tmp5'),
|
|
|
- 'wpasswd': 'My changed password-α',
|
|
|
- 'hash_preset': '2',
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'passchg',
|
|
|
- pwfile: 'passchg',
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '14': { 'kapasswd': 'Maxwell',
|
|
|
+ 'wpasswd': 'The Halving',
|
|
|
+ 'addr_idx_list': '61,998,502-504,7-9',
|
|
|
+ 'seed_len': 256,
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'walletgen14',
|
|
|
+ 'addrs': 'addrgen14',
|
|
|
+ 'akeys.mmenc': 'keyaddrgen14',
|
|
|
+ },
|
|
|
},
|
|
|
- '6': {
|
|
|
- 'name': 'reference wallet check (128-bit)',
|
|
|
- 'seed_len': 128,
|
|
|
- 'seed_id': 'FE3C6545',
|
|
|
- 'ref_bw_seed_id': '33F10310',
|
|
|
- 'addrfile_chk': {
|
|
|
- 'btc': ('B230 7526 638F 38CB','A9DC 5A13 12CB 1317'),
|
|
|
- 'ltc': ('2B23 5E97 848A B961','AEC3 E774 0B21 0202'),
|
|
|
- },
|
|
|
- 'addrfile_segwit_chk': {
|
|
|
- 'btc': ('9914 6D10 2307 F348','83C8 A6B6 ADA8 25B2'),
|
|
|
- 'ltc': ('CC09 A190 B7DF B7CD','0425 7893 C6F1 ECA3'),
|
|
|
- },
|
|
|
- 'addrfile_bech32_chk': {
|
|
|
- 'btc': ('C529 D686 31AA ACD4','21D0 26AD 3A22 5465'),
|
|
|
- 'ltc': ('3DFB CFCC E180 DC9D','8C72 D5C2 07E0 5F7B'),
|
|
|
- },
|
|
|
- 'addrfile_compressed_chk': {
|
|
|
- 'btc': ('95EB 8CC0 7B3B 7856','16E6 6170 154D 2202'),
|
|
|
- 'ltc': ('35D5 8ECA 9A42 46C3','15B3 5492 D3D3 6854'),
|
|
|
- },
|
|
|
- 'keyaddrfile_chk': {
|
|
|
- 'btc': ('CF83 32FB 8A8B 08E2','1F67 B73A FF8C 5D15'),
|
|
|
- 'ltc': ('1896 A26C 7F14 2D01','FA0E CD4E ADAF DBF4'),
|
|
|
- },
|
|
|
- 'keyaddrfile_segwit_chk': {
|
|
|
- 'btc': ('C13B F717 D4E8 CF59','BB71 175C 5416 19D8'),
|
|
|
- 'ltc': ('054B 9794 55B4 5D82','DE85 3CF3 9636 FE2E'),
|
|
|
- },
|
|
|
- 'keyaddrfile_bech32_chk': {
|
|
|
- 'btc': ('934F 1C33 6C06 B18C','A283 5BAB 7AF3 3EA4'),
|
|
|
- 'ltc': ('A6AD DF53 5968 7B6A','9572 43E0 A4DC 0B2E'),
|
|
|
- },
|
|
|
- 'keyaddrfile_compressed_chk': {
|
|
|
- 'btc': ('E43A FA46 5751 720A','FDEE 8E45 1C0A 02AD'),
|
|
|
- 'ltc': ('7603 2FE3 2145 FFAD','3FE0 5A8E 5FBE FF3E'),
|
|
|
- },
|
|
|
- 'passfile_chk': 'EB29 DC4F 924B 289F',
|
|
|
- 'passfile32_chk': '37B6 C218 2ABC 7508',
|
|
|
- 'passfilehex_chk': '523A F547 0E69 8323',
|
|
|
- 'wpasswd': 'reference password',
|
|
|
- 'ref_wallet': 'FE3C6545-D782B529[128,1].mmdat',
|
|
|
- 'ic_wallet': 'FE3C6545-E29303EA-5E229E30[128,1].mmincog',
|
|
|
- 'ic_wallet_hex': 'FE3C6545-BC4BE3F2-32586837[128,1].mmincox',
|
|
|
-
|
|
|
- 'hic_wallet': 'FE3C6545-161E495F-BEB7548E[128,1].incog-offset123',
|
|
|
- 'hic_wallet_old': 'FE3C6545-161E495F-9860A85B[128,1].incog-old.offset123',
|
|
|
-
|
|
|
- 'tmpdir': os.path.join('test','tmp6'),
|
|
|
- 'kapasswd': '',
|
|
|
- 'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
|
|
|
- 'pass_idx_list': '1,4,9-11,1100',
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'refwalletgen1',
|
|
|
- pwfile: 'refwalletgen1',
|
|
|
- 'addrs': 'refaddrgen1',
|
|
|
- 'akeys.mmenc': 'refkeyaddrgen1'
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '15': { 'wpasswd': 'Dorian-α',
|
|
|
+ 'kapasswd': 'Grok the blockchain',
|
|
|
+ 'addr_idx_list': '12,99,5-10,5,12',
|
|
|
+ 'dep_generators': {
|
|
|
+ pwfile: 'walletgen_dfl_wallet',
|
|
|
+ 'addrs': 'addrgen_dfl_wallet',
|
|
|
+ 'rawtx': 'txcreate_dfl_wallet',
|
|
|
+ 'sigtx': 'txsign_dfl_wallet',
|
|
|
+ 'mmseed': 'export_seed_dfl_wallet',
|
|
|
+ 'del_dw_run': 'delete_dfl_wallet',
|
|
|
+ },
|
|
|
},
|
|
|
- '7': {
|
|
|
- 'name': 'reference wallet check (192-bit)',
|
|
|
- 'seed_len': 192,
|
|
|
- 'seed_id': '1378FC64',
|
|
|
- 'ref_bw_seed_id': 'CE918388',
|
|
|
- 'addrfile_chk': {
|
|
|
- 'btc': ('8C17 A5FA 0470 6E89','764C 66F9 7502 AAEA'),
|
|
|
- 'ltc': ('2B77 A009 D5D0 22AD','51D1 979D 0A35 F24B'),
|
|
|
- },
|
|
|
- 'addrfile_segwit_chk': {
|
|
|
- 'btc': ('91C4 0414 89E4 2089','BF9F C67F ED22 A47B'),
|
|
|
- 'ltc': ('8F12 FA7B 9F12 594C','2609 8494 A23C F836'),
|
|
|
- },
|
|
|
- 'addrfile_bech32_chk': {
|
|
|
- 'btc': ('2AA3 78DF B965 82EB','027B 1C1F 7FB2 D859'),
|
|
|
- 'ltc': ('951C 8FB2 FCA5 87D1','4A5D 67E0 8210 FEF2'),
|
|
|
- },
|
|
|
- 'addrfile_compressed_chk': {
|
|
|
- 'btc': ('2615 8401 2E98 7ECA','A386 EE07 A356 906D'),
|
|
|
- 'ltc': ('197C C48C 3C37 AB0F','8DDC 5FE3 BFF9 1226'),
|
|
|
- },
|
|
|
- 'keyaddrfile_chk': {
|
|
|
- 'btc': ('9648 5132 B98E 3AD9','1BD3 5A36 D51C 256D'),
|
|
|
- 'ltc': ('DBD4 FAB6 7E46 CD07','8822 3FDF FEC0 6A8C'),
|
|
|
- },
|
|
|
- 'keyaddrfile_segwit_chk': {
|
|
|
- 'btc': ('C98B DF08 A3D5 204B','7E7F DF50 FE04 6F68'),
|
|
|
- 'ltc': ('1829 7FE7 2567 CB91','BE92 D19C 7589 EF30'),
|
|
|
- },
|
|
|
- 'keyaddrfile_bech32_chk': {
|
|
|
- 'btc': ('4A6B 3762 DF30 9368','12DD 1888 36BA 85F7'),
|
|
|
- 'ltc': ('5C12 FDD4 17AB F179','E195 B28C 59C4 C5EC'),
|
|
|
- },
|
|
|
- 'keyaddrfile_compressed_chk': {
|
|
|
- 'btc': ('6D6D 3D35 04FD B9C3','94BF 4BCF 10B2 394B'),
|
|
|
- 'ltc': ('F5DA 9D60 6798 C4E9','7918 88DE 9096 DD7A'),
|
|
|
- },
|
|
|
- 'passfile_chk': 'ADEA 0083 094D 489A',
|
|
|
- 'passfile32_chk': '2A28 C5C7 36EC 217A',
|
|
|
- 'passfilehex_chk': 'B11C AC6A 1464 608D',
|
|
|
- 'wpasswd': 'reference password',
|
|
|
- 'ref_wallet': '1378FC64-6F0F9BB4[192,1].mmdat',
|
|
|
- 'ic_wallet': '1378FC64-2907DE97-F980D21F[192,1].mmincog',
|
|
|
- 'ic_wallet_hex': '1378FC64-4DCB5174-872806A7[192,1].mmincox',
|
|
|
-
|
|
|
- 'hic_wallet': '1378FC64-B55E9958-77256FC1[192,1].incog.offset123',
|
|
|
- 'hic_wallet_old': '1378FC64-B55E9958-D85FF20C[192,1].incog-old.offset123',
|
|
|
-
|
|
|
- 'tmpdir': os.path.join('test','tmp7'),
|
|
|
- 'kapasswd': '',
|
|
|
- 'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
|
|
|
- 'pass_idx_list': '1,4,9-11,1100',
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'refwalletgen2',
|
|
|
- pwfile: 'refwalletgen2',
|
|
|
- 'addrs': 'refaddrgen2',
|
|
|
- 'akeys.mmenc': 'refkeyaddrgen2'
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
+ '16': { 'wpasswd': 'My changed password',
|
|
|
+ 'hash_preset': '2',
|
|
|
+ 'dep_generators': {
|
|
|
+ pwfile: 'passchg_dfl_wallet',
|
|
|
+ },
|
|
|
},
|
|
|
- '8': {
|
|
|
- 'name': 'reference wallet check (256-bit)',
|
|
|
- 'seed_len': 256,
|
|
|
- 'seed_id': '98831F3A',
|
|
|
- 'ref_bw_seed_id': 'B48CD7FC',
|
|
|
- 'addrfile_chk': {
|
|
|
- 'btc': ('6FEF 6FB9 7B13 5D91','424E 4326 CFFE 5F51'),
|
|
|
- 'ltc': ('AD52 C3FE 8924 AAF0','4EBE 2E85 E969 1B30'),
|
|
|
- },
|
|
|
- 'addrfile_segwit_chk': {
|
|
|
- 'btc': ('06C1 9C87 F25C 4EE6','072C 8B07 2730 CB7A'),
|
|
|
- 'ltc': ('63DF E42A 0827 21C3','5DD1 D186 DBE1 59F2'),
|
|
|
- },
|
|
|
- 'addrfile_bech32_chk': {
|
|
|
- 'btc': ('9D2A D4B6 5117 F02E','0527 9C39 6C1B E39A'),
|
|
|
- 'ltc': ('FF1C 7939 5967 AB82','ED3D 8AA4 BED4 0B40'),
|
|
|
- },
|
|
|
- 'addrfile_compressed_chk': {
|
|
|
- 'btc': ('A33C 4FDE F515 F5BC','6C48 AA57 2056 C8C8'),
|
|
|
- 'ltc': ('3FC0 8F03 C2D6 BD19','4C0A 49B6 2DD1 1BE0'),
|
|
|
- },
|
|
|
- 'keyaddrfile_chk': {
|
|
|
- 'btc': ('9F2D D781 1812 8BAD','88CC 5120 9A91 22C2'),
|
|
|
- 'ltc': ('B804 978A 8796 3ED4','98B5 AC35 F334 0398'),
|
|
|
- },
|
|
|
- 'keyaddrfile_segwit_chk': {
|
|
|
- 'btc': ('A447 12C2 DD14 5A9B','C770 7391 C415 21F9'),
|
|
|
- 'ltc': ('E8A3 9F6E E164 A521','D3D5 BFDD F5D5 20BD'),
|
|
|
- },
|
|
|
- 'keyaddrfile_bech32_chk': {
|
|
|
- 'btc': ('D0DD BDE3 87BE 15AE','7552 D70C AAB8 DEAA'),
|
|
|
- 'ltc': ('74A0 7DD5 963B 6326','2CDA A007 4B9F E9A5'),
|
|
|
- },
|
|
|
- 'keyaddrfile_compressed_chk': {
|
|
|
- 'btc': ('420A 8EB5 A9E2 7814','F43A CB4A 81F3 F735'),
|
|
|
- 'ltc': ('8D1C 781F EB7F 44BC','05F3 5C68 FD31 FCEF'),
|
|
|
+ '17': {},
|
|
|
+ '18': {},
|
|
|
+ '19': { 'wpasswd':'abc' }, # B2X
|
|
|
+ '20': { 'wpasswd': 'Vsize it',
|
|
|
+ 'addr_idx_list': '1-8',
|
|
|
+ 'seed_len': 256,
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'walletgen5',
|
|
|
+ 'addrs': 'addrgen5',
|
|
|
+ 'rawtx': 'txcreate5',
|
|
|
+ 'sigtx': 'txsign5',
|
|
|
},
|
|
|
- 'passfile_chk': '2D6D 8FBA 422E 1315',
|
|
|
- 'passfile32_chk': 'F6C1 CDFB 97D9 FCAE',
|
|
|
- 'passfilehex_chk': 'BD4F A0AC 8628 4BE4',
|
|
|
- 'wpasswd': 'reference password',
|
|
|
- 'ref_wallet': '98831F3A-{}[256,1].mmdat'.format(('27F2BF93','E2687906')[g.testnet]),
|
|
|
- 'ref_addrfile': '98831F3A{}[1,31-33,500-501,1010-1011]{}.addrs',
|
|
|
- 'ref_segwitaddrfile':'98831F3A{}-S[1,31-33,500-501,1010-1011]{}.addrs',
|
|
|
- 'ref_bech32addrfile':'98831F3A{}-B[1,31-33,500-501,1010-1011]{}.addrs',
|
|
|
- 'ref_keyaddrfile': '98831F3A{}[1,31-33,500-501,1010-1011]{}.akeys.mmenc',
|
|
|
- 'ref_passwdfile': '98831F3A-фубар@crypto.org-b58-20[1,4,9-11,1100].pws',
|
|
|
- 'ref_addrfile_chksum': {
|
|
|
- 'btc': ('6FEF 6FB9 7B13 5D91','424E 4326 CFFE 5F51'),
|
|
|
- 'ltc': ('AD52 C3FE 8924 AAF0','4EBE 2E85 E969 1B30'),
|
|
|
- },
|
|
|
- 'ref_segwitaddrfile_chksum': {
|
|
|
- 'btc': ('06C1 9C87 F25C 4EE6','072C 8B07 2730 CB7A'),
|
|
|
- 'ltc': ('63DF E42A 0827 21C3','5DD1 D186 DBE1 59F2'),
|
|
|
- },
|
|
|
- 'ref_bech32addrfile_chksum': {
|
|
|
- 'btc': ('9D2A D4B6 5117 F02E','0527 9C39 6C1B E39A'),
|
|
|
- 'ltc': ('FF1C 7939 5967 AB82','ED3D 8AA4 BED4 0B40'),
|
|
|
- },
|
|
|
- 'ref_keyaddrfile_chksum': {
|
|
|
- 'btc': ('9F2D D781 1812 8BAD','88CC 5120 9A91 22C2'),
|
|
|
- 'ltc': ('B804 978A 8796 3ED4','98B5 AC35 F334 0398'),
|
|
|
- },
|
|
|
- 'ref_addrfile_chksum_zec': '903E 7225 DD86 6E01',
|
|
|
- 'ref_addrfile_chksum_zec_z': '9C7A 72DC 3D4A B3AF',
|
|
|
- 'ref_addrfile_chksum_xmr': '4369 0253 AC2C 0E38',
|
|
|
- 'ref_addrfile_chksum_dash':'FBC1 6B6A 0988 4403',
|
|
|
- 'ref_addrfile_chksum_eth': 'E554 076E 7AF6 66A3',
|
|
|
- 'ref_addrfile_chksum_etc': 'E97A D796 B495 E8BC',
|
|
|
- 'ref_keyaddrfile_chksum_zec': 'F05A 5A5C 0C8E 2617',
|
|
|
- 'ref_keyaddrfile_chksum_zec_z': '6B87 9B2D 0D8D 8D1E',
|
|
|
- 'ref_keyaddrfile_chksum_xmr': 'E0D7 9612 3D67 404A',
|
|
|
- 'ref_keyaddrfile_chksum_dash': 'E83D 2C63 FEA2 4142',
|
|
|
- 'ref_keyaddrfile_chksum_eth': 'E400 70D9 0AE3 C7C2',
|
|
|
- 'ref_keyaddrfile_chksum_etc': 'EF49 967D BD6C FE45',
|
|
|
- 'ref_passwdfile_chksum': 'A983 DAB9 5514 27FB',
|
|
|
- 'ref_tx_file': {
|
|
|
- 'btc': ('0B8D5A[15.31789,14,tl=1320969600].rawtx',
|
|
|
- '0C7115[15.86255,14,tl=1320969600].testnet.rawtx'),
|
|
|
- 'bch': ('460D4D-BCH[10.19764,tl=1320969600].rawtx',
|
|
|
- '359FD5-BCH[6.68868,tl=1320969600].testnet.rawtx'),
|
|
|
- 'ltc': ('AF3CDF-LTC[620.76194,1453,tl=1320969600].rawtx',
|
|
|
- 'A5A1E0-LTC[1454.64322,1453,tl=1320969600].testnet.rawtx'),
|
|
|
- 'eth': ('88FEFD-ETH[23.45495,40000].rawtx',
|
|
|
- 'B472BD-ETH[23.45495,40000].testnet.rawtx'),
|
|
|
- 'erc20': ('5881D2-MM1[1.23456,50000].rawtx',
|
|
|
- '6BDB25-MM1[1.23456,50000].testnet.rawtx'),
|
|
|
- 'etc': ('ED3848-ETC[1.2345,40000].rawtx','')
|
|
|
- },
|
|
|
- 'ic_wallet': '98831F3A-5482381C-18460FB1[256,1].mmincog',
|
|
|
- 'ic_wallet_hex': '98831F3A-1630A9F2-870376A9[256,1].mmincox',
|
|
|
-
|
|
|
- 'hic_wallet': '98831F3A-F59B07A0-559CEF19[256,1].incog.offset123',
|
|
|
- 'hic_wallet_old': '98831F3A-F59B07A0-848535F3[256,1].incog-old.offset123',
|
|
|
-
|
|
|
- 'tmpdir': os.path.join('test','tmp8'),
|
|
|
- 'kapasswd': '',
|
|
|
- 'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
|
|
|
- 'pass_idx_list': '1,4,9-11,1100',
|
|
|
-
|
|
|
- 'dep_generators': {
|
|
|
- 'mmdat': 'refwalletgen3',
|
|
|
- pwfile: 'refwalletgen3',
|
|
|
- 'addrs': 'refaddrgen3',
|
|
|
- 'akeys.mmenc': 'refkeyaddrgen3'
|
|
|
- },
|
|
|
- 'segwit': get_segwit_bool()
|
|
|
},
|
|
|
- '9': {
|
|
|
- 'tmpdir': os.path.join('test','tmp9'),
|
|
|
- 'tool_enc_infn': 'tool_encrypt.in',
|
|
|
-# 'tool_enc_ref_infn': 'tool_encrypt_ref.in',
|
|
|
- 'wpasswd': 'reference password',
|
|
|
- 'dep_generators': {
|
|
|
- 'tool_encrypt.in': 'tool_encrypt',
|
|
|
- 'tool_encrypt.in.mmenc': 'tool_encrypt',
|
|
|
-# 'tool_encrypt_ref.in': 'tool_encrypt_ref',
|
|
|
-# 'tool_encrypt_ref.in.mmenc': 'tool_encrypt_ref',
|
|
|
+ '21': { 'wpasswd': 'Vsize it',
|
|
|
+ 'addr_idx_list': '1-8',
|
|
|
+ 'seed_len': 256,
|
|
|
+ 'dep_generators': {
|
|
|
+ 'mmdat': 'walletgen6',
|
|
|
+ 'addrs': 'addrgen6',
|
|
|
+ 'rawtx': 'txcreate6',
|
|
|
+ 'sigtx': 'txsign6',
|
|
|
},
|
|
|
},
|
|
|
+ '22': {},
|
|
|
+ '31': {},
|
|
|
+ '32': {},
|
|
|
+ '33': {},
|
|
|
+ '34': {},
|
|
|
}
|
|
|
|
|
|
-dfl_words = os.path.join(ref_dir,cfgs['8']['seed_id']+'.mmwords')
|
|
|
-
|
|
|
-eth_rem_addrs = ('4','1')
|
|
|
-if g.coin in ('ETH','ETC'):
|
|
|
- # The Parity dev address with lots of coins. Create with "ethkey -b info ''":
|
|
|
- eth_addr = '00a329c0648769a73afac7f9381e08fb43dbea72'
|
|
|
- eth_addr_chk = '00a329c0648769A73afAc7F9381E08FB43dBEA72'
|
|
|
- eth_key = '4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7'
|
|
|
- eth_burn_addr = 'deadbeef'*5
|
|
|
- eth_amt1 = '999999.12345689012345678'
|
|
|
- eth_amt2 = '888.111122223333444455'
|
|
|
-
|
|
|
- # Token sends require varying amounts of gas, depending on compiler version
|
|
|
- solc_ver = re.search(r'Version:\s*(.*)',
|
|
|
- subprocess.Popen(['solc','--version'],stdout=subprocess.PIPE
|
|
|
- ).stdout.read().decode()).group(1)
|
|
|
-
|
|
|
- if re.match(r'\b0.5.1\b',solc_ver): # Raspbian Stretch
|
|
|
- vbal1 = '1.2288337'
|
|
|
- vbal2 = '99.997085083'
|
|
|
- vbal3 = '1.23142165'
|
|
|
- vbal4 = '127.0287837'
|
|
|
- elif re.match(r'\b0.5.3\b',solc_ver): # Ubuntu Bionic
|
|
|
- vbal1 = '1.2288487'
|
|
|
- vbal2 = '99.997092733'
|
|
|
- vbal3 = '1.23142915'
|
|
|
- vbal4 = '127.0287987'
|
|
|
-
|
|
|
- eth_bals = {
|
|
|
- '1': [ ('98831F3A:E:1','123.456')],
|
|
|
- '2': [ ('98831F3A:E:1','123.456'),('98831F3A:E:11','1.234')],
|
|
|
- '3': [ ('98831F3A:E:1','123.456'),('98831F3A:E:11','1.234'),('98831F3A:E:21','2.345')],
|
|
|
- '4': [ ('98831F3A:E:1','100'),
|
|
|
- ('98831F3A:E:2','23.45495'),
|
|
|
- ('98831F3A:E:11','1.234'),
|
|
|
- ('98831F3A:E:21','2.345')],
|
|
|
- '5': [ ('98831F3A:E:1','100'),
|
|
|
- ('98831F3A:E:2','23.45495'),
|
|
|
- ('98831F3A:E:11','1.234'),
|
|
|
- ('98831F3A:E:21','2.345'),
|
|
|
- (eth_burn_addr + '\s+Non-MMGen',eth_amt1)],
|
|
|
- '8': [ ('98831F3A:E:1','0'),
|
|
|
- ('98831F3A:E:2','23.45495'),
|
|
|
- ('98831F3A:E:11',vbal1,'a'),
|
|
|
- ('98831F3A:E:12','99.99895'),
|
|
|
- ('98831F3A:E:21','2.345'),
|
|
|
- (eth_burn_addr + '\s+Non-MMGen',eth_amt1)],
|
|
|
- '9': [ ('98831F3A:E:1','0'),
|
|
|
- ('98831F3A:E:2','23.45495'),
|
|
|
- ('98831F3A:E:11',vbal1,'a'),
|
|
|
- ('98831F3A:E:12',vbal2),
|
|
|
- ('98831F3A:E:21','2.345'),
|
|
|
- (eth_burn_addr + '\s+Non-MMGen',eth_amt1)]
|
|
|
- }
|
|
|
- eth_token_bals = {
|
|
|
- '1': [ ('98831F3A:E:11','1000','1.234')],
|
|
|
- '2': [ ('98831F3A:E:11','998.76544',vbal3,'a'),
|
|
|
- ('98831F3A:E:12','1.23456','0')],
|
|
|
- '3': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
|
|
|
- ('98831F3A:E:12','1.23456','0')],
|
|
|
- '4': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
|
|
|
- ('98831F3A:E:12','1.23456','0'),
|
|
|
- (eth_burn_addr + '\s+Non-MMGen',eth_amt2,eth_amt1)],
|
|
|
- '5': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
|
|
|
- ('98831F3A:E:12','1.23456','99.99895'),
|
|
|
- (eth_burn_addr + '\s+Non-MMGen',eth_amt2,eth_amt1)],
|
|
|
- '6': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
|
|
|
- ('98831F3A:E:12','0',vbal2),
|
|
|
- ('98831F3A:E:13','1.23456','0'),
|
|
|
- (eth_burn_addr + '\s+Non-MMGen',eth_amt2,eth_amt1)]
|
|
|
- }
|
|
|
- eth_token_bals_getbalance = {
|
|
|
- '1': (vbal4,'999999.12345689012345678'),
|
|
|
- '2': ('111.888877776666555545','888.111122223333444455')
|
|
|
- }
|
|
|
-
|
|
|
- def eth_args():
|
|
|
- if g.coin not in ('ETH','ETC'):
|
|
|
- raise TestSuiteException('for ethdev tests, --coin must be set to either ETH or ETC')
|
|
|
- return ['--outdir={}'.format(cfgs['22']['tmpdir']),'--rpc-port=8549','--quiet']
|
|
|
+for k in cfgs:
|
|
|
+ cfgs[k]['tmpdir'] = os.path.join('test','tmp{}'.format(k))
|
|
|
+ cfgs[k]['segwit'] = randbool() if opt.segwit_random else bool(opt.segwit or opt.bech32)
|
|
|
|
|
|
from copy import deepcopy
|
|
|
for a,b in (('6','11'),('7','12'),('8','13')):
|
|
@@ -733,3433 +330,552 @@ for a,b in (('6','11'),('7','12'),('8','13')):
|
|
|
if g.debug_utf8:
|
|
|
for k in cfgs: cfgs[k]['tmpdir'] += '-α'
|
|
|
|
|
|
-from collections import OrderedDict
|
|
|
-
|
|
|
-cmd_group = OrderedDict()
|
|
|
-
|
|
|
-cmd_group['help'] = OrderedDict([
|
|
|
-# test description depends
|
|
|
- ['helpscreens', (1,'help screens', [])],
|
|
|
- ['longhelpscreens', (1,'help screens (--longhelp)',[])],
|
|
|
-])
|
|
|
-
|
|
|
-cmd_group['dfl_wallet'] = OrderedDict([
|
|
|
- ['walletgen_dfl_wallet', (15,'wallet generation (default wallet)',[[[],15]])],
|
|
|
- ['export_seed_dfl_wallet',(15,'seed export to mmseed format (default wallet)',[[[pwfile],15]])],
|
|
|
- ['addrgen_dfl_wallet',(15,'address generation (default wallet)',[[[pwfile],15]])],
|
|
|
- ['txcreate_dfl_wallet',(15,'transaction creation (default wallet)',[[['addrs'],15]])],
|
|
|
- ['txsign_dfl_wallet',(15,'transaction signing (default wallet)',[[['rawtx',pwfile],15]])],
|
|
|
- ['passchg_dfl_wallet',(16,'password, label and hash preset change (default wallet)',[[[pwfile],15]])],
|
|
|
- ['walletchk_newpass_dfl_wallet',(16,'wallet check with new pw, label and hash preset',[[[pwfile],16]])],
|
|
|
- ['delete_dfl_wallet',(15,'delete default wallet',[[[pwfile],15]])],
|
|
|
-])
|
|
|
-
|
|
|
-cmd_group['main'] = OrderedDict([
|
|
|
- ['walletgen', (1,'wallet generation', [[['del_dw_run'],15]])],
|
|
|
-# ['walletchk', (1,'wallet check', [[['mmdat'],1]])],
|
|
|
- ['passchg', (5,'password, label and hash preset change',[[['mmdat',pwfile],1]])],
|
|
|
- ['passchg_keeplabel',(5,'password, label and hash preset change (keep label)',[[['mmdat',pwfile],1]])],
|
|
|
- ['passchg_usrlabel',(5,'password, label and hash preset change (interactive label)',[[['mmdat',pwfile],1]])],
|
|
|
- ['walletchk_newpass',(5,'wallet check with new pw, label and hash preset',[[['mmdat',pwfile],5]])],
|
|
|
- ['addrgen', (1,'address generation', [[['mmdat',pwfile],1]])],
|
|
|
- ['txcreate', (1,'transaction creation', [[['addrs'],1]])],
|
|
|
- ['txbump', (1,'transaction fee bumping (no send)',[[['rawtx'],1]])],
|
|
|
- ['txsign', (1,'transaction signing', [[['mmdat','rawtx',pwfile,'txbump'],1]])],
|
|
|
- ['txsend', (1,'transaction sending', [[['sigtx'],1]])],
|
|
|
- # txdo must go after txsign
|
|
|
- ['txdo', (1,'online transaction', [[['sigtx','mmdat'],1]])],
|
|
|
-
|
|
|
- ['export_hex', (1,'seed export to hexadecimal format', [[['mmdat'],1]])],
|
|
|
- ['export_seed', (1,'seed export to mmseed format', [[['mmdat'],1]])],
|
|
|
- ['export_mnemonic', (1,'seed export to mmwords format', [[['mmdat'],1]])],
|
|
|
- ['export_incog', (1,'seed export to mmincog format', [[['mmdat'],1]])],
|
|
|
- ['export_incog_hex',(1,'seed export to mmincog hex format', [[['mmdat'],1]])],
|
|
|
- ['export_incog_hidden',(1,'seed export to hidden mmincog format', [[['mmdat'],1]])],
|
|
|
-
|
|
|
- ['addrgen_hex', (1,'address generation from mmhex file', [[['mmhex','addrs'],1]])],
|
|
|
- ['addrgen_seed', (1,'address generation from mmseed file', [[['mmseed','addrs'],1]])],
|
|
|
- ['addrgen_mnemonic',(1,'address generation from mmwords file',[[['mmwords','addrs'],1]])],
|
|
|
- ['addrgen_incog', (1,'address generation from mmincog file',[[['mmincog','addrs'],1]])],
|
|
|
- ['addrgen_incog_hex',(1,'address generation from mmincog hex file',[[['mmincox','addrs'],1]])],
|
|
|
- ['addrgen_incog_hidden',(1,'address generation from hidden mmincog file', [[[hincog_fn,'addrs'],1]])],
|
|
|
-
|
|
|
- ['keyaddrgen', (1,'key-address file generation', [[['mmdat',pwfile],1]])],
|
|
|
- ['txsign_keyaddr',(1,'transaction signing with key-address file', [[['akeys.mmenc','rawtx'],1]])],
|
|
|
-
|
|
|
- ['txcreate_ni', (1,'transaction creation (non-interactive)', [[['addrs'],1]])],
|
|
|
-
|
|
|
- ['walletgen2',(2,'wallet generation (2), 128-bit seed', [[['del_dw_run'],15]])],
|
|
|
- ['addrgen2', (2,'address generation (2)', [[['mmdat'],2]])],
|
|
|
- ['txcreate2', (2,'transaction creation (2)', [[['addrs'],2]])],
|
|
|
- ['txsign2', (2,'transaction signing, two transactions',[[['mmdat','rawtx'],1],[['mmdat','rawtx'],2]])],
|
|
|
- ['export_mnemonic2', (2,'seed export to mmwords format (2)',[[['mmdat'],2]])],
|
|
|
-
|
|
|
- ['walletgen3',(3,'wallet generation (3)', [[['del_dw_run'],15]])],
|
|
|
- ['addrgen3', (3,'address generation (3)', [[['mmdat'],3]])],
|
|
|
- ['txcreate3', (3,'tx creation with inputs and outputs from two wallets', [[['addrs'],1],[['addrs'],3]])],
|
|
|
- ['txsign3', (3,'tx signing with inputs and outputs from two wallets',[[['mmdat'],1],[['mmdat','rawtx'],3]])],
|
|
|
-
|
|
|
- ['walletgen14', (14,'wallet generation (14)', [[['del_dw_run'],15]],14)],
|
|
|
- ['addrgen14', (14,'address generation (14)', [[['mmdat'],14]])],
|
|
|
- ['keyaddrgen14',(14,'key-address file generation (14)', [[['mmdat'],14]],14)],
|
|
|
- ['walletgen4',(4,'wallet generation (4) (brainwallet)', [[['del_dw_run'],15]])],
|
|
|
- ['addrgen4', (4,'address generation (4)', [[['mmdat'],4]])],
|
|
|
- ['txcreate4', (4,'tx creation with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['addrs'],1],[['addrs'],2],[['addrs'],3],[['addrs'],4],[['addrs','akeys.mmenc'],14]])],
|
|
|
- ['txsign4', (4,'tx signing with inputs and outputs from incog file, mnemonic file, wallet, brainwallet, key-address file and non-MMGen inputs and outputs', [[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['mmbrain','rawtx'],4],[['akeys.mmenc'],14]])],
|
|
|
- ['txdo4', (4,'tx creation,signing and sending with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['addrs'],1],[['addrs'],2],[['addrs'],3],[['addrs'],4],[['addrs','akeys.mmenc'],14],[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['mmbrain','rawtx'],4],[['akeys.mmenc'],14]])], # must go after txsign4
|
|
|
- ['txbump4', (4,'tx fee bump + send with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['akeys.mmenc'],14],[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['akeys.mmenc'],14],[['mmbrain','sigtx','mmdat','txdo'],4]])], # must go after txsign4
|
|
|
-
|
|
|
- ['walletgen5',(20,'wallet generation (5)', [[['del_dw_run'],15]],20)],
|
|
|
- ['addrgen5', (20,'address generation (5)', [[['mmdat'],20]])],
|
|
|
- ['txcreate5', (20,'transaction creation with bad vsize (5)', [[['addrs'],20]])],
|
|
|
- ['txsign5', (20,'transaction signing with bad vsize', [[['mmdat','rawtx'],20]])],
|
|
|
- ['walletgen6',(21,'wallet generation (6)', [[['del_dw_run'],15]],21)],
|
|
|
- ['addrgen6', (21,'address generation (6)', [[['mmdat'],21]])],
|
|
|
- ['txcreate6', (21,'transaction creation with corrected vsize (6)', [[['addrs'],21]])],
|
|
|
- ['txsign6', (21,'transaction signing with corrected vsize', [[['mmdat','rawtx'],21]])],
|
|
|
-])
|
|
|
-
|
|
|
-cmd_group['tool'] = OrderedDict([
|
|
|
- ['tool_encrypt', (9,"'mmgen-tool encrypt' (random data)", [])],
|
|
|
- ['tool_decrypt', (9,"'mmgen-tool decrypt' (random data)", [[[cfgs['9']['tool_enc_infn'],cfgs['9']['tool_enc_infn']+'.mmenc'],9]])],
|
|
|
-# ['tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])],
|
|
|
- ['tool_find_incog_data', (9,"'mmgen-tool find_incog_data'", [[[hincog_fn],1],[[incog_id_fn],1]])],
|
|
|
-# ['pywallet', (9,"'mmgen-pywallet'", [])],
|
|
|
-])
|
|
|
-
|
|
|
-# generated reference data
|
|
|
-cmd_group['ref'] = (
|
|
|
- # reading
|
|
|
- ('ref_wallet_chk', ([],'saved reference wallet')),
|
|
|
- ('ref_seed_chk', ([],'saved seed file')),
|
|
|
- ('ref_hex_chk', ([],'saved mmhex file')),
|
|
|
- ('ref_mn_chk', ([],'saved mnemonic file')),
|
|
|
- ('ref_hincog_chk', ([],'saved hidden incog reference wallet')),
|
|
|
- ('ref_brain_chk', ([],'saved brainwallet')),
|
|
|
- # generating new reference ('abc' brainwallet) files:
|
|
|
- ('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)')),
|
|
|
- ('ref_hexpasswdgen',(['mmdat',pwfile],'new refwallet passwd file chksum (base32)')),
|
|
|
-)
|
|
|
-
|
|
|
-# reference files
|
|
|
-cmd_group['ref_files'] = (
|
|
|
- ('ref_addrfile_chk', 'saved reference address file'), # TODO: move to tooltest2
|
|
|
- ('ref_segwitaddrfile_chk','saved reference address file (segwit)'), # TODO: move to tooltest2
|
|
|
- ('ref_bech32addrfile_chk','saved reference address file (bech32)'), # TODO: move to tooltest2
|
|
|
- ('ref_keyaddrfile_chk','saved reference key-address file'),
|
|
|
- ('ref_passwdfile_chk', 'saved reference password file'),
|
|
|
-# Create the fake inputs:
|
|
|
-# ('txcreate8', 'transaction creation (8)'),
|
|
|
- ('ref_tx_chk', 'saved reference tx file'), # TODO: move to tooltest2
|
|
|
- ('ref_brain_chk_spc3', 'saved brainwallet (non-standard spacing)'),
|
|
|
- ('ref_tool_decrypt', 'decryption of saved MMGen-encrypted file'),
|
|
|
-)
|
|
|
-
|
|
|
-# mmgen-walletconv:
|
|
|
-cmd_group['conv_in'] = ( # reading
|
|
|
- ('ref_wallet_conv', 'conversion of saved reference wallet'),
|
|
|
- ('ref_mn_conv', 'conversion of saved mnemonic'),
|
|
|
- ('ref_seed_conv', 'conversion of saved seed file'),
|
|
|
- ('ref_hex_conv', 'conversion of saved hexadecimal seed file'),
|
|
|
- ('ref_brain_conv', 'conversion of ref brainwallet'),
|
|
|
- ('ref_incog_conv', 'conversion of saved incog wallet'),
|
|
|
- ('ref_incox_conv', 'conversion of saved hex incog wallet'),
|
|
|
- ('ref_hincog_conv', 'conversion of saved hidden incog wallet'),
|
|
|
- ('ref_hincog_conv_old','conversion of saved hidden incog wallet (old format)')
|
|
|
-)
|
|
|
-
|
|
|
-cmd_group['conv_out'] = ( # writing
|
|
|
- ('ref_wallet_conv_out', 'ref seed conversion to wallet'),
|
|
|
- ('ref_mn_conv_out', 'ref seed conversion to mnemonic'),
|
|
|
- ('ref_hex_conv_out', 'ref seed conversion to hex seed'),
|
|
|
- ('ref_seed_conv_out', 'ref seed conversion to seed'),
|
|
|
- ('ref_incog_conv_out', 'ref seed conversion to incog data'),
|
|
|
- ('ref_incox_conv_out', 'ref seed conversion to hex incog data'),
|
|
|
- ('ref_hincog_conv_out', 'ref seed conversion to hidden incog data'),
|
|
|
- ('ref_hincog_blkdev_conv_out', 'ref seed conversion to hidden incog data on block device')
|
|
|
-)
|
|
|
-
|
|
|
-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_add_label', "adding a 40-character UTF-8 encoded label"),
|
|
|
- ('regtest_bob_twview', "viewing Bob's tracking wallet"),
|
|
|
- ('regtest_bob_split1', "splitting Bob's funds"),
|
|
|
- ('regtest_generate', 'mining a block'),
|
|
|
- ('regtest_bob_bal2', "Bob's balance"),
|
|
|
- ('regtest_bob_bal2a', "Bob's balance (age_fmt=confs)"),
|
|
|
- ('regtest_bob_bal2b', "Bob's balance (showempty=1)"),
|
|
|
- ('regtest_bob_bal2c', "Bob's balance (showempty=1 minconf=2 age_fmt=days)"),
|
|
|
- ('regtest_bob_bal2d', "Bob's balance (minconf=2)"),
|
|
|
- ('regtest_bob_bal2e', "Bob's balance (showempty=1 sort=age)"),
|
|
|
- ('regtest_bob_bal2f', "Bob's balance (showempty=1 sort=age,reverse)"),
|
|
|
- ('regtest_bob_rbf_send', 'sending funds to Alice (RBF)'),
|
|
|
- ('regtest_get_mempool1', 'mempool (before RBF bump)'),
|
|
|
- ('regtest_bob_rbf_bump', 'bumping RBF transaction'),
|
|
|
- ('regtest_get_mempool2', 'mempool (after RBF bump)'),
|
|
|
- ('regtest_generate', 'mining a block'),
|
|
|
- ('regtest_bob_bal3', "Bob's balance"),
|
|
|
- ('regtest_bob_pre_import', 'sending to non-imported address'),
|
|
|
- ('regtest_generate', 'mining a block'),
|
|
|
- ('regtest_bob_import_addr', 'importing non-MMGen address with --rescan'),
|
|
|
- ('regtest_bob_bal4', "Bob's balance (after import with rescan)"),
|
|
|
- ('regtest_bob_import_list', 'importing flat address list'),
|
|
|
- ('regtest_bob_split2', "splitting Bob's funds"),
|
|
|
- ('regtest_generate', 'mining a block'),
|
|
|
- ('regtest_bob_bal5', "Bob's balance"),
|
|
|
- ('regtest_bob_bal5_getbalance',"Bob's balance"),
|
|
|
- ('regtest_bob_send_non_mmgen', 'sending funds to Alice (from non-MMGen addrs)'),
|
|
|
- ('regtest_generate', 'mining a block'),
|
|
|
- ('regtest_alice_add_label1', 'adding a label'),
|
|
|
- ('regtest_alice_chk_label1', 'the label'),
|
|
|
- ('regtest_alice_add_label2', 'adding a label'),
|
|
|
- ('regtest_alice_chk_label2', 'the label'),
|
|
|
- ('regtest_alice_edit_label1', 'editing a label'),
|
|
|
- ('regtest_alice_chk_label3', 'the label'),
|
|
|
- ('regtest_alice_remove_label1','removing a label'),
|
|
|
- ('regtest_alice_chk_label4', 'the label'),
|
|
|
- ('regtest_alice_add_label_coinaddr','adding a label using the coin address'),
|
|
|
- ('regtest_alice_chk_label_coinaddr','the label'),
|
|
|
- ('regtest_alice_add_label_badaddr1','adding a label with invalid address'),
|
|
|
- ('regtest_alice_add_label_badaddr2','adding a label with invalid address for this chain'),
|
|
|
- ('regtest_alice_add_label_badaddr3','adding a label with wrong MMGen address'),
|
|
|
- ('regtest_alice_add_label_badaddr4','adding a label with wrong coin address'),
|
|
|
- ('regtest_alice_bal_rpcfail','RPC failure code'),
|
|
|
- ('regtest_alice_send_estimatefee','tx creation with no fee on command line'),
|
|
|
- ('regtest_generate', 'mining a block'),
|
|
|
- ('regtest_bob_bal6', "Bob's balance"),
|
|
|
- ('regtest_bob_alice_bal', "Bob and Alice's balances"),
|
|
|
- ('regtest_alice_bal2', "Alice's balance"),
|
|
|
- ('regtest_stop', 'stopping regtest daemon'),
|
|
|
-)
|
|
|
-
|
|
|
-cmd_group['regtest_split'] = (
|
|
|
- ('regtest_split_setup', 'regtest forking scenario setup'),
|
|
|
- ('regtest_walletgen_bob', "generating Bob's wallet"),
|
|
|
- ('regtest_addrgen_bob', "generating Bob's addresses"),
|
|
|
- ('regtest_addrimport_bob', "importing Bob's addresses"),
|
|
|
- ('regtest_fund_bob', "funding Bob's wallet"),
|
|
|
- ('regtest_split_fork', 'regtest split fork'),
|
|
|
- ('regtest_split_start_btc', 'start regtest daemon (BTC)'),
|
|
|
- ('regtest_split_start_b2x', 'start regtest daemon (B2X)'),
|
|
|
- ('regtest_split_gen_btc', 'mining a block (BTC)'),
|
|
|
- ('regtest_split_gen_b2x', 'mining 100 blocks (B2X)'),
|
|
|
- ('regtest_split_do_split', 'creating coin splitting transactions'),
|
|
|
- ('regtest_split_sign_b2x', 'signing B2X split transaction'),
|
|
|
- ('regtest_split_sign_btc', 'signing BTC split transaction'),
|
|
|
- ('regtest_split_send_b2x', 'sending B2X split transaction'),
|
|
|
- ('regtest_split_send_btc', 'sending BTC split transaction'),
|
|
|
- ('regtest_split_gen_btc', 'mining a block (BTC)'),
|
|
|
- ('regtest_split_gen_b2x2', 'mining a block (B2X)'),
|
|
|
- ('regtest_split_txdo_timelock_bad_btc', 'sending transaction with bad locktime (BTC)'),
|
|
|
- ('regtest_split_txdo_timelock_good_btc','sending transaction with good locktime (BTC)'),
|
|
|
- ('regtest_split_txdo_timelock_bad_b2x', 'sending transaction with bad locktime (B2X)'),
|
|
|
- ('regtest_split_txdo_timelock_good_b2x','sending transaction with good locktime (B2X)'),
|
|
|
-)
|
|
|
-
|
|
|
-cmd_group['ethdev'] = (
|
|
|
- ('ethdev_setup', 'Ethereum Parity dev mode tests for coin {} (start parity)'.format(g.coin)),
|
|
|
- ('ethdev_addrgen', 'generating addresses'),
|
|
|
- ('ethdev_addrimport', 'importing addresses'),
|
|
|
- ('ethdev_addrimport_dev_addr', "importing Parity dev address 'Ox00a329c..'"),
|
|
|
-
|
|
|
- ('ethdev_txcreate1', 'creating a transaction (spend from dev address to address :1)'),
|
|
|
- ('ethdev_txsign1', 'signing the transaction'),
|
|
|
- ('ethdev_txsign1_ni', 'signing the transaction (non-interactive)'),
|
|
|
- ('ethdev_txsend1', 'sending the transaction'),
|
|
|
- ('ethdev_bal1', 'the {} balance'.format(g.coin)),
|
|
|
-
|
|
|
- ('ethdev_txcreate2', 'creating a transaction (spend from dev address to address :11)'),
|
|
|
- ('ethdev_txsign2', 'signing the transaction'),
|
|
|
- ('ethdev_txsend2', 'sending the transaction'),
|
|
|
- ('ethdev_bal2', 'the {} balance'.format(g.coin)),
|
|
|
-
|
|
|
- ('ethdev_txcreate3', 'creating a transaction (spend from dev address to address :21)'),
|
|
|
- ('ethdev_txsign3', 'signing the transaction'),
|
|
|
- ('ethdev_txsend3', 'sending the transaction'),
|
|
|
- ('ethdev_bal3', 'the {} balance'.format(g.coin)),
|
|
|
-
|
|
|
- ('ethdev_tx_status1', 'getting the transaction status'),
|
|
|
-
|
|
|
- ('ethdev_txcreate4', 'creating a transaction (spend from MMGen address, low TX fee)'),
|
|
|
- ('ethdev_txbump', 'bumping the transaction fee'),
|
|
|
-
|
|
|
- ('ethdev_txsign4', 'signing the transaction'),
|
|
|
- ('ethdev_txsend4', 'sending the transaction'),
|
|
|
- ('ethdev_bal4', 'the {} balance'.format(g.coin)),
|
|
|
-
|
|
|
- ('ethdev_txcreate5', 'creating a transaction (fund burn address)'),
|
|
|
- ('ethdev_txsign5', 'signing the transaction'),
|
|
|
- ('ethdev_txsend5', 'sending the transaction'),
|
|
|
-
|
|
|
- ('ethdev_addrimport_burn_addr',"importing burn address"),
|
|
|
- ('ethdev_bal5', 'the {} balance'.format(g.coin)),
|
|
|
-
|
|
|
- ('ethdev_add_label', 'adding a UTF-8 label'),
|
|
|
- ('ethdev_chk_label', 'the label'),
|
|
|
- ('ethdev_remove_label', 'removing the label'),
|
|
|
-
|
|
|
- ('ethdev_token_compile1', 'compiling ERC20 token #1'),
|
|
|
-
|
|
|
- ('ethdev_token_deploy1a', 'deploying ERC20 token #1 (SafeMath)'),
|
|
|
- ('ethdev_token_deploy1b', 'deploying ERC20 token #1 (Owned)'),
|
|
|
- ('ethdev_token_deploy1c', 'deploying ERC20 token #1 (Token)'),
|
|
|
-
|
|
|
- ('ethdev_tx_status2', 'getting the transaction status'),
|
|
|
- ('ethdev_bal6', 'the {} balance'.format(g.coin)),
|
|
|
+utils = {
|
|
|
+# 'check_deps': 'check dependencies for specified command (WIP)', # TODO
|
|
|
+ 'clean': 'clean specified tmp dir(s) (specify by integer, no arg = all dirs)',
|
|
|
+}
|
|
|
|
|
|
- ('ethdev_token_compile2', 'compiling ERC20 token #2'),
|
|
|
+def list_cmds():
|
|
|
+ gm = CmdGroupMgr()
|
|
|
+ cw,d = 0,[]
|
|
|
+ Msg(green('AVAILABLE COMMANDS:'))
|
|
|
+ for gname in gm.cmd_groups:
|
|
|
+ ts = gm.init_group(None,gname,None)
|
|
|
+ d.append((gname,ts.__doc__.strip(),gm.cmd_list,gm.dpy_data))
|
|
|
+ cw = max(max(len(k) for k in gm.dpy_data),cw)
|
|
|
|
|
|
- ('ethdev_token_deploy2a', 'deploying ERC20 token #2 (SafeMath)'),
|
|
|
- ('ethdev_token_deploy2b', 'deploying ERC20 token #2 (Owned)'),
|
|
|
- ('ethdev_token_deploy2c', 'deploying ERC20 token #2 (Token)'),
|
|
|
+ for gname,gdesc,clist,dpdata in d:
|
|
|
+ Msg('\n'+green('{!r} - {}:'.format(gname,gdesc)))
|
|
|
+ for cmd in clist:
|
|
|
+ data = dpdata[cmd]
|
|
|
+ Msg(' {:{w}} - {}'.format(cmd,data if type(data) == str else data[1],w=cw))
|
|
|
|
|
|
- ('ethdev_contract_deploy', 'deploying contract (create,sign,send)'),
|
|
|
+ w = max(map(len,utils))
|
|
|
+ Msg('\n'+green('AVAILABLE UTILITIES:'))
|
|
|
+ for cmd in sorted(utils):
|
|
|
+ Msg(' {:{w}} - {}'.format(cmd,utils[cmd],w=w))
|
|
|
|
|
|
- ('ethdev_token_fund_users', 'transferring token funds from dev to user'),
|
|
|
- ('ethdev_token_user_bals', 'show balances after transfer'),
|
|
|
- ('ethdev_token_addrgen', 'generating token addresses'),
|
|
|
- ('ethdev_token_addrimport_badaddr1','importing token addresses (no token address)'),
|
|
|
- ('ethdev_token_addrimport_badaddr2','importing token addresses (bad token address)'),
|
|
|
- ('ethdev_token_addrimport', 'importing token addresses'),
|
|
|
+ sys.exit(0)
|
|
|
|
|
|
- ('ethdev_bal7', 'the {} balance'.format(g.coin)),
|
|
|
- ('ethdev_token_bal1', 'the {} balance and token balance'.format(g.coin)),
|
|
|
+def do_between():
|
|
|
+ if opt.pause:
|
|
|
+ confirm_continue()
|
|
|
+ elif opt.verbose or opt.exact_output:
|
|
|
+ sys.stderr.write('\n')
|
|
|
|
|
|
- ('ethdev_token_txcreate1', 'creating a token transaction'),
|
|
|
- ('ethdev_token_txsign1', 'signing the transaction'),
|
|
|
- ('ethdev_token_txsend1', 'sending the transaction'),
|
|
|
- ('ethdev_token_bal2', 'the {} balance and token balance'.format(g.coin)),
|
|
|
+def list_tmpdirs():
|
|
|
+ return dict(((k,cfgs[k]['tmpdir']) for k in cfgs))
|
|
|
|
|
|
- ('ethdev_token_txcreate2', 'creating a token transaction (to burn address)'),
|
|
|
- ('ethdev_token_txbump', 'bumping the transaction fee'),
|
|
|
+def clean(usr_dirs=None):
|
|
|
+ if opt.skip_deps: return
|
|
|
+ all_dirs = list_tmpdirs()
|
|
|
+ dirnums = map(int,(usr_dirs if usr_dirs is not None else all_dirs))
|
|
|
+ dirlist = list(map(str,sorted(dirnums)))
|
|
|
+ for d in dirlist:
|
|
|
+ if d in all_dirs:
|
|
|
+ cleandir(all_dirs[d])
|
|
|
+ else:
|
|
|
+ die(1,'{}: invalid directory number'.format(d))
|
|
|
+ if dirlist:
|
|
|
+ iqmsg(green('Cleaned tmp director{} {}'.format(suf(dirlist,'y'),' '.join(dirlist))))
|
|
|
+ cleandir(data_dir)
|
|
|
+ cleandir(trash_dir)
|
|
|
+ iqmsg(green("Cleaned directories '{}'".format("' '".join([data_dir,trash_dir]))))
|
|
|
|
|
|
- ('ethdev_token_txsign2', 'signing the transaction'),
|
|
|
- ('ethdev_token_txsend2', 'sending the transaction'),
|
|
|
- ('ethdev_token_bal3', 'the {} balance and token balance'.format(g.coin)),
|
|
|
+def create_tmp_dirs(shm_dir):
|
|
|
+ if g.platform == 'win':
|
|
|
+ for cfg in sorted(cfgs):
|
|
|
+ mk_tmpdir(cfgs[cfg]['tmpdir'])
|
|
|
+ else:
|
|
|
+ for cfg in sorted(cfgs):
|
|
|
+ src = os.path.join(shm_dir,cfgs[cfg]['tmpdir'].split('/')[-1])
|
|
|
+ mk_tmpdir(src)
|
|
|
+ try:
|
|
|
+ os.unlink(cfgs[cfg]['tmpdir'])
|
|
|
+ except OSError as e:
|
|
|
+ if e.errno != 2: raise
|
|
|
+ finally:
|
|
|
+ os.symlink(src,cfgs[cfg]['tmpdir'])
|
|
|
|
|
|
- ('ethdev_del_dev_addr', "deleting the dev address"),
|
|
|
+def set_environ_for_spawned_scripts():
|
|
|
+ if os.getenv('MMGEN_DEBUG_ALL'):
|
|
|
+ for name in g.env_opts:
|
|
|
+ if name[:11] == 'MMGEN_DEBUG':
|
|
|
+ os.environ[name] = '1'
|
|
|
+ if not opt.pexpect_spawn: os.environ['MMGEN_TEST_SUITE_POPEN_SPAWN'] = '1'
|
|
|
+ if not opt.system: os.environ['PYTHONPATH'] = repo_root
|
|
|
+ if not opt.buf_keypress:
|
|
|
+ os.environ['MMGEN_DISABLE_HOLD_PROTECT'] = '1'
|
|
|
+
|
|
|
+ # If test.py itself is running under traceback, the spawned script shouldn't be, so disable this:
|
|
|
+ if os.getenv('MMGEN_TRACEBACK') and not opt.traceback:
|
|
|
+ os.environ['MMGEN_TRACEBACK'] = ''
|
|
|
+
|
|
|
+ # Disable color in spawned scripts so pexpect can parse their output
|
|
|
+ os.environ['MMGEN_DISABLE_COLOR'] = '1'
|
|
|
+ os.environ['MMGEN_NO_LICENSE'] = '1'
|
|
|
+ os.environ['MMGEN_MIN_URANDCHARS'] = '3'
|
|
|
+ os.environ['MMGEN_BOGUS_SEND'] = '1'
|
|
|
+ # Tell spawned programs they're running in the test suite
|
|
|
+ os.environ['MMGEN_TEST_SUITE'] = '1'
|
|
|
+
|
|
|
+def set_restore_term_at_exit():
|
|
|
+ import termios,atexit
|
|
|
+ fd = sys.stdin.fileno()
|
|
|
+ old = termios.tcgetattr(fd)
|
|
|
+ def at_exit():
|
|
|
+ termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
|
|
+ atexit.register(at_exit)
|
|
|
|
|
|
- ('ethdev_bal1_getbalance', 'the {} balance (getbalance)'.format(g.coin)),
|
|
|
+class CmdGroupMgr(object):
|
|
|
+
|
|
|
+ cmd_groups = {
|
|
|
+ 'helpscreens': ('TestSuiteHelp',{'modname':'misc','full_data':True}),
|
|
|
+ 'main': ('TestSuiteMain',{'full_data':True}),
|
|
|
+ 'conv': ('TestSuiteWalletConv',{'is3seed':True,'modname':'wallet'}),
|
|
|
+ 'ref3': ('TestSuiteRef3Seed',{'is3seed':True,'modname':'ref_3seed'}),
|
|
|
+ 'ref': ('TestSuiteRef',{}),
|
|
|
+ 'ref_altcoin': ('TestSuiteRefAltcoin',{}),
|
|
|
+ 'tool': ('TestSuiteTool',{'modname':'misc','full_data':True}),
|
|
|
+ 'regtest': ('TestSuiteRegtest',{}),
|
|
|
+# 'chainsplit': ('TestSuiteChainsplit',{}),
|
|
|
+ 'ethdev': ('TestSuiteEthdev',{}),
|
|
|
+ 'autosign': ('TestSuiteAutosign',{}),
|
|
|
+ 'autosign_minimal': ('TestSuiteAutosignMinimal',{'modname':'autosign'}),
|
|
|
+ 'autosign_live': ('TestSuiteAutosignLive',{'modname':'autosign'}),
|
|
|
+ 'create_ref_tx': ('TestSuiteRefTX',{'modname':'misc','full_data':True}),
|
|
|
+ }
|
|
|
|
|
|
- ('ethdev_addrimport_token_burn_addr',"importing the token burn address"),
|
|
|
+ dfl_groups = ( 'helpscreens',
|
|
|
+ 'main',
|
|
|
+ 'conv',
|
|
|
+ 'ref',
|
|
|
+ 'ref3',
|
|
|
+ 'ref_altcoin',
|
|
|
+ 'tool',
|
|
|
+ 'autosign_minimal',
|
|
|
+ 'regtest',
|
|
|
+ 'ethdev')
|
|
|
+
|
|
|
+ def load_mod(self,gname,modname=None):
|
|
|
+ clsname,kwargs = self.cmd_groups[gname]
|
|
|
+ if modname == None and 'modname' in kwargs:
|
|
|
+ modname = kwargs['modname']
|
|
|
+ gl = globals()
|
|
|
+ exec('from test.test_py_d import ts_{}'.format(modname or gname),gl,gl)
|
|
|
+ exec('from test.test_py_d.ts_{} import {}'.format(modname or gname,clsname),gl,gl)
|
|
|
+ return clsname
|
|
|
+
|
|
|
+ def create_group(self,gname,full_data=False,modname=None,is3seed=False,add_dpy=False):
|
|
|
+ """
|
|
|
+ Initializes the list 'cmd_list' and dict 'dpy_data' from module's cmd_group data.
|
|
|
+ Alternatively, if called with 'add_dpy=True', updates 'dpy_data' from module data
|
|
|
+ without touching 'cmd_list'
|
|
|
+ """
|
|
|
+ clsname = self.load_mod(gname,modname)
|
|
|
+ tmpdir_nums = globals()[clsname].tmpdir_nums
|
|
|
+
|
|
|
+ cdata = []
|
|
|
+ for a,b in getattr(globals()[clsname],'cmd_group'):
|
|
|
+ if is3seed:
|
|
|
+ for n,(i,j) in enumerate(zip(tmpdir_nums,(128,192,256))):
|
|
|
+ k = '{}_{}'.format(a,n+1)
|
|
|
+ if type(b) == str:
|
|
|
+ cdata.append( (k, (i,'{} ({}-bit)'.format(b,j),[[[],i]])) )
|
|
|
+ else:
|
|
|
+ cdata.append( (k, (i,'{} ({}-bit)'.format(b[1],j),[[b[0],i]])) )
|
|
|
+ else:
|
|
|
+ cdata.append( (a, b if full_data else (tmpdir_nums[0],b,[[[],tmpdir_nums[0]]])) )
|
|
|
|
|
|
- ('ethdev_token_bal4', 'the {} balance and token balance'.format(g.coin)),
|
|
|
- ('ethdev_token_bal_getbalance','the token balance (getbalance)'),
|
|
|
+ if add_dpy:
|
|
|
+ self.dpy_data.update(dict(cdata))
|
|
|
+ else:
|
|
|
+ self.cmd_list = tuple(e[0] for e in cdata)
|
|
|
+ self.dpy_data = dict(cdata)
|
|
|
+
|
|
|
+ return clsname
|
|
|
+
|
|
|
+ def init_group(self,trunner,gname,spawn_prog):
|
|
|
+ clsname,kwargs = self.cmd_groups[gname]
|
|
|
+ self.create_group(gname,**kwargs)
|
|
|
+ return globals()[clsname](trunner,cfgs,spawn_prog)
|
|
|
+
|
|
|
+ def find_cmd_in_groups(self,cmd,group=None):
|
|
|
+ """
|
|
|
+ Search for a test command in specified group or all configured command groups
|
|
|
+ and return it as a string. Loads modules but alters no global variables.
|
|
|
+ """
|
|
|
+ if group:
|
|
|
+ if not group in [e[0] for e in self.cmd_groups]:
|
|
|
+ die(1,'{!r}: unrecognized group'.format(group))
|
|
|
+ groups = [self.cmd_groups[group]]
|
|
|
+ else:
|
|
|
+ groups = self.cmd_groups
|
|
|
+
|
|
|
+ for gname in groups:
|
|
|
+ clsname,kwargs = self.cmd_groups[gname]
|
|
|
+ self.load_mod(gname,kwargs['modname'] if 'modname' in kwargs else None)
|
|
|
+ if cmd in dict(globals()[clsname].cmd_group): # first search the class
|
|
|
+ return gname
|
|
|
+ if cmd in dir(globals()[clsname](None,None,None)): # then a throwaway instance
|
|
|
+ return gname # cmd might be in several groups - we'll go with the first
|
|
|
+ return None
|
|
|
+
|
|
|
+class TestSuiteRunner(object):
|
|
|
+ 'test suite runner'
|
|
|
+
|
|
|
+ def __init__(self,data_dir,trash_dir):
|
|
|
+ self.data_dir = data_dir
|
|
|
+ self.trash_dir = trash_dir
|
|
|
+ self.cmd_total = 0
|
|
|
+ from collections import OrderedDict
|
|
|
+ self.rebuild_list = OrderedDict()
|
|
|
+ self.gm = CmdGroupMgr()
|
|
|
+
|
|
|
+ if opt.log:
|
|
|
+ self.log_fd = open(log_file,'a')
|
|
|
+ self.log_fd.write('\nLog started: {} UTC\n'.format(make_timestr()))
|
|
|
+ omsg('INFO → Logging to file {!r}'.format(log_file))
|
|
|
+ else:
|
|
|
+ self.log_fd = None
|
|
|
|
|
|
- ('ethdev_txcreate_noamt', 'creating a transaction (full amount send)'),
|
|
|
- ('ethdev_txsign_noamt', 'signing the transaction'),
|
|
|
- ('ethdev_txsend_noamt', 'sending the transaction'),
|
|
|
+ if opt.coverage:
|
|
|
+ self.coverdir,self.accfile = init_coverage()
|
|
|
+ omsg('INFO → Writing coverage files to {!r}'.format(self.coverdir))
|
|
|
|
|
|
- ('ethdev_bal8', 'the {} balance'.format(g.coin)),
|
|
|
- ('ethdev_token_bal5', 'the token balance'),
|
|
|
+ def spawn_wrapper( self, cmd,
|
|
|
+ args = [],
|
|
|
+ extra_desc = '',
|
|
|
+ no_output = False,
|
|
|
+ msg_only = False,
|
|
|
+ no_msg = False,
|
|
|
+ cmd_dir = 'cmds' ):
|
|
|
|
|
|
- ('ethdev_token_txcreate_noamt', 'creating a token transaction (full amount send)'),
|
|
|
- ('ethdev_token_txsign_noamt', 'signing the transaction'),
|
|
|
- ('ethdev_token_txsend_noamt', 'sending the transaction'),
|
|
|
+ desc = self.ts.test_name if opt.names else self.gm.dpy_data[self.ts.test_name][1]
|
|
|
+ if extra_desc: desc += ' ' + extra_desc
|
|
|
|
|
|
- ('ethdev_bal9', 'the {} balance'.format(g.coin)),
|
|
|
- ('ethdev_token_bal6', 'the token balance'),
|
|
|
+ if not opt.system:
|
|
|
+ cmd = os.path.relpath(os.path.join(repo_root,cmd_dir,cmd))
|
|
|
+ elif g.platform == 'win':
|
|
|
+ cmd = os.path.join('/mingw64','opt','bin',cmd)
|
|
|
|
|
|
- ('ethdev_listaddresses1', 'listaddresses'),
|
|
|
- ('ethdev_listaddresses2', 'listaddresses minconf=999999999 (ignored)'),
|
|
|
- ('ethdev_listaddresses3', 'listaddresses sort=age (ignored)'),
|
|
|
- ('ethdev_listaddresses4', 'listaddresses showempty=1 sort=age (ignored)'),
|
|
|
+ passthru_opts = ['--{}{}'.format(k.replace('_','-'),
|
|
|
+ '=' + getattr(opt,k) if getattr(opt,k) != True else '')
|
|
|
+ for k in self.ts.passthru_opts if getattr(opt,k)]
|
|
|
|
|
|
- ('ethdev_token_listaddresses1','listaddresses --token=mm1'),
|
|
|
- ('ethdev_token_listaddresses2','listaddresses --token=mm1 showempty=1'),
|
|
|
+ args = [cmd] + passthru_opts + ['--data-dir='+self.data_dir] + args
|
|
|
|
|
|
- ('ethdev_twview1','twview'),
|
|
|
- ('ethdev_twview2','twview wide=1'),
|
|
|
- ('ethdev_twview3','twview wide=1 sort=age (ignored)'),
|
|
|
- ('ethdev_twview4','twview wide=1 minconf=999999999 (ignored)'),
|
|
|
- ('ethdev_twview5','twview wide=1 minconf=0 (ignored)'),
|
|
|
- ('ethdev_twview6','twview age_fmt=days (ignored)'),
|
|
|
+ if g.platform == 'win':
|
|
|
+ args = ['python3'] + args
|
|
|
|
|
|
- ('ethdev_token_twview1','twview --token=mm1'),
|
|
|
- ('ethdev_token_twview2','twview --token=mm1 wide=1'),
|
|
|
- ('ethdev_token_twview3','twview --token=mm1 wide=1 sort=age (ignored)'),
|
|
|
+ for i in args:
|
|
|
+ if type(i) != str:
|
|
|
+ m = 'Error: missing input files in cmd line?:\nName: {}\nCmdline: {!r}'
|
|
|
+ die(2,m.format(self.ts.test_name,args))
|
|
|
|
|
|
- ('ethdev_edit_label1','adding label to addr #{} in {} tracking wallet'.format(eth_rem_addrs[0],g.coin)),
|
|
|
- ('ethdev_edit_label2','adding label to addr #{} in {} tracking wallet'.format(eth_rem_addrs[1],g.coin)),
|
|
|
- ('ethdev_edit_label3','removing label from addr #{} in {} tracking wallet'.format(eth_rem_addrs[0],g.coin)),
|
|
|
+ if opt.coverage:
|
|
|
+ args = ['python3','-m','trace','--count','--coverdir='+self.coverdir,'--file='+self.accfile] + args
|
|
|
+ elif opt.traceback:
|
|
|
+ args = ['scripts/traceback_run.py'] + args
|
|
|
|
|
|
- ('ethdev_remove_addr1','removing addr #{} from {} tracking wallet'.format(eth_rem_addrs[0],g.coin)),
|
|
|
- ('ethdev_remove_addr2','removing addr #{} from {} tracking wallet'.format(eth_rem_addrs[1],g.coin)),
|
|
|
- ('ethdev_remove_token_addr1','removing addr #{} from {} token tracking wallet'.format(eth_rem_addrs[0],g.coin)),
|
|
|
- ('ethdev_remove_token_addr2','removing addr #{} from {} token tracking wallet'.format(eth_rem_addrs[1],g.coin)),
|
|
|
+ qargs = ['{q}{}{q}'.format(a,q=('',"'")[' ' in a]) for a in args]
|
|
|
+ cmd_disp = ' '.join(qargs).replace('\\','/') # for mingw
|
|
|
|
|
|
- ('ethdev_stop', 'stopping parity'),
|
|
|
-)
|
|
|
+ if not no_msg:
|
|
|
+ if opt.verbose or opt.print_cmdline or opt.exact_output:
|
|
|
+ clr1,clr2 = ((green,cyan),(nocolor,nocolor))[bool(opt.print_cmdline)]
|
|
|
+ omsg(green('Testing: {}'.format(desc)))
|
|
|
+ if not msg_only:
|
|
|
+ s = repr(cmd_disp) if g.platform == 'win' else cmd_disp
|
|
|
+ omsg(clr1('Executing: ') + clr2(s))
|
|
|
+ else:
|
|
|
+ omsg_r('Testing {}: '.format(desc))
|
|
|
|
|
|
-cmd_group['autosign'] = (
|
|
|
- ('autosign', 'transaction autosigning (BTC,BCH,LTC,ETH,ETC)'),
|
|
|
-)
|
|
|
-cmd_group['autosign_minimal'] = (
|
|
|
- ('autosign_minimal', 'transaction autosigning (BTC,ETH,ETC)'),
|
|
|
-)
|
|
|
-cmd_group['autosign_live'] = (
|
|
|
- ('autosign_live', 'transaction autosigning (BTC,ETH,ETC - test device insertion/removal + LED)'),
|
|
|
-)
|
|
|
+ if msg_only: return
|
|
|
|
|
|
-cmd_group['ref_alt'] = (
|
|
|
- ('ref_addrfile_gen_eth', 'generate address file (ETH)'),
|
|
|
- ('ref_addrfile_gen_etc', 'generate address file (ETC)'),
|
|
|
- ('ref_addrfile_gen_dash', 'generate address file (DASH)'),
|
|
|
- ('ref_addrfile_gen_zec', 'generate address file (ZEC-T)'),
|
|
|
- ('ref_addrfile_gen_zec_z','generate address file (ZEC-Z)'),
|
|
|
- ('ref_addrfile_gen_xmr', 'generate address file (XMR)'),
|
|
|
- # we test the old ed25519 library in test-release.sh, so skip this
|
|
|
-# ('ref_addrfile_gen_xmr_old','generate address file (XMR - old (slow) ed25519 library)'),
|
|
|
+ if opt.log: self.log_fd.write(cmd_disp+'\n')
|
|
|
|
|
|
- ('ref_keyaddrfile_gen_eth', 'generate key-address file (ETH)'),
|
|
|
- ('ref_keyaddrfile_gen_etc', 'generate key-address file (ETC)'),
|
|
|
- ('ref_keyaddrfile_gen_dash', 'generate key-address file (DASH)'),
|
|
|
- ('ref_keyaddrfile_gen_zec', 'generate key-address file (ZEC-T)'),
|
|
|
- ('ref_keyaddrfile_gen_zec_z','generate key-address file (ZEC-Z)'),
|
|
|
- ('ref_keyaddrfile_gen_xmr', 'generate key-address file (XMR)'),
|
|
|
+ from test.pexpect import MMGenPexpect
|
|
|
+ return MMGenPexpect(args,no_output=no_output)
|
|
|
|
|
|
- ('ref_addrfile_chk_eth', 'reference address file (ETH)'),
|
|
|
- ('ref_addrfile_chk_etc', 'reference address file (ETC)'),
|
|
|
- ('ref_addrfile_chk_dash','reference address file (DASH)'),
|
|
|
- ('ref_addrfile_chk_zec', 'reference address file (ZEC-T)'),
|
|
|
- ('ref_addrfile_chk_zec_z','reference address file (ZEC-Z)'),
|
|
|
- ('ref_addrfile_chk_xmr', 'reference address file (XMR)'),
|
|
|
+ def end_msg(self):
|
|
|
+ t = int(time.time()) - self.start_time
|
|
|
+ m = '{} test{} performed. Elapsed time: {:02d}:{:02d}\n'
|
|
|
+ sys.stderr.write(green(m.format(self.cmd_total,suf(self.cmd_total),t//60,t%60)))
|
|
|
|
|
|
- ('ref_keyaddrfile_chk_eth', 'reference key-address file (ETH)'),
|
|
|
- ('ref_keyaddrfile_chk_etc', 'reference key-address file (ETC)'),
|
|
|
- ('ref_keyaddrfile_chk_dash','reference key-address file (DASH)'),
|
|
|
- ('ref_keyaddrfile_chk_zec', 'reference key-address file (ZEC-T)'),
|
|
|
- ('ref_keyaddrfile_chk_zec_z','reference key-address file (ZEC-Z)'),
|
|
|
- ('ref_keyaddrfile_chk_xmr', 'reference key-address file (XMR)'),
|
|
|
-)
|
|
|
+ def init_group(self,gname,cmd=None):
|
|
|
+ ts_cls = globals()[CmdGroupMgr().load_mod(gname)]
|
|
|
|
|
|
-# undocumented admin cmds - precede with 'admin'
|
|
|
-cmd_group_admin = OrderedDict()
|
|
|
-cmd_group_admin['create_ref_tx'] = OrderedDict([
|
|
|
- ['ref_tx_addrgen1', (31,'address generation (legacy)', [[[],1]])],
|
|
|
- ['ref_tx_addrgen2', (32,'address generation (compressed)', [[[],1]])],
|
|
|
- ['ref_tx_addrgen3', (33,'address generation (segwit)', [[[],1]])],
|
|
|
- ['ref_tx_addrgen4', (34,'address generation (bech32)', [[[],1]])],
|
|
|
- ['ref_tx_txcreate', (31,'transaction creation', [[['addrs'],31],[['addrs'],32],[['addrs'],33],[['addrs'],34]])],
|
|
|
-])
|
|
|
-cmd_list_admin = OrderedDict()
|
|
|
-for k in cmd_group_admin: cmd_list_admin[k] = []
|
|
|
+ for k in ('segwit','segwit_random','bech32'):
|
|
|
+ if getattr(opt,k):
|
|
|
+ segwit_opt = k
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ segwit_opt = None
|
|
|
+
|
|
|
+ m1 = ('test group {g!r}','{g}:{c}')[bool(cmd)].format(g=gname,c=cmd)
|
|
|
+ m2 = ' for {} {}net'.format(g.coin.lower(),'test' if g.testnet else 'main') \
|
|
|
+ if len(ts_cls.networks) != 1 else ''
|
|
|
+ m3 = ' (--{})'.format(segwit_opt.replace('_','-')) if segwit_opt else ''
|
|
|
+ m = m1 + m2 + m3
|
|
|
+
|
|
|
+ if segwit_opt and not getattr(ts_cls,'segwit_opts_ok'):
|
|
|
+ iqmsg('INFO → skipping ' + m)
|
|
|
+ return False
|
|
|
+
|
|
|
+ # 'networks = ()' means all networks allowed
|
|
|
+ nws = [(e.split('_')[0],'testnet') if '_' in e else (e,'mainnet') for e in ts_cls.networks]
|
|
|
+ if nws:
|
|
|
+ coin = g.coin.lower()
|
|
|
+ nw = ('mainnet','testnet')[g.testnet]
|
|
|
+ for a,b in nws:
|
|
|
+ if a == coin and b == nw:
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ iqmsg('INFO → skipping ' + m)
|
|
|
+ return False
|
|
|
|
|
|
-cmd_data_admin = OrderedDict()
|
|
|
-for k,v in [('create_ref_tx',('reference transaction creation',[31,32,33,34]))]:
|
|
|
- cmd_data_admin['info_'+k] = v
|
|
|
- for i in cmd_group_admin[k]:
|
|
|
- cmd_list_admin[k].append(i)
|
|
|
- cmd_data_admin[i] = cmd_group_admin[k][i]
|
|
|
+ bmsg('Executing ' + m)
|
|
|
|
|
|
-cmd_data_admin['info_create_ref_tx'] = 'create reference tx',[8]
|
|
|
+ self.ts = self.gm.init_group(self,gname,self.spawn_wrapper)
|
|
|
|
|
|
-cmd_list = OrderedDict()
|
|
|
-for k in cmd_group: cmd_list[k] = []
|
|
|
+ if opt.exit_after and opt.exit_after not in self.gm.cmd_list:
|
|
|
+ die(1,'{!r}: command not recognized'.format(opt.exit_after))
|
|
|
|
|
|
-cmd_data = OrderedDict()
|
|
|
-for k,v in (
|
|
|
- ('help', ('help screens',[])),
|
|
|
- ('dfl_wallet', ('basic operations with default wallet',[15,16])),
|
|
|
- ('main', ('basic operations',[1,2,3,4,5,6,15,16])),
|
|
|
- ('tool', ('tools',[9]))
|
|
|
- ):
|
|
|
- cmd_data['info_'+k] = v
|
|
|
- for i in cmd_group[k]:
|
|
|
- cmd_list[k].append(i)
|
|
|
- cmd_data[i] = cmd_group[k][i]
|
|
|
+ return True
|
|
|
|
|
|
-cmd_data['info_ref'] = 'generated reference data',[6,7,8]
|
|
|
-for a,b in cmd_group['ref']:
|
|
|
- for i,j in ((1,128),(2,192),(3,256)):
|
|
|
- k = a+str(i)
|
|
|
- cmd_list['ref'].append(k)
|
|
|
- cmd_data[k] = (5+i,'{} ({}-bit)'.format(b[1],j),[[b[0],5+i]])
|
|
|
+ def run_tests(self,usr_args):
|
|
|
+ self.start_time = int(time.time())
|
|
|
+ if usr_args:
|
|
|
+ for arg in usr_args:
|
|
|
+ if arg in self.gm.cmd_groups:
|
|
|
+ if not self.init_group(arg): continue
|
|
|
+ clean(self.ts.tmpdir_nums)
|
|
|
+ for cmd in self.gm.cmd_list:
|
|
|
+ self.check_needs_rerun(cmd,build=True)
|
|
|
+ do_between()
|
|
|
+ elif arg in utils:
|
|
|
+ params = usr_args[usr_args.index(arg)+1:]
|
|
|
+ globals()[arg](*params)
|
|
|
+ sys.exit(0)
|
|
|
+ else:
|
|
|
+ if ':' in arg:
|
|
|
+ gname,arg = arg.split(':')
|
|
|
+ else:
|
|
|
+ gname = self.gm.find_cmd_in_groups(arg)
|
|
|
+ if gname:
|
|
|
+ if not self.init_group(gname,arg): continue
|
|
|
+ clean(self.ts.tmpdir_nums)
|
|
|
+ self.check_needs_rerun(arg,build=True)
|
|
|
+ do_between()
|
|
|
+ else:
|
|
|
+ die(1,'{!r}: command not recognized'.format(arg))
|
|
|
+ else:
|
|
|
+ if opt.exclude_groups:
|
|
|
+ exclude = opt.exclude_groups.split(',')
|
|
|
+ for e in exclude:
|
|
|
+ if e not in self.gm.dfl_groups:
|
|
|
+ die(1,'{!r}: group not recognized'.format(e))
|
|
|
+ for gname in self.gm.dfl_groups:
|
|
|
+ if opt.exclude_groups and gname in exclude: continue
|
|
|
+ if not self.init_group(gname): continue
|
|
|
+ clean(self.ts.tmpdir_nums)
|
|
|
+ for cmd in self.gm.cmd_list:
|
|
|
+ self.check_needs_rerun(cmd,build=True)
|
|
|
+ do_between()
|
|
|
+
|
|
|
+ self.end_msg()
|
|
|
+
|
|
|
+ def check_needs_rerun(self,
|
|
|
+ cmd,
|
|
|
+ build=False,
|
|
|
+ root=True,
|
|
|
+ force_delete=False,
|
|
|
+ dpy=False
|
|
|
+ ):
|
|
|
|
|
|
-cmd_data['info_ref_files'] = 'reference files',[8]
|
|
|
-for a,b in cmd_group['ref_files']:
|
|
|
- cmd_list['ref_files'].append(a)
|
|
|
- cmd_data[a] = (8,b,[[[],8]])
|
|
|
+ rerun = root # force_delete is not passed to recursive call
|
|
|
+
|
|
|
+ fns = []
|
|
|
+ if force_delete or not root:
|
|
|
+ # does cmd produce a needed dependency(ies)?
|
|
|
+ ret = self.get_num_exts_for_cmd(cmd,dpy)
|
|
|
+ if ret:
|
|
|
+ for ext in ret[1]:
|
|
|
+ fn = get_file_with_ext(cfgs[ret[0]]['tmpdir'],ext,delete=build)
|
|
|
+ if fn:
|
|
|
+ if force_delete: os.unlink(fn)
|
|
|
+ else: fns.append(fn)
|
|
|
+ else: rerun = True
|
|
|
+
|
|
|
+ fdeps = self.generate_file_deps(cmd)
|
|
|
+ cdeps = self.generate_cmd_deps(fdeps)
|
|
|
+
|
|
|
+ for fn in fns:
|
|
|
+ my_age = os.stat(fn).st_mtime
|
|
|
+ for num,ext in fdeps:
|
|
|
+ f = get_file_with_ext(cfgs[num]['tmpdir'],ext,delete=build)
|
|
|
+ if f and os.stat(f).st_mtime > my_age:
|
|
|
+ rerun = True
|
|
|
+
|
|
|
+ for cdep in cdeps:
|
|
|
+ if self.check_needs_rerun(cdep,build=build,root=False,dpy=cmd):
|
|
|
+ rerun = True
|
|
|
|
|
|
-cmd_data['info_conv_in'] = 'wallet conversion from reference data',[11,12,13]
|
|
|
-for a,b in cmd_group['conv_in']:
|
|
|
- for i,j in ((1,128),(2,192),(3,256)):
|
|
|
- k = a+str(i)
|
|
|
- cmd_list['conv_in'].append(k)
|
|
|
- cmd_data[k] = (10+i,'{} ({}-bit)'.format(b,j),[[[],10+i]])
|
|
|
+ if build:
|
|
|
+ if rerun:
|
|
|
+ for fn in fns:
|
|
|
+ if not root: os.unlink(fn)
|
|
|
+ if not (dpy and opt.skip_deps):
|
|
|
+ self.run_test(cmd)
|
|
|
+ if not root: do_between()
|
|
|
+ else:
|
|
|
+ # If prog produces multiple files:
|
|
|
+ if cmd not in self.rebuild_list or rerun == True:
|
|
|
+ self.rebuild_list[cmd] = (rerun,fns[0] if fns else '') # FIX
|
|
|
|
|
|
-cmd_data['info_conv_out'] = 'wallet conversion to reference data',[11,12,13]
|
|
|
-for a,b in cmd_group['conv_out']:
|
|
|
- for i,j in ((1,128),(2,192),(3,256)):
|
|
|
- k = a+str(i)
|
|
|
- cmd_list['conv_out'].append(k)
|
|
|
- cmd_data[k] = (10+i,'{} ({}-bit)'.format(b,j),[[[],10+i]])
|
|
|
+ return rerun
|
|
|
|
|
|
-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]])
|
|
|
+ def run_test(self,cmd):
|
|
|
|
|
|
-cmd_data['info_ethdev'] = 'Ethereum tracking wallet and transaction ops',[22]
|
|
|
-for a,b in cmd_group['ethdev']:
|
|
|
- cmd_list['ethdev'].append(a)
|
|
|
- cmd_data[a] = (22,b,[[[],22]])
|
|
|
+ # delete files produced by this cmd
|
|
|
+# for ext,tmpdir in find_generated_exts(cmd):
|
|
|
+# print cmd, get_file_with_ext(tmpdir,ext)
|
|
|
|
|
|
-cmd_data['info_autosign'] = 'autosign',[18]
|
|
|
-for a,b in cmd_group['autosign']:
|
|
|
- cmd_list['autosign'].append(a)
|
|
|
- cmd_data[a] = (18,b,[[[],18]])
|
|
|
+ d = [(str(num),ext) for exts,num in self.gm.dpy_data[cmd][2] for ext in exts]
|
|
|
|
|
|
-cmd_data['info_autosign_minimal'] = 'autosign_minimal',[18]
|
|
|
-for a,b in cmd_group['autosign_minimal']:
|
|
|
- cmd_list['autosign_minimal'].append(a)
|
|
|
- cmd_data[a] = (18,b,[[[],18]])
|
|
|
+ # delete files depended on by this cmd
|
|
|
+ arg_list = [get_file_with_ext(cfgs[num]['tmpdir'],ext) for num,ext in d]
|
|
|
|
|
|
-cmd_data['info_autosign_live'] = 'autosign_live',[18]
|
|
|
-for a,b in cmd_group['autosign_live']:
|
|
|
- cmd_list['autosign_live'].append(a)
|
|
|
- cmd_data[a] = (18,b,[[[],18]])
|
|
|
|
|
|
-cmd_data['info_ref_alt'] = 'altcoin reference files',[8]
|
|
|
-for a,b in cmd_group['ref_alt']:
|
|
|
- cmd_list['ref_alt'].append(a)
|
|
|
- cmd_data[a] = (8,b,[[[],8]])
|
|
|
+ if opt.resume:
|
|
|
+ if cmd == opt.resume:
|
|
|
+ bmsg('Resuming at {!r}'.format(cmd))
|
|
|
+ opt.resume = False
|
|
|
+ opt.skip_deps = False
|
|
|
+ else:
|
|
|
+ return
|
|
|
|
|
|
-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)',
|
|
|
-}
|
|
|
+ if opt.profile: start = time.time()
|
|
|
|
|
|
-addrs_per_wallet = 8
|
|
|
+ cdata = self.gm.dpy_data[cmd]
|
|
|
+ self.ts.test_name = cmd
|
|
|
+# self.ts.test_dpydata = cdata
|
|
|
+ self.ts.tmpdir_num = cdata[0]
|
|
|
+# self.ts.cfg = cfgs[str(cdata[0])] # will remove this eventually
|
|
|
+ cfg = cfgs[str(cdata[0])]
|
|
|
+ for k in ( 'seed_len', 'seed_id',
|
|
|
+ 'wpasswd', 'kapasswd',
|
|
|
+ 'segwit', 'hash_preset',
|
|
|
+ 'bw_filename', 'bw_params', 'ref_bw_seed_id',
|
|
|
+ 'addr_idx_list', 'pass_idx_list' ):
|
|
|
+ if k in cfg:
|
|
|
+ setattr(self.ts,k,cfg[k])
|
|
|
+
|
|
|
+ self.process_retval(cmd,getattr(self.ts,cmd)(*arg_list)) # run the test
|
|
|
|
|
|
-meta_cmds = OrderedDict([
|
|
|
- ['gen', ('walletgen','addrgen')],
|
|
|
- ['pass', ('passchg','walletchk_newpass')],
|
|
|
- ['tx', ('txcreate','txsign','txsend')],
|
|
|
- ['export', [k for k in cmd_data if k[:7] == 'export_' and cmd_data[k][0] == 1]],
|
|
|
- ['gen_sp', [k for k in cmd_data if k[:8] == 'addrgen_' and cmd_data[k][0] == 1]],
|
|
|
- ['online', ('keyaddrgen','txsign_keyaddr')],
|
|
|
- ['2', [k for k in cmd_data if cmd_data[k][0] == 2]],
|
|
|
- ['3', [k for k in cmd_data if cmd_data[k][0] == 3]],
|
|
|
- ['4', [k for k in cmd_data if cmd_data[k][0] == 4]],
|
|
|
- ['5', [k for k in cmd_data if cmd_data[k][0] == 20]],
|
|
|
- ['6', [k for k in cmd_data if cmd_data[k][0] == 21]],
|
|
|
+ if opt.profile:
|
|
|
+ omsg('\r\033[50C{:.4f}'.format(time.time() - start))
|
|
|
|
|
|
- ['ref1', [c[0]+'1' for c in cmd_group['ref']]],
|
|
|
- ['ref2', [c[0]+'2' for c in cmd_group['ref']]],
|
|
|
- ['ref3', [c[0]+'3' for c in cmd_group['ref']]],
|
|
|
+ if cmd == opt.exit_after:
|
|
|
+ sys.exit(0)
|
|
|
|
|
|
- ['conv_in1', [c[0]+'1' for c in cmd_group['conv_in']]],
|
|
|
- ['conv_in2', [c[0]+'2' for c in cmd_group['conv_in']]],
|
|
|
- ['conv_in3', [c[0]+'3' for c in cmd_group['conv_in']]],
|
|
|
+ def process_retval(self,cmd,ret):
|
|
|
+ if type(ret).__name__ == 'MMGenPexpect':
|
|
|
+ ret.ok()
|
|
|
+ self.cmd_total += 1
|
|
|
+ elif ret == 'ok':
|
|
|
+ ok()
|
|
|
+ self.cmd_total += 1
|
|
|
+ elif ret == 'skip':
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ rdie(1,'{!r} returned {}'.format(cmd,ret))
|
|
|
|
|
|
- ['conv_out1', [c[0]+'1' for c in cmd_group['conv_out']]],
|
|
|
- ['conv_out2', [c[0]+'2' for c in cmd_group['conv_out']]],
|
|
|
- ['conv_out3', [c[0]+'3' for c in cmd_group['conv_out']]],
|
|
|
-])
|
|
|
+ def check_deps(self,cmds): # TODO: broken
|
|
|
+ if len(cmds) != 1:
|
|
|
+ die(1,'Usage: {} check_deps <command>'.format(g.prog_name))
|
|
|
|
|
|
-del cmd_group
|
|
|
+ cmd = cmds[0]
|
|
|
|
|
|
-if opt.profile: opt.names = True
|
|
|
-if opt.resume: opt.skip_deps = True
|
|
|
+ if cmd not in self.gm.cmd_list:
|
|
|
+ die(1,'{!r}: unrecognized command'.format(cmd))
|
|
|
|
|
|
-log_fd = None
|
|
|
-if opt.log:
|
|
|
- log_fd = open(log_file,'a')
|
|
|
- log_fd.write('\nLog started: {}\n'.format(make_timestr()))
|
|
|
+ if not opt.quiet:
|
|
|
+ omsg('Checking dependencies for {!r}'.format(cmd))
|
|
|
|
|
|
-usr_rand_chars = (5,30)[bool(opt.usr_random)]
|
|
|
-usr_rand_arg = '-r{}'.format(usr_rand_chars)
|
|
|
-cmd_total = 0
|
|
|
+ self.check_needs_rerun(self.ts,cmd,build=False)
|
|
|
|
|
|
-# Disable color in spawned scripts so pexpect can parse their output
|
|
|
-os.environ['MMGEN_DISABLE_COLOR'] = '1'
|
|
|
-os.environ['MMGEN_NO_LICENSE'] = '1'
|
|
|
-os.environ['MMGEN_MIN_URANDCHARS'] = '3'
|
|
|
-os.environ['MMGEN_BOGUS_SEND'] = '1'
|
|
|
-# Tell spawned programs they're running in the test suite
|
|
|
-os.environ['MMGEN_TEST_SUITE'] = '1'
|
|
|
+ w = max(map(len,self.rebuild_list)) + 1
|
|
|
+ for cmd in self.rebuild_list:
|
|
|
+ c = self.rebuild_list[cmd]
|
|
|
+ m = 'Rebuild' if (c[0] and c[1]) else 'Build' if c[0] else 'OK'
|
|
|
+ omsg('cmd {:<{w}} {}'.format(cmd+':', m, w=w))
|
|
|
|
|
|
-def get_segwit_arg(cfg):
|
|
|
- return ['--type='+('segwit','bech32')[bool(opt.bech32)]] if cfg['segwit'] else []
|
|
|
+ def generate_file_deps(self,cmd):
|
|
|
+ return [(str(n),e) for exts,n in self.gm.dpy_data[cmd][2] for e in exts]
|
|
|
|
|
|
-if opt.exact_output:
|
|
|
- def imsg(s): os.write(2,s.encode() + b'\n')
|
|
|
- def imsg_r(s): os.write(2,s.encode())
|
|
|
- def msg(s): pass
|
|
|
- qmsg = qmsg_r = vmsg = vmsg_r = msg_r = msg
|
|
|
-else:
|
|
|
- def imsg(s): pass
|
|
|
- def imsg_r(s): pass
|
|
|
+ def generate_cmd_deps(self,fdeps):
|
|
|
+ return [cfgs[str(n)]['dep_generators'][ext] for n,ext in fdeps]
|
|
|
|
|
|
-devnull_fh = open('/dev/null','w')
|
|
|
+ def get_num_exts_for_cmd(self,cmd,dpy=False): # dpy ignored here
|
|
|
+ try:
|
|
|
+ num = str(self.gm.dpy_data[cmd][0])
|
|
|
+ except KeyError:
|
|
|
+ qmsg_r('Missing dependency {!r}'.format(cmd))
|
|
|
+ gname = self.gm.find_cmd_in_groups(cmd)
|
|
|
+ if gname:
|
|
|
+ kwargs = self.gm.cmd_groups[gname][1]
|
|
|
+ kwargs.update({'add_dpy':True})
|
|
|
+ self.gm.create_group(gname,**kwargs)
|
|
|
+ num = str(self.gm.dpy_data[cmd][0])
|
|
|
+ qmsg(' found in group {!r}'.format(gname))
|
|
|
+ else:
|
|
|
+ qmsg(' not found in any command group!')
|
|
|
+ raise
|
|
|
+ dgl = cfgs[num]['dep_generators']
|
|
|
+ if cmd in dgl.values():
|
|
|
+ exts = [k for k in dgl if dgl[k] == cmd]
|
|
|
+ return (num,exts)
|
|
|
+ else:
|
|
|
+ return None
|
|
|
|
|
|
-def silence():
|
|
|
- if not (opt.verbose or opt.exact_output):
|
|
|
- g.stderr_fileno = g.stdout_fileno = devnull_fh.fileno()
|
|
|
+# main()
|
|
|
|
|
|
-def end_silence():
|
|
|
- if not (opt.verbose or opt.exact_output):
|
|
|
- g.stderr_fileno = 2
|
|
|
- g.stdout_fileno = 1
|
|
|
+if not opt.skip_deps: # do this before list cmds exit, so we stay in sync with shm_dir
|
|
|
+ create_tmp_dirs(shm_dir)
|
|
|
|
|
|
if opt.list_cmd_groups:
|
|
|
- Msg(' '.join(cmd_list))
|
|
|
- sys.exit(0)
|
|
|
-
|
|
|
-if opt.list_cmds:
|
|
|
- from mmgen.term import get_terminal_size
|
|
|
- tw = get_terminal_size()[0]
|
|
|
- fs = ' {:<{w}} - {}'
|
|
|
-
|
|
|
- Msg(green('AVAILABLE COMMANDS:'))
|
|
|
- w = max(map(len,cmd_data))
|
|
|
- for cmd in cmd_data:
|
|
|
- if cmd[:5] == 'info_':
|
|
|
- Msg(green(' {}:'.format(capfirst(cmd_data[cmd][0]))))
|
|
|
- continue
|
|
|
- Msg(' '+fs.format(cmd,cmd_data[cmd][1],w=w))
|
|
|
+ Die(0,' '.join(CmdGroupMgr.cmd_groups))
|
|
|
+elif opt.list_cmds:
|
|
|
+ list_cmds()
|
|
|
|
|
|
- for cl,lbl in ((meta_cmds,'METACOMMANDS'),(cmd_list,'COMMAND GROUPS')):
|
|
|
- w = max(map(len,cl))
|
|
|
- Msg('\n'+green('AVAILABLE {}:'.format(lbl)))
|
|
|
- for cmd in cl:
|
|
|
- ft = format_par(' '.join(cl[cmd]),width=tw,indent=4,as_list=True)
|
|
|
- sep = '' if not ft else ' ' if len(ft[0]) + len(cmd) < tw - 4 else '\n '
|
|
|
- Msg(' {}{}{}'.format(yellow(cmd+':'),sep,'\n'.join(ft).lstrip()))
|
|
|
-
|
|
|
- Msg('\n'+green('AVAILABLE UTILITIES:'))
|
|
|
- w = max(map(len,utils))
|
|
|
- for cmd in sorted(utils):
|
|
|
- Msg(fs.format(cmd,utils[cmd],w=w))
|
|
|
-
|
|
|
- sys.exit(0)
|
|
|
-
|
|
|
-NL = ('\r\n','\n')[g.platform=='linux' and bool(opt.popen_spawn)]
|
|
|
-
|
|
|
-def get_file_with_ext(ext,mydir,delete=True,no_dot=False,return_list=False,delete_all=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 or delete_all:
|
|
|
- if delete or delete_all:
|
|
|
- if not opt.quiet:
|
|
|
- msg("Multiple *.{} files in '{}' - deleting".format(ext,mydir))
|
|
|
- for f in flist:
|
|
|
- os.unlink(f)
|
|
|
- return False
|
|
|
- else:
|
|
|
- return flist[0]
|
|
|
-
|
|
|
-def find_generated_exts(cmd):
|
|
|
- out = []
|
|
|
- for k in cfgs:
|
|
|
- for ext,prog in list(cfgs[k]['dep_generators'].items()):
|
|
|
- if prog == cmd:
|
|
|
- out.append((ext,cfgs[k]['tmpdir']))
|
|
|
- return out
|
|
|
-
|
|
|
-def get_addrfile_checksum(display=False):
|
|
|
- addrfile = get_file_with_ext('addrs',cfg['tmpdir'])
|
|
|
- silence()
|
|
|
- chk = AddrList(addrfile).chksum
|
|
|
- if opt.verbose and display: msg('Checksum: {}'.format(cyan(chk)))
|
|
|
- end_silence()
|
|
|
- return chk
|
|
|
-
|
|
|
-def verify_checksum_or_exit(checksum,chk):
|
|
|
- if checksum != chk:
|
|
|
- raise TestSuiteFatalException('Checksum error: {}'.format(chk))
|
|
|
- vmsg(green('Checksums match: ') + cyan(chk))
|
|
|
+if opt.pause:
|
|
|
+ set_restore_term_at_exit()
|
|
|
|
|
|
-from test.mmgen_pexpect import MMGenPexpect
|
|
|
-class MMGenExpect(MMGenPexpect):
|
|
|
-
|
|
|
- def __init__(self,name,mmgen_cmd,cmd_args=[],extra_desc='',no_output=False,msg_only=False,no_msg=False):
|
|
|
-
|
|
|
- desc = ((cmd_data[name][1],name)[bool(opt.names)] + (' ' + extra_desc)).strip()
|
|
|
- passthru_args = ['testnet','rpc_host','rpc_port','regtest','coin']
|
|
|
-
|
|
|
- if not opt.system:
|
|
|
- mmgen_cmd = os.path.relpath(os.path.join(repo_root,'cmds',mmgen_cmd))
|
|
|
- elif g.platform == 'win':
|
|
|
- mmgen_cmd = os.path.join('/mingw64','opt','bin',mmgen_cmd)
|
|
|
-
|
|
|
- return MMGenPexpect.__init__(
|
|
|
- self,
|
|
|
- name,
|
|
|
- mmgen_cmd,
|
|
|
- cmd_args,
|
|
|
- desc,
|
|
|
- no_output=no_output,
|
|
|
- passthru_args=passthru_args,
|
|
|
- msg_only=msg_only,
|
|
|
- no_msg=no_msg,
|
|
|
- log_fd=log_fd)
|
|
|
-
|
|
|
-def create_fake_unspent_entry(coinaddr,al_id=None,idx=None,lbl=None,non_mmgen=False,segwit=False):
|
|
|
- if 'S' not in g.proto.mmtypes: segwit = False
|
|
|
- if lbl: lbl = ' ' + lbl
|
|
|
- k = coinaddr.addr_fmt
|
|
|
- if not segwit and k == 'p2sh': k = 'p2pkh'
|
|
|
- s_beg,s_end = { 'p2pkh': ('76a914','88ac'),
|
|
|
- 'p2sh': ('a914','87'),
|
|
|
- 'bech32': (g.proto.witness_vernum_hex.decode()+'14','') }[k]
|
|
|
- amt1,amt2 = {'btc':(10,40),'bch':(10,40),'ltc':(1000,4000)}[coin_sel]
|
|
|
- ret = {
|
|
|
- lbl_id: '{}:{}'.format(g.proto.base_coin.lower(),coinaddr) if non_mmgen \
|
|
|
- else ('{}:{}{}'.format(al_id,idx,lbl)),
|
|
|
- 'vout': int(getrandnum(4) % 8),
|
|
|
- 'txid': hexlify(os.urandom(32)),
|
|
|
- 'amount': g.proto.coin_amt('{}.{}'.format(amt1 + getrandnum(4) % amt2, getrandnum(4) % 100000000)),
|
|
|
- 'address': coinaddr,
|
|
|
- 'spendable': False,
|
|
|
- 'scriptPubKey': '{}{}{}'.format(s_beg,coinaddr.hex.decode(),s_end).encode(),
|
|
|
- 'confirmations': getrandnum(3) // 2 # max: 8388608 (7 digits)
|
|
|
- }
|
|
|
- return ret
|
|
|
-
|
|
|
-labels = [
|
|
|
- "Automotive",
|
|
|
- "Travel expenses",
|
|
|
- "Healthcare",
|
|
|
- ref_tx_label_jp[:40],
|
|
|
- ref_tx_label_zh[:40],
|
|
|
- "Alice's allowance",
|
|
|
- "Bob's bequest",
|
|
|
- "House purchase",
|
|
|
- "Real estate fund",
|
|
|
- "Job 1",
|
|
|
- "XYZ Corp.",
|
|
|
- "Eddie's endowment",
|
|
|
- "Emergency fund",
|
|
|
- "Real estate fund",
|
|
|
- "Ian's inheritance",
|
|
|
- "",
|
|
|
- "Rainy day",
|
|
|
- "Fred's funds",
|
|
|
- "Job 2",
|
|
|
- "Carl's capital",
|
|
|
-]
|
|
|
-
|
|
|
-def get_label(do_shuffle=False):
|
|
|
- from random import shuffle
|
|
|
- global label_iter
|
|
|
- try:
|
|
|
- return str(next(label_iter))
|
|
|
- except:
|
|
|
- if do_shuffle: shuffle(labels)
|
|
|
- label_iter = iter(labels)
|
|
|
- return str(next(label_iter))
|
|
|
-
|
|
|
-def create_fake_unspent_data(adata,tx_data,non_mmgen_input='',non_mmgen_input_compressed=True):
|
|
|
-
|
|
|
- out = []
|
|
|
- for d in tx_data.values():
|
|
|
- al = adata.addrlist(d['al_id'])
|
|
|
- for n,(idx,coinaddr) in enumerate(al.addrpairs()):
|
|
|
- lbl = get_label(do_shuffle=True)
|
|
|
- out.append(create_fake_unspent_entry(coinaddr,d['al_id'],idx,lbl,segwit=d['segwit']))
|
|
|
- if n == 0: # create a duplicate address. This means addrs_per_wallet += 1
|
|
|
- out.append(create_fake_unspent_entry(coinaddr,d['al_id'],idx,lbl,segwit=d['segwit']))
|
|
|
-
|
|
|
- if non_mmgen_input:
|
|
|
- privkey = PrivKey(os.urandom(32),compressed=non_mmgen_input_compressed,pubkey_type='std')
|
|
|
- rand_coinaddr = AddrGenerator('p2pkh').to_addr(KeyGenerator('std').to_pubhex(privkey))
|
|
|
- of = os.path.join(cfgs[non_mmgen_input]['tmpdir'],non_mmgen_fn)
|
|
|
- write_data_to_file(of, privkey.wif+'\n','compressed {} key'.format(g.proto.name),
|
|
|
- silent=True,ignore_opt_outdir=True)
|
|
|
- out.append(create_fake_unspent_entry(rand_coinaddr,non_mmgen=True,segwit=False))
|
|
|
-
|
|
|
-# msg('\n'.join([repr(o) for o in out])); sys.exit(0)
|
|
|
- return out
|
|
|
-
|
|
|
-def write_fake_data_to_file(d):
|
|
|
- unspent_data_file = os.path.join(cfg['tmpdir'],'unspent.json')
|
|
|
- write_data_to_file(unspent_data_file,d,'Unspent outputs',silent=True,ignore_opt_outdir=True)
|
|
|
- os.environ['MMGEN_BOGUS_WALLET_DATA'] = unspent_data_file
|
|
|
- bwd_msg = 'MMGEN_BOGUS_WALLET_DATA={}'.format(unspent_data_file)
|
|
|
- if opt.print_cmdline: msg(bwd_msg)
|
|
|
- if opt.log: log_fd.write(bwd_msg + ' ')
|
|
|
- if opt.verbose or opt.exact_output:
|
|
|
- sys.stderr.write("Fake transaction wallet data written to file {!r}\n".format(unspent_data_file))
|
|
|
-
|
|
|
-def create_tx_data(sources,addrs_per_wallet=addrs_per_wallet):
|
|
|
- tx_data,ad = {},AddrData()
|
|
|
- for s in sources:
|
|
|
- afile = get_file_with_ext('addrs',cfgs[s]['tmpdir'])
|
|
|
- al = AddrList(afile)
|
|
|
- ad.add(al)
|
|
|
- aix = AddrIdxList(fmt_str=cfgs[s]['addr_idx_list'])
|
|
|
- if len(aix) != addrs_per_wallet:
|
|
|
- raise TestSuiteFatalException(
|
|
|
- 'Address index list length != {}: {}'.format(addrs_per_wallet,repr(aix)))
|
|
|
- tx_data[s] = {
|
|
|
- 'addrfile': afile,
|
|
|
- 'chk': al.chksum,
|
|
|
- 'al_id': al.al_id,
|
|
|
- 'addr_idxs': aix[-2:],
|
|
|
- 'segwit': cfgs[s]['segwit']
|
|
|
- }
|
|
|
- return ad,tx_data
|
|
|
-
|
|
|
-def make_txcreate_cmdline(tx_data):
|
|
|
- privkey = PrivKey(os.urandom(32),compressed=True,pubkey_type='std')
|
|
|
- t = ('p2pkh','segwit')['S' in g.proto.mmtypes]
|
|
|
- rand_coinaddr = AddrGenerator(t).to_addr(KeyGenerator('std').to_pubhex(privkey))
|
|
|
-
|
|
|
- # total of two outputs must be < 10 BTC (<1000 LTC)
|
|
|
- mods = {'btc':(6,4),'bch':(6,4),'ltc':(600,400)}[coin_sel]
|
|
|
- for k in cfgs:
|
|
|
- cfgs[k]['amts'] = [None,None]
|
|
|
- for idx,mod in enumerate(mods):
|
|
|
- cfgs[k]['amts'][idx] = '{}.{}'.format(getrandnum(4) % mod, str(getrandnum(4))[:5])
|
|
|
-
|
|
|
- cmd_args = ['--outdir='+cfg['tmpdir']]
|
|
|
- for num in tx_data:
|
|
|
- s = tx_data[num]
|
|
|
- cmd_args += [
|
|
|
- '{}:{},{}'.format(s['al_id'],s['addr_idxs'][0],cfgs[num]['amts'][0]),
|
|
|
- ]
|
|
|
- # + one change address and one BTC address
|
|
|
- if num is list(tx_data.keys())[-1]:
|
|
|
- cmd_args += ['{}:{}'.format(s['al_id'],s['addr_idxs'][1])]
|
|
|
- cmd_args += ['{},{}'.format(rand_coinaddr,cfgs[num]['amts'][1])]
|
|
|
-
|
|
|
- return cmd_args + [tx_data[num]['addrfile'] for num in tx_data]
|
|
|
-
|
|
|
-def add_comments_to_addr_file(addrfile,outfile,use_labels=False):
|
|
|
- silence()
|
|
|
- gmsg("Adding comments to address file '{}'".format(addrfile))
|
|
|
- a = AddrList(addrfile)
|
|
|
- for n,idx in enumerate(a.idxs(),1):
|
|
|
- if use_labels:
|
|
|
- a.set_comment(idx,get_label())
|
|
|
- else:
|
|
|
- if n % 2: a.set_comment(idx,'Test address {}'.format(n))
|
|
|
- a.format(enable_comments=True)
|
|
|
- write_data_to_file(outfile,a.fmt_data,silent=True,ignore_opt_outdir=True)
|
|
|
- end_silence()
|
|
|
-
|
|
|
-# 100 words chosen randomly from here:
|
|
|
-# https://github.com/bitcoin/bips/pull/432/files/6332230d63149a950d05db78964a03bfd344e6b0
|
|
|
-rwords = """
|
|
|
- алфавит алый амнезия амфора артист баян белый биатлон брат бульвар веревка вернуть весть возраст
|
|
|
- восток горло горный десяток дятел ежевика жест жизнь жрать заговор здание зона изделие итог кабина
|
|
|
- кавалер каждый канал керосин класс клятва князь кривой крыша крючок кузнец кукла ландшафт мальчик
|
|
|
- масса масштаб матрос мрак муравей мычать негодяй носок ночной нрав оборот оружие открытие оттенок
|
|
|
- палуба пароход период пехота печать письмо позор полтора понятие поцелуй почему приступ пруд пятно
|
|
|
- ранее режим речь роса рынок рябой седой сердце сквозь смех снимок сойти соперник спичка стон
|
|
|
- сувенир сугроб суть сцена театр тираж толк удивить улыбка фирма читатель эстония эстрада юность
|
|
|
- """
|
|
|
-def make_brainwallet_file(fn):
|
|
|
- # Print random words with random whitespace in between
|
|
|
- wl = rwords.split()
|
|
|
- nwords,ws_list,max_spaces = 10,' \n',5
|
|
|
- def rand_ws_seq():
|
|
|
- nchars = getrandnum(1) % max_spaces + 1
|
|
|
- return ''.join([ws_list[getrandnum_range(1,200) % len(ws_list)] for i in range(nchars)])
|
|
|
- rand_pairs = [wl[getrandnum_range(1,200) % len(wl)] + rand_ws_seq() for i in range(nwords)]
|
|
|
- d = ''.join(rand_pairs).rstrip() + '\n'
|
|
|
- if opt.verbose: msg_r('Brainwallet password:\n{}'.format(cyan(d)))
|
|
|
- write_data_to_file(fn,d,'brainwallet password',silent=True,ignore_opt_outdir=True)
|
|
|
-
|
|
|
-def confirm_continue():
|
|
|
- if keypress_confirm(blue('Continue?'),default_yes=True):
|
|
|
- if opt.verbose or opt.exact_output: sys.stderr.write('\n')
|
|
|
- else:
|
|
|
- raise KeyboardInterrupt('Exiting at user request')
|
|
|
-
|
|
|
-def do_between():
|
|
|
- if opt.pause:
|
|
|
- confirm_continue()
|
|
|
- elif opt.verbose or opt.exact_output:
|
|
|
- sys.stderr.write('\n')
|
|
|
-
|
|
|
-rebuild_list = OrderedDict()
|
|
|
-
|
|
|
-def check_needs_rerun(
|
|
|
- ts,
|
|
|
- cmd,
|
|
|
- build=False,
|
|
|
- root=True,
|
|
|
- force_delete=False,
|
|
|
- dpy=False
|
|
|
- ):
|
|
|
-
|
|
|
- rerun = (False,True)[root] # force_delete is not passed to recursive call
|
|
|
-
|
|
|
- fns = []
|
|
|
- if force_delete or not root:
|
|
|
- # does cmd produce a needed dependency(ies)?
|
|
|
- ret = ts.get_num_exts_for_cmd(cmd,dpy)
|
|
|
- if ret:
|
|
|
- for ext in ret[1]:
|
|
|
- fn = get_file_with_ext(ext,cfgs[ret[0]]['tmpdir'],delete=build)
|
|
|
- if fn:
|
|
|
- if force_delete: os.unlink(fn)
|
|
|
- else: fns.append(fn)
|
|
|
- else: rerun = True
|
|
|
-
|
|
|
- fdeps = ts.generate_file_deps(cmd)
|
|
|
- cdeps = ts.generate_cmd_deps(fdeps)
|
|
|
-# print 'cmd,fdeps,cdeps,fns: ',cmd,fdeps,cdeps,fns # DEBUG
|
|
|
-
|
|
|
- for fn in fns:
|
|
|
- my_age = os.stat(fn).st_mtime
|
|
|
- for num,ext in fdeps:
|
|
|
- f = get_file_with_ext(ext,cfgs[num]['tmpdir'],delete=build)
|
|
|
- if f and os.stat(f).st_mtime > my_age:
|
|
|
- rerun = True
|
|
|
-
|
|
|
- for cdep in cdeps:
|
|
|
- if check_needs_rerun(ts,cdep,build=build,root=False,dpy=cmd):
|
|
|
- rerun = True
|
|
|
-
|
|
|
- if build:
|
|
|
- if rerun:
|
|
|
- for fn in fns:
|
|
|
- if not root: os.unlink(fn)
|
|
|
- if not (dpy and opt.skip_deps):
|
|
|
- ts.do_cmd(cmd)
|
|
|
- if not root: do_between()
|
|
|
- else:
|
|
|
- # If prog produces multiple files:
|
|
|
- if cmd not in rebuild_list or rerun == True:
|
|
|
- rebuild_list[cmd] = (rerun,fns[0] if fns else '') # FIX
|
|
|
-
|
|
|
- return rerun
|
|
|
-
|
|
|
-def refcheck(desc,chk,refchk):
|
|
|
- vmsg("Comparing {} '{}' to stored reference".format(desc,chk))
|
|
|
- if chk == refchk:
|
|
|
- ok()
|
|
|
- else:
|
|
|
- m = "\nFatal error - {} '{}' does not match reference value '{}'. Aborting test"
|
|
|
- raise TestSuiteFatalException(m.format(desc,chk,refchk))
|
|
|
-
|
|
|
-def check_deps(cmds):
|
|
|
- if len(cmds) != 1:
|
|
|
- die(1,'Usage: {} check_deps <command>'.format(g.prog_name))
|
|
|
-
|
|
|
- cmd = cmds[0]
|
|
|
-
|
|
|
- if cmd not in cmd_data:
|
|
|
- die(1,"'{}': unrecognized command".format(cmd))
|
|
|
-
|
|
|
- if not opt.quiet:
|
|
|
- msg("Checking dependencies for '{}'".format(cmd))
|
|
|
-
|
|
|
- check_needs_rerun(ts,cmd,build=False)
|
|
|
-
|
|
|
- w = max(map(len,rebuild_list)) + 1
|
|
|
- for cmd in rebuild_list:
|
|
|
- c = rebuild_list[cmd]
|
|
|
- m = 'Rebuild' if (c[0] and c[1]) else 'Build' if c[0] else 'OK'
|
|
|
- msg('cmd {:<{w}} {}'.format(cmd+':', m, w=w))
|
|
|
-# mmsg(cmd,c)
|
|
|
-
|
|
|
-
|
|
|
-def clean(usr_dirs=[]):
|
|
|
- if opt.skip_deps: return
|
|
|
- all_dirs = MMGenTestSuite().list_tmp_dirs()
|
|
|
- dirnums = (usr_dirs or all_dirs)
|
|
|
- for d in sorted(dirnums):
|
|
|
- if str(d) in all_dirs:
|
|
|
- cleandir(all_dirs[str(d)])
|
|
|
- else:
|
|
|
- die(1,'{}: invalid directory number'.format(d))
|
|
|
- cleandir(data_dir)
|
|
|
- cleandir(trash_dir)
|
|
|
-
|
|
|
-def skip_for_win():
|
|
|
- if g.platform == 'win':
|
|
|
- import traceback
|
|
|
- f = traceback.extract_stack()[-2][-2]
|
|
|
- msg("Skipping test '{}': not supported on Windows platform".format(f))
|
|
|
- return True
|
|
|
- else:
|
|
|
- return False
|
|
|
-
|
|
|
-class MMGenTestSuite(object):
|
|
|
-
|
|
|
- def __init__(self):
|
|
|
- pass
|
|
|
-
|
|
|
- def list_tmp_dirs(self):
|
|
|
- d = {}
|
|
|
- for k in cfgs: d[k] = cfgs[k]['tmpdir']
|
|
|
- return d
|
|
|
-
|
|
|
- def get_num_exts_for_cmd(self,cmd,dpy=False): # dpy ignored here
|
|
|
- num = str(cmd_data[cmd][0])
|
|
|
- dgl = cfgs[num]['dep_generators']
|
|
|
-# mmsg(num,cmd,dgl)
|
|
|
- if cmd in dgl.values():
|
|
|
- exts = [k for k in dgl if dgl[k] == cmd]
|
|
|
- return (num,exts)
|
|
|
- else:
|
|
|
- return None
|
|
|
-
|
|
|
- def do_cmd(self,cmd):
|
|
|
-
|
|
|
- # delete files produced by this cmd
|
|
|
-# for ext,tmpdir in find_generated_exts(cmd):
|
|
|
-# print cmd, get_file_with_ext(ext,tmpdir)
|
|
|
-
|
|
|
- d = [(str(num),ext) for exts,num in cmd_data[cmd][2] for ext in exts]
|
|
|
-
|
|
|
- # delete files depended on by this cmd
|
|
|
- al = [get_file_with_ext(ext,cfgs[num]['tmpdir']) for num,ext in d]
|
|
|
-
|
|
|
- global cfg
|
|
|
- cfg = cfgs[str(cmd_data[cmd][0])]
|
|
|
-
|
|
|
- if opt.resume:
|
|
|
- if cmd == opt.resume:
|
|
|
- ymsg("Resuming at '{}'".format(cmd))
|
|
|
- opt.resume = False
|
|
|
- opt.skip_deps = False
|
|
|
- else:
|
|
|
- return
|
|
|
-
|
|
|
- if opt.profile: start = time.time()
|
|
|
- self.__class__.__dict__[cmd](*([self,cmd] + al))
|
|
|
- if opt.profile:
|
|
|
- msg('\r\033[50C{:.4f}'.format(time.time() - start))
|
|
|
- global cmd_total
|
|
|
- cmd_total += 1
|
|
|
-
|
|
|
- if cmd == opt.exit_after:
|
|
|
- sys.exit(0)
|
|
|
-
|
|
|
- def generate_file_deps(self,cmd):
|
|
|
- return [(str(n),e) for exts,n in cmd_data[cmd][2] for e in exts]
|
|
|
-
|
|
|
- def generate_cmd_deps(self,fdeps):
|
|
|
- return [cfgs[str(n)]['dep_generators'][ext] for n,ext in fdeps]
|
|
|
-
|
|
|
- def helpscreens(self,name,arg='--help'):
|
|
|
- scripts = (
|
|
|
- 'walletgen','walletconv','walletchk','txcreate','txsign','txsend','txdo','txbump',
|
|
|
- 'addrgen','addrimport','keygen','passchg','tool','passgen','regtest','autosign')
|
|
|
- for s in scripts:
|
|
|
- t = MMGenExpect(name,('mmgen-'+s),[arg],extra_desc='(mmgen-{})'.format(s),no_output=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def longhelpscreens(self,name): self.helpscreens(name,arg='--longhelp')
|
|
|
-
|
|
|
- def walletgen(self,name,del_dw_run='dummy',seed_len=None,gen_dfl_wallet=False):
|
|
|
- write_to_tmpfile(cfg,pwfile,cfg['wpasswd']+'\n')
|
|
|
- args = ['-p1']
|
|
|
- if not gen_dfl_wallet: args += ['-d',cfg['tmpdir']]
|
|
|
- if seed_len: args += ['-l',str(seed_len)]
|
|
|
- t = MMGenExpect(name,'mmgen-walletgen', args + [usr_rand_arg])
|
|
|
- t.license()
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
- t.expect('Generating')
|
|
|
- t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
|
|
|
- t.label()
|
|
|
- global have_dfl_wallet
|
|
|
- if not have_dfl_wallet and gen_dfl_wallet:
|
|
|
- t.expect('move it to the data directory? (Y/n): ','y')
|
|
|
- have_dfl_wallet = True
|
|
|
- t.written_to_file('MMGen wallet')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def walletgen_dfl_wallet(self,name,seed_len=None):
|
|
|
- self.walletgen(name,seed_len=seed_len,gen_dfl_wallet=True)
|
|
|
-
|
|
|
- def brainwalletgen_ref(self,name):
|
|
|
- sl_arg = '-l{}'.format(cfg['seed_len'])
|
|
|
- hp_arg = '-p{}'.format(ref_wallet_hash_preset)
|
|
|
- label = "test.py ref. wallet (pw '{}', seed len {}) α".format(ref_wallet_brainpass,cfg['seed_len'])
|
|
|
- bf = 'ref.mmbrain'
|
|
|
- args = ['-d',cfg['tmpdir'],hp_arg,sl_arg,'-ib','-L',label]
|
|
|
- write_to_tmpfile(cfg,bf,ref_wallet_brainpass)
|
|
|
- write_to_tmpfile(cfg,pwfile,cfg['wpasswd'])
|
|
|
- t = MMGenExpect(name,'mmgen-walletconv', args + [usr_rand_arg])
|
|
|
- t.license()
|
|
|
- t.expect('Enter brainwallet: ', ref_wallet_brainpass+'\n')
|
|
|
- t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
- sid = os.path.basename(t.written_to_file('MMGen wallet')).split('-')[0]
|
|
|
- refcheck('Seed ID',sid,cfg['seed_id'])
|
|
|
-
|
|
|
- def refwalletgen(self,name): self.brainwalletgen_ref(name)
|
|
|
-
|
|
|
- def passchg(self,name,wf,pf,label_action='cmdline'):
|
|
|
- silence()
|
|
|
- write_to_tmpfile(cfg,pwfile,get_data_from_file(pf))
|
|
|
- end_silence()
|
|
|
- add_args = {'cmdline': ['-d',cfg['tmpdir'],'-L','Changed label (UTF-8) α'],
|
|
|
- 'keep': ['-d',trash_dir,'--keep-label'],
|
|
|
- 'user': ['-d',trash_dir]
|
|
|
- }[label_action]
|
|
|
- t = MMGenExpect(name,'mmgen-passchg', add_args + [usr_rand_arg, '-p2'] + ([],[wf])[bool(wf)])
|
|
|
- t.license()
|
|
|
- t.passphrase('MMGen wallet',cfgs['1']['wpasswd'],pwtype='old')
|
|
|
- t.expect_getend('Hash preset changed to ')
|
|
|
- t.passphrase('MMGen wallet',cfg['wpasswd'],pwtype='new') # reuse passphrase?
|
|
|
- t.expect('Repeat passphrase: ',cfg['wpasswd']+'\n')
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
- if label_action == 'user':
|
|
|
- t.expect('Enter a wallet label.*: ','Interactive Label (UTF-8) α\n',regex=True)
|
|
|
- t.expect_getend(('Label changed to ','Reusing label ')[label_action=='keep'])
|
|
|
-# t.expect_getend('Key ID changed: ')
|
|
|
- if not wf:
|
|
|
- t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
|
|
|
- t.written_to_file('New wallet')
|
|
|
- t.expect('Securely deleting old wallet')
|
|
|
-# t.expect('Okay to WIPE 1 regular file ? (Yes/No)','Yes\n')
|
|
|
- t.expect('Wallet passphrase has changed')
|
|
|
- t.expect_getend('has been changed to ')
|
|
|
- else:
|
|
|
- t.written_to_file('MMGen wallet')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def passchg_keeplabel(self,name,wf,pf):
|
|
|
- return self.passchg(name,wf,pf,label_action='keep')
|
|
|
-
|
|
|
- def passchg_usrlabel(self,name,wf,pf):
|
|
|
- return self.passchg(name,wf,pf,label_action='user')
|
|
|
-
|
|
|
- def passchg_dfl_wallet(self,name,pf):
|
|
|
- return self.passchg(name=name,wf=None,pf=pf)
|
|
|
-
|
|
|
- def walletchk(self,name,wf,pf,desc='MMGen wallet',add_args=[],sid=None,pw=False,extra_desc=''):
|
|
|
- args = []
|
|
|
- hp = cfg['hash_preset'] if 'hash_preset' in cfg else '1'
|
|
|
- wf_arg = [wf] if wf else []
|
|
|
- t = MMGenExpect(name,'mmgen-walletchk',
|
|
|
- add_args+args+['-p',hp]+wf_arg,
|
|
|
- extra_desc=extra_desc)
|
|
|
- if desc != 'hidden incognito data':
|
|
|
- t.expect("Getting {} from file '".format(desc))
|
|
|
- if pw:
|
|
|
- t.passphrase(desc,cfg['wpasswd'])
|
|
|
- t.expect(['Passphrase is OK', 'Passphrase.* are correct'],regex=True)
|
|
|
- chk = t.expect_getend('Valid {} for Seed ID '.format(desc))[:8]
|
|
|
- if sid: t.cmp_or_die(chk,sid)
|
|
|
- else: t.ok()
|
|
|
-
|
|
|
- def walletchk_newpass(self,name,wf,pf):
|
|
|
- return self.walletchk(name,wf,pf,pw=True)
|
|
|
-
|
|
|
- def walletchk_newpass_dfl_wallet(self,name,pf):
|
|
|
- return self.walletchk_newpass(name,wf=None,pf=pf)
|
|
|
-
|
|
|
- def delete_dfl_wallet(self,name,pf):
|
|
|
- with open(os.path.join(cfg['tmpdir'],'del_dw_run'),'w') as f: pass
|
|
|
- if opt.no_dw_delete: return True
|
|
|
- for wf in [f for f in os.listdir(g.data_dir) if f[-6:]=='.mmdat']:
|
|
|
- os.unlink(os.path.join(g.data_dir,wf))
|
|
|
- MMGenExpect(name,'',msg_only=True)
|
|
|
- global have_dfl_wallet
|
|
|
- have_dfl_wallet = False
|
|
|
- ok()
|
|
|
-
|
|
|
- def addrgen(self,name,wf,pf=None,check_ref=False,ftype='addr',id_str=None,extra_args=[],mmtype=None):
|
|
|
- if ftype[:4] != 'pass' and not mmtype:
|
|
|
- if cfg['segwit']: mmtype = ('segwit','bech32')[bool(opt.bech32)]
|
|
|
- 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] if id_str else []) +
|
|
|
- [cfg['{}_idx_list'.format(cmd_pfx)]],
|
|
|
- extra_desc='({})'.format(mmtype) if mmtype in ('segwit','bech32') else '')
|
|
|
- t.license()
|
|
|
- t.passphrase('MMGen wallet',cfg['wpasswd'])
|
|
|
- t.expect('Passphrase is OK')
|
|
|
- desc = ('address','password')[ftype[:4]=='pass']
|
|
|
- chk = t.expect_getend(r'Checksum for {} data .*?: '.format(desc),regex=True)
|
|
|
- if ftype[:4] == 'pass':
|
|
|
- t.expect('Encrypt password list? (y/N): ','\n')
|
|
|
- t.written_to_file('Password list',oo=True)
|
|
|
- else:
|
|
|
- t.written_to_file('Addresses',oo=True)
|
|
|
- if check_ref:
|
|
|
- try: k = { 'pass32': 'passfile32_chk',
|
|
|
- 'passhex': 'passfilehex_chk',
|
|
|
- 'pass': 'passfile_chk'}[ftype]
|
|
|
- except: k = '{}file{}_chk'.format(ftype,'_'+mmtype if mmtype else '')
|
|
|
- chk_ref = cfg[k] if ftype[:4] == 'pass' else cfg[k][fork][g.testnet]
|
|
|
- refcheck('{}list data checksum'.format(ftype),chk,chk_ref)
|
|
|
- else:
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def addrgen_dfl_wallet(self,name,pf=None,check_ref=False):
|
|
|
- return self.addrgen(name,wf=None,pf=pf,check_ref=check_ref)
|
|
|
-
|
|
|
- def refaddrgen(self,name,wf,pf):
|
|
|
- self.addrgen(name,wf,pf=pf,check_ref=True)
|
|
|
-
|
|
|
- def refaddrgen_compressed(self,name,wf,pf):
|
|
|
- if opt.segwit or opt.bech32:
|
|
|
- msg('Skipping non-Segwit address generation'); return True
|
|
|
- self.addrgen(name,wf,pf=pf,check_ref=True,mmtype='compressed')
|
|
|
-
|
|
|
- def txcreate_ui_common(self,t,name,
|
|
|
- menu=[],inputs='1',
|
|
|
- file_desc='Transaction',
|
|
|
- input_sels_prompt='to spend',
|
|
|
- bad_input_sels=False,non_mmgen_inputs=0,
|
|
|
- interactive_fee='',
|
|
|
- fee_desc='transaction fee',fee_res=None,eth_fee_res=None,
|
|
|
- add_comment='',view='t',save=True,no_ok=False):
|
|
|
- for choice in menu + ['q']:
|
|
|
- t.expect(r'\[q\]uit view, .*?:.',choice,regex=True)
|
|
|
- if bad_input_sels:
|
|
|
- for r in ('x','3-1','9999'):
|
|
|
- t.expect(input_sels_prompt+': ',r+'\n')
|
|
|
- t.expect(input_sels_prompt+': ',inputs+'\n')
|
|
|
-
|
|
|
- if not name[:4] == 'txdo':
|
|
|
- for i in range(non_mmgen_inputs):
|
|
|
- t.expect('Accept? (y/N): ','y')
|
|
|
-
|
|
|
- have_est_fee = t.expect([fee_desc+': ','OK? (Y/n): ']) == 1
|
|
|
- if have_est_fee and not interactive_fee:
|
|
|
- t.send('y')
|
|
|
- else:
|
|
|
- if have_est_fee: t.send('n')
|
|
|
- if eth_fee_res:
|
|
|
- t.expect('or gas price: ',interactive_fee+'\n')
|
|
|
- else:
|
|
|
- t.send(interactive_fee+'\n')
|
|
|
- if fee_res: t.expect(fee_res)
|
|
|
- t.expect('OK? (Y/n): ','y')
|
|
|
-
|
|
|
- t.expect('(Y/n): ','\n') # chg amt OK?
|
|
|
- t.do_comment(add_comment)
|
|
|
- t.view_tx(view)
|
|
|
- if not name[:4] == 'txdo':
|
|
|
- t.expect('(y/N): ',('n','y')[save])
|
|
|
- t.written_to_file(file_desc)
|
|
|
- if not no_ok: t.ok()
|
|
|
-
|
|
|
- def txsign_ui_common(self,t,name, view='t',add_comment='',
|
|
|
- ni=False,save=True,do_passwd=False,
|
|
|
- file_desc='Signed transaction',no_ok=False,has_label=False):
|
|
|
- txdo = name[:4] == 'txdo'
|
|
|
-
|
|
|
- if do_passwd:
|
|
|
- t.passphrase('MMGen wallet',cfg['wpasswd'])
|
|
|
-
|
|
|
- if not ni and not txdo:
|
|
|
- t.view_tx(view)
|
|
|
- t.do_comment(add_comment,has_label=has_label)
|
|
|
- t.expect('(Y/n): ',('n','y')[save])
|
|
|
-
|
|
|
- t.written_to_file(file_desc)
|
|
|
-
|
|
|
- if not txdo and not no_ok: t.ok()
|
|
|
-
|
|
|
- def do_confirm_send(self,t,quiet=False,confirm_send=True):
|
|
|
- t.expect('Are you sure you want to broadcast this')
|
|
|
- m = ('YES, I REALLY WANT TO DO THIS','YES')[quiet]
|
|
|
- t.expect("'{}' to confirm: ".format(m),('',m)[confirm_send]+'\n')
|
|
|
-
|
|
|
- def txsend_ui_common(self,t,name, view='n',add_comment='',
|
|
|
- confirm_send=True,bogus_send=True,quiet=False,
|
|
|
- file_desc='Sent transaction',no_ok=False,has_label=False):
|
|
|
-
|
|
|
- txdo = name[:4] == 'txdo'
|
|
|
- if not txdo:
|
|
|
- t.license() # MMGEN_NO_LICENSE is set, so does nothing
|
|
|
- t.view_tx(view)
|
|
|
- t.do_comment(add_comment,has_label=has_label)
|
|
|
-
|
|
|
- self.do_confirm_send(t,quiet=quiet,confirm_send=confirm_send)
|
|
|
-
|
|
|
- if bogus_send:
|
|
|
- txid = ''
|
|
|
- t.expect('BOGUS transaction NOT sent')
|
|
|
- else:
|
|
|
- txid = t.expect_getend('Transaction sent: ')
|
|
|
- assert len(txid) == 64,"'{}': Incorrect txid length!".format(txid)
|
|
|
-
|
|
|
- t.written_to_file(file_desc)
|
|
|
- if not txdo and not no_ok: t.ok()
|
|
|
-
|
|
|
- return txid
|
|
|
-
|
|
|
- def txcreate_common(self,name,
|
|
|
- sources=['1'],
|
|
|
- non_mmgen_input='',
|
|
|
- do_label=False,
|
|
|
- txdo_args=[],
|
|
|
- add_args=[],
|
|
|
- view='n',
|
|
|
- addrs_per_wallet=addrs_per_wallet,
|
|
|
- non_mmgen_input_compressed=True,
|
|
|
- cmdline_inputs=False):
|
|
|
-
|
|
|
- if opt.verbose or opt.exact_output:
|
|
|
- sys.stderr.write(green('Generating fake tracking wallet info\n'))
|
|
|
-
|
|
|
- silence()
|
|
|
- ad,tx_data = create_tx_data(sources,addrs_per_wallet)
|
|
|
- dfake = create_fake_unspent_data(ad,tx_data,non_mmgen_input,non_mmgen_input_compressed)
|
|
|
- write_fake_data_to_file(repr(dfake))
|
|
|
- cmd_args = make_txcreate_cmdline(tx_data)
|
|
|
- if cmdline_inputs:
|
|
|
- from mmgen.tx import TwLabel
|
|
|
- cmd_args = ['--inputs={},{},{},{},{},{}'.format(
|
|
|
- TwLabel(dfake[0][lbl_id]).mmid,dfake[1]['address'],
|
|
|
- TwLabel(dfake[2][lbl_id]).mmid,dfake[3]['address'],
|
|
|
- TwLabel(dfake[4][lbl_id]).mmid,dfake[5]['address']
|
|
|
- ),'--outdir='+trash_dir] + cmd_args[1:]
|
|
|
- end_silence()
|
|
|
-
|
|
|
- if opt.verbose or opt.exact_output: sys.stderr.write('\n')
|
|
|
-
|
|
|
- t = MMGenExpect(name,
|
|
|
- 'mmgen-'+('txcreate','txdo')[bool(txdo_args)],
|
|
|
- ([],['--rbf'])[g.proto.cap('rbf')] +
|
|
|
- ['-f',tx_fee,'-B'] + add_args + cmd_args + txdo_args)
|
|
|
-
|
|
|
- if t.expect([('Get','Transac')[cmdline_inputs],'Unable to connect to \S+'],regex=True) == 1:
|
|
|
- raise TestSuiteException('\n'+t.p.after)
|
|
|
-
|
|
|
- if cmdline_inputs:
|
|
|
- t.written_to_file('tion')
|
|
|
- t.ok()
|
|
|
- return
|
|
|
-
|
|
|
- t.license()
|
|
|
-
|
|
|
- if txdo_args and add_args: # txdo4
|
|
|
- t.do_decrypt_ka_data(hp='1',pw=cfgs['14']['kapasswd'])
|
|
|
-
|
|
|
- for num in tx_data:
|
|
|
- t.expect_getend('ting address data from file ')
|
|
|
- chk=t.expect_getend(r'Checksum for address data .*?: ',regex=True)
|
|
|
- verify_checksum_or_exit(tx_data[num]['chk'],chk)
|
|
|
-
|
|
|
- # not in tracking wallet warning, (1 + num sources) times
|
|
|
- for num in range(len(tx_data) + 1):
|
|
|
- t.expect('Continue anyway? (y/N): ','y')
|
|
|
-
|
|
|
- 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)
|
|
|
-
|
|
|
- self.txcreate_ui_common(t,name,
|
|
|
- menu=(['M'],['M','D','m','g'])[name=='txcreate'],
|
|
|
- inputs=' '.join(map(str,outputs_list)),
|
|
|
- add_comment=('',ref_tx_label_lat_cyr_gr)[do_label],
|
|
|
- non_mmgen_inputs=(0,1)[bool(non_mmgen_input and not txdo_args)],
|
|
|
- view=view)
|
|
|
-
|
|
|
- return t
|
|
|
-
|
|
|
- def txcreate(self,name,addrfile):
|
|
|
- self.txcreate_common(name,sources=['1'],add_args=['--vsize-adj=1.01'])
|
|
|
-
|
|
|
- def txcreate_ni(self,name,addrfile):
|
|
|
- self.txcreate_common(name,sources=['1'],cmdline_inputs=True,add_args=['--yes'])
|
|
|
-
|
|
|
- def txbump(self,name,txfile,prepend_args=[],seed_args=[]):
|
|
|
- if not g.proto.cap('rbf'):
|
|
|
- msg('Skipping RBF'); return True
|
|
|
- args = prepend_args + ['--quiet','--outdir='+cfg['tmpdir'],txfile] + seed_args
|
|
|
- t = MMGenExpect(name,'mmgen-txbump',args)
|
|
|
- if seed_args:
|
|
|
- t.do_decrypt_ka_data(hp='1',pw=cfgs['14']['kapasswd'])
|
|
|
- t.expect('deduct the fee from (Hit ENTER for the change output): ','1\n')
|
|
|
- # Fee must be > tx_fee + network relay fee (currently 0.00001)
|
|
|
- t.expect('OK? (Y/n): ','\n')
|
|
|
- t.expect('Enter transaction fee: ',txbump_fee+'\n')
|
|
|
- t.expect('OK? (Y/n): ','\n')
|
|
|
- if seed_args: # sign and send
|
|
|
- t.do_comment(False,has_label=True)
|
|
|
- for cnum,desc in (('1','incognito data'),('3','MMGen wallet'),('4','MMGen wallet')):
|
|
|
- t.passphrase(desc,cfgs[cnum]['wpasswd'])
|
|
|
- self.do_confirm_send(t,quiet=not g.debug,confirm_send=True)
|
|
|
- if g.debug:
|
|
|
- t.written_to_file('Transaction')
|
|
|
- else:
|
|
|
- t.do_comment(False)
|
|
|
- t.expect('Save transaction? (y/N): ','y')
|
|
|
- t.written_to_file('Transaction')
|
|
|
- os.unlink(txfile) # our tx file replaces the original
|
|
|
- cmd = 'touch ' + os.path.join(cfg['tmpdir'],'txbump')
|
|
|
- os.system(cmd.encode())
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def txdo(self,name,addrfile,wallet):
|
|
|
- t = self.txcreate_common(name,sources=['1'],txdo_args=[wallet])
|
|
|
- self.txsign_ui_common(t,name,view='n',do_passwd=True)
|
|
|
- self.txsend_ui_common(t,name)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def txcreate_dfl_wallet(self,name,addrfile):
|
|
|
- self.txcreate_common(name,sources=['15'])
|
|
|
-
|
|
|
- def txsign_end(self,t,tnum=None,has_label=False):
|
|
|
- t.expect('Signing transaction')
|
|
|
- t.do_comment(False,has_label=has_label)
|
|
|
- t.expect('Save signed transaction.*?\? \(Y/n\): ','y',regex=True)
|
|
|
- t.written_to_file('Signed transaction' + (' #' + tnum if tnum else ''), oo=True)
|
|
|
-
|
|
|
- def txsign(self,name,txfile,wf,pf='',bumpf='',save=True,has_label=False,do_passwd=True,extra_opts=[]):
|
|
|
- t = MMGenExpect(name,'mmgen-txsign', extra_opts + ['-d',cfg['tmpdir'],txfile]+([],[wf])[bool(wf)])
|
|
|
- t.license()
|
|
|
- t.view_tx('n')
|
|
|
- if do_passwd: t.passphrase('MMGen wallet',cfg['wpasswd'])
|
|
|
- if save:
|
|
|
- self.txsign_end(t,has_label=has_label)
|
|
|
- t.ok()
|
|
|
- else:
|
|
|
- t.do_comment(False,has_label=has_label)
|
|
|
- t.expect('Save signed transaction? (Y/n): ','n')
|
|
|
- t.ok(exit_val=1)
|
|
|
-
|
|
|
- def txsign_dfl_wallet(self,name,txfile,pf='',save=True,has_label=False):
|
|
|
- return self.txsign(name,txfile,wf=None,pf=pf,save=save,has_label=has_label)
|
|
|
-
|
|
|
- def txsend(self,name,sigfile,bogus_send=True,extra_opts=[]):
|
|
|
- if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = ''
|
|
|
- t = MMGenExpect(name,'mmgen-txsend', extra_opts + ['-d',cfg['tmpdir'],sigfile])
|
|
|
- if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = '1'
|
|
|
- self.txsend_ui_common(t,name,view='t',add_comment='')
|
|
|
-
|
|
|
- def walletconv_export(self,name,wf,desc,uargs=[],out_fmt='w',pf=None,out_pw=False):
|
|
|
- opts = ['-d',cfg['tmpdir'],'-o',out_fmt] + uargs + \
|
|
|
- ([],[wf])[bool(wf)] + ([],['-P',pf])[bool(pf)]
|
|
|
- t = MMGenExpect(name,'mmgen-walletconv',opts)
|
|
|
- t.license()
|
|
|
- if not pf:
|
|
|
- t.passphrase('MMGen wallet',cfg['wpasswd'])
|
|
|
- if out_pw:
|
|
|
- t.passphrase_new('new '+desc,cfg['wpasswd'])
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
-
|
|
|
- if ' '.join(desc.split()[-2:]) == 'incognito data':
|
|
|
- m = 'Generating encryption key from OS random data '
|
|
|
- t.expect(m); t.expect(m)
|
|
|
- ic_id = t.expect_getend('New Incog Wallet ID: ')
|
|
|
- t.expect(m)
|
|
|
- if desc == 'hidden incognito data':
|
|
|
- write_to_tmpfile(cfg,incog_id_fn,ic_id)
|
|
|
- ret = t.expect(['Create? (Y/n): ',"'YES' to confirm: "])
|
|
|
- if ret == 0:
|
|
|
- t.send('\n')
|
|
|
- t.expect('Enter file size: ',str(hincog_bytes)+'\n')
|
|
|
- else:
|
|
|
- t.send('YES\n')
|
|
|
- if out_fmt == 'w': t.label()
|
|
|
- return t.written_to_file(capfirst(desc),oo=True),t
|
|
|
-
|
|
|
- def export_seed(self,name,wf,desc='seed data',out_fmt='seed',pf=None):
|
|
|
- f,t = self.walletconv_export(name,wf,desc=desc,out_fmt=out_fmt,pf=pf)
|
|
|
- silence()
|
|
|
- msg('{}: {}'.format(capfirst(desc),cyan(get_data_from_file(f,desc))))
|
|
|
- end_silence()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def export_hex(self,name,wf,desc='hexadecimal seed data',out_fmt='hex',pf=None):
|
|
|
- self.export_seed(name,wf,desc=desc,out_fmt=out_fmt,pf=pf)
|
|
|
-
|
|
|
- def export_seed_dfl_wallet(self,name,pf,desc='seed data',out_fmt='seed'):
|
|
|
- self.export_seed(name,wf=None,desc=desc,out_fmt=out_fmt,pf=pf)
|
|
|
-
|
|
|
- def export_mnemonic(self,name,wf):
|
|
|
- self.export_seed(name,wf,desc='mnemonic data',out_fmt='words')
|
|
|
-
|
|
|
- def export_incog(self,name,wf,desc='incognito data',out_fmt='i',add_args=[]):
|
|
|
- uargs = ['-p1',usr_rand_arg] + add_args
|
|
|
- f,t = self.walletconv_export(name,wf,desc=desc,out_fmt=out_fmt,uargs=uargs,out_pw=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def export_incog_hex(self,name,wf):
|
|
|
- self.export_incog(name,wf,desc='hex incognito data',out_fmt='xi')
|
|
|
-
|
|
|
- # TODO: make outdir and hidden incog compatible (ignore --outdir and warn user?)
|
|
|
- def export_incog_hidden(self,name,wf):
|
|
|
- rf = os.path.join(cfg['tmpdir'],hincog_fn)
|
|
|
- add_args = ['-J','{},{}'.format(rf,hincog_offset)]
|
|
|
- self.export_incog(
|
|
|
- name,wf,desc='hidden incognito data',out_fmt='hi',add_args=add_args)
|
|
|
-
|
|
|
- def addrgen_seed(self,name,wf,foo,desc='seed data',in_fmt='seed'):
|
|
|
- stdout = (False,True)[desc=='seed data'] #capture output to screen once
|
|
|
- add_args = ([],['-S'])[bool(stdout)] + get_segwit_arg(cfg)
|
|
|
- t = MMGenExpect(name,'mmgen-addrgen', add_args +
|
|
|
- ['-i'+in_fmt,'-d',cfg['tmpdir'],wf,cfg['addr_idx_list']])
|
|
|
- t.license()
|
|
|
- t.expect_getend('Valid {} for Seed ID '.format(desc))
|
|
|
- vmsg('Comparing generated checksum with checksum from previous address file')
|
|
|
- chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
|
|
|
- if stdout: t.read()
|
|
|
- verify_checksum_or_exit(get_addrfile_checksum(),chk)
|
|
|
- if in_fmt == 'seed':
|
|
|
- t.ok()
|
|
|
- else:
|
|
|
- t.no_overwrite()
|
|
|
- t.ok(exit_val=1)
|
|
|
-
|
|
|
- def addrgen_hex(self,name,wf,foo,desc='hexadecimal seed data',in_fmt='hex'):
|
|
|
- self.addrgen_seed(name,wf,foo,desc=desc,in_fmt=in_fmt)
|
|
|
-
|
|
|
- def addrgen_mnemonic(self,name,wf,foo):
|
|
|
- self.addrgen_seed(name,wf,foo,desc='mnemonic data',in_fmt='words')
|
|
|
-
|
|
|
- def addrgen_incog(self,name,wf=[],foo='',in_fmt='i',desc='incognito data',args=[]):
|
|
|
- t = MMGenExpect(name,'mmgen-addrgen', args + get_segwit_arg(cfg) + ['-i'+in_fmt,'-d',cfg['tmpdir']]+
|
|
|
- ([],[wf])[bool(wf)] + [cfg['addr_idx_list']])
|
|
|
- t.license()
|
|
|
- t.expect_getend('Incog Wallet ID: ')
|
|
|
- t.hash_preset(desc,'1')
|
|
|
- t.passphrase('{} \w{{8}}'.format(desc),cfg['wpasswd'])
|
|
|
- vmsg('Comparing generated checksum with checksum from address file')
|
|
|
- chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
|
|
|
- verify_checksum_or_exit(get_addrfile_checksum(),chk)
|
|
|
- t.no_overwrite()
|
|
|
- t.ok(exit_val=1)
|
|
|
-
|
|
|
- def addrgen_incog_hex(self,name,wf,foo):
|
|
|
- self.addrgen_incog(name,wf,'',in_fmt='xi',desc='hex incognito data')
|
|
|
-
|
|
|
- def addrgen_incog_hidden(self,name,wf,foo):
|
|
|
- rf = os.path.join(cfg['tmpdir'],hincog_fn)
|
|
|
- self.addrgen_incog(name,[],'',in_fmt='hi',desc='hidden incognito data',
|
|
|
- args=['-H','{},{}'.format(rf,hincog_offset),'-l',str(hincog_seedlen)])
|
|
|
-
|
|
|
- def keyaddrgen(self,name,wf,pf=None,check_ref=False,mmtype=None):
|
|
|
- if cfg['segwit'] and not mmtype:
|
|
|
- mmtype = ('segwit','bech32')[bool(opt.bech32)]
|
|
|
- args = ['-d',cfg['tmpdir'],usr_rand_arg,wf,cfg['addr_idx_list']]
|
|
|
- t = MMGenExpect(name,'mmgen-keygen',
|
|
|
- ([],['--type='+str(mmtype)])[bool(mmtype)] + args,
|
|
|
- extra_desc='({})'.format(mmtype) if mmtype in ('segwit','bech32') else '')
|
|
|
- t.license()
|
|
|
- t.passphrase('MMGen wallet',cfg['wpasswd'])
|
|
|
- chk = t.expect_getend(r'Checksum for key-address data .*?: ',regex=True)
|
|
|
- if check_ref:
|
|
|
- k = 'keyaddrfile{}_chk'.format('_'+mmtype if mmtype else '')
|
|
|
- refcheck('key-address data checksum',chk,cfg[k][fork][g.testnet])
|
|
|
- return
|
|
|
- t.expect('Encrypt key list? (y/N): ','y')
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
- t.hash_preset('new key list','1')
|
|
|
- t.passphrase_new('new key list',cfg['kapasswd'])
|
|
|
- t.written_to_file('Encrypted secret keys',oo=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def refkeyaddrgen(self,name,wf,pf):
|
|
|
- self.keyaddrgen(name,wf,pf,check_ref=True)
|
|
|
-
|
|
|
- def refkeyaddrgen_compressed(self,name,wf,pf):
|
|
|
- if opt.segwit or opt.bech32:
|
|
|
- msg('Skipping non-Segwit key-address generation'); return True
|
|
|
- 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')
|
|
|
-
|
|
|
- def ref_b32passwdgen(self,name,wf,pf):
|
|
|
- ea = ['--base32','--passwd-len','17']
|
|
|
- self.addrgen(name,wf,pf,check_ref=True,ftype='pass32',id_str='фубар@crypto.org',extra_args=ea)
|
|
|
-
|
|
|
- def ref_hexpasswdgen(self,name,wf,pf):
|
|
|
- ea = ['--hex']
|
|
|
- self.addrgen(name,wf,pf,check_ref=True,ftype='passhex',id_str='фубар@crypto.org',extra_args=ea)
|
|
|
-
|
|
|
- def txsign_keyaddr(self,name,keyaddr_file,txfile):
|
|
|
- t = MMGenExpect(name,'mmgen-txsign', ['-d',cfg['tmpdir'],'-M',keyaddr_file,txfile])
|
|
|
- t.license()
|
|
|
- t.do_decrypt_ka_data(hp='1',pw=cfg['kapasswd'])
|
|
|
- t.view_tx('n')
|
|
|
- self.txsign_end(t)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def walletgen2(self,name,del_dw_run='dummy'):
|
|
|
- self.walletgen(name,seed_len=128)
|
|
|
-
|
|
|
- def addrgen2(self,name,wf):
|
|
|
- self.addrgen(name,wf,pf='')
|
|
|
-
|
|
|
- def txcreate2(self,name,addrfile):
|
|
|
- self.txcreate_common(name,sources=['2'])
|
|
|
-
|
|
|
- def txsign2(self,name,txf1,wf1,txf2,wf2):
|
|
|
- t = MMGenExpect(name,'mmgen-txsign', ['-d',cfg['tmpdir'],txf1,wf1,txf2,wf2])
|
|
|
- t.license()
|
|
|
- for cnum in ('1','2'):
|
|
|
- t.view_tx('n')
|
|
|
- t.passphrase('MMGen wallet',cfgs[cnum]['wpasswd'])
|
|
|
- self.txsign_end(t,cnum)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def export_mnemonic2(self,name,wf):
|
|
|
- self.export_mnemonic(name,wf)
|
|
|
-
|
|
|
- def walletgen3(self,name,del_dw_run='dummy'):
|
|
|
- self.walletgen(name)
|
|
|
-
|
|
|
- def addrgen3(self,name,wf):
|
|
|
- self.addrgen(name,wf,pf='')
|
|
|
-
|
|
|
- def txcreate3(self,name,addrfile1,addrfile2):
|
|
|
- self.txcreate_common(name,sources=['1','3'])
|
|
|
-
|
|
|
- def txsign3(self,name,wf1,wf2,txf2):
|
|
|
- t = MMGenExpect(name,'mmgen-txsign', ['-d',cfg['tmpdir'],wf1,wf2,txf2])
|
|
|
- t.license()
|
|
|
- t.view_tx('n')
|
|
|
- for cnum in ('1','3'):
|
|
|
- t.passphrase('MMGen wallet',cfgs[cnum]['wpasswd'])
|
|
|
- self.txsign_end(t)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def walletgen4(self,name,del_dw_run='dummy'):
|
|
|
- bwf = os.path.join(cfg['tmpdir'],cfg['bw_filename'])
|
|
|
- make_brainwallet_file(bwf)
|
|
|
- seed_len = str(cfg['seed_len'])
|
|
|
- args = ['-d',cfg['tmpdir'],'-p1',usr_rand_arg,'-l'+seed_len,'-ib']
|
|
|
- t = MMGenExpect(name,'mmgen-walletconv', args + [bwf])
|
|
|
- t.license()
|
|
|
- t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
- t.label()
|
|
|
- t.written_to_file('MMGen wallet')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def addrgen4(self,name,wf):
|
|
|
- self.addrgen(name,wf,pf='')
|
|
|
-
|
|
|
- def txcreate4(self,name,f1,f2,f3,f4,f5,f6):
|
|
|
- self.txcreate_common(name,sources=['1','2','3','4','14'],non_mmgen_input='4',do_label=True,view='y')
|
|
|
-
|
|
|
- def txdo4(self,name,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12):
|
|
|
- non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
|
|
|
- add_args = ['-d',cfg['tmpdir'],'-i','brain','-b'+cfg['bw_params'],'-p1','-k',non_mm_fn,'-M',f12]
|
|
|
- get_file_with_ext('sigtx',cfg['tmpdir'],delete_all=True) # delete tx signed by txsign4
|
|
|
- t = self.txcreate_common(name,sources=['1','2','3','4','14'],
|
|
|
- non_mmgen_input='4',do_label=True,txdo_args=[f7,f8,f9,f10],add_args=add_args)
|
|
|
-
|
|
|
- for cnum,desc in (('1','incognito data'),('3','MMGen wallet')):
|
|
|
- t.passphrase('{}'.format(desc),cfgs[cnum]['wpasswd'])
|
|
|
-
|
|
|
- self.txsign_ui_common(t,name)
|
|
|
- self.txsend_ui_common(t,name)
|
|
|
-
|
|
|
- cmd = 'touch ' + os.path.join(cfg['tmpdir'],'txdo')
|
|
|
- os.system(cmd.encode())
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def txsign4(self,name,f1,f2,f3,f4,f5,f6):
|
|
|
- non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
|
|
|
- a = ['-d',cfg['tmpdir'],'-i','brain','-b'+cfg['bw_params'],'-p1','-k',non_mm_fn,'-M',f6,f1,f2,f3,f4,f5]
|
|
|
- t = MMGenExpect(name,'mmgen-txsign',a)
|
|
|
- t.license()
|
|
|
- t.do_decrypt_ka_data(hp='1',pw=cfgs['14']['kapasswd'])
|
|
|
- t.view_tx('t')
|
|
|
-
|
|
|
- for cnum,desc in (('1','incognito data'),('3','MMGen wallet')):
|
|
|
- t.passphrase('{}'.format(desc),cfgs[cnum]['wpasswd'])
|
|
|
-
|
|
|
- self.txsign_end(t,has_label=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def txbump4(self,name,f1,f2,f3,f4,f5,f6,f7,f8,f9): # f7:txfile,f9:'txdo'
|
|
|
- non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
|
|
|
- self.txbump(name,f7,prepend_args=['-p1','-k',non_mm_fn,'-M',f1],seed_args=[f2,f3,f4,f5,f6,f8])
|
|
|
-
|
|
|
- def walletgen5(self,name,del_dw_run='dummy'):
|
|
|
- self.walletgen(name)
|
|
|
-
|
|
|
- def addrgen5(self,name,wf):
|
|
|
- self.addrgen(name,wf,pf='')
|
|
|
-
|
|
|
- def txcreate5(self,name,addrfile):
|
|
|
- self.txcreate_common(name,sources=['20'],non_mmgen_input='20',non_mmgen_input_compressed=False)
|
|
|
-
|
|
|
- def txsign5(self,name,txf,wf,bad_vsize=True,add_args=[]):
|
|
|
- non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
|
|
|
- t = MMGenExpect(name,'mmgen-txsign', add_args + ['-d',cfg['tmpdir'],'-k',non_mm_fn,txf,wf])
|
|
|
- t.license()
|
|
|
- t.view_tx('n')
|
|
|
- t.passphrase('MMGen wallet',cfgs['20']['wpasswd'])
|
|
|
- if bad_vsize:
|
|
|
- t.expect('Estimated transaction vsize')
|
|
|
- t.expect('1 transaction could not be signed')
|
|
|
- exit_val = 2
|
|
|
- else:
|
|
|
- t.do_comment(False)
|
|
|
- t.expect('Save signed transaction? (Y/n): ','y')
|
|
|
- exit_val = 0
|
|
|
- t.read()
|
|
|
- t.ok(exit_val=exit_val)
|
|
|
-
|
|
|
- def walletgen6(self,name,del_dw_run='dummy'):
|
|
|
- self.walletgen(name)
|
|
|
-
|
|
|
- def addrgen6(self,name,wf):
|
|
|
- self.addrgen(name,wf,pf='')
|
|
|
-
|
|
|
- def txcreate6(self,name,addrfile):
|
|
|
- self.txcreate_common(
|
|
|
- name,sources=['21'],non_mmgen_input='21',non_mmgen_input_compressed=False,add_args=['--vsize-adj=1.08'])
|
|
|
-
|
|
|
- def txsign6(self,name,txf,wf):
|
|
|
- return self.txsign5(name,txf,wf,bad_vsize=False,add_args=['--vsize-adj=1.08'])
|
|
|
-
|
|
|
-
|
|
|
- def tool_encrypt(self,name,infile=''):
|
|
|
- if infile:
|
|
|
- infn = infile
|
|
|
- else:
|
|
|
- d = os.urandom(1033)
|
|
|
- tmp_fn = cfg['tool_enc_infn']
|
|
|
- write_to_tmpfile(cfg,tmp_fn,d,binary=True)
|
|
|
- infn = get_tmpfile_fn(cfg,tmp_fn)
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['-d',cfg['tmpdir'],usr_rand_arg,'encrypt',infn])
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
- t.hash_preset('user data','1')
|
|
|
- t.passphrase_new('user data',tool_enc_passwd)
|
|
|
- t.written_to_file('Encrypted data')
|
|
|
- t.ok()
|
|
|
-
|
|
|
-# Generate the reference mmenc file
|
|
|
-# def tool_encrypt_ref(self,name):
|
|
|
-# infn = get_tmpfile_fn(cfg,cfg['tool_enc_ref_infn'])
|
|
|
-# write_data_to_file(infn,cfg['tool_enc_reftext'],silent=True)
|
|
|
-# self.tool_encrypt(name,infn)
|
|
|
-
|
|
|
- def tool_decrypt(self,name,f1,f2):
|
|
|
- of = name + '.out'
|
|
|
- pre = []
|
|
|
- t = MMGenExpect(name,'mmgen-tool',
|
|
|
- pre+['-d',cfg['tmpdir'],'decrypt',f2,'outfile='+of,'hash_preset=1'])
|
|
|
- t.passphrase('user data',tool_enc_passwd)
|
|
|
- t.written_to_file('Decrypted data')
|
|
|
- d1 = read_from_file(f1,binary=True)
|
|
|
- d2 = read_from_file(get_tmpfile_fn(cfg,of),binary=True)
|
|
|
- cmp_or_die(d1,d2,skip_ok=False)
|
|
|
-
|
|
|
- def tool_find_incog_data(self,name,f1,f2):
|
|
|
- i_id = read_from_file(f2).rstrip()
|
|
|
- vmsg('Incog ID: {}'.format(cyan(i_id)))
|
|
|
- t = MMGenExpect(name,'mmgen-tool',
|
|
|
- ['-d',cfg['tmpdir'],'find_incog_data',f1,i_id])
|
|
|
- o = t.expect_getend('Incog data for ID {} found at offset '.format(i_id))
|
|
|
- os.unlink(f1)
|
|
|
- cmp_or_die(hincog_offset,int(o))
|
|
|
-
|
|
|
- def autosign_live(self,name):
|
|
|
- return self.autosign_minimal(name,live=True)
|
|
|
-
|
|
|
- def autosign_minimal(self,name,live=False):
|
|
|
- return self.autosign(name,
|
|
|
- coins=['btc','eth'],
|
|
|
- txfiles=['btc','eth','erc20','etc'],
|
|
|
- txcount=7,
|
|
|
- live=live)
|
|
|
-
|
|
|
- # tests everything except device detection, mount/unmount
|
|
|
- def autosign( self,name,
|
|
|
- coins=['btc','bch','ltc','eth'],
|
|
|
- txfiles=['btc','bch','ltc','eth','erc20','etc'],
|
|
|
- txcount=11,
|
|
|
- live=False):
|
|
|
-
|
|
|
- if skip_for_win(): return
|
|
|
-
|
|
|
- def make_wallet(opts):
|
|
|
- t = MMGenExpect(name,'mmgen-autosign',opts+['gen_key'],extra_desc='(gen_key)')
|
|
|
- t.expect_getend('Wrote key file ')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- t = MMGenExpect(name,'mmgen-autosign',opts+['setup'],extra_desc='(setup)')
|
|
|
- t.expect('words: ','3')
|
|
|
- t.expect('OK? (Y/n): ','\n')
|
|
|
- mn_fn = os.path.join(ref_dir,cfgs['8']['seed_id']+'.mmwords') # 98831F3A
|
|
|
- mn = read_from_file(mn_fn).strip().split()
|
|
|
- mn = ['foo'] + mn[:5] + ['realiz','realized'] + mn[5:]
|
|
|
- wnum = 1
|
|
|
- max_wordlen = 12
|
|
|
-
|
|
|
- def get_pad_chars(n):
|
|
|
- ret = ''
|
|
|
- for i in range(n):
|
|
|
- m = int(hexlify(os.urandom(1)),16) % 32
|
|
|
- ret += r'123579!@#$%^&*()_+-=[]{}"?/,.<>|'[m]
|
|
|
- return ret
|
|
|
-
|
|
|
- for i in range(len(mn)):
|
|
|
- w = mn[i]
|
|
|
- if len(w) > 5:
|
|
|
- w = w + '\n'
|
|
|
- else:
|
|
|
- w = get_pad_chars(3 if randbool() else 0) + w[0] + get_pad_chars(3) + w[1:] + get_pad_chars(7)
|
|
|
- w = w[:max_wordlen+1]
|
|
|
- em,rm = 'Enter word #{}: ','Repeat word #{}: '
|
|
|
- ret = t.expect((em.format(wnum),rm.format(wnum-1)))
|
|
|
- if ret == 0: wnum += 1
|
|
|
- for j in range(len(w)):
|
|
|
- t.send(w[j])
|
|
|
- time.sleep(0.005)
|
|
|
- wf = t.written_to_file('Autosign wallet')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def copy_files(mountpoint,remove_signed_only=False,include_bad_tx=True):
|
|
|
- fdata_in = (('btc',''),
|
|
|
- ('bch',''),
|
|
|
- ('ltc','litecoin'),
|
|
|
- ('eth','ethereum'),
|
|
|
- ('erc20','ethereum'),
|
|
|
- ('etc','ethereum_classic'))
|
|
|
- fdata = [e for e in fdata_in if e[0] in txfiles]
|
|
|
- tfns = [cfgs['8']['ref_tx_file'][c][1] for c,d in fdata] + \
|
|
|
- [cfgs['8']['ref_tx_file'][c][0] for c,d in fdata]
|
|
|
- tfs = [os.path.join(ref_dir,d[1],fn) for d,fn in zip(fdata+fdata,tfns)]
|
|
|
-
|
|
|
- for f,fn in zip(tfs,tfns):
|
|
|
- if fn: # use empty fn to skip file
|
|
|
- target = os.path.join(mountpoint,'tx',fn)
|
|
|
- remove_signed_only or shutil.copyfile(f,target)
|
|
|
- try: os.unlink(target.replace('.rawtx','.sigtx'))
|
|
|
- except: pass
|
|
|
-
|
|
|
- # make a bad tx file
|
|
|
- bad_tx = os.path.join(mountpoint,'tx','bad.rawtx')
|
|
|
- if include_bad_tx and not remove_signed_only:
|
|
|
- with open(bad_tx,'w') as f:
|
|
|
- f.write('bad tx data')
|
|
|
- if not include_bad_tx:
|
|
|
- try: os.unlink(bad_tx)
|
|
|
- except: pass
|
|
|
-
|
|
|
- def do_autosign_live(opts,mountpoint,led_opts=[],gen_wallet=True):
|
|
|
-
|
|
|
- def do_mount():
|
|
|
- try: subprocess.check_call(['mount',mountpoint])
|
|
|
- except: pass
|
|
|
-
|
|
|
- def do_unmount():
|
|
|
- try: subprocess.check_call(['umount',mountpoint])
|
|
|
- except: pass
|
|
|
- omsg_r(blue('\nRemove removable device and then hit ENTER '))
|
|
|
- input()
|
|
|
-
|
|
|
- if gen_wallet: make_wallet(opts)
|
|
|
- else: do_mount()
|
|
|
-
|
|
|
- copy_files(mountpoint,include_bad_tx=not led_opts)
|
|
|
-
|
|
|
- desc = '(sign)'
|
|
|
- m1 = "Running 'mmgen-autosign wait'"
|
|
|
- m2 = 'Insert removable device '
|
|
|
-
|
|
|
- if led_opts:
|
|
|
- if led_opts == ['--led']:
|
|
|
- m1 = "Running 'mmgen-autosign wait' with --led. The LED should start blinking slowly now"
|
|
|
- elif led_opts == ['--stealth-led']:
|
|
|
- m1 = "Running 'mmgen-autosign wait' with --stealth-led. You should see no LED activity now"
|
|
|
- m2 = 'Insert removable device and watch for fast LED activity during signing'
|
|
|
- desc = '(sign - {})'.format(led_opts[0])
|
|
|
-
|
|
|
- def do_loop():
|
|
|
- omsg(blue(m2))
|
|
|
- t.expect('{} transactions signed'.format(txcount))
|
|
|
- if not led_opts:
|
|
|
- t.expect('1 transaction failed to sign')
|
|
|
- t.expect('Waiting')
|
|
|
-
|
|
|
- do_unmount()
|
|
|
- omsg(green(m1))
|
|
|
- t = MMGenExpect(name,'mmgen-autosign',opts+led_opts+['wait'],extra_desc=desc)
|
|
|
- if not opt.exact_output: omsg('')
|
|
|
- do_loop()
|
|
|
- do_mount() # race condition due to device insertion detection
|
|
|
- copy_files(mountpoint,remove_signed_only=True,include_bad_tx=not led_opts)
|
|
|
- do_unmount()
|
|
|
- do_loop()
|
|
|
- t.kill(2)
|
|
|
- t.ok(exit_val=1)
|
|
|
-
|
|
|
- def do_autosign(opts,mountpoint):
|
|
|
- make_wallet(opts)
|
|
|
- copy_files(mountpoint,include_bad_tx=True)
|
|
|
- t = MMGenExpect(name,'mmgen-autosign',opts+['wait'],extra_desc='(sign)')
|
|
|
- t.expect('{} transactions signed'.format(txcount))
|
|
|
- t.expect('1 transaction failed to sign')
|
|
|
- t.expect('Waiting')
|
|
|
- t.kill(2)
|
|
|
- t.ok(exit_val=1)
|
|
|
-
|
|
|
- if live:
|
|
|
- mountpoint = '/mnt/tx'
|
|
|
- if not os.path.ismount(mountpoint):
|
|
|
- try:
|
|
|
- subprocess.check_call(['mount',mountpoint])
|
|
|
- imsg("Mounted '{}'".format(mountpoint))
|
|
|
- except:
|
|
|
- imsg("Could not mount '{}'! Exiting".format(mountpoint))
|
|
|
- return
|
|
|
-
|
|
|
- txdir = os.path.join(mountpoint,'tx')
|
|
|
- if not os.path.isdir(txdir):
|
|
|
- imsg("Directory '{}' does not exist! Exiting".format(mountpoint))
|
|
|
- return
|
|
|
-
|
|
|
- opts = ['--coins='+','.join(coins)]
|
|
|
- led_files = { 'opi': ('/sys/class/leds/orangepi:red:status/brightness',),
|
|
|
- 'rpi': ('/sys/class/leds/led0/brightness','/sys/class/leds/led0/trigger') }
|
|
|
- for k in ('opi','rpi'):
|
|
|
- if os.path.exists(led_files[k][0]):
|
|
|
- led_support = k
|
|
|
- break
|
|
|
- else:
|
|
|
- led_support = None
|
|
|
-
|
|
|
- if led_support:
|
|
|
- for fn in (led_files[led_support]):
|
|
|
- subprocess.check_call(['sudo','chmod','0666',fn])
|
|
|
- omsg(purple('Running autosign test with no LED'))
|
|
|
- do_autosign_live(opts,mountpoint)
|
|
|
- omsg(purple("Running autosign test with '--led'"))
|
|
|
- do_autosign_live(opts,mountpoint,led_opts=['--led'],gen_wallet=False)
|
|
|
- omsg(purple("Running autosign test with '--stealth-led'"))
|
|
|
- do_autosign_live(opts,mountpoint,led_opts=['--stealth-led'],gen_wallet=False)
|
|
|
- else:
|
|
|
- do_autosign_live(opts,mountpoint)
|
|
|
- else:
|
|
|
- mountpoint = cfg['tmpdir']
|
|
|
- opts = ['--no-insert-check','--mountpoint='+mountpoint,'--coins='+','.join(coins)]
|
|
|
- try: os.mkdir(os.path.join(mountpoint,'tx'))
|
|
|
- except: pass
|
|
|
- do_autosign(opts,mountpoint)
|
|
|
-
|
|
|
-
|
|
|
- # Saved reference file tests
|
|
|
- def ref_wallet_conv(self,name):
|
|
|
- wf = os.path.join(ref_dir,cfg['ref_wallet'])
|
|
|
- self.walletconv_in(name,wf,'MMGen wallet',pw=True,oo=True)
|
|
|
-
|
|
|
- def ref_mn_conv(self,name,ext='mmwords',desc='Mnemonic data'):
|
|
|
- wf = os.path.join(ref_dir,cfg['seed_id']+'.'+ext)
|
|
|
- self.walletconv_in(name,wf,desc,oo=True)
|
|
|
-
|
|
|
- def ref_seed_conv(self,name):
|
|
|
- self.ref_mn_conv(name,ext='mmseed',desc='Seed data')
|
|
|
-
|
|
|
- def ref_hex_conv(self,name):
|
|
|
- self.ref_mn_conv(name,ext='mmhex',desc='Hexadecimal seed data')
|
|
|
-
|
|
|
- def ref_brain_conv(self,name):
|
|
|
- uopts = ['-i','b','-p','1','-l',str(cfg['seed_len'])]
|
|
|
- self.walletconv_in(name,None,'brainwallet',uopts,oo=True)
|
|
|
-
|
|
|
- def ref_incog_conv(self,name,wfk='ic_wallet',in_fmt='i',desc='incognito data'):
|
|
|
- uopts = ['-i',in_fmt,'-p','1','-l',str(cfg['seed_len'])]
|
|
|
- wf = os.path.join(ref_dir,cfg[wfk])
|
|
|
- self.walletconv_in(name,wf,desc,uopts,oo=True,pw=True)
|
|
|
-
|
|
|
- def ref_incox_conv(self,name):
|
|
|
- self.ref_incog_conv(name,in_fmt='xi',wfk='ic_wallet_hex',desc='hex incognito data')
|
|
|
-
|
|
|
- def ref_hincog_conv(self,name,wfk='hic_wallet',add_uopts=[]):
|
|
|
- ic_f = os.path.join(ref_dir,cfg[wfk])
|
|
|
- uopts = ['-i','hi','-p','1','-l',str(cfg['seed_len'])] + add_uopts
|
|
|
- hi_opt = ['-H','{},{}'.format(ic_f,ref_wallet_incog_offset)]
|
|
|
- self.walletconv_in(name,None,'hidden incognito data',uopts+hi_opt,oo=True,pw=True)
|
|
|
-
|
|
|
- def ref_hincog_conv_old(self,name):
|
|
|
- self.ref_hincog_conv(name,wfk='hic_wallet_old',add_uopts=['-O'])
|
|
|
-
|
|
|
- def ref_wallet_conv_out(self,name):
|
|
|
- self.walletconv_out(name,'MMGen wallet','w',pw=True)
|
|
|
-
|
|
|
- def ref_mn_conv_out(self,name):
|
|
|
- self.walletconv_out(name,'mnemonic data','mn')
|
|
|
-
|
|
|
- def ref_seed_conv_out(self,name):
|
|
|
- self.walletconv_out(name,'seed data','seed')
|
|
|
-
|
|
|
- def ref_hex_conv_out(self,name):
|
|
|
- self.walletconv_out(name,'hexadecimal seed data','hexseed')
|
|
|
-
|
|
|
- def ref_incog_conv_out(self,name):
|
|
|
- self.walletconv_out(name,'incognito data',out_fmt='i',pw=True)
|
|
|
-
|
|
|
- def ref_incox_conv_out(self,name):
|
|
|
- self.walletconv_out(name,'hex incognito data',out_fmt='xi',pw=True)
|
|
|
-
|
|
|
- def ref_hincog_conv_out(self,name,ic_f=None):
|
|
|
- if not ic_f: ic_f = os.path.join(cfg['tmpdir'],hincog_fn)
|
|
|
- hi_parms = '{},{}'.format(ic_f,ref_wallet_incog_offset)
|
|
|
- sl_parm = '-l' + str(cfg['seed_len'])
|
|
|
- self.walletconv_out(name,
|
|
|
- 'hidden incognito data', 'hi',
|
|
|
- uopts=['-J',hi_parms,sl_parm],
|
|
|
- uopts_chk=['-H',hi_parms,sl_parm],
|
|
|
- pw=True
|
|
|
- )
|
|
|
-
|
|
|
- def ref_hincog_blkdev_conv_out(self,name):
|
|
|
- imsg('Creating block device image file')
|
|
|
- ic_img = os.path.join(cfg['tmpdir'],'hincog_blkdev_img')
|
|
|
- subprocess.check_output(['dd','if=/dev/zero','of='+ic_img,'bs=1K','count=1'],stderr=subprocess.PIPE)
|
|
|
- ic_dev = subprocess.check_output(['losetup','-f']).strip().decode()
|
|
|
- ic_dev_mode_orig = '{:o}'.format(os.stat(ic_dev).st_mode & 0xfff)
|
|
|
- ic_dev_mode = '0666'
|
|
|
- imsg("Changing permissions on loop device to '{}'".format(ic_dev_mode))
|
|
|
- subprocess.check_output(['sudo','chmod',ic_dev_mode,ic_dev],stderr=subprocess.PIPE)
|
|
|
- imsg("Attaching loop device '{}'".format(ic_dev))
|
|
|
- subprocess.check_output(['losetup',ic_dev,ic_img])
|
|
|
- self.ref_hincog_conv_out(name,ic_f=ic_dev)
|
|
|
- imsg("Detaching loop device '{}'".format(ic_dev))
|
|
|
- subprocess.check_output(['losetup','-d',ic_dev])
|
|
|
- imsg("Resetting permissions on loop device to '{}'".format(ic_dev_mode_orig))
|
|
|
- subprocess.check_output(['sudo','chmod',ic_dev_mode_orig,ic_dev],stderr=subprocess.PIPE)
|
|
|
-
|
|
|
- def ref_wallet_chk(self,name):
|
|
|
- wf = os.path.join(ref_dir,cfg['ref_wallet'])
|
|
|
- self.walletchk(name,wf,pf=None,pw=True,sid=cfg['seed_id'])
|
|
|
-
|
|
|
- def ref_ss_chk(self,name,ss=None):
|
|
|
- wf = os.path.join(ref_dir,'{}.{}'.format(cfg['seed_id'],ss.ext))
|
|
|
- self.walletchk(name,wf,pf=None,desc=ss.desc,sid=cfg['seed_id'])
|
|
|
-
|
|
|
- def ref_seed_chk(self,name):
|
|
|
- from mmgen.seed import SeedFile
|
|
|
- self.ref_ss_chk(name,ss=SeedFile)
|
|
|
-
|
|
|
- def ref_hex_chk(self,name):
|
|
|
- from mmgen.seed import HexSeedFile
|
|
|
- self.ref_ss_chk(name,ss=HexSeedFile)
|
|
|
-
|
|
|
- def ref_mn_chk(self,name):
|
|
|
- from mmgen.seed import Mnemonic
|
|
|
- self.ref_ss_chk(name,ss=Mnemonic)
|
|
|
-
|
|
|
- def ref_brain_chk(self,name,bw_file=ref_bw_file):
|
|
|
- wf = os.path.join(ref_dir,bw_file)
|
|
|
- add_args = ['-l{}'.format(cfg['seed_len']), '-p'+ref_bw_hash_preset]
|
|
|
- self.walletchk(name,wf,pf=None,add_args=add_args,
|
|
|
- desc='brainwallet',sid=cfg['ref_bw_seed_id'])
|
|
|
-
|
|
|
- def ref_brain_chk_spc3(self,name):
|
|
|
- self.ref_brain_chk(name,bw_file=ref_bw_file_spc)
|
|
|
-
|
|
|
- def ref_hincog_chk(self,name,desc='hidden incognito data'):
|
|
|
- for wtype,edesc,of_arg in ('hic_wallet','',[]), \
|
|
|
- ('hic_wallet_old','(old format)',['-O']):
|
|
|
- ic_arg = ['-H{},{}'.format(os.path.join(ref_dir,cfg[wtype]),ref_wallet_incog_offset)]
|
|
|
- slarg = ['-l{} '.format(cfg['seed_len'])]
|
|
|
- hparg = ['-p1']
|
|
|
- if wtype == 'hic_wallet_old' and opt.profile: msg('')
|
|
|
- t = MMGenExpect(name,'mmgen-walletchk',
|
|
|
- slarg + hparg + of_arg + ic_arg,
|
|
|
- extra_desc=edesc)
|
|
|
- t.passphrase(desc,cfg['wpasswd'])
|
|
|
- if wtype == 'hic_wallet_old':
|
|
|
- t.expect('Is the Seed ID correct? (Y/n): ','\n')
|
|
|
- chk = t.expect_getend('Seed ID: ')
|
|
|
- t.close()
|
|
|
- cmp_or_die(cfg['seed_id'],chk)
|
|
|
-
|
|
|
- def ref_addrfile_chk(self,name,ftype='addr',coin=None,subdir=None,pfx=None,mmtype=None,add_args=[]):
|
|
|
- af_key = 'ref_{}file'.format(ftype)
|
|
|
- af_fn = cfg[af_key].format(pfx or altcoin_pfx,'' if coin else tn_ext)
|
|
|
- af = os.path.join(ref_dir,(subdir or ref_subdir,'')[ftype=='passwd'],af_fn)
|
|
|
- coin_arg = [] if coin == None else ['--coin='+coin]
|
|
|
- tool_cmd = ftype.replace('segwit','').replace('bech32','')+'file_chksum'
|
|
|
- t = MMGenExpect(name,'mmgen-tool',coin_arg+[tool_cmd,af]+add_args)
|
|
|
- if ftype == 'keyaddr':
|
|
|
- t.do_decrypt_ka_data(hp=ref_kafile_hash_preset,pw=ref_kafile_pass)
|
|
|
- rc = cfg[ 'ref_' + ftype + 'file_chksum' +
|
|
|
- ('_'+coin.lower() if coin else '') +
|
|
|
- ('_'+mmtype if mmtype else '')]
|
|
|
- ref_chksum = rc if (ftype == 'passwd' or coin) else rc[g.proto.base_coin.lower()][g.testnet]
|
|
|
- t.expect(chksum_pat,regex=True)
|
|
|
- m = t.p.match.group(0)
|
|
|
- t.read()
|
|
|
- cmp_or_die(ref_chksum,m)
|
|
|
-
|
|
|
- def ref_altcoin_addrgen(self,name,coin,mmtype,gen_what='addr',coin_suf='',add_args=[]):
|
|
|
- wf = os.path.join(ref_dir,cfg['seed_id']+'.mmwords')
|
|
|
- t = MMGenExpect(name,'mmgen-{}gen'.format(gen_what),
|
|
|
- ['-Sq','--coin='+coin] +
|
|
|
- (['--type='+mmtype] if mmtype else []) +
|
|
|
- add_args +
|
|
|
- [wf,cfg['addr_idx_list']])
|
|
|
- if gen_what == 'key':
|
|
|
- t.expect('Encrypt key list? (y/N): ','N')
|
|
|
- chk = t.expect_getend(r'.* data checksum for \S*: ',regex=True)
|
|
|
- chk_ref = cfg['ref_{}addrfile_chksum_{}{}'.format(('','key')[gen_what=='key'],coin.lower(),coin_suf)]
|
|
|
- t.read()
|
|
|
- refcheck('{}list data checksum'.format(gen_what),chk,chk_ref)
|
|
|
-
|
|
|
- def ref_addrfile_gen_eth(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ETH',mmtype='ethereum')
|
|
|
-
|
|
|
- def ref_addrfile_gen_etc(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ETC',mmtype='ethereum')
|
|
|
-
|
|
|
- def ref_addrfile_gen_dash(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='DASH',mmtype='compressed')
|
|
|
-
|
|
|
- def ref_addrfile_gen_zec(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='compressed')
|
|
|
-
|
|
|
- def ref_addrfile_gen_zec_z(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='zcash_z',coin_suf='_z')
|
|
|
-
|
|
|
- def ref_addrfile_gen_xmr(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='XMR',mmtype='monero')
|
|
|
-
|
|
|
- def ref_addrfile_gen_xmr_old(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='XMR',mmtype='monero',add_args=['--use-old-ed25519'])
|
|
|
-
|
|
|
- def ref_keyaddrfile_gen_eth(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ETH',mmtype='ethereum',gen_what='key')
|
|
|
-
|
|
|
- def ref_keyaddrfile_gen_etc(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ETC',mmtype='ethereum',gen_what='key')
|
|
|
-
|
|
|
- def ref_keyaddrfile_gen_dash(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='DASH',mmtype='compressed',gen_what='key')
|
|
|
-
|
|
|
- def ref_keyaddrfile_gen_zec(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='compressed',gen_what='key')
|
|
|
-
|
|
|
- def ref_keyaddrfile_gen_zec_z(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='zcash_z',coin_suf='_z',gen_what='key')
|
|
|
-
|
|
|
- def ref_keyaddrfile_gen_xmr(self,name):
|
|
|
- self.ref_altcoin_addrgen(name,coin='XMR',mmtype='monero',gen_what='key')
|
|
|
-
|
|
|
-
|
|
|
- def ref_addrfile_chk_eth(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='addr',coin='ETH',subdir='ethereum',pfx='-ETH')
|
|
|
-
|
|
|
- def ref_addrfile_chk_etc(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='addr',coin='ETC',subdir='ethereum_classic',pfx='-ETC')
|
|
|
-
|
|
|
- def ref_addrfile_chk_dash(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='addr',coin='DASH',subdir='dash',pfx='-DASH-C')
|
|
|
-
|
|
|
- def ref_addrfile_chk_zec(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='addr',coin='ZEC',subdir='zcash',pfx='-ZEC-C')
|
|
|
-
|
|
|
- def ref_addrfile_chk_zec_z(self,name):
|
|
|
- if skip_for_win(): return
|
|
|
- self.ref_addrfile_chk(name,ftype='addr',coin='ZEC',subdir='zcash',pfx='-ZEC-Z',mmtype='z')
|
|
|
-
|
|
|
- def ref_addrfile_chk_xmr(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='addr',coin='XMR',subdir='monero',pfx='-XMR-M')
|
|
|
-
|
|
|
-
|
|
|
- def ref_keyaddrfile_chk_eth(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='keyaddr',coin='ETH',subdir='ethereum',pfx='-ETH')
|
|
|
-
|
|
|
- def ref_keyaddrfile_chk_etc(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='keyaddr',coin='ETC',subdir='ethereum_classic',pfx='-ETC')
|
|
|
-
|
|
|
- def ref_keyaddrfile_chk_dash(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='keyaddr',coin='DASH',subdir='dash',pfx='-DASH-C')
|
|
|
-
|
|
|
- def ref_keyaddrfile_chk_zec(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='keyaddr',coin='ZEC',subdir='zcash',pfx='-ZEC-C')
|
|
|
-
|
|
|
- def ref_keyaddrfile_chk_zec_z(self,name):
|
|
|
- if skip_for_win(): return
|
|
|
- self.ref_addrfile_chk(name,ftype='keyaddr',coin='ZEC',subdir='zcash',pfx='-ZEC-Z',mmtype='z')
|
|
|
-
|
|
|
- def ref_keyaddrfile_chk_xmr(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='keyaddr',coin='XMR',subdir='monero',pfx='-XMR-M')
|
|
|
-
|
|
|
-
|
|
|
- def ref_keyaddrfile_chk(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='keyaddr')
|
|
|
-
|
|
|
- def ref_passwdfile_chk(self,name):
|
|
|
- self.ref_addrfile_chk(name,ftype='passwd')
|
|
|
-
|
|
|
- def ref_segwitaddrfile_chk(self,name):
|
|
|
- if not 'S' in g.proto.mmtypes:
|
|
|
- msg_r('Skipping {} (not supported)'.format(name)); ok()
|
|
|
- else:
|
|
|
- self.ref_addrfile_chk(name,ftype='segwitaddr')
|
|
|
-
|
|
|
- def ref_bech32addrfile_chk(self,name):
|
|
|
- if not 'B' in g.proto.mmtypes:
|
|
|
- msg_r('Skipping {} (not supported)'.format(name)); ok()
|
|
|
- else:
|
|
|
- self.ref_addrfile_chk(name,ftype='bech32addr')
|
|
|
-
|
|
|
-# def txcreate8(self,name,addrfile):
|
|
|
-# self.txcreate_common(name,sources=['8'])
|
|
|
-
|
|
|
- def ref_tx_chk(self,name):
|
|
|
- fn = cfg['ref_tx_file'][g.coin.lower()][bool(tn_ext)]
|
|
|
- if not fn: return
|
|
|
- tf = os.path.join(ref_dir,ref_subdir,fn)
|
|
|
- wf = dfl_words
|
|
|
- write_to_tmpfile(cfg,pwfile,cfg['wpasswd'])
|
|
|
- pf = get_tmpfile_fn(cfg,pwfile)
|
|
|
- self.txsign(name,tf,wf,pf,save=False,has_label=True,do_passwd=False)
|
|
|
-
|
|
|
- def ref_tool_decrypt(self,name):
|
|
|
- f = os.path.join(ref_dir,ref_enc_fn)
|
|
|
- disable_debug()
|
|
|
- dec_fn = get_tmpfile_fn(cfg,'famous.txt')
|
|
|
- t = MMGenExpect(name,'mmgen-tool', ['-q','decrypt',f,'outfile='+dec_fn,'hash_preset=1'])
|
|
|
- restore_debug()
|
|
|
- t.passphrase('user data',tool_enc_passwd)
|
|
|
- t.written_to_file('Decrypted data')
|
|
|
- dec_txt = read_from_file(dec_fn)
|
|
|
- imsg_r(dec_txt)
|
|
|
- cmp_or_die(sample_text,dec_txt)
|
|
|
-
|
|
|
- # wallet conversion tests
|
|
|
- def walletconv_in(self,name,infile,desc,uopts=[],pw=False,oo=False):
|
|
|
- opts = ['-d',cfg['tmpdir'],'-o','words',usr_rand_arg]
|
|
|
- if_arg = [infile] if infile else []
|
|
|
- d = '(convert)'
|
|
|
- t = MMGenExpect(name,'mmgen-walletconv',opts+uopts+if_arg,extra_desc=d)
|
|
|
- t.license()
|
|
|
- if desc == 'brainwallet':
|
|
|
- t.expect('Enter brainwallet: ',ref_wallet_brainpass+'\n')
|
|
|
- if pw:
|
|
|
- t.passphrase(desc,cfg['wpasswd'])
|
|
|
- if name[:19] == 'ref_hincog_conv_old':
|
|
|
- t.expect('Is the Seed ID correct? (Y/n): ','\n')
|
|
|
- else:
|
|
|
- t.expect(['Passphrase is OK',' are correct'])
|
|
|
- # Output
|
|
|
- wf = t.written_to_file('Mnemonic data',oo=oo)
|
|
|
- t.p.wait()
|
|
|
- t.ok()
|
|
|
- # back check of result
|
|
|
- if opt.profile: msg('')
|
|
|
- self.walletchk(name,wf,pf=None,
|
|
|
- desc='mnemonic data',
|
|
|
- sid=cfg['seed_id'],
|
|
|
- extra_desc='(check)'
|
|
|
- )
|
|
|
-
|
|
|
- def walletconv_out(self,name,desc,out_fmt='w',uopts=[],uopts_chk=[],pw=False):
|
|
|
- opts = ['-d',cfg['tmpdir'],'-p1','-o',out_fmt] + uopts
|
|
|
- infile = os.path.join(ref_dir,cfg['seed_id']+'.mmwords')
|
|
|
- t = MMGenExpect(name,'mmgen-walletconv',[usr_rand_arg]+opts+[infile],extra_desc='(convert)')
|
|
|
-
|
|
|
- add_args = ['-l{}'.format(cfg['seed_len'])]
|
|
|
- t.license()
|
|
|
- if pw:
|
|
|
- t.passphrase_new('new '+desc,cfg['wpasswd'])
|
|
|
- t.usr_rand(usr_rand_chars)
|
|
|
- if ' '.join(desc.split()[-2:]) == 'incognito data':
|
|
|
- for i in (1,2,3):
|
|
|
- t.expect('Generating encryption key from OS random data ')
|
|
|
- if desc == 'hidden incognito data':
|
|
|
- ret = t.expect(['Create? (Y/n): ',"'YES' to confirm: "])
|
|
|
- if ret == 0:
|
|
|
- t.send('\n')
|
|
|
- t.expect('Enter file size: ',str(hincog_bytes)+'\n')
|
|
|
- else:
|
|
|
- t.send('YES\n')
|
|
|
- if out_fmt == 'w': t.label()
|
|
|
- wf = t.written_to_file(capfirst(desc),oo=True)
|
|
|
- pf = None
|
|
|
- t.ok()
|
|
|
-
|
|
|
- if desc == 'hidden incognito data':
|
|
|
- add_args += uopts_chk
|
|
|
- wf = None
|
|
|
- if opt.profile: msg('')
|
|
|
- self.walletchk(name,wf,pf=pf,
|
|
|
- desc=desc,sid=cfg['seed_id'],pw=pw,
|
|
|
- add_args=add_args,
|
|
|
- extra_desc='(check)')
|
|
|
-
|
|
|
- def regtest_setup(self,name):
|
|
|
- os.environ['MMGEN_BOGUS_WALLET_DATA'] = ''
|
|
|
- if g.testnet:
|
|
|
- die(2,'--testnet option incompatible with regtest test suite')
|
|
|
- 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',['-n','setup'])
|
|
|
- os.environ['MMGEN_TEST_SUITE'] = '1'
|
|
|
- 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',rt_pw)
|
|
|
- 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,coin=None):
|
|
|
- return os.path.join(data_dir,'regtest',coin or g.coin.lower(),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,wf=None,passwd=rt_pw,addr_range='1-5'):
|
|
|
- from mmgen.addr import MMGenAddrType
|
|
|
- for mmtype in g.proto.mmtypes:
|
|
|
- t = MMGenExpect(name,'mmgen-addrgen',
|
|
|
- ['--quiet','--'+user,'--type='+mmtype,'--outdir={}'.format(self.regtest_user_dir(user))] +
|
|
|
- ([],[wf])[bool(wf)] + [addr_range],
|
|
|
- extra_desc='({})'.format(MMGenAddrType.mmtypes[mmtype]['name']))
|
|
|
- t.passphrase('MMGen wallet',passwd)
|
|
|
- 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,sid=None,addr_range='1-5',num_addrs=5):
|
|
|
- id_strs = { 'legacy':'', 'compressed':'-C', 'segwit':'-S', 'bech32':'-B' }
|
|
|
- if not sid: sid = self.regtest_user_sid(user)
|
|
|
- from mmgen.addr import MMGenAddrType
|
|
|
- for mmtype in g.proto.mmtypes:
|
|
|
- desc = MMGenAddrType.mmtypes[mmtype]['name']
|
|
|
- fn = os.path.join(self.regtest_user_dir(user),
|
|
|
- '{}{}{}[{}]{x}.testnet.addrs'.format(
|
|
|
- sid,altcoin_pfx,id_strs[desc],addr_range,
|
|
|
- x='-α' if g.debug_utf8 else ''))
|
|
|
- if mmtype == g.proto.mmtypes[0] and user == 'bob':
|
|
|
- psave = g.proto
|
|
|
- g.proto = CoinProtocol(g.coin,True)
|
|
|
- add_comments_to_addr_file(fn,fn,use_labels=True)
|
|
|
- g.proto = psave
|
|
|
- t = MMGenExpect(name,'mmgen-addrimport', ['--quiet','--'+user,'--batch',fn],extra_desc='('+desc+')')
|
|
|
- if g.debug:
|
|
|
- t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
|
|
|
- t.expect('Importing')
|
|
|
- t.expect('{} addresses imported'.format(num_addrs))
|
|
|
- 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,sid=None,addr_range='1-5'):
|
|
|
- if not sid: sid = self.regtest_user_sid(user)
|
|
|
- addr = self.get_addr_from_regtest_addrlist(user,sid,mmtype,0,addr_range=addr_range)
|
|
|
- t = MMGenExpect(name,'mmgen-regtest', ['send',str(addr),str(amt)])
|
|
|
- t.expect('Sending {} {}'.format(amt,g.coin))
|
|
|
- t.expect('Mined 1 block')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_fund_bob(self,name): self.regtest_fund_wallet(name,'bob','C',rtFundAmt)
|
|
|
- def regtest_fund_alice(self,name): self.regtest_fund_wallet(name,'alice',('L','S')[g.proto.cap('segwit')],rtFundAmt)
|
|
|
-
|
|
|
- def regtest_user_twview(self,name,user):
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--'+user,'twview'])
|
|
|
- t.expect(r'1\).*\b{}\b'.format(rtAmts[0]),regex=True)
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_bob_twview(self,name):
|
|
|
- return self.regtest_user_twview(name,'bob')
|
|
|
-
|
|
|
- def regtest_user_bal(self,name,user,bal,args=['showempty=1'],skip_check=False,exit_val=0):
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses'] + args)
|
|
|
- if skip_check:
|
|
|
- t.read()
|
|
|
- t.ok(exit_val=exit_val)
|
|
|
- else:
|
|
|
- total = t.expect_getend('TOTAL: ')
|
|
|
- cmp_or_die('{} {}'.format(bal,g.coin),total)
|
|
|
-
|
|
|
- def regtest_alice_bal1(self,name):
|
|
|
- return self.regtest_user_bal(name,'alice',rtFundAmt)
|
|
|
-
|
|
|
- def regtest_alice_bal2(self,name):
|
|
|
- return self.regtest_user_bal(name,'alice',rtBals[8])
|
|
|
-
|
|
|
- def regtest_bob_bal1(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtFundAmt)
|
|
|
-
|
|
|
- def regtest_bob_bal2(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[0])
|
|
|
-
|
|
|
- def regtest_bob_bal2a(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','age_fmt="confs"'])
|
|
|
-
|
|
|
- def regtest_bob_bal2b(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1'])
|
|
|
-
|
|
|
- def regtest_bob_bal2c(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','minconf=2','age_fmt="days"'],skip_check=True)
|
|
|
-
|
|
|
- def regtest_bob_bal2d(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[0],args=['minconf=2'],skip_check=True)
|
|
|
-
|
|
|
- def regtest_bob_bal2e(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','sort=age'])
|
|
|
-
|
|
|
- def regtest_bob_bal2f(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','sort=age,reverse'])
|
|
|
-
|
|
|
- def regtest_bob_bal3(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[1])
|
|
|
-
|
|
|
- def regtest_bob_bal4(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[2])
|
|
|
-
|
|
|
- def regtest_bob_bal5(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[3])
|
|
|
-
|
|
|
- def regtest_bob_bal6(self,name):
|
|
|
- return self.regtest_user_bal(name,'bob',rtBals[7])
|
|
|
-
|
|
|
- def regtest_bob_bal5_getbalance(self,name):
|
|
|
- t_ext,t_mmgen = rtBals_gb[0],rtBals_gb[1]
|
|
|
- assert Decimal(t_ext) + Decimal(t_mmgen) == Decimal(rtBals[3])
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--bob','getbalance'])
|
|
|
- t.expect(r'\n[0-9A-F]{8}: .* '+t_mmgen,regex=True)
|
|
|
- t.expect(r'\nNon-MMGen: .* '+t_ext,regex=True)
|
|
|
- t.expect(r'\nTOTAL: .* '+rtBals[3],regex=True)
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- 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(rtBals[4],ret,skip_ok=True)
|
|
|
- ret = t.expect_getend("Alice's balance:").strip()
|
|
|
- cmp_or_die(rtBals[5],ret,skip_ok=True)
|
|
|
- ret = t.expect_getend("Total balance:").strip()
|
|
|
- cmp_or_die(rtBals[6],ret,skip_ok=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_user_txdo( self,name,user,fee,
|
|
|
- outputs_cl,
|
|
|
- outputs_list,
|
|
|
- extra_args=[],
|
|
|
- wf=None,
|
|
|
- pw=rt_pw,
|
|
|
- do_label=False,
|
|
|
- bad_locktime=False,
|
|
|
- full_tx_view=False):
|
|
|
- os.environ['MMGEN_BOGUS_SEND'] = ''
|
|
|
- t = MMGenExpect(name,'mmgen-txdo',
|
|
|
- ['-d',cfg['tmpdir'],'-B','--'+user] +
|
|
|
- (['--tx-fee='+fee] if fee else []) +
|
|
|
- extra_args + ([],[wf])[bool(wf)] + outputs_cl)
|
|
|
- os.environ['MMGEN_BOGUS_SEND'] = '1'
|
|
|
-
|
|
|
- self.txcreate_ui_common(t,'txdo',
|
|
|
- menu=['M'],inputs=outputs_list,
|
|
|
- file_desc='Signed transaction',
|
|
|
- interactive_fee=(tx_fee,'')[bool(fee)],
|
|
|
- add_comment=ref_tx_label_jp,
|
|
|
- view='t',save=True)
|
|
|
-
|
|
|
- t.passphrase('MMGen wallet',pw)
|
|
|
- t.written_to_file('Signed transaction')
|
|
|
- self.do_confirm_send(t)
|
|
|
- s,exit_val = (('Transaction sent',0),("can't be included",1))[bad_locktime]
|
|
|
- t.expect(s)
|
|
|
- t.ok(exit_val)
|
|
|
-
|
|
|
- def regtest_bob_split1(self,name):
|
|
|
- sid = self.regtest_user_sid('bob')
|
|
|
- outputs_cl = [sid+':C:1,100', sid+':L:2,200',sid+':'+rtBobOp3]
|
|
|
- return self.regtest_user_txdo(name,'bob',rtFee[0],outputs_cl,'1',do_label=True,full_tx_view=True)
|
|
|
-
|
|
|
- def get_addr_from_regtest_addrlist(self,user,sid,mmtype,idx,addr_range='1-5'):
|
|
|
- id_str = { 'L':'', 'S':'-S', 'C':'-C', 'B':'-B' }[mmtype]
|
|
|
- ext = '{}{}{}[{}]{x}.testnet.addrs'.format(
|
|
|
- sid,altcoin_pfx,id_str,addr_range,x='-α' if g.debug_utf8 else '')
|
|
|
- fn = get_file_with_ext(ext,self.regtest_user_dir(user),no_dot=True)
|
|
|
- psave = g.proto
|
|
|
- g.proto = CoinProtocol(g.coin,True)
|
|
|
- if hasattr(g.proto,'bech32_hrp_rt'):
|
|
|
- g.proto.bech32_hrp = g.proto.bech32_hrp_rt
|
|
|
- silence()
|
|
|
- addr = AddrList(fn).data[idx].addr
|
|
|
- end_silence()
|
|
|
- g.proto = psave
|
|
|
- return addr
|
|
|
-
|
|
|
- def create_tx_outputs(self,user,data):
|
|
|
- sid = self.regtest_user_sid(user)
|
|
|
- return [self.get_addr_from_regtest_addrlist(user,sid,mmtype,idx-1)+amt_str for mmtype,idx,amt_str in data]
|
|
|
-
|
|
|
- def regtest_bob_rbf_send(self,name):
|
|
|
- outputs_cl = self.create_tx_outputs('alice',(('L',1,',60'),('C',1,',40'))) # alice_sid:L:1, alice_sid:C:1
|
|
|
- outputs_cl += [self.regtest_user_sid('bob')+':'+rtBobOp3]
|
|
|
- return self.regtest_user_txdo(name,'bob',rtFee[1],outputs_cl,'3',
|
|
|
- extra_args=([],['--rbf'])[g.proto.cap('rbf')])
|
|
|
-
|
|
|
- def regtest_bob_send_non_mmgen(self,name):
|
|
|
- outputs_cl = self.create_tx_outputs('alice',(
|
|
|
- (('L','S')[g.proto.cap('segwit')],2,',10'),
|
|
|
- (('L','S')[g.proto.cap('segwit')],3,'')
|
|
|
- )) # alice_sid:S:2, alice_sid:S:3
|
|
|
- fn = os.path.join(cfg['tmpdir'],'non-mmgen.keys')
|
|
|
- return self.regtest_user_txdo(name,'bob',rtFee[3],outputs_cl,'1,4-10',
|
|
|
- extra_args=['--keys-from-file='+fn,'--vsize-adj=1.02'])
|
|
|
-
|
|
|
- def regtest_alice_send_estimatefee(self,name):
|
|
|
- outputs_cl = self.create_tx_outputs('bob',(('L',1,''),)) # bob_sid:L:1
|
|
|
- return self.regtest_user_txdo(name,'alice',None,outputs_cl,'1') # fee=None
|
|
|
-
|
|
|
- def regtest_user_txbump(self,name,user,txfile,fee,red_op):
|
|
|
- if not g.proto.cap('rbf'):
|
|
|
- msg('Skipping RBF'); return True
|
|
|
- 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.do_comment(False,has_label=True)
|
|
|
- t.passphrase('MMGen wallet',rt_pw)
|
|
|
- t.written_to_file('Signed transaction')
|
|
|
- self.txsend_ui_common(t,'txdo',bogus_send=False,file_desc='Signed transaction')
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_bob_rbf_bump(self,name):
|
|
|
- ext = ',{}]{x}.testnet.sigtx'.format(rtFee[1][:-1],x='-α' if g.debug_utf8 else '')
|
|
|
- txfile = get_file_with_ext(ext,cfg['tmpdir'],delete=False,no_dot=True)
|
|
|
- return self.regtest_user_txbump(name,'bob',txfile,rtFee[2],'c')
|
|
|
-
|
|
|
- def regtest_generate(self,name,coin=None,num_blocks=1):
|
|
|
- int(num_blocks)
|
|
|
- if coin: opt.coin = coin
|
|
|
- t = MMGenExpect(name,'mmgen-regtest',['generate',str(num_blocks)])
|
|
|
- t.expect('Mined {} block'.format(num_blocks))
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_get_mempool(self,name):
|
|
|
- disable_debug()
|
|
|
- ret = MMGenExpect(name,'mmgen-regtest',['show_mempool']).read()
|
|
|
- restore_debug()
|
|
|
- from ast import literal_eval
|
|
|
- return literal_eval(ret.split('\n')[0]) # allow for extra output by handler at end
|
|
|
-
|
|
|
- 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):
|
|
|
- if not g.proto.cap('rbf'):
|
|
|
- msg('Skipping post-RBF mempool check'); return True
|
|
|
- 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()
|
|
|
-
|
|
|
- @staticmethod
|
|
|
- def gen_pairs(n):
|
|
|
- disable_debug()
|
|
|
- ret = [subprocess.check_output(
|
|
|
- ['python3',os.path.join('cmds','mmgen-tool'),'--testnet=1'] +
|
|
|
- (['--type=compressed'],[])[i==0] +
|
|
|
- ['-r0','randpair']
|
|
|
- ).decode().split() for i in range(n)]
|
|
|
- restore_debug()
|
|
|
- return ret
|
|
|
-
|
|
|
- def regtest_bob_pre_import(self,name):
|
|
|
- pairs = self.gen_pairs(5)
|
|
|
- write_to_tmpfile(cfg,'non-mmgen.keys','\n'.join([a[0] for a in pairs])+'\n')
|
|
|
- write_to_tmpfile(cfg,'non-mmgen.addrs','\n'.join([a[1] for a in pairs])+'\n')
|
|
|
- return self.regtest_user_txdo(name,'bob',rtFee[4],[pairs[0][1]],'3')
|
|
|
-
|
|
|
- def regtest_user_import(self,name,user,args):
|
|
|
- t = MMGenExpect(name,'mmgen-addrimport',['--quiet','--'+user]+args)
|
|
|
- if g.debug:
|
|
|
- t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
|
|
|
- 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])
|
|
|
-
|
|
|
- def regtest_bob_import_list(self,name):
|
|
|
- fn = os.path.join(cfg['tmpdir'],'non-mmgen.addrs')
|
|
|
- return self.regtest_user_import(name,'bob',['--addrlist',fn])
|
|
|
-
|
|
|
- def regtest_bob_split2(self,name):
|
|
|
- addrs = read_from_tmpfile(cfg,'non-mmgen.addrs').split()
|
|
|
- amts = (1.12345678,2.87654321,3.33443344,4.00990099,5.43214321)
|
|
|
- outputs1 = list(map('{},{}'.format,addrs,amts))
|
|
|
- sid = self.regtest_user_sid('bob')
|
|
|
- l1,l2 = (':S',':B') if 'B' in g.proto.mmtypes else (':S',':S') if g.proto.cap('segwit') else (':L',':L')
|
|
|
- outputs2 = [sid+':C:2,6.333', sid+':L:3,6.667',sid+l1+':4,0.123',sid+l2+':5']
|
|
|
- return self.regtest_user_txdo(name,'bob',rtFee[5],outputs1+outputs2,'1-2')
|
|
|
-
|
|
|
- def regtest_user_add_label(self,name,user,addr,label):
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--'+user,'add_label',addr,label])
|
|
|
- t.expect('Added label.*in tracking wallet',regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_user_remove_label(self,name,user,addr):
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--'+user,'remove_label',addr])
|
|
|
- t.expect('Removed label.*in tracking wallet',regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
-# utf8_label = u'Edited label (40 characters, UTF8/JP) 月へ' # '\xe6\x9c\x88\xe3\x81\xb8' (Jp.)
|
|
|
-# utf8_label_pat = ur'Edited label \(40 characters, UTF8/JP\) ......'
|
|
|
- utf8_label = ref_tx_label_zh[:40]
|
|
|
- utf8_label_pat = utf8_label
|
|
|
-
|
|
|
- def regtest_bob_add_label(self,name):
|
|
|
- sid = self.regtest_user_sid('bob')
|
|
|
- return self.regtest_user_add_label(name,'bob',sid+':C:1',self.utf8_label)
|
|
|
-
|
|
|
- def regtest_alice_add_label1(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_add_label(name,'alice',sid+':C:1','Original Label - 月へ')
|
|
|
-
|
|
|
- def regtest_alice_add_label2(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_add_label(name,'alice',sid+':C:1','Replacement Label')
|
|
|
-
|
|
|
- def regtest_alice_add_label_coinaddr(self,name):
|
|
|
- mmaddr = self.regtest_user_sid('alice') + ':C:2'
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--alice','listaddress',mmaddr],no_msg=True)
|
|
|
- btcaddr = [i for i in t.read().splitlines() if i.lstrip()[0:len(mmaddr)] == mmaddr][0].split()[1]
|
|
|
- return self.regtest_user_add_label(name,'alice',btcaddr,'Label added using coin address')
|
|
|
-
|
|
|
- def regtest_alice_chk_label_coinaddr(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_chk_label(name,'alice',sid+':C:2','Label added using coin address')
|
|
|
-
|
|
|
- def regtest_alice_add_label_badaddr(self,name,addr,reply):
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--alice','add_label',addr,'(none)'])
|
|
|
- t.expect(reply,regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_alice_add_label_badaddr1(self,name):
|
|
|
- return self.regtest_alice_add_label_badaddr(name,rt_pw,'Invalid coin address for this chain: '+rt_pw)
|
|
|
-
|
|
|
- def regtest_alice_add_label_badaddr2(self,name):
|
|
|
- addr = g.proto.pubhash2addr(b'00'*20,False) # mainnet zero address
|
|
|
- return self.regtest_alice_add_label_badaddr(name,addr,'Invalid coin address for this chain: '+addr)
|
|
|
-
|
|
|
- def regtest_alice_add_label_badaddr3(self,name):
|
|
|
- addr = self.regtest_user_sid('alice') + ':C:123'
|
|
|
- return self.regtest_alice_add_label_badaddr(name,addr,
|
|
|
- "MMGen address '{}' not found in tracking wallet".format(addr))
|
|
|
-
|
|
|
- def regtest_alice_add_label_badaddr4(self,name):
|
|
|
- addr = CoinProtocol(g.coin,True).pubhash2addr(b'00'*20,False) # testnet zero address
|
|
|
- return self.regtest_alice_add_label_badaddr(name,addr,
|
|
|
- "Address '{}' not found in tracking wallet".format(addr))
|
|
|
-
|
|
|
- def regtest_alice_bal_rpcfail(self,name):
|
|
|
- addr = self.regtest_user_sid('alice') + ':C:2'
|
|
|
- os.environ['MMGEN_RPC_FAIL_ON_COMMAND'] = 'listunspent'
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--alice','getbalance'])
|
|
|
- os.environ['MMGEN_RPC_FAIL_ON_COMMAND'] = ''
|
|
|
- t.expect('Method not found')
|
|
|
- t.read()
|
|
|
- ok()
|
|
|
-
|
|
|
- def regtest_alice_remove_label1(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_remove_label(name,'alice',sid+':C:1')
|
|
|
-
|
|
|
- def regtest_user_chk_label(self,name,user,addr,label,label_pat=None):
|
|
|
- t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','all_labels=1'])
|
|
|
- t.expect(r'{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,(label_pat or label)),regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_alice_chk_label1(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_chk_label(name,'alice',sid+':C:1','Original Label - 月へ')
|
|
|
-
|
|
|
- def regtest_alice_chk_label2(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_chk_label(name,'alice',sid+':C:1','Replacement Label')
|
|
|
-
|
|
|
- def regtest_alice_edit_label1(self,name):
|
|
|
- return self.regtest_user_edit_label(name,'alice','1',self.utf8_label)
|
|
|
-
|
|
|
- def regtest_alice_chk_label3(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_chk_label(name,'alice',sid+':C:1',self.utf8_label,label_pat=self.utf8_label_pat)
|
|
|
-
|
|
|
- def regtest_alice_chk_label4(self,name):
|
|
|
- sid = self.regtest_user_sid('alice')
|
|
|
- return self.regtest_user_chk_label(name,'alice',sid+':C:1','-')
|
|
|
-
|
|
|
- def regtest_user_edit_label(self,name,user,output,label):
|
|
|
- t = MMGenExpect(name,'mmgen-txcreate',['-B','--'+user,'-i'])
|
|
|
- t.expect(r'add \[l\]abel:.','M',regex=True)
|
|
|
- t.expect(r'add \[l\]abel:.','l',regex=True)
|
|
|
- t.expect(r"Enter unspent.*return to main menu\):.",output+'\n',regex=True)
|
|
|
- t.expect(r"Enter label text.*return to main menu\):.",label+'\n',regex=True)
|
|
|
- t.expect(r'\[q\]uit view, .*?:.','q',regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_stop(self,name):
|
|
|
- if opt.no_daemon_stop:
|
|
|
- MMGenExpect(name,'',msg_only=True)
|
|
|
- msg_r('(leaving daemon running by user request)')
|
|
|
- ok()
|
|
|
- else:
|
|
|
- t = MMGenExpect(name,'mmgen-regtest',['stop'])
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_split_setup(self,name):
|
|
|
- if g.coin != 'BTC': die(1,'Test valid only for coin BTC')
|
|
|
- opt.coin = 'BTC'
|
|
|
- return self.regtest_setup(name)
|
|
|
-
|
|
|
- def regtest_split_fork(self,name):
|
|
|
- opt.coin = 'B2X'
|
|
|
- t = MMGenExpect(name,'mmgen-regtest',['fork','btc'])
|
|
|
- t.expect('Creating fork from coin')
|
|
|
- t.expect('successfully created')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_split_start(self,name,coin):
|
|
|
- opt.coin = coin
|
|
|
- t = MMGenExpect(name,'mmgen-regtest',['bob'])
|
|
|
- t.expect('Starting')
|
|
|
- t.expect('done')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_split_start_btc(self,name): self.regtest_split_start(name,coin='BTC')
|
|
|
- def regtest_split_start_b2x(self,name): self.regtest_split_start(name,coin='B2X')
|
|
|
- def regtest_split_gen_btc(self,name): self.regtest_generate(name,coin='BTC')
|
|
|
- def regtest_split_gen_b2x(self,name): self.regtest_generate(name,coin='B2X',num_blocks=100)
|
|
|
- def regtest_split_gen_b2x2(self,name): self.regtest_generate(name,coin='B2X')
|
|
|
-
|
|
|
- def regtest_split_do_split(self,name):
|
|
|
- opt.coin = 'B2X'
|
|
|
- sid = self.regtest_user_sid('bob')
|
|
|
- t = MMGenExpect(name,'mmgen-split',[
|
|
|
- '--bob',
|
|
|
- '--outdir='+cfg['tmpdir'],
|
|
|
- '--tx-fees=0.0001,0.0003',
|
|
|
- sid+':S:1',sid+':S:2'])
|
|
|
- t.expect(r'\[q\]uit view, .*?:.','q', regex=True)
|
|
|
- t.expect('outputs to spend: ','1\n')
|
|
|
-
|
|
|
- for tx in ('timelocked','split'):
|
|
|
- for q in ('fee','change'): t.expect('OK? (Y/n): ','y')
|
|
|
- t.do_comment(False)
|
|
|
- t.view_tx('t')
|
|
|
-
|
|
|
- t.written_to_file('Long chain (timelocked) transaction')
|
|
|
- t.written_to_file('Short chain transaction')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def regtest_split_sign(self,name,coin,ext):
|
|
|
- wf = get_file_with_ext('mmdat',self.regtest_user_dir('bob',coin=coin.lower()))
|
|
|
- txfile = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
|
|
|
- opt.coin = coin
|
|
|
- self.txsign(name,txfile,wf,extra_opts=['--bob'])
|
|
|
-
|
|
|
- def regtest_split_sign_b2x(self,name):
|
|
|
- return self.regtest_split_sign(name,coin='B2X',ext='533].rawtx')
|
|
|
-
|
|
|
- def regtest_split_sign_btc(self,name):
|
|
|
- return self.regtest_split_sign(name,coin='BTC',ext='9997].rawtx')
|
|
|
-
|
|
|
- def regtest_split_send(self,name,coin,ext):
|
|
|
- opt.coin = coin
|
|
|
- txfile = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
|
|
|
- self.txsend(name,txfile,bogus_send=False,extra_opts=['--bob'])
|
|
|
-
|
|
|
- def regtest_split_send_b2x(self,name):
|
|
|
- return self.regtest_split_send(name,coin='B2X',ext='533].sigtx')
|
|
|
-
|
|
|
- def regtest_split_send_btc(self,name):
|
|
|
- return self.regtest_split_send(name,coin='BTC',ext='9997].sigtx')
|
|
|
-
|
|
|
- def regtest_split_txdo_timelock(self,name,coin,locktime,bad_locktime):
|
|
|
- opt.coin = coin
|
|
|
- sid = self.regtest_user_sid('bob')
|
|
|
- self.regtest_user_txdo(
|
|
|
- name,'bob','0.0001',[sid+':S:5'],'1',pw=rt_pw,
|
|
|
- extra_args=['--locktime='+str(locktime)],
|
|
|
- bad_locktime=bad_locktime)
|
|
|
-
|
|
|
- def regtest_split_txdo_timelock_bad_btc(self,name):
|
|
|
- self.regtest_split_txdo_timelock(name,'BTC',locktime=8888,bad_locktime=True)
|
|
|
- def regtest_split_txdo_timelock_good_btc(self,name):
|
|
|
- self.regtest_split_txdo_timelock(name,'BTC',locktime=1321009871,bad_locktime=False)
|
|
|
- def regtest_split_txdo_timelock_bad_b2x(self,name):
|
|
|
- self.regtest_split_txdo_timelock(name,'B2X',locktime=8888,bad_locktime=True)
|
|
|
- def regtest_split_txdo_timelock_good_b2x(self,name):
|
|
|
- self.regtest_split_txdo_timelock(name,'B2X',locktime=1321009871,bad_locktime=False)
|
|
|
-
|
|
|
- def ethdev_setup(self,name):
|
|
|
- MMGenExpect(name,'',msg_only=True)
|
|
|
- os.environ['MMGEN_BOGUS_WALLET_DATA'] = ''
|
|
|
- if subprocess.call(['which','parity'],stdout=subprocess.PIPE) == 0:
|
|
|
- lf_arg = '--log-file=' + os.path.join(data_dir,'parity.log')
|
|
|
- ss = 'parity.*--log-file=test/data_dir.*/parity.log' # allow for UTF8_DEBUG
|
|
|
- try:
|
|
|
- pid = subprocess.check_output(['pgrep','-af',ss]).split()[0]
|
|
|
- os.kill(int(pid),9)
|
|
|
- except: pass
|
|
|
- # '--base-path' doesn't work together with daemon mode, so we have to clobber the main dev chain
|
|
|
- dc_dir = os.path.join(os.environ['HOME'],'.local/share/io.parity.ethereum/chains/DevelopmentChain')
|
|
|
- shutil.rmtree(dc_dir,ignore_errors=True)
|
|
|
- bdir = os.path.join(data_dir,'parity')
|
|
|
- try: os.mkdir(bdir)
|
|
|
- except: pass
|
|
|
- pid_fn = get_tmpfile_fn(cfg,cfg['parity_pidfile'])
|
|
|
- opts = ['--ports-shift=4','--config=dev']
|
|
|
- redir = None if opt.exact_output else subprocess.PIPE
|
|
|
- subprocess.check_call(['parity',lf_arg] + opts + ['daemon',pid_fn],stderr=redir,stdout=redir)
|
|
|
- time.sleep(3) # race condition
|
|
|
- pid = read_from_tmpfile(cfg,cfg['parity_pidfile'])
|
|
|
- elif subprocess.call('netstat -tnl | grep -q 127.0.0.1:8549',shell=True) == 0:
|
|
|
- m1 = 'No parity executable found on system, but port 8549 is active!'
|
|
|
- m2 = 'Before continuing, you should probably run the command'
|
|
|
- m3 = 'test/test.py ethdev_setup'
|
|
|
- m4 = 'on the remote host.'
|
|
|
- sys.stderr.write('{}\n{}\n{} {}\n'.format(m1,m2,cyan(m3),m4))
|
|
|
- confirm_continue()
|
|
|
- else:
|
|
|
- die(1,'No parity executable found!')
|
|
|
- ok()
|
|
|
-
|
|
|
- def ethdev_addrgen(self,name,addrs='1-3,11-13,21-23'):
|
|
|
- from mmgen.addr import MMGenAddrType
|
|
|
- t = MMGenExpect(name,'mmgen-addrgen', eth_args() + [dfl_words,addrs])
|
|
|
- t.written_to_file('Addresses')
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_addrimport(self,name,ext='21-23]{}.addrs',expect='9/9',add_args=[],bad_input=False):
|
|
|
- ext = ext.format('-α' if g.debug_utf8 else '')
|
|
|
- fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True,delete=False)
|
|
|
- t = MMGenExpect(name,'mmgen-addrimport', eth_args()[1:] + add_args + [fn])
|
|
|
- if bad_input:
|
|
|
- t.read(); t.ok(2); return
|
|
|
- if g.debug: t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
|
|
|
- t.expect('Importing')
|
|
|
- t.expect(expect)
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_addrimport_one_addr(self,name,addr=None,extra_args=[]):
|
|
|
- t = MMGenExpect(name,'mmgen-addrimport', eth_args()[1:] + extra_args + ['--address='+addr])
|
|
|
- t.expect('OK')
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_addrimport_dev_addr(self,name):
|
|
|
- self.ethdev_addrimport_one_addr(name,addr=eth_addr)
|
|
|
-
|
|
|
- def ethdev_addrimport_burn_addr(self,name):
|
|
|
- self.ethdev_addrimport_one_addr(name,addr=eth_burn_addr)
|
|
|
-
|
|
|
- def ethdev_txcreate(self,name,args=[],menu=[],acct='1',non_mmgen_inputs=0,
|
|
|
- interactive_fee='50G',
|
|
|
- fee_res='0.00105 {} (50 gas price in Gwei)'.format(g.coin),
|
|
|
- eth_fee_res=None,
|
|
|
- fee_desc = 'gas price'):
|
|
|
- t = MMGenExpect(name,'mmgen-txcreate', eth_args() + ['-B'] + args)
|
|
|
- t.expect(r'add \[l\]abel, .*?:.','p', regex=True)
|
|
|
- t.written_to_file('Account balances listing')
|
|
|
- self.txcreate_ui_common(t,name,
|
|
|
- menu=menu,
|
|
|
- input_sels_prompt='to spend from',
|
|
|
- inputs=acct,file_desc='Ethereum transaction',
|
|
|
- bad_input_sels=True,non_mmgen_inputs=non_mmgen_inputs,
|
|
|
- interactive_fee=interactive_fee,fee_res=fee_res,
|
|
|
- fee_desc=fee_desc,eth_fee_res=eth_fee_res,
|
|
|
- add_comment=ref_tx_label_jp)
|
|
|
-
|
|
|
- def ethdev_txsign(self,name,ni=False,ext='{}.rawtx',add_args=[]):
|
|
|
- ext = ext.format('-α' if g.debug_utf8 else '')
|
|
|
- key_fn = get_tmpfile_fn(cfg,cfg['parity_keyfile'])
|
|
|
- write_to_tmpfile(cfg,cfg['parity_keyfile'],eth_key+'\n')
|
|
|
- tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
|
|
|
- t = MMGenExpect(name,'mmgen-txsign',eth_args()+add_args + ([],['--yes'])[ni] + ['-k',key_fn,tx_fn,dfl_words])
|
|
|
- self.txsign_ui_common(t,name,ni=ni,has_label=True)
|
|
|
-
|
|
|
- def ethdev_txsend(self,name,ni=False,bogus_send=False,ext='{}.sigtx',add_args=[]):
|
|
|
- ext = ext.format('-α' if g.debug_utf8 else '')
|
|
|
- tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
|
|
|
- if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = ''
|
|
|
- t = MMGenExpect(name,'mmgen-txsend', eth_args()+add_args + [tx_fn])
|
|
|
- if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = '1'
|
|
|
- self.txsend_ui_common(t,name,quiet=True,bogus_send=bogus_send,has_label=True)
|
|
|
-
|
|
|
- def ethdev_txcreate1(self,name):
|
|
|
- # valid_keypresses = 'adrMmeqpvwl'
|
|
|
- menu = ['a','d','r','M','D','e','m','m'] # include one invalid keypress, 'D'
|
|
|
- args = ['98831F3A:E:1,123.456']
|
|
|
- return self.ethdev_txcreate(name,args=args,menu=menu,acct='1',non_mmgen_inputs=1)
|
|
|
-
|
|
|
- def ethdev_txsign1(self,name): self.ethdev_txsign(name)
|
|
|
- def ethdev_txsign1_ni(self,name): self.ethdev_txsign(name,ni=True)
|
|
|
- def ethdev_txsend1(self,name): self.ethdev_txsend(name)
|
|
|
- def ethdev_bal1(self,name): self.ethdev_bal(name,n='1')
|
|
|
-
|
|
|
- def ethdev_txcreate2(self,name):
|
|
|
- args = ['98831F3A:E:11,1.234']
|
|
|
- return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
|
|
|
- def ethdev_txsign2(self,name): self.ethdev_txsign(name,ni=True,ext='1.234,50000]{}.rawtx')
|
|
|
- def ethdev_txsend2(self,name): self.ethdev_txsend(name,ext='1.234,50000]{}.sigtx')
|
|
|
- def ethdev_bal2(self,name): self.ethdev_bal(name,n='2')
|
|
|
-
|
|
|
- def ethdev_txcreate3(self,name):
|
|
|
- args = ['98831F3A:E:21,2.345']
|
|
|
- return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
|
|
|
- def ethdev_txsign3(self,name): self.ethdev_txsign(name,ni=True,ext='2.345,50000]{}.rawtx')
|
|
|
- def ethdev_txsend3(self,name): self.ethdev_txsend(name,ext='2.345,50000]{}.sigtx')
|
|
|
- def ethdev_bal3(self,name): self.ethdev_bal(name,n='3')
|
|
|
-
|
|
|
- def ethdev_tx_status(self,name,ext,expect_str):
|
|
|
- ext = ext.format('-α' if g.debug_utf8 else '')
|
|
|
- tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
|
|
|
- t = MMGenExpect(name,'mmgen-txsend', eth_args() + ['--status',tx_fn])
|
|
|
- t.expect(expect_str)
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_tx_status1(self,name):
|
|
|
- self.ethdev_tx_status(name,ext='2.345,50000]{}.sigtx',expect_str='has 1 confirmation')
|
|
|
-
|
|
|
- def ethdev_txcreate4(self,name):
|
|
|
- args = ['98831F3A:E:2,23.45495']
|
|
|
- interactive_fee='40G'
|
|
|
- fee_res='0.00084 {} (40 gas price in Gwei)'.format(g.coin)
|
|
|
- return self.ethdev_txcreate(name,args=args,acct='1',non_mmgen_inputs=0,
|
|
|
- interactive_fee=interactive_fee,fee_res=fee_res,eth_fee_res=True)
|
|
|
-
|
|
|
- def ethdev_txbump(self,name,ext=',40000]{}.rawtx',fee='50G',add_args=[]):
|
|
|
- ext = ext.format('-α' if g.debug_utf8 else '')
|
|
|
- tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
|
|
|
- t = MMGenExpect(name,'mmgen-txbump', eth_args() + add_args + ['--yes',tx_fn])
|
|
|
- t.expect('or gas price: ',fee+'\n')
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_txsign4(self,name): self.ethdev_txsign(name,ni=True,ext='.45495,50000]{}.rawtx')
|
|
|
- def ethdev_txsend4(self,name): self.ethdev_txsend(name,ext='.45495,50000]{}.sigtx')
|
|
|
- def ethdev_bal4(self,name): self.ethdev_bal(name,n='4')
|
|
|
-
|
|
|
- def ethdev_txcreate5(self,name):
|
|
|
- args = [eth_burn_addr + ','+eth_amt1]
|
|
|
- return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
|
|
|
- def ethdev_txsign5(self,name): self.ethdev_txsign(name,ni=True,ext=eth_amt1+',50000]{}.rawtx')
|
|
|
- def ethdev_txsend5(self,name): self.ethdev_txsend(name,ext=eth_amt1+',50000]{}.sigtx')
|
|
|
- def ethdev_bal5(self,name): self.ethdev_bal(name,n='5')
|
|
|
-
|
|
|
- bal_corr = Decimal('0.0000032') # gas use for token sends varies between ETH and ETC!
|
|
|
- def ethdev_bal(self,name,n=None):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + ['twview','wide=1'])
|
|
|
- for b in eth_bals[n]:
|
|
|
- addr,amt,adj = b if len(b) == 3 else b + (False,)
|
|
|
- if adj and g.coin == 'ETC': amt = str(Decimal(amt) + self.bal_corr)
|
|
|
- pat = r'{}\s+{}\s'.format(addr,amt.replace('.',r'\.'))
|
|
|
- t.expect(pat,regex=True)
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_token_bal(self,name,n=None):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + ['--token=mm1','twview','wide=1'])
|
|
|
- for b in eth_token_bals[n]:
|
|
|
- addr,amt1,amt2,adj = b if len(b) == 4 else b + (False,)
|
|
|
- if adj and g.coin == 'ETC': amt2 = str(Decimal(amt2) + self.bal_corr)
|
|
|
- pat = r'{}\s+{}\s+{}\s'.format(addr,amt1.replace('.',r'\.'),amt2.replace('.',r'\.'))
|
|
|
- t.expect(pat,regex=True)
|
|
|
- t.read()
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_bal_getbalance(self,name,idx,etc_adj=False,extra_args=[]):
|
|
|
- bal1 = eth_token_bals_getbalance[idx][0]
|
|
|
- bal2 = eth_token_bals_getbalance[idx][1]
|
|
|
- bal1 = Decimal(bal1)
|
|
|
- if etc_adj and g.coin == 'ETC': bal1 += self.bal_corr
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + extra_args + ['getbalance'])
|
|
|
- t.expect(r'\n[0-9A-F]{8}: .* '+str(bal1),regex=True)
|
|
|
- t.expect(r'\nNon-MMGen: .* '+bal2,regex=True)
|
|
|
- total = t.expect_getend(r'\nTOTAL:\s+',regex=True).split()[0]
|
|
|
- t.read()
|
|
|
- assert Decimal(bal1) + Decimal(bal2) == Decimal(total)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_add_label(self,name,addr='98831F3A:E:3',lbl=utf8_label):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + ['add_label',addr,lbl])
|
|
|
- t.expect('Added label.*in tracking wallet',regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_chk_label(self,name,addr='98831F3A:E:3',label_pat=utf8_label_pat):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + ['listaddresses','all_labels=1'])
|
|
|
- t.expect(r'{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,(label_pat or label)),regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_remove_label(self,name,addr='98831F3A:E:3'):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + ['remove_label',addr])
|
|
|
- t.expect('Removed label.*in tracking wallet',regex=True)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_rpc_init(self):
|
|
|
- init_coin(g.coin)
|
|
|
- g.proto.rpc_port = 8549
|
|
|
- rpc_init()
|
|
|
-
|
|
|
- def ethdev_token_compile(self,name,token_data={}):
|
|
|
- MMGenExpect(name,'',msg_only=True)
|
|
|
- cmd_args = ['--{}={}'.format(k,v) for k,v in list(token_data.items())]
|
|
|
- imsg("Compiling solidity token contract '{}' with 'solc'".format(token_data['symbol']))
|
|
|
- cmd = ['scripts/create-token.py','--coin='+g.coin,'--outdir='+cfg['tmpdir']] + cmd_args + [eth_addr_chk]
|
|
|
- imsg("Executing: {}".format(' '.join(cmd)))
|
|
|
- subprocess.check_output(cmd,stderr=subprocess.STDOUT)
|
|
|
- imsg("ERC20 token '{}' compiled".format(token_data['symbol']))
|
|
|
- ok()
|
|
|
-
|
|
|
- def ethdev_token_compile1(self,name):
|
|
|
- token_data = { 'name':'MMGen Token 1', 'symbol':'MM1', 'supply':10**26, 'decimals':18 }
|
|
|
- self.ethdev_token_compile(name,token_data)
|
|
|
-
|
|
|
- def ethdev_token_compile2(self,name):
|
|
|
- token_data = { 'name':'MMGen Token 2', 'symbol':'MM2', 'supply':10**18, 'decimals':10 }
|
|
|
- self.ethdev_token_compile(name,token_data)
|
|
|
-
|
|
|
- def ethdev_token_deploy(self,name,num,key,gas,mmgen_cmd='txdo',tx_fee='8G'):
|
|
|
- self.ethdev_rpc_init()
|
|
|
- key_fn = get_tmpfile_fn(cfg,cfg['parity_keyfile'])
|
|
|
- fn = os.path.join(cfg['tmpdir'],key+'.bin')
|
|
|
- os.environ['MMGEN_BOGUS_SEND'] = ''
|
|
|
- args = ['-B','--tx-fee='+tx_fee,'--tx-gas={}'.format(gas),'--contract-data='+fn,'--inputs='+eth_addr,'--yes']
|
|
|
- if mmgen_cmd == 'txdo': args += ['-k',key_fn]
|
|
|
- t = MMGenExpect(name,'mmgen-'+mmgen_cmd, eth_args() + args)
|
|
|
- if mmgen_cmd == 'txcreate':
|
|
|
- t.written_to_file('Ethereum transaction')
|
|
|
- ext = '[0,8000]{}.rawtx'.format('-α' if g.debug_utf8 else '')
|
|
|
- tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
|
|
|
- t = MMGenExpect(name,'mmgen-txsign', eth_args() + ['--yes','-k',key_fn,tx_fn],no_msg=True)
|
|
|
- self.txsign_ui_common(t,name,ni=True,no_ok=True)
|
|
|
- tx_fn = tx_fn.replace('.rawtx','.sigtx')
|
|
|
- t = MMGenExpect(name,'mmgen-txsend', eth_args() + [tx_fn],no_msg=True)
|
|
|
-
|
|
|
- os.environ['MMGEN_BOGUS_SEND'] = '1'
|
|
|
- txid = self.txsend_ui_common(t,mmgen_cmd,quiet=True,bogus_send=False,no_ok=True)
|
|
|
- addr = t.expect_getend('Contract address: ')
|
|
|
- from mmgen.altcoins.eth.tx import EthereumMMGenTX as etx
|
|
|
- assert etx.get_exec_status(txid.encode(),True) != 0,(
|
|
|
- "Contract '{}:{}' failed to execute. Aborting".format(num,key))
|
|
|
- if key == 'Token':
|
|
|
- write_to_tmpfile(cfg,'token_addr{}'.format(num),addr+'\n')
|
|
|
- imsg('\nToken #{} ({}) deployed!'.format(num,addr))
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_token_deploy1a(self,name): self.ethdev_token_deploy(name,num=1,key='SafeMath',gas=200000)
|
|
|
- def ethdev_token_deploy1b(self,name): self.ethdev_token_deploy(name,num=1,key='Owned',gas=250000)
|
|
|
- def ethdev_token_deploy1c(self,name): self.ethdev_token_deploy(name,num=1,key='Token',gas=1100000,tx_fee='7G')
|
|
|
-
|
|
|
- def ethdev_tx_status2(self,name):
|
|
|
- self.ethdev_tx_status(name,ext=g.coin+'[0,7000]{}.sigtx',expect_str='successfully executed')
|
|
|
-
|
|
|
- def ethdev_bal6(self,name): return self.ethdev_bal5(name)
|
|
|
-
|
|
|
- def ethdev_token_deploy2a(self,name): self.ethdev_token_deploy(name,num=2,key='SafeMath',gas=200000)
|
|
|
- def ethdev_token_deploy2b(self,name): self.ethdev_token_deploy(name,num=2,key='Owned',gas=250000)
|
|
|
- def ethdev_token_deploy2c(self,name): self.ethdev_token_deploy(name,num=2,key='Token',gas=1100000)
|
|
|
-
|
|
|
- def ethdev_contract_deploy(self,name): # test create,sign,send
|
|
|
- self.ethdev_token_deploy(name,num=2,key='SafeMath',gas=1100000,mmgen_cmd='txcreate')
|
|
|
-
|
|
|
- def ethdev_token_transfer_ops(self,name,op,amt=1000):
|
|
|
- MMGenExpect(name,'',msg_only=True)
|
|
|
- sid = cfgs['8']['seed_id']
|
|
|
- from mmgen.tool import MMGenToolCmd
|
|
|
- usr_mmaddrs = ['{}:E:{}'.format(sid,i) for i in (11,21)]
|
|
|
- usr_addrs = [MMGenToolCmd().gen_addr(addr,dfl_words) for addr in usr_mmaddrs]
|
|
|
- self.ethdev_rpc_init()
|
|
|
-
|
|
|
- from mmgen.altcoins.eth.contract import Token
|
|
|
- from mmgen.altcoins.eth.tx import EthereumMMGenTX as etx
|
|
|
- def do_transfer():
|
|
|
- for i in range(2):
|
|
|
- tk = Token(read_from_tmpfile(cfg,'token_addr{}'.format(i+1)).strip())
|
|
|
- imsg_r('\n'+tk.info())
|
|
|
- imsg('dev token balance (pre-send): {}'.format(tk.balance(eth_addr)))
|
|
|
- imsg('Sending {} {} to address {} ({})'.format(amt,g.coin,usr_addrs[i],usr_mmaddrs[i]))
|
|
|
- txid = tk.transfer(eth_addr,usr_addrs[i],amt,eth_key,
|
|
|
- start_gas=ETHAmt(60000,'wei'),gasPrice=ETHAmt(8,'Gwei'))
|
|
|
- assert etx.get_exec_status(txid,True) != 0,'Transfer of token funds failed. Aborting'
|
|
|
-
|
|
|
- def show_bals():
|
|
|
- for i in range(2):
|
|
|
- tk = Token(read_from_tmpfile(cfg,'token_addr{}'.format(i+1)).strip())
|
|
|
- imsg('Token: {}'.format(tk.symbol()))
|
|
|
- imsg('dev token balance: {}'.format(tk.balance(eth_addr)))
|
|
|
- imsg('usr token balance: {} ({} {})'.format(
|
|
|
- tk.balance(usr_addrs[i]),usr_mmaddrs[i],usr_addrs[i]))
|
|
|
-
|
|
|
- silence()
|
|
|
- if op == 'show_bals': show_bals()
|
|
|
- elif op == 'do_transfer': do_transfer()
|
|
|
- end_silence()
|
|
|
- ok()
|
|
|
-
|
|
|
- def ethdev_token_fund_users(self,name):
|
|
|
- return self.ethdev_token_transfer_ops(name,op='do_transfer')
|
|
|
-
|
|
|
- def ethdev_token_user_bals(self,name):
|
|
|
- return self.ethdev_token_transfer_ops(name,op='show_bals')
|
|
|
-
|
|
|
- def ethdev_token_addrgen(self,name):
|
|
|
- self.ethdev_addrgen(name,addrs='11-13')
|
|
|
- self.ethdev_addrgen(name,addrs='21-23')
|
|
|
-
|
|
|
- def ethdev_token_addrimport_badaddr1(self,name):
|
|
|
- self.ethdev_addrimport(name,ext='[11-13]{}.addrs',add_args=['--token=abc'],bad_input=True)
|
|
|
-
|
|
|
- def ethdev_token_addrimport_badaddr2(self,name):
|
|
|
- self.ethdev_addrimport(name,ext='[11-13]{}.addrs',add_args=['--token='+'00deadbeef'*4],bad_input=True)
|
|
|
-
|
|
|
- def ethdev_token_addrimport(self,name):
|
|
|
- for n,r in ('1','11-13'),('2','21-23'):
|
|
|
- tk_addr = read_from_tmpfile(cfg,'token_addr'+n).strip()
|
|
|
- self.ethdev_addrimport(name,ext='['+r+']{}.addrs',expect='3/3',add_args=['--token='+tk_addr])
|
|
|
-
|
|
|
- def ethdev_bal7(self,name): return self.ethdev_bal5(name)
|
|
|
- def ethdev_token_bal1(self,name): self.ethdev_token_bal(name,n='1')
|
|
|
-
|
|
|
- def ethdev_token_txcreate(self,name,args=[],token='',inputs='1',fee='50G'):
|
|
|
- t = MMGenExpect(name,'mmgen-txcreate', eth_args() + ['--token='+token,'-B','--tx-fee='+fee] + args)
|
|
|
- self.txcreate_ui_common(t,name,menu=[],
|
|
|
- input_sels_prompt='to spend from',
|
|
|
- inputs=inputs,file_desc='Ethereum token transaction',
|
|
|
- add_comment=ref_tx_label_lat_cyr_gr)
|
|
|
- return t
|
|
|
- def ethdev_token_txsign(self,name,ext='',token=''):
|
|
|
- self.ethdev_txsign(name,ni=True,ext=ext,add_args=['--token='+token])
|
|
|
- def ethdev_token_txsend(self,name,ext='',token=''):
|
|
|
- self.ethdev_txsend(name,ext=ext,add_args=['--token=mm1'])
|
|
|
-
|
|
|
- def ethdev_token_txcreate1(self,name):
|
|
|
- return self.ethdev_token_txcreate(name,args=['98831F3A:E:12,1.23456'],token='mm1')
|
|
|
- def ethdev_token_txsign1(self,name):
|
|
|
- self.ethdev_token_txsign(name,ext='1.23456,50000]{}.rawtx',token='mm1')
|
|
|
- def ethdev_token_txsend1(self,name):
|
|
|
- self.ethdev_token_txsend(name,ext='1.23456,50000]{}.sigtx',token='mm1')
|
|
|
- def ethdev_token_bal2(self,name): self.ethdev_token_bal(name,n='2')
|
|
|
-
|
|
|
- def ethdev_twview(self,name,args=[],expect_str='',tool_args=[],exit_val=0):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + args + ['twview'] + tool_args)
|
|
|
- if expect_str:
|
|
|
- t.expect(expect_str,regex=True)
|
|
|
- t.read()
|
|
|
- t.ok(exit_val=exit_val)
|
|
|
-
|
|
|
- def ethdev_token_txcreate2(self,name):
|
|
|
- return self.ethdev_token_txcreate(name,args=[eth_burn_addr+','+eth_amt2],token='mm1')
|
|
|
-
|
|
|
- def ethdev_token_txbump(self,name):
|
|
|
- self.ethdev_txbump(name,ext=eth_amt2+',50000]{}.rawtx',fee='56G',add_args=['--token=mm1'])
|
|
|
-
|
|
|
- def ethdev_token_txsign2(self,name):
|
|
|
- self.ethdev_token_txsign(name,ext=eth_amt2+',50000]{}.rawtx',token='mm1')
|
|
|
- def ethdev_token_txsend2(self,name):
|
|
|
- self.ethdev_token_txsend(name,ext=eth_amt2+',50000]{}.sigtx',token='mm1')
|
|
|
-
|
|
|
- def ethdev_token_bal3(self,name): self.ethdev_token_bal(name,n='3')
|
|
|
-
|
|
|
- def ethdev_del_dev_addr(self,name):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + ['remove_address',eth_addr])
|
|
|
- t.read() # TODO
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_bal1_getbalance(self,name):
|
|
|
- self.ethdev_bal_getbalance(name,'1',etc_adj=True)
|
|
|
-
|
|
|
- def ethdev_addrimport_token_burn_addr(self,name):
|
|
|
- self.ethdev_addrimport_one_addr(name,addr=eth_burn_addr,extra_args=['--token=mm1'])
|
|
|
-
|
|
|
- def ethdev_token_bal4(self,name): self.ethdev_token_bal(name,n='4')
|
|
|
-
|
|
|
- def ethdev_token_bal_getbalance(self,name):
|
|
|
- self.ethdev_bal_getbalance(name,'2',extra_args=['--token=mm1'])
|
|
|
-
|
|
|
- def ethdev_txcreate_noamt(self,name):
|
|
|
- return self.ethdev_txcreate(name,args=['98831F3A:E:12'],eth_fee_res=True)
|
|
|
- def ethdev_txsign_noamt(self,name):
|
|
|
- self.ethdev_txsign(name,ext='99.99895,50000]{}.rawtx')
|
|
|
- def ethdev_txsend_noamt(self,name):
|
|
|
- self.ethdev_txsend(name,ext='99.99895,50000]{}.sigtx')
|
|
|
-
|
|
|
- def ethdev_bal8(self,name): self.ethdev_bal(name,n='8')
|
|
|
- def ethdev_token_bal5(self,name): self.ethdev_token_bal(name,n='5')
|
|
|
-
|
|
|
- def ethdev_token_txcreate_noamt(self,name):
|
|
|
- return self.ethdev_token_txcreate(name,args=['98831F3A:E:13'],token='mm1',inputs='2',fee='51G')
|
|
|
- def ethdev_token_txsign_noamt(self,name):
|
|
|
- self.ethdev_token_txsign(name,ext='1.23456,51000]{}.rawtx',token='mm1')
|
|
|
- def ethdev_token_txsend_noamt(self,name):
|
|
|
- self.ethdev_token_txsend(name,ext='1.23456,51000]{}.sigtx',token='mm1')
|
|
|
-
|
|
|
- def ethdev_bal9(self,name): self.ethdev_bal(name,n='9')
|
|
|
- def ethdev_token_bal6(self,name): self.ethdev_token_bal(name,n='6')
|
|
|
-
|
|
|
- def ethdev_listaddresses(self,name,args=[],tool_args=['all_labels=1'],exit_val=0):
|
|
|
- t = MMGenExpect(name,'mmgen-tool', eth_args() + args + ['listaddresses'] + tool_args)
|
|
|
- t.read()
|
|
|
- t.ok(exit_val=exit_val)
|
|
|
-
|
|
|
- def ethdev_listaddresses1(self,name):
|
|
|
- return self.ethdev_listaddresses(name)
|
|
|
- def ethdev_listaddresses2(self,name):
|
|
|
- return self.ethdev_listaddresses(name,tool_args=['minconf=999999999'])
|
|
|
- def ethdev_listaddresses3(self,name):
|
|
|
- return self.ethdev_listaddresses(name,tool_args=['sort=age'])
|
|
|
- def ethdev_listaddresses4(self,name):
|
|
|
- return self.ethdev_listaddresses(name,tool_args=['sort=age','showempty=1'])
|
|
|
-
|
|
|
- def ethdev_token_listaddresses1(self,name):
|
|
|
- return self.ethdev_listaddresses(name,args=['--token=mm1'])
|
|
|
- def ethdev_token_listaddresses2(self,name):
|
|
|
- return self.ethdev_listaddresses(name,args=['--token=mm1'],tool_args=['showempty=1'])
|
|
|
-
|
|
|
- def ethdev_twview1(self,name):
|
|
|
- return self.ethdev_twview(name)
|
|
|
- def ethdev_twview2(self,name):
|
|
|
- return self.ethdev_twview(name,tool_args=['wide=1'])
|
|
|
- def ethdev_twview3(self,name):
|
|
|
- return self.ethdev_twview(name,tool_args=['wide=1','sort=age'])
|
|
|
- def ethdev_twview4(self,name):
|
|
|
- return self.ethdev_twview(name,tool_args=['wide=1','minconf=999999999'])
|
|
|
- def ethdev_twview5(self,name):
|
|
|
- return self.ethdev_twview(name,tool_args=['wide=1','minconf=0'])
|
|
|
- def ethdev_twview6(self,name):
|
|
|
- return self.ethdev_twview(name,tool_args=['age_fmt=days'])
|
|
|
-
|
|
|
- def ethdev_token_twview1(self,name):
|
|
|
- return self.ethdev_twview(name,args=['--token=mm1'])
|
|
|
- def ethdev_token_twview2(self,name):
|
|
|
- return self.ethdev_twview(name,args=['--token=mm1'],tool_args=['wide=1'])
|
|
|
- def ethdev_token_twview3(self,name):
|
|
|
- return self.ethdev_twview(name,args=['--token=mm1'],tool_args=['wide=1','sort=age'])
|
|
|
-
|
|
|
- def ethdev_edit_label(self,name,out_num,args=[],action='l',label_text=None):
|
|
|
- t = MMGenExpect(name,'mmgen-txcreate', eth_args() + args + ['-B','-i'])
|
|
|
- p1,p2 = ('emove address:\b','return to main menu): ')
|
|
|
- p3,r3 = (p2,label_text+'\n') if label_text is not None else ('(y/N): ','y')
|
|
|
- p4,r4 = (('(y/N): ',),('y',)) if label_text == '' else ((),())
|
|
|
- for p,r in zip((p1,p1,p2,p3)+p4+(p1,p1),('M',action,out_num+'\n',r3)+r4+('M','q')):
|
|
|
- t.expect(p,r)
|
|
|
- t.ok()
|
|
|
-
|
|
|
- def ethdev_edit_label1(self,name):
|
|
|
- self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],label_text='First added label-α')
|
|
|
- def ethdev_edit_label2(self,name):
|
|
|
- self.ethdev_edit_label(name,out_num=eth_rem_addrs[1],label_text='Second added label')
|
|
|
- def ethdev_edit_label3(self,name):
|
|
|
- self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],label_text='')
|
|
|
-
|
|
|
- def ethdev_remove_addr1(self,name):
|
|
|
- self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],action='R')
|
|
|
- def ethdev_remove_addr2(self,name):
|
|
|
- self.ethdev_edit_label(name,out_num=eth_rem_addrs[1],action='R')
|
|
|
- def ethdev_remove_token_addr1(self,name):
|
|
|
- self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],args=['--token=mm1'],action='R')
|
|
|
- def ethdev_remove_token_addr2(self,name):
|
|
|
- self.ethdev_edit_label(name,out_num=eth_rem_addrs[1],args=['--token=mm1'],action='R')
|
|
|
-
|
|
|
- def ethdev_stop(self,name):
|
|
|
- MMGenExpect(name,'',msg_only=True)
|
|
|
- if subprocess.call(['which','parity'],stdout=subprocess.PIPE) == 0:
|
|
|
- pid = read_from_tmpfile(cfg,cfg['parity_pidfile'])
|
|
|
- if opt.no_daemon_stop:
|
|
|
- msg_r('(leaving daemon running by user request)')
|
|
|
- else:
|
|
|
- subprocess.check_call(['kill',pid])
|
|
|
- else:
|
|
|
- imsg('No parity executable found on system. Ignoring')
|
|
|
- ok()
|
|
|
-
|
|
|
- # undocumented admin commands
|
|
|
- def ref_tx_addrgen(self,name,atype='L'):
|
|
|
- if atype not in g.proto.mmtypes: return
|
|
|
- t = MMGenExpect(name,'mmgen-addrgen',['--outdir='+cfg['tmpdir'],'--type='+atype,dfl_words,'1-2'])
|
|
|
- t.read()
|
|
|
-
|
|
|
- def ref_tx_addrgen1(self,name): self.ref_tx_addrgen(name,atype='L')
|
|
|
- def ref_tx_addrgen2(self,name): self.ref_tx_addrgen(name,atype='C')
|
|
|
- def ref_tx_addrgen3(self,name): self.ref_tx_addrgen(name,atype='S')
|
|
|
- def ref_tx_addrgen4(self,name): self.ref_tx_addrgen(name,atype='B')
|
|
|
-
|
|
|
- def ref_tx_txcreate(self,name,f1,f2,f3,f4):
|
|
|
- sources = ['31','32']
|
|
|
- if 'S' in g.proto.mmtypes: sources += ['33']
|
|
|
- if 'B' in g.proto.mmtypes: sources += ['34']
|
|
|
- self.txcreate_common(name, sources=sources,
|
|
|
- addrs_per_wallet=2,
|
|
|
- add_args=['--locktime=1320969600'],
|
|
|
- do_label=True)
|
|
|
-
|
|
|
- # END methods
|
|
|
- for k in (
|
|
|
- 'ref_wallet_conv',
|
|
|
- 'ref_mn_conv',
|
|
|
- 'ref_seed_conv',
|
|
|
- 'ref_hex_conv',
|
|
|
- 'ref_brain_conv',
|
|
|
- 'ref_incog_conv',
|
|
|
- 'ref_incox_conv',
|
|
|
- 'ref_hincog_conv',
|
|
|
- 'ref_hincog_conv_old',
|
|
|
- 'ref_wallet_conv_out',
|
|
|
- 'ref_mn_conv_out',
|
|
|
- 'ref_seed_conv_out',
|
|
|
- 'ref_hex_conv_out',
|
|
|
- 'ref_incog_conv_out',
|
|
|
- 'ref_incox_conv_out',
|
|
|
- 'ref_hincog_conv_out',
|
|
|
- 'ref_hincog_blkdev_conv_out',
|
|
|
- 'ref_wallet_chk',
|
|
|
- 'refwalletgen',
|
|
|
- 'ref_seed_chk',
|
|
|
- 'ref_hex_chk',
|
|
|
- 'ref_mn_chk',
|
|
|
- 'ref_brain_chk',
|
|
|
- 'ref_hincog_chk',
|
|
|
- 'refaddrgen',
|
|
|
- 'refkeyaddrgen',
|
|
|
- 'refaddrgen_compressed',
|
|
|
- 'refkeyaddrgen_compressed',
|
|
|
- 'refpasswdgen',
|
|
|
- 'ref_b32passwdgen',
|
|
|
- 'ref_hexpasswdgen'
|
|
|
- ):
|
|
|
- for i in ('1','2','3'):
|
|
|
- locals()[k+i] = locals()[k]
|
|
|
-
|
|
|
- for k in ('walletgen','addrgen','keyaddrgen'): locals()[k+'14'] = locals()[k]
|
|
|
-
|
|
|
-# create temporary dirs
|
|
|
-if not opt.resume and not opt.skip_deps:
|
|
|
- if g.platform == 'win':
|
|
|
- for cfg in sorted(cfgs):
|
|
|
- mk_tmpdir(cfgs[cfg]['tmpdir'])
|
|
|
- else:
|
|
|
- for cfg in sorted(cfgs):
|
|
|
- src = os.path.join(shm_dir,cfgs[cfg]['tmpdir'].split('/')[-1])
|
|
|
- mk_tmpdir(src)
|
|
|
- try:
|
|
|
- os.unlink(cfgs[cfg]['tmpdir'])
|
|
|
- except OSError as e:
|
|
|
- if e.errno != 2: raise
|
|
|
- finally:
|
|
|
- os.symlink(src,cfgs[cfg]['tmpdir'])
|
|
|
-
|
|
|
-have_dfl_wallet = False
|
|
|
-
|
|
|
-# main()
|
|
|
-if opt.pause:
|
|
|
- import termios,atexit
|
|
|
- fd = sys.stdin.fileno()
|
|
|
- old = termios.tcgetattr(fd)
|
|
|
- def at_exit():
|
|
|
- termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
|
|
- atexit.register(at_exit)
|
|
|
-
|
|
|
-start_time = int(time.time())
|
|
|
-
|
|
|
-def end_msg():
|
|
|
- t = int(time.time()) - start_time
|
|
|
- m = '{} test{} performed. Elapsed time: {:02d}:{:02d}\n'
|
|
|
- sys.stderr.write(green(m.format(cmd_total,suf(cmd_total),t//60,t%60)))
|
|
|
-
|
|
|
-ts = MMGenTestSuite()
|
|
|
-
|
|
|
-if cmd_args and cmd_args[0] == 'admin':
|
|
|
- cmd_args.pop(0)
|
|
|
- cmd_data = cmd_data_admin
|
|
|
- cmd_list = cmd_list_admin
|
|
|
-
|
|
|
-if opt.exit_after:
|
|
|
- if opt.exit_after not in cmd_data.keys():
|
|
|
- die(1,"'{}': command not recognized".format(opt.exit_after))
|
|
|
+set_environ_for_spawned_scripts()
|
|
|
|
|
|
try:
|
|
|
- if cmd_args:
|
|
|
- for arg in cmd_args:
|
|
|
- if arg in utils:
|
|
|
- globals()[arg](cmd_args[cmd_args.index(arg)+1:])
|
|
|
- sys.exit(0)
|
|
|
- elif 'info_'+arg in cmd_data:
|
|
|
- dirs = cmd_data['info_'+arg][1]
|
|
|
- if dirs: clean(dirs)
|
|
|
- for cmd in cmd_list[arg]:
|
|
|
- check_needs_rerun(ts,cmd,build=True)
|
|
|
- elif arg in meta_cmds:
|
|
|
- for cmd in meta_cmds[arg]:
|
|
|
- check_needs_rerun(ts,cmd,build=True)
|
|
|
- elif arg in cmd_data:
|
|
|
- check_needs_rerun(ts,arg,build=True)
|
|
|
- else:
|
|
|
- die(1,'{}: unrecognized command'.format(arg))
|
|
|
- else:
|
|
|
- clean()
|
|
|
- for cmd in cmd_data:
|
|
|
- if cmd == 'info_regtest': break # don't run everything after this by default
|
|
|
- if cmd[:5] == 'info_':
|
|
|
- gmsg('{}Testing {}'.format(('\n','')[bool(opt.resume)],cmd_data[cmd][0]))
|
|
|
- continue
|
|
|
- ts.do_cmd(cmd)
|
|
|
- if cmd is not list(cmd_data.keys())[-1]: do_between()
|
|
|
+ tr = TestSuiteRunner(data_dir,trash_dir)
|
|
|
+ tr.run_tests(usr_args)
|
|
|
except KeyboardInterrupt:
|
|
|
die(1,'\nExiting at user request')
|
|
|
except TestSuiteException as e:
|
|
|
ydie(1,e.args[0])
|
|
|
except TestSuiteFatalException as e:
|
|
|
rdie(1,e.args[0])
|
|
|
-except opt.traceback and Exception:
|
|
|
- import traceback
|
|
|
- print(''.join(traceback.format_exception(*sys.exc_info())))
|
|
|
- try:
|
|
|
- os.stat('my.err')
|
|
|
- with open('my.err') as f:
|
|
|
- t = f.readlines()
|
|
|
- if t: msg_r('\n'+yellow(''.join(t[:-1]))+red(t[-1]))
|
|
|
- except: pass
|
|
|
- die(1,blue('Test script exited with error'))
|
|
|
+except Exception:
|
|
|
+ if opt.traceback:
|
|
|
+ import traceback
|
|
|
+ print(''.join(traceback.format_exception(*sys.exc_info())))
|
|
|
+ try:
|
|
|
+ os.stat('my.err')
|
|
|
+ with open('my.err') as f:
|
|
|
+ t = f.readlines()
|
|
|
+ if t: msg_r('\n'+yellow(''.join(t[:-1]))+red(t[-1]))
|
|
|
+ except: pass
|
|
|
+ die(1,blue('Test script exited with error'))
|
|
|
+ else:
|
|
|
+ raise
|
|
|
except:
|
|
|
raise
|
|
|
-
|
|
|
-end_msg()
|