#!/usr/bin/env python3

"""
test/unit_tests_d/ut_xmrseed: Monero mnemonic unit test for the MMGen suite
"""

altcoin_dep = True

from mmgen.util import msg,msg_r,ymsg

from ..include.common import cfg,qmsg,vmsg

class unit_test:

	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'
		),
	)

	def run_test(self,name,ut):

		def test_fromhex(b):
			vmsg('')
			qmsg('Checking seed to mnemonic conversion:')
			for privhex,chk in self.vectors:
				vmsg(f'    {chk}')
				chk = tuple(chk.split())
				res = b.fromhex(privhex)
				if use_monero_python:
					mp_chk = tuple( 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}'

		def test_tohex(b):
			vmsg('')
			qmsg('Checking mnemonic to seed conversion:')
			for chk,words in self.vectors:
				vmsg(f'    {chk}')
				res = b.tohex( words.split() )
				if use_monero_python:
					mp_chk = 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}'

		msg_r('Testing xmrseed conversion routines...')
		qmsg('')

		from mmgen.xmrseed import xmrseed

		b = xmrseed()
		b.check_wordlist(cfg)

		try:
			from monero.wordlists.english import English
			wl = English()
		except ImportError:
			use_monero_python = False
			ymsg('Warning: unable to import monero-python, skipping external library checks')
		else:
			use_monero_python = True

		test_fromhex(b)
		test_tohex(b)

		vmsg('')
		qmsg('Checking 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]

		th = b.tohex
		fh = b.fromhex

		hse = 'HexadecimalStringError'
		sle = 'SeedLengthError'
		ase = 'AssertionError'
		mne = 'MnemonicError'

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

		ut.process_bad_data(bad_data)

		vmsg('')
		msg('OK')

		return True