ut_xmrseed.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/env python3
  2. """
  3. test.modtest_d.ut_xmrseed: Monero mnemonic unit test for the MMGen suite
  4. """
  5. altcoin_dep = True
  6. from mmgen.util import ymsg
  7. from mmgen.xmrseed import xmrseed
  8. from ..include.common import cfg, vmsg
  9. class unit_tests:
  10. vectors = ( # private keys are reduced
  11. (
  12. '148d78d2aba7dbca5cd8f6abcfb0b3c009ffbdbea1ff373d50ed94d78286640e', # Monero repo
  13. 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches ' +
  14. 'lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted',
  15. ), (
  16. 'e8164dda6d42bd1e261a3406b2038dcbddadbeefdeadbeefdeadbeefdeadbe0f',
  17. 'viewpoint donuts ardent template unveil agile meant unafraid urgent athlete rustled mime azure ' +
  18. 'jaded hawk baby jagged haystack baby jagged haystack ramped oncoming point template'
  19. ), (
  20. '6900dea9753f5c7ced87b53bdcfb109a8417bca6a2797a708194157b227fb60b',
  21. 'criminal bamboo scamper gnaw limits womanly wrong tuition birth mundane donuts square cohesive ' +
  22. 'dolphin titans narrate fuel saved wrap aloof magically mirror together update wrap'
  23. ), (
  24. '0000000000000000000000000000000000000000000000000000000000000001',
  25. 'abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey ' +
  26. 'abbey abbey abbey abbey abbey bamboo jaws jerseys abbey'
  27. ), (
  28. '1c95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
  29. 'powder directed sayings enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
  30. 'soil software foamy solved soggy foamy solved soggy jury yawning ankle solved'
  31. ), (
  32. '2c94988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
  33. 'memoir apart olive enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying soil ' +
  34. 'software foamy solved soggy foamy solved soggy jury yawning ankle foamy'
  35. ), (
  36. '4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364102',
  37. 'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
  38. 'jagged origin yeti dunes obtains godfather unbending pastry vortex washing citadel'
  39. ), (
  40. '4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364100',
  41. 'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
  42. 'jagged origin yeti dunes obtains godfather unbending kangaroo auctions audio citadel'
  43. ), (
  44. '1d95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0e',
  45. 'pram distance scamper enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
  46. 'soil software foamy solved soggy foamy solved soggy hashing mullet onboard solved'
  47. ), (
  48. 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f',
  49. 'foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy ' +
  50. 'foamy solved soggy foamy solved soggy jury yawning ankle soggy'
  51. ),
  52. )
  53. @property
  54. def _use_monero_python(self):
  55. if not hasattr(self, '_use_monero_python_'):
  56. try:
  57. from monero.wordlists.english import English
  58. self.wl = English()
  59. except ImportError:
  60. self._use_monero_python_ = False
  61. ymsg('Warning: unable to import monero-python, skipping external library checks')
  62. else:
  63. self._use_monero_python_ = True
  64. return self._use_monero_python_
  65. def wordlist(self, name, ut, desc='Monero wordlist'):
  66. xmrseed().check_wordlist(cfg)
  67. return True
  68. def fromhex(self, name, ut, desc='fromhex() method'):
  69. b = xmrseed()
  70. vmsg('Checking seed to mnemonic conversion:')
  71. for privhex, chk in self.vectors:
  72. vmsg(f' {chk}')
  73. chk = tuple(chk.split())
  74. res = b.fromhex(privhex)
  75. if self._use_monero_python:
  76. mp_chk = tuple(self.wl.encode(privhex).split())
  77. assert res == mp_chk, f'check failed:\nres: {res}\nchk: {chk}'
  78. assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
  79. return True
  80. def tohex(self, name, ut, desc='tohex() method'):
  81. b = xmrseed()
  82. vmsg('Checking mnemonic to seed conversion:')
  83. for chk, words in self.vectors:
  84. vmsg(f' {chk}')
  85. res = b.tohex(words.split())
  86. if self._use_monero_python:
  87. mp_chk = self.wl.decode(words)
  88. assert res == mp_chk, f'check failed:\nres: {res}\nchk: {mp_chk}'
  89. assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
  90. return True
  91. def errors(self, name, ut, desc='error handling'):
  92. bad_chksum_mn = ('abbey ' * 21 + 'bamboo jaws jerseys donuts').split()
  93. bad_word_mn = "admire zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo".split()
  94. bad_seed = 'deadbeef'
  95. good_mn = self.vectors[0][1].split()
  96. good_hex = self.vectors[0][0]
  97. bad_len_mn = good_mn[:22]
  98. b = xmrseed()
  99. th = b.tohex
  100. fh = b.fromhex
  101. hse = 'HexadecimalStringError'
  102. sle = 'SeedLengthError'
  103. ase = 'AssertionError'
  104. mne = 'MnemonicError'
  105. ut.process_bad_data((
  106. ('hex', hse, 'not a hexadecimal', lambda: fh('xx')),
  107. ('seed len', sle, 'invalid seed byte len', lambda: fh(bad_seed)),
  108. ('mnemonic type', ase, 'must be list', lambda: th('string')),
  109. ('pad arg (fromhex)', ase, "invalid 'pad' arg", lambda: fh(good_hex, pad=23)),
  110. ('pad arg (tohex)', ase, "invalid 'pad' arg", lambda: th(good_mn, pad=23)),
  111. ('word', mne, "not in Monero", lambda: th(bad_word_mn)),
  112. ('checksum', mne, "checksum", lambda: th(bad_chksum_mn)),
  113. ('seed phrase len', mne, "phrase len", lambda: th(bad_len_mn)),
  114. ))
  115. return True