release/testing: UTF8 testing fixes, other fixes and improvements

This commit is contained in:
The MMGen Project 2020-02-22 19:54:03 +00:00
commit 5fe92460ad
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
15 changed files with 136 additions and 117 deletions

View file

@ -1,10 +1,6 @@
***Note: This is the source code repository of the MMGen wallet system. For an
easier way to install MMGen, check out the prebuilt bootable USB images on the
[MMGenLive][8] home page.***
# MMGen = Multi-Mode GENerator
##### a Bitcoin and altcoin online/offline software wallet for the command line
##### An online/offline cryptocurrency wallet for the command line
### Description
@ -15,7 +11,7 @@ offline computers to provide a robust solution for securely storing, tracking,
sending and receiving your crypto assets.
The online computer is used for tracking balances and creating and sending
transactions, while the offline computer (typically an air-gapped, low-power
transactions, while the offline machine (typically an air-gapped, low-power
device such as a Raspberry Pi) takes care of wallet creation, address generation
and transaction signing. All operations involving secret data are handled
offline: **your seed and private keys never come into contact with a
@ -34,36 +30,11 @@ of address/key pairs from a single seed. Your wallet never changes, so you need
back it up only once.
At the heart of the MMGen system is the seed, the “master key” providing access
to all your crypto assets. The seed can be stored in five different ways:
1. as a password-encrypted wallet. The crack-resistant Scrypt hash function
is used for password hashing. Scrypt’s parameters can be tuned to make
your wallet’s password very difficult to crack should it fall into the
wrong hands. The wallet is a compact, six-line text file suitable for
printing or even writing out by hand;
2. as a seed file: a one-line, conveniently formatted base-58 representation
of your unencrypted seed plus a checksum;
3. as an Electrum-like mnemonic seed phrase of 12, 18 or 24 words;
4. as a brainwallet passphrase (this option is recommended only for users who
understand the risks of brainwallets and know how to create a strong
brainwallet passphrase). The brainwallet is hashed using Scrypt with
tunable parameters, making it much harder to crack than standard SHA256
brainwallets; or
5. as “incognito data”, a wallet encrypted to make it indistinguishable
from random data. This data can be hidden on a disk partition filled with
random data, or in a file at an offset of your choice. This makes it
possible to hide a wallet at a non-private location—on cloud storage, for
example. Incognito wallet hiding/retrieval is seamlessly integrated into
MMGen, making its use nearly as easy as that of the standard wallet.
The best part is that all these methods can be combined. If you forget your
mnemonic seed phrase, for example, you can regenerate it from a stored wallet
or seed file. Correspondingly, a lost wallet can be regenerated from a mnemonic
or seed or vice-versa.
to all your crypto assets. The seed can be stored in many different formats:
as a password-encrypted wallet (the default), as a one-line base58 or
hexidecimal seed file, as an Electrum-based mnemonic seed phrase, as a
brainwallet passphrase, or as “incognito data” hideable within random data in a
file or block device. Conversion between all formats is supported.
***mmgen-txcreate running in a terminal window***
![mmgen-txcreate running in a terminal window][9]
@ -94,7 +65,7 @@ the more prosaic 2048-word [BIP39 wordlist][bw] used in most wallets today.
[Litecoin][bx], [Ethereum][E], Ethereum Classic and [ERC20 tokens][E].
- **[Address generation support][ag]** for the above coins, plus [Monero][mx],
[Zcash][zx] (t and z addresses) and [144 Bitcoin-derived altcoins][ax].
- **Support for all Bitcoin address types** including segwit-p2sh and bech32.
- **Support for all Bitcoin address types** including Segwit-P2SH and Bech32.
- **Independent key derivation for each address type:** No two addresses ever
share the same private key. Certain wallets in wide use today regrettably
fail to guarantee this property, leading to the danger of inadvertent key
@ -118,11 +89,12 @@ the more prosaic 2048-word [BIP39 wordlist][bw] used in most wallets today.
always be regenerated from their parent.
- **[Transaction autosigning][X]:** This feature puts your offline signing
machine into “hands-off” mode, allowing you to transact directly from cold
storage securely and conveniently. Additional LED signaling support is
storage securely and conveniently. Additional LED blinking support is
provided for Raspbian and Armbian platforms.
- **[Password generation][G]:** MMGen can be used to generate and manage your
online passwords. Passwords are identified by arbitrarily chosen strings like
“alice@github” or “bob@reddit”.
online passwords. Password lists are identified by arbitrarily chosen strings
like “alice@github” or “bob@reddit”. Passwords of different lengths and
formats are supported.
- **Selectable seed lengths** of 128, 192 or 256 bits. Subwallets may have
shorter seeds than their parent.
- **User-enhanced entropy:** All operations requiring random data will prompt
@ -145,6 +117,10 @@ the more prosaic 2048-word [BIP39 wordlist][bw] used in most wallets today.
you to automate repetitive tasks using shell scripts. Most of the
`mmgen-tool` utility’s commands can be piped.
#### Supported platforms:
Linux, Armbian, Raspbian, Windows/MSYS2
### Download/Install
> #### [Install a prebuilt bootable image (MMGenLive) on a USB stick][8]

View file

@ -4,11 +4,11 @@
- XOR seed splitting: 7311f474, 237567bc, c7ca0c3d (see
[XOR-Seed-Splitting:-Theory-and-Practice][xo] for additional information)
- ETH tracking-wallet balance caching, Parity light client optimizations:
d0f8c44b
- Full BIP39 mnemonic support: 8519b68b, 8705e57b
- Monero new-style mnemonic support: cfa16418
- New die-roll wallet format, interactive die-roll entry: c7786369, 4714ef84
- New dieroll wallet format, interactive dieroll entry: c7786369, 4714ef84
- ETH tracking-wallet balance caching, Parity light client optimizations:
d0f8c44b
#### Other changes/additions/improvements:
@ -17,28 +17,26 @@
- Monero wallet creation/syncing tool reimplemented, now works under MSYS2:
3951925a
- New Tool API interface: f8056630
- Full automation of test suite, automatic starting/stopping of daemons
- Plus lots of code cleanups, bugfixes, and additional tests!
- New [Daemon control interface][dc] and [test daemon start/stop utilities][ss]
- Full automation of test suite with automatic starting/stopping of daemons
- UTF8 password entry works reliably under MSYS2, warnings disabled
- Plus lots of code cleanups, bugfixes, new tests and [expanded documentation][w]
This release has been tested on the following platforms:
Debian Buster / x86_64
Ubuntu Bionic / x86_64 / qemu-x86_64
Armbian Bionic / Orange Pi PC2 (armv8)
Raspbian Buster / Raspberry Pi B (armv7) (no Parity, no Monerod)
Windows 10 Enterprise Eng. / MSYS2 / qemu-x86_64
and with the following coin daemon versions:
Bitcoin Core v0.19.0.1
Bitcoin-ABC v0.20.9
Litecoin Core v0.17.1
Monerod v0.15.0.1
Parity Ethereum v2.7.2
Testing TBD on the following platforms:
Ubuntu Bionic / x86_64 / qemu-x86_64
Ubuntu Xenial (+Python 3.6.7) / x86_64
Armbian Bionic / Orange Pi PC2 (no Parity or Monerod)
Raspbian Stretch / Raspberry Pi B (no Parity or Monerod)
Bitcoin Core 0.17.1, 0.19.0.1
Bitcoin-ABC 0.21.0
Litecoin Core 0.17.1
Monerod 0.15.0.1
Parity Ethereum 2.7.2
Altcoin address generation has been additionally tested using the following
tools as references:
@ -48,3 +46,6 @@ tools as references:
vanitygen-plus 22123128 (https://github.com/exploitagency/vanitygen-plus)
[xo]: https://github.com/mmgen/mmgen/wiki/XOR-Seed-Splitting:-Theory-and-Practice.md
[dc]: https://github.com/mmgen/mmgen/blob/master/mmgen/daemon.py
[ss]: https://github.com/mmgen/mmgen/blob/master/test/start-coin-daemons.py
[w]: https://github.com/mmgen/mmgen/wiki

View file

@ -158,13 +158,20 @@ class Daemon(MMGenObject):
self.stop(silent=silent)
return self.start(silent=silent)
def test_socket(self,host,port,timeout=10):
import socket
try: socket.create_connection((host,port),timeout=timeout).close()
except: return False
else: return True
def wait_for_state(self,req_state):
for i in range(200):
for i in range(300):
if self.state == req_state:
return True
time.sleep(0.2)
else:
die(2,'Daemon wait timeout for {} {} exceeded'.format(self.daemon_id.upper(),self.network))
m = 'Wait for state {!r} timeout exceeded for daemon {} {}'
die(2,m.format(req_state,self.daemon_id.upper(),self.network))
@classmethod
def check_implement(cls):
@ -221,6 +228,8 @@ class MoneroWalletDaemon(Daemon):
@property
def state(self):
if not self.test_socket(g.monero_wallet_rpc_host,self.rpc_port):
return 'stopped'
from mmgen.rpc import MoneroWalletRPCConnection
try:
MoneroWalletRPCConnection(
@ -291,7 +300,11 @@ class CoinDaemon(Daemon):
if network == 'regtest':
me.desc = 'regtest daemon'
if test_suite:
rel_datadir = os.path.join('test','data_dir','regtest',daemon_id)
rel_datadir = os.path.join(
'test',
'data_dir{}'.format('' if g.debug_utf8 else ''),
'regtest',
daemon_id )
else:
me.datadir = os.path.join(g.data_dir_root,'regtest',daemon_id)
elif test_suite:
@ -431,6 +444,8 @@ class MoneroDaemon(CoinDaemon):
@property
def state(self):
if not self.test_socket(g.monero_wallet_rpc_host,self.rpc_port):
return 'stopped'
cp = self.run_cmd(
[self.coind_exec]
+ self.shared_args

View file

@ -209,9 +209,6 @@ class g(object):
max_tx_file_size = 100000
max_input_size = 1024 * 1024
# pexpect chokes on these utf8 chars under MSYS2
lq,rq = (('',''),('"','"'))[bool(os.getenv('MMGEN_TEST_SUITE')) and platform=='win']
passwd_max_tries = 5
max_urandchars = 80

View file

@ -294,10 +294,6 @@ def init(opts_data,add_opts=[],opt_filter=None,parse_only=False):
if not 'code' in opts_data:
opts_data['code'] = {}
opts_data['code']['long_options'] = common_opts_data['code']
if g.debug_utf8:
for k in opts_data:
if type(opts_data[k]) == str:
opts_data[k] += ''
mmgen.share.Opts.print_help(opts_data,opt_filter) # exits
if g.bob or g.alice:

View file

@ -866,12 +866,12 @@ class MMGenMnemonic(SeedSourceUnenc):
m = 'Enter your {ml}-word seed phrase, hitting ENTER or SPACE after each word.\n'
m += "Optionally, you may use pad characters. Anything you type that's not a\n"
m += 'lowercase letter will be treated as a {lq}pad character{rq}, i.e. it will simply\n'
m += 'lowercase letter will be treated as a “pad character”, i.e. it will simply\n'
m += 'be discarded. Pad characters may be typed before, after, or in the middle\n'
m += "of words. For each word, once you've typed {lw} characters total (including\n"
m += 'pad characters) any pad character will enter the word.'
msg(m.format(ml=mn_len,lw=longest_word,lq=g.lq,rq=g.rq))
msg(m.format(ml=mn_len,lw=longest_word))
from string import ascii_lowercase
from mmgen.term import get_char_raw

View file

@ -495,8 +495,11 @@ class MMGenToolCmdMnemonic(MMGenToolCmdBase):
@staticmethod
def _xmr_reduce(bytestr):
from mmgen.protocol import MoneroProtocol
return MoneroProtocol.preprocess_key(bytestr,None)
from mmgen.protocol import MoneroProtocol as mp
if len(bytestr) != mp.privkey_len:
m = '{!r}: invalid bit length for Monero private key (must be {})'
die(1,m.format(len(bytestr*8),mp.privkey_len*8))
return mp.preprocess_key(bytestr,None)
def _do_random_mn(self,nbytes:int,fmt:str):
assert nbytes in (16,24,32), 'nbytes must be 16, 24 or 32'
@ -891,7 +894,13 @@ class MMGenToolCmdRPC(MMGenToolCmdBase):
return ret
class MMGenToolCmdMonero(MMGenToolCmdBase):
"Monero wallet utilities"
"""
Monero wallet utilities
Note that the use of these commands requires private data to be exposed on
a network-connected machine in order to unlock the Monero wallets. This is
a violation of MMGen's security policy.
"""
_monero_chain_height = None
monerod_args = []
@ -918,14 +927,14 @@ class MMGenToolCmdMonero(MMGenToolCmdBase):
xmr_keyaddrfile:str,
blockheight:'(default: current height)' = 0,
addrs:'(integer range or list)' = ''):
"create Monero wallets from key-address list"
"create Monero wallets from a key-address list"
return self.monero_wallet_ops( infile = xmr_keyaddrfile,
op = 'create',
blockheight = blockheight,
addrs = addrs)
def syncmonerowallets(self,xmr_keyaddrfile:str,addrs:'(integer range or list)'=''):
"sync Monero wallets from key-address list"
"sync Monero wallets from a key-address list"
return self.monero_wallet_ops(infile=xmr_keyaddrfile,op='sync',addrs=addrs)
def monero_wallet_ops(self,infile:str,op:str,blockheight=0,addrs='',monerod_args=[]):

View file

@ -23,7 +23,7 @@ common.py: Shared routines and data for the MMGen test suites
class TestSuiteException(Exception): pass
class TestSuiteFatalException(Exception): pass
import os
import os,time
from mmgen.common import *
from mmgen.devtools import *
@ -166,13 +166,18 @@ def iqmsg_r(s):
if not opt.quiet: omsg_r(s)
def start_test_daemons(*network_ids):
if hasattr(opt,'no_daemon_autostart') and opt.no_daemon_autostart:
return
return test_daemons_ops(*network_ids,op='start')
def stop_test_daemons(*network_ids):
if hasattr(opt,'no_daemon_stop') and opt.no_daemon_stop:
return
return test_daemons_ops(*network_ids,op='stop')
def restart_test_daemons(*network_ids):
return test_daemons_ops(*network_ids,op='restart')
stop_test_daemons(*network_ids)
return start_test_daemons(*network_ids)
def test_daemons_ops(*network_ids,op):
if opt.no_daemon_autostart:

View file

@ -37,18 +37,19 @@ rounds=100 rounds_min=20 rounds_mid=250 rounds_max=500
xmr_addrs='3,99,2,22-24,101-104'
dfl_tests='misc obj color unit hash ref altref alts xmr eth autosign btc btc_tn btc_rt bch bch_rt ltc ltc_rt tool tool2 gen'
extra_tests='autosign_minimal autosign_live etc ltc_tn bch_tn'
noalt_tests='misc obj color unit hash ref autosign_minimal btc btc_tn btc_rt tool tool2 gen'
extra_tests='autosign_btc autosign_live etc ltc_tn bch_tn'
noalt_tests='misc obj color unit hash ref autosign_btc btc btc_tn btc_rt tool tool2 gen'
quick_tests='misc obj color unit hash ref altref alts xmr eth autosign btc btc_rt tool tool2 gen'
qskip_tests='btc_tn bch bch_rt ltc ltc_rt'
PROGNAME=$(basename $0)
while getopts hbCfFi:I:lOpRtvV OPT
while getopts hAbCfFi:I:lOpRtvV OPT
do
case "$OPT" in
h) printf " %-16s Test MMGen release\n" "${PROGNAME}:"
echo " USAGE: $PROGNAME [options] [tests or test group]"
echo " OPTIONS: '-h' Print this help message"
echo " '-A' Skip tests requiring altcoin modules or daemons"
echo " '-b' Buffer keypresses for all invocations of 'test/test.py'"
echo " '-C' Run tests in coverage mode"
echo " '-f' Speed up the tests by using fewer rounds"
@ -100,6 +101,7 @@ do
echo
echo " By default, all tests are run"
exit ;;
A) SKIP_ALT=1 ;;
b) test_py+=" --buf-keypress" ;;
C) mkdir -p 'test/trace'
touch 'test/trace.acc'
@ -151,7 +153,7 @@ case $1 in
'') tests=$dfl_tests ;;
'default') tests=$dfl_tests ;;
'extra') tests=$extra_tests ;;
'noalt') tests=$noalt_tests ;;
'noalt') tests=$noalt_tests SKIP_ALT=1 ;;
'quick') tests=$quick_tests ;;
'qskip') tests=$qskip_tests ;;
*) tests="$*" ;;
@ -316,16 +318,16 @@ t_alts="
# keyconv
$gentest_py --all --type=legacy 2:keyconv $rounds
$gentest_py --all --type=compressed 2:keyconv $rounds
# ethkey
$gentest_py --all 2:ethkey $rounds
"
[ "$MSYS2" ] || { # no moneropy (pysha3), zcash-mini (golang), ethkey (?)
[ "$MSYS2" ] || { # no moneropy (pysha3), zcash-mini (golang)
t_alts+="
# moneropy
$gentest_py --all --coin=xmr 2:moneropy $rounds_min # very slow, be patient!
# zcash-mini
$gentest_py --all 2:zcash-mini $rounds_mid
# ethkey
$gentest_py --all 2:ethkey $rounds
"
}
@ -343,7 +345,7 @@ else
mkdir -p $TMPDIR
fi
mmgen_tool_xmr="$mmgen_tool -q --accept-defaults --outdir $TMPDIR"
mmgen_tool_xmr="$mmgen_tool -q --accept-defaults --outdir $TMPDIR --monero-wallet-rpc-password=passw0rd"
i_xmr='Monero'
s_xmr='Testing key-address file generation and wallet creation and sync operations for Monero'
s_xmr='The monerod (mainnet) daemon must be running for the following tests'
@ -387,10 +389,10 @@ s_autosign='The bitcoin, bitcoin-abc and litecoin mainnet and testnet daemons mu
t_autosign="$test_py autosign"
f_autosign='Autosign test completed'
i_autosign_minimal='Autosign Minimal'
s_autosign_minimal='The bitcoin mainnet and testnet daemons must be running for the following test'
t_autosign_minimal="$test_py autosign_minimal"
f_autosign_minimal='Autosign Minimal test completed'
i_autosign_btc='Autosign BTC'
s_autosign_btc='The bitcoin mainnet and testnet daemons must be running for the following test'
t_autosign_btc="$test_py autosign_btc"
f_autosign_btc='Autosign BTC test completed'
i_autosign_live='Autosign Live'
s_autosign_live="The bitcoin mainnet and testnet daemons must be running for the following test\n"
@ -402,7 +404,7 @@ f_autosign_live='Autosign Live test completed'
i_btc='Bitcoin mainnet'
s_btc='The bitcoin (mainnet) daemon must both be running for the following tests'
t_btc="
$test_py --exclude regtest,autosign_minimal,ref_altcoin
$test_py --exclude regtest,autosign,ref_altcoin
$test_py --segwit
$test_py --segwit-random
$test_py --bech32
@ -473,7 +475,6 @@ t_tool2="
$tooltest2_py --tool-api --coin=eth
$tooltest2_py --tool-api --coin=xmr
$tooltest2_py --tool-api --coin=zec
$tooltest2_py --fork # run once with --fork so commands are actually executed
$tooltest2_py
$tooltest2_py --testnet=1
$tooltest2_py --coin=ltc
@ -488,8 +489,10 @@ t_tool2="
$tooltest2_py --coin=eth --token=mm1
$tooltest2_py --coin=eth --token=mm1 --testnet=1
$tooltest2_py --coin=etc
$tooltest2_py --fork # run once with --fork so commands are actually executed
"
f_tool2='tooltest2 tests completed'
[ "$SKIP_ALT" ] && t_tool2_skip='17 18'
i_tool='Tooltest'
s_tool="The following tests will run '$tooltest_py' for all supported coins"

View file

@ -476,7 +476,7 @@ class CmdGroupMgr(object):
# 'chainsplit': ('TestSuiteChainsplit',{}),
'ethdev': ('TestSuiteEthdev',{}),
'autosign': ('TestSuiteAutosign',{}),
'autosign_minimal': ('TestSuiteAutosignMinimal',{'modname':'autosign'}),
'autosign_btc': ('TestSuiteAutosignBTC',{'modname':'autosign'}),
'autosign_live': ('TestSuiteAutosignLive',{'modname':'autosign'}),
'create_ref_tx': ('TestSuiteRefTX',{'modname':'misc','full_data':True}),
}
@ -491,7 +491,7 @@ class CmdGroupMgr(object):
'tool',
'input',
'output',
'autosign_minimal',
'autosign',
'regtest',
'ethdev')
@ -600,6 +600,7 @@ class TestSuiteRunner(object):
self.rebuild_list = OrderedDict()
self.gm = CmdGroupMgr()
self.repo_root = repo_root
self.skipped_warnings = []
if opt.log:
self.log_fd = open(log_file,'a')
@ -863,6 +864,12 @@ class TestSuiteRunner(object):
if cmd == opt.exit_after:
sys.exit(0)
def warn_skipped(self):
if self.skipped_warnings:
print(yellow('The following tests were skipped and may require attention:'))
r = '-' * 72 + '\n'
print(r+('\n'+r).join(self.skipped_warnings))
def process_retval(self,cmd,ret):
if type(ret).__name__ == 'MMGenPexpect':
ret.ok()
@ -872,6 +879,9 @@ class TestSuiteRunner(object):
self.cmd_total += 1
elif ret == 'skip':
pass
elif type(ret) == tuple and ret[0] == 'skip_warn':
self.skipped_warnings.append(
'Test {!r} was skipped:\n {}'.format(cmd,'\n '.join(ret[1].split('\n'))))
else:
rdie(1,'{!r} returned {}'.format(cmd,ret))
@ -942,9 +952,11 @@ start_test_daemons(network_id)
try:
tr = TestSuiteRunner(data_dir,trash_dir)
tr.run_tests(usr_args)
tr.warn_skipped()
stop_test_daemons(network_id)
except KeyboardInterrupt:
stop_test_daemons(network_id)
tr.warn_skipped()
die(1,'\ntest.py exiting at user request')
except TestSuiteException as e:
ydie(1,e.args[0])

View file

@ -40,14 +40,14 @@ class TestSuiteAutosign(TestSuiteBase):
)
def autosign_live(self):
return self.autosign_minimal(live=True)
return self.autosign_btc(live=True)
def autosign_minimal(self,live=False):
def autosign_btc(self,live=False):
return self.autosign(
coins=['btc','eth'],
coins=['btc'],
daemon_coins=['btc'],
txfiles=['btc','eth','mm1','etc'],
txcount=8,
txfiles=['btc'],
txcount=3,
live=live)
# tests everything except device detection, mount/unmount
@ -228,13 +228,13 @@ class TestSuiteAutosign(TestSuiteBase):
stop_test_daemons(*network_ids)
return ret
class TestSuiteAutosignMinimal(TestSuiteAutosign):
'autosigning with BTC, ETH and ETC'
class TestSuiteAutosignBTC(TestSuiteAutosign):
'autosigning with BTC'
cmd_group = (
('autosign_minimal', 'transaction autosigning (BTC,ETH,ETC)'),
('autosign_btc', 'transaction autosigning (BTC only)'),
)
class TestSuiteAutosignLive(TestSuiteAutosignMinimal):
class TestSuiteAutosignLive(TestSuiteAutosignBTC):
'live autosigning operations with device insertion/removal and LED check'
cmd_group = (
('autosign_live', 'transaction autosigning (BTC,ETH,ETC - test device insertion/removal + LED)'),

View file

@ -135,16 +135,18 @@ class TestSuiteInput(TestSuiteBase):
def password_entry_noecho(self):
if self.skip_for_win():
msg('Perform this test by hand on MSWin with non-ASCII password abc-α:')
msg(' test/misc/password_entry.py')
return 'skip' # getpass() can't handle utf8, and pexpect double-escapes utf8, so skip
m = "getpass() doesn't work with pexpect.popen_spawn!\n"
m += 'Perform the following test by hand with non-ASCII password abc-α:\n'
m += ' test/misc/password_entry.py'
return ('skip_warn',m)
return self.password_entry('Enter passphrase: ',[])
def password_entry_echo(self):
if self.skip_for_win():
msg('Perform this test by hand on MSWin with non-ASCII password abc-α:')
msg(' test/misc/password_entry.py --echo-passphrase')
return 'skip' # pexpect double-escapes utf8, so skip
m = "getpass() doesn't work with pexpect.popen_spawn!\n"
m += 'Perform the following test by hand with non-ASCII password abc-α:\n'
m += ' test/misc/password_entry.py --echo-passphrase'
return ('skip_warn',m)
return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase'])
def _user_seed_entry(self,fmt,usr_rand=False,out_fmt=None):

View file

@ -231,12 +231,12 @@ class TestSuiteRef(TestSuiteBase,TestSuiteShared):
def ref_segwitaddrfile_chk(self):
if not 'S' in g.proto.mmtypes:
return skip('not supported')
return skip('not supported by {}'.format(g.proto.__name__))
return self.ref_addrfile_chk(ftype='segwitaddr',pat='{}.*Segwit'.format(nw_name))
def ref_bech32addrfile_chk(self):
if not 'B' in g.proto.mmtypes:
return skip('not supported')
return skip('not supported by {}'.format(g.proto.__name__))
return self.ref_addrfile_chk(ftype='bech32addr',pat='{}.*Bech32'.format(nw_name))
def ref_keyaddrfile_chk(self):

View file

@ -150,10 +150,11 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared):
fn = os.path.split(t.written_to_file(capfirst(ocls.desc)))[-1]
import re
idx = int(self.test_name[-1]) - 1
pat = r'{}-[0-9A-F]{{8}}\[{},1\].mmdat'.format(
pat = r'{}-[0-9A-F]{{8}}\[{},1\]{}.mmdat'.format(
self.chk_data['sids'][idx],
self.chk_data['lens'][idx] )
assert re.match(pat,fn)
self.chk_data['lens'][idx],
'' if g.debug_utf8 else '')
assert re.match(pat,fn),'{} != {}'.format(pat,fn)
sid = os.path.basename(fn.split('-')[0])
cmp_or_die(sid,self.seed_id,desc='Seed ID')
return t
@ -170,9 +171,9 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared):
if re_pat:
import re
pat = re_pat.format(sid,slen)
assert re.match(pat,fn),'{} {}'.format(pat,fn)
assert re.match(pat,fn),'{} != {}'.format(pat,fn)
else:
cmp_or_die('{}[{}].{}'.format(sid,slen,wcls.ext),fn)
cmp_or_die('{}[{}]{}.{}'.format(sid,slen,'' if g.debug_utf8 else '',wcls.ext),fn)
return t
def ref_walletconv_words(self): return self.ref_walletconv(ofmt='mn')
@ -184,7 +185,7 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared):
def ref_walletconv_incog(self,ofmt='incog',ext='mmincog'):
args = ['-r0','-p1']
pat = r'{}-[0-9A-F]{{8}}-[0-9A-F]{{8}}\[{},1\].' + ext
pat = r'{}-[0-9A-F]{{8}}-[0-9A-F]{{8}}\[{},1\]' + ('' if g.debug_utf8 else '') + '.' + ext
return self.ref_walletconv(ofmt=ofmt,extra_args=args,re_pat=pat)
def ref_walletconv_xincog(self):

View file

@ -630,9 +630,11 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
return t
def _get_mempool(self):
disable_debug()
if not g.debug_utf8:
disable_debug()
ret = self.spawn('mmgen-regtest',['mempool']).read()
restore_debug()
if not g.debug_utf8:
restore_debug()
m = re.search(r'(\[\s*"[a-f0-9]{64}"\s*])',ret) # allow for extra output by handler at end
return json.loads(m.group(1))