ut_cashaddr.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #!/usr/bin/env python3
  2. """
  3. test.modtest_d.ut_cashaddr: unit test for the BCH cashaddr module
  4. """
  5. altcoin_dep = True
  6. from collections import namedtuple
  7. from mmgen.proto.bch.cashaddr import cashaddr_parse_addr, cashaddr_decode_addr, cashaddr_encode_addr
  8. from mmgen.addr import CoinAddr
  9. from ..include.common import cfg, vmsg
  10. from mmgen.protocol import init_proto
  11. proto = init_proto(cfg, 'bch')
  12. # Source: https://upgradespecs.bitcoincashnode.org/cashaddr
  13. alias_data = """
  14. 1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a
  15. 1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy
  16. 16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r
  17. 3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq
  18. 3LDsS579y7sruadqu11beEJoTjdFiFCdX4 bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e
  19. 31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37
  20. """
  21. vec_data = """
  22. F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9
  23. 20 0 bitcoincash:qr6m7j9njldwwzlg9v7v53unlr4jkmx6eylep8ekg2
  24. 20 1 bchtest:pr6m7j9njldwwzlg9v7v53unlr4jkmx6eyvwc0uz5t
  25. 20 1 pref:pr6m7j9njldwwzlg9v7v53unlr4jkmx6ey65nvtks5
  26. 20 15 prefix:0r6m7j9njldwwzlg9v7v53unlr4jkmx6ey3qnjwsrf
  27. 7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA
  28. 24 0 bitcoincash:q9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2ws4mr9g0
  29. 24 1 bchtest:p9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2u94tsynr
  30. 24 1 pref:p9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2khlwwk5v
  31. 24 15 prefix:09adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2p29kc2lp
  32. 3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B
  33. 28 0 bitcoincash:qgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcw59jxxuz
  34. 28 1 bchtest:pgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcvs7md7wt
  35. 28 1 pref:pgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcrsr6gzkn
  36. 28 15 prefix:0gagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkc5djw8s9g
  37. 3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060
  38. 32 0 bitcoincash:qvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq5nlegake
  39. 32 1 bchtest:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq7fqng6m6
  40. 32 1 pref:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq4k9m7qf9
  41. 32 15 prefix:0vch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxqsh6jgp6w
  42. C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB
  43. 40 0 bitcoincash:qnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklv39gr3uvz
  44. 40 1 bchtest:pnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklvmgm6ynej
  45. 40 1 pref:pnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklv0vx5z0w3
  46. 40 15 prefix:0nq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklvwsvctzqy
  47. E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C
  48. 48 0 bitcoincash:qh3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqex2w82sl
  49. 48 1 bchtest:ph3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqnzf7mt6x
  50. 48 1 pref:ph3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqjntdfcwg
  51. 48 15 prefix:0h3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqakcssnmn
  52. D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041
  53. 56 0 bitcoincash:qmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqscw8jd03f
  54. 56 1 bchtest:pmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqs6kgdsg2g
  55. 56 1 pref:pmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqsammyqffl
  56. 56 15 prefix:0mvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqsgjrqpnw8
  57. D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B
  58. 64 0 bitcoincash:qlg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mtky5sv5w
  59. 64 1 bchtest:plg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mc773cwez
  60. 64 1 pref:plg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mg7pj3lh8
  61. 64 15 prefix:0lg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96ms92w6845
  62. """
  63. class unit_tests:
  64. @property
  65. def vectors(self):
  66. t = namedtuple('vectors', ['size', 'type', 'addr', 'data'])
  67. def gen():
  68. for a in vec_data.splitlines():
  69. if a:
  70. d = a.split()
  71. if len(d) == 1:
  72. data = d[0].lower()
  73. else:
  74. yield t(int(d[0]), int(d[1]), d[2], data)
  75. return list(gen())
  76. @property
  77. def aliases(self):
  78. t = namedtuple('aliases', ['legacy', 'cashaddr'])
  79. return [t(*a.split()) for a in alias_data.splitlines() if a]
  80. def encode(self, name, ut, desc='low-level address encoding'):
  81. data = None
  82. for v in self.vectors:
  83. if not data or data != v.data:
  84. data = v.data
  85. vmsg(f'\n{data}')
  86. vmsg(f' {v.addr}')
  87. ret = cashaddr_encode_addr(v.type, v.size, cashaddr_parse_addr(v.addr).pfx, bytes.fromhex(v.data))
  88. assert ret.addr == v.addr
  89. return True
  90. def decode(self, name, ut, desc='low-level address decoding'):
  91. data = None
  92. for v in self.vectors:
  93. if not data or data != v.data:
  94. data = v.data
  95. vmsg(f'\n{data}')
  96. vmsg(f' {v.addr}')
  97. ret = cashaddr_decode_addr(v.addr)
  98. assert ret.bytes.hex() == v.data
  99. return True
  100. def coinaddr(self, name, ut, desc='CoinAddr class'):
  101. for e in self.aliases:
  102. for addr in (
  103. e.cashaddr.upper(),
  104. e.cashaddr,
  105. e.cashaddr.split(':')[1],
  106. e.legacy,
  107. ):
  108. a = CoinAddr(proto, addr)
  109. vmsg(addr)
  110. assert e.legacy == a.views[1]
  111. assert e.cashaddr == a.proto.cashaddr_pfx + ':' + a.views[0]
  112. vmsg('')
  113. return True
  114. def errors(self, name, ut, desc='error handling'):
  115. # could do these in objtest.py:
  116. def bad1(): a = CoinAddr(proto, self.aliases[0].cashaddr.replace('g', 'G'))
  117. def bad2(): a = CoinAddr(proto, 'x' + self.aliases[0].cashaddr)
  118. def bad3(): a = CoinAddr(proto, self.aliases[0].cashaddr[:-1])
  119. def bad4(): a = CoinAddr(proto, self.aliases[0].cashaddr[:-1]+'i')
  120. def bad5(): a = CoinAddr(proto, self.aliases[0].cashaddr[:-1]+'x')
  121. ut.process_bad_data((
  122. ('case', 'ObjectInitError', 'mixed case', bad1),
  123. ('prefix', 'ObjectInitError', 'invalid prefix', bad2),
  124. ('data', 'ObjectInitError', 'too short', bad3),
  125. ('b32 char', 'ObjectInitError', 'substring', bad4),
  126. ('chksum', 'ObjectInitError', 'checksum', bad5),
  127. ))
  128. return True