mmgen-wallet/test/modtest_d/xmrseed.py

128 lines
5.4 KiB
Python
Executable file

#!/usr/bin/env python3
"""
test.modtest_d.xmrseed: Monero mnemonic unit test for the MMGen suite
"""
from mmgen.util import ymsg
from mmgen.xmrseed import xmrseed
from ..include.common import cfg, vmsg
class unit_tests:
vectors = ( # private keys are reduced
(
'148d78d2aba7dbca5cd8f6abcfb0b3c009ffbdbea1ff373d50ed94d78286640e', # Monero repo
'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches ' +
'lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted',
), (
'e8164dda6d42bd1e261a3406b2038dcbddadbeefdeadbeefdeadbeefdeadbe0f',
'viewpoint donuts ardent template unveil agile meant unafraid urgent athlete rustled mime azure ' +
'jaded hawk baby jagged haystack baby jagged haystack ramped oncoming point template'
), (
'6900dea9753f5c7ced87b53bdcfb109a8417bca6a2797a708194157b227fb60b',
'criminal bamboo scamper gnaw limits womanly wrong tuition birth mundane donuts square cohesive ' +
'dolphin titans narrate fuel saved wrap aloof magically mirror together update wrap'
), (
'0000000000000000000000000000000000000000000000000000000000000001',
'abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey ' +
'abbey abbey abbey abbey abbey bamboo jaws jerseys abbey'
), (
'1c95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
'powder directed sayings enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
'soil software foamy solved soggy foamy solved soggy jury yawning ankle solved'
), (
'2c94988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
'memoir apart olive enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying soil ' +
'software foamy solved soggy foamy solved soggy jury yawning ankle foamy'
), (
'4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364102',
'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
'jagged origin yeti dunes obtains godfather unbending pastry vortex washing citadel'
), (
'4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364100',
'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
'jagged origin yeti dunes obtains godfather unbending kangaroo auctions audio citadel'
), (
'1d95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0e',
'pram distance scamper enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
'soil software foamy solved soggy foamy solved soggy hashing mullet onboard solved'
), (
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f',
'foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy ' +
'foamy solved soggy foamy solved soggy jury yawning ankle soggy'
),
)
@property
def _use_monero_python(self):
if not hasattr(self, '_use_monero_python_'):
try:
from monero.wordlists.english import English
self.wl = English()
except ImportError:
self._use_monero_python_ = False
ymsg('Warning: unable to import monero-python, skipping external library checks')
else:
self._use_monero_python_ = True
return self._use_monero_python_
def wordlist(self, name, ut, desc='Monero wordlist'):
xmrseed().check_wordlist(cfg)
return True
def fromhex(self, name, ut, desc='fromhex() method'):
b = xmrseed()
vmsg('Checking seed to mnemonic conversion:')
for privhex, chk in self.vectors:
vmsg(f' {chk}')
chk = tuple(chk.split())
res = b.fromhex(privhex)
if self._use_monero_python:
mp_chk = tuple(self.wl.encode(privhex).split())
assert res == mp_chk, f'check failed:\nres: {res}\nchk: {chk}'
assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
return True
def tohex(self, name, ut, desc='tohex() method'):
b = xmrseed()
vmsg('Checking mnemonic to seed conversion:')
for chk, words in self.vectors:
vmsg(f' {chk}')
res = b.tohex(words.split())
if self._use_monero_python:
mp_chk = self.wl.decode(words)
assert res == mp_chk, f'check failed:\nres: {res}\nchk: {mp_chk}'
assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
return True
def errors(self, name, ut, desc='error handling'):
bad_chksum_mn = ('abbey ' * 21 + 'bamboo jaws jerseys donuts').split()
bad_word_mn = "admire zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo".split()
bad_seed = 'deadbeef'
good_mn = self.vectors[0][1].split()
good_hex = self.vectors[0][0]
bad_len_mn = good_mn[:22]
b = xmrseed()
th = b.tohex
fh = b.fromhex
hse = 'HexadecimalStringError'
sle = 'SeedLengthError'
ase = 'AssertionError'
mne = 'MnemonicError'
ut.process_bad_data((
('hex', hse, 'not a hexadecimal', lambda: fh('xx')),
('seed len', sle, 'invalid seed byte len', lambda: fh(bad_seed)),
('mnemonic type', ase, 'must be list', lambda: th('string')),
('pad arg (fromhex)', ase, "invalid 'pad' arg", lambda: fh(good_hex, pad=23)),
('pad arg (tohex)', ase, "invalid 'pad' arg", lambda: th(good_mn, pad=23)),
('word', mne, "not in Monero", lambda: th(bad_word_mn)),
('checksum', mne, "checksum", lambda: th(bad_chksum_mn)),
('seed phrase len', mne, "phrase len", lambda: th(bad_len_mn)),
))
return True