altcoin.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2021 The MMGen Project <mmgen@tuta.io>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. altcoin.py - Coin constants for Bitcoin-derived altcoins
  20. """
  21. # Sources:
  22. # lb: https://github.com/libbitcoin/libbitcoin/wiki/Altcoin-Version-Mappings
  23. # pc: https://github.com/richardkiss/pycoin/blob/master/pycoin/networks/legacy_networks.py
  24. # vg: https://github.com/exploitagency/vanitygen-plus/blob/master/keyconv.c
  25. # wn: https://walletgenerator.net
  26. # cc: https://www.cryptocompare.com/api/data/coinlist/ (names,symbols only)
  27. # BIP44
  28. # https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
  29. # BIP44 registered coin types: https://github.com/satoshilabs/slips/blob/master/slip-0044.md
  30. # WIP:
  31. # NSR: 149/191 c/u, 63/('S'), 64/('S'|'T')
  32. # NBT: 150/191 c/u, 25/('B'), 26/('B')
  33. import sys
  34. def msg(s): sys.stderr.write(s+'\n')
  35. def test_equal(desc,a,b,*cdata):
  36. if type(a) == int:
  37. a = hex(a)
  38. b = hex(b)
  39. (network,coin,e,b_desc,verbose) = cdata
  40. if verbose:
  41. m = ' {:20}: {!r}'
  42. msg(m.format(desc,a))
  43. if a != b:
  44. m = '{}s for {} {} do not match:\n CoinInfo: {}\n {}: {}'
  45. raise ValueError(m.format(desc.capitalize(),coin.upper(),network,a,b_desc,b))
  46. from collections import namedtuple
  47. ce = namedtuple('CoinInfoEntry',
  48. ['name','symbol','wif_ver_num','p2pkh_info','p2sh_info','has_segwit','trust_level'])
  49. class CoinInfo(object):
  50. coin_constants = {}
  51. coin_constants['mainnet'] = (
  52. # Trust levels: -1=disabled 0=untested 1=low 2=med 3=high 4=very high (no warn) 5=unconditional
  53. # Trust levels apply to key/address generation only.
  54. # Non core-coin fork coins (i.e. BCG) must be disabled here to prevent generation from
  55. # incorrect scrambled seed.
  56. ce('Bitcoin', 'BTC', 0x80, (0x00,'1'), (0x05,'3'), True, 5),
  57. ce('BitcoinCashNode', 'BCH', 0x80, (0x00,'1'), (0x05,'3'), False, 5),
  58. ce('BitcoinGold', 'BCG', 0x80, (0x00,'1'), (0x05,'3'), True, -1),
  59. ce('2GiveCoin', '2GIVE', 0xa7, (0x27,('G','H')), None, False, 0),
  60. ce('42Coin', '42', 0x88, (0x08,'4'), None, False, 1),
  61. ce('ACoin', 'ACOIN', 0xe6, (0x17,'A'), None, False, 0),
  62. ce('Alphacoin', 'ALF', 0xd2, (0x52,('Z','a')), None, False, 0),
  63. ce('Anoncoin', 'ANC', 0x97, (0x17,'A'), None, False, 1),
  64. ce('Apexcoin', 'APEX', 0x97, (0x17,'A'), None, False, 0),
  65. ce('Aquariuscoin', 'ARCO', 0x97, (0x17,'A'), None, False, 0),
  66. ce('Argentum', 'ARG', 0x97, (0x17,'A'), (0x05,'3'), False, 1),
  67. ce('AsiaCoin', 'AC', 0x97, (0x17,'A'), (0x08,'4'), False, 1),
  68. ce('Auroracoin', 'AUR', 0x97, (0x17,'A'), None, False, 1),
  69. ce('BBQcoin', 'BQC', 0xd5, (0x55,'b'), None, False, 1),
  70. ce('BitcoinDark', 'BTCD', 0xbc, (0x3c,'R'), (0x55,'b'), False, 1),
  71. ce('BitcoinFast', 'BCF', 0xe0, (0x60,('f','g')), None, False, 0),
  72. ce('BitQuark', 'BTQ', 0xba, (0x3a,'Q'), None, False, 0),
  73. ce('Blackcoin', 'BLK', 0x99, (0x19,'B'), (0x55,'b'), False, 1),
  74. ce('BlackmoonCrypto', 'BMC', 0x83, (0x03,'2'), None, False, 0),
  75. ce('BlockCat', 'CAT', 0x95, (0x15,'9'), None, False, 0),
  76. ce('CanadaECoin', 'CDN', 0x9c, (0x1c,'C'), (0x05,'3'), False, 1),
  77. ce('CannabisCoin', 'CANN', 0x9c, (0x1c,'C'), None, False, 0),
  78. ce('CannaCoin', 'CCN', 0x9c, (0x1c,'C'), (0x05,'3'), False, 1),
  79. ce('Capricoin', 'CPC', 0x9c, (0x1c,'C'), None, False, 0),
  80. ce('CashCoin', 'CASH', 0xa2, (0x22,('E','F')), None, False, 0),
  81. ce('CashOut', 'CSH', 0xa2, (0x22,('E','F')), None, False, 0),
  82. ce('ChainCoin', 'CHC', 0x9c, (0x1c,'C'), None, False, 0),
  83. ce('Clams', 'CLAM', 0x85, (0x89,'x'), (0x0d,'6'), False, 1),
  84. ce('CoinMagi', 'XMG', 0x94, (0x14,'9'), None, False, 0),
  85. ce('Condensate', 'RAIN', 0xbc, (0x3c,'R'), None, False, 0),
  86. ce('CryptoBullion', 'CBX', 0x8b, (0x0b,'5'), None, False, 0),
  87. ce('Cryptonite', 'XCN', 0x80, (0x1c,'C'), None, False, 0),
  88. ce('CryptoPennies', 'CRPS', 0xc2, (0x42,'T'), None, False, 0),
  89. ce('Dash', 'DASH', 0xcc, (0x4c,'X'), (0x10,'7'), False, 1),
  90. ce('Decred', 'DCR', 0x22de, (0x073f,'D'), (0x071a,'D'), False, 1),
  91. ce('DeepOnion', 'ONION', 0x9f, (0x1f,'D'), None, False, 1),
  92. ce('Defcoin', 'DFC', 0x9e, (0x1e,'D'), (0x05,'3'), False, 1),
  93. ce('Devcoin', 'DVC', 0x80, (0x00,'1'), None, False, 1),
  94. ce('DigiByte', 'DGB', 0x80, (0x1e,'D'), (0x05,'3'), False, 1),
  95. ce('DigiCoin', 'DGC', 0x9e, (0x1e,'D'), (0x05,'3'), False, 1),
  96. ce('DogecoinDark', 'DOGED', 0x9e, (0x1e,'D'), (0x21,'E'), False, 1),
  97. ce('Dogecoin', 'DOGE', 0x9e, (0x1e,'D'), (0x16,('9','A')), False, 2),
  98. ce('DopeCoin', 'DOPE', 0x88, (0x08,'4'), (0x05,'3'), False, 1),
  99. ce('EGulden', 'EFL', 0xb0, (0x30,'L'), (0x05,'3'), False, 1),
  100. ce('Emerald', 'EMD', 0xa2, (0x22,('E','F')), None, False, 0),
  101. ce('Emercoin', 'EMC', 0x80, (0x21,'E'), (0x5c,'e'), False, 2),
  102. ce('EnergyCoin', 'ENRG', 0xdc, (0x5c,'e'), None, False, 0),
  103. ce('Espers', 'ESP', 0xa1, (0x21,'E'), None, False, 0),
  104. ce('Faircoin', 'FAI', 0xdf, (0x5f,'f'), (0x24,'F'), False, 1),
  105. ce('Fastcoin', 'FST', 0xe0, (0x60,('f','g')), None, False, 0),
  106. ce('Feathercoin', 'FTC', 0x8e, (0x0e,('6','7')), (0x05,'3'), False, 2),
  107. ce('Fibre', 'FIBRE', 0xa3, (0x23,'F'), None, False, 0),
  108. ce('FlorinCoin', 'FLO', 0xb0, (0x23,'F'), None, False, 0),
  109. ce('Fluttercoin', 'FLT', 0xa3, (0x23,'F'), None, False, 0),
  110. ce('Fuel2Coin', 'FC2', 0x80, (0x24,'F'), None, False, 0),
  111. ce('Fujicoin', 'FJC', 0xa4, (0x24,'F'), None, False, 0),
  112. ce('Fujinto', 'NTO', 0xa4, (0x24,'F'), None, False, 0),
  113. ce('GlobalBoost', 'BSTY', 0xa6, (0x26,'G'), None, False, 0),
  114. ce('GlobalCurrencyReserve', 'GCR', 0x9a, (0x26,'G'), (0x61,'g'), False, 1),
  115. ce('GoldenBird', 'XGB', 0xaf, (0x2f,('K','L')), None, False, 0),
  116. ce('Goodcoin', 'GOOD', 0xa6, (0x26,'G'), None, False, 0),
  117. ce('GridcoinResearch', 'GRC', 0xbe, (0x3e,('R','S')), None, False, 1),
  118. ce('Gulden', 'NLG', 0xa6, (0x26,'G'), None, False, 1),
  119. ce('Guncoin', 'GUN', 0xa7, (0x27,('G','H')), None, False, 1),
  120. ce('HamRadioCoin', 'HAM', 0x80, (0x00,'1'), None, False, 1),
  121. ce('HTML5Coin', 'HTML5', 0xa8, (0x28,'H'), None, False, 0),
  122. ce('HyperStake', 'HYP', 0xf5, (0x75,'p'), None, False, 0),
  123. ce('iCash', 'ICASH', 0xcc, (0x66,'i'), None, False, 0),
  124. ce('ImperiumCoin', 'IPC', 0xb0, (0x30,'L'), None, False, 0),
  125. ce('IncaKoin', 'NKA', 0xb5, (0x35,'N'), None, False, 0),
  126. ce('Influxcoin', 'INFX', 0xe6, (0x66,'i'), None, False, 0),
  127. ce('InPay', 'INPAY', 0xb7, (0x37,'P'), None, False, 0),
  128. # ce('iXcoin', 'IXC', 0x80, (0x8a,'x'), None, False, 1),
  129. ce('Judgecoin', 'JUDGE', 0xab, (0x2b,'J'), None, False, 0),
  130. ce('Jumbucks', 'JBS', 0xab, (0x2b,'J'), (0x69,'j'), False, 2),
  131. ce('Lanacoin', 'LANA', 0xb0, (0x30,'L'), None, False, 0),
  132. ce('Latium', 'LAT', 0x80, (0x17,'A'), None, False, 0),
  133. ce('Litecoin', 'LTC', 0xb0, (0x30,'L'), (0x32,'M'), True, 5), # old p2sh: 0x05
  134. ce('LiteDoge', 'LDOGE', 0xab, (0x5a,'d'), None, False, 0),
  135. ce('LomoCoin', 'LMC', 0xb0, (0x30,'L'), None, False, 0),
  136. ce('Marscoin', 'MARS', 0xb2, (0x32,'M'), None, False, 0),
  137. ce('MarsCoin', 'MRS', 0xb2, (0x32,'M'), None, False, 0),
  138. ce('MartexCoin', 'MXT', 0xb2, (0x32,'M'), None, False, 0),
  139. ce('MasterCar', 'MCAR', 0xe6, (0x17,'A'), None, False, 0),
  140. ce('MazaCoin', 'MZC', 0xe0, (0x32,'M'), (0x09,('4','5')), False, 2),
  141. ce('MegaCoin', 'MEC', 0xb2, (0x32,'M'), None, False, 1),
  142. ce('MintCoin', 'MINT', 0xb3, (0x33,'M'), None, False, 0),
  143. ce('Mobius', 'MOBI', 0x80, (0x00,'1'), None, False, 0),
  144. ce('MonaCoin', 'MONA', 0xb0, (0x32,'M'), (0x05,'3'), False, 1),
  145. ce('MonetaryUnit', 'MUE', 0x8f, (0x0f,'7'), (0x09,('4','5')), False, 1),
  146. ce('MoonCoin', 'MOON', 0x83, (0x03,'2'), None, False, 0),
  147. ce('MyriadCoin', 'MYR', 0xb2, (0x32,'M'), (0x09,('4','5')), False, 1),
  148. ce('Myriadcoin', 'MYRIAD', 0xb2, (0x32,'M'), None, False, 1),
  149. ce('Namecoin', 'NMC', 0xb4, (0x34,('M','N')), (0x0d,'6'), False, 1),
  150. ce('Neoscoin', 'NEOS', 0xef, (0x3f,'S'), (0xbc,'2'), False, 1),
  151. ce('NevaCoin', 'NEVA', 0xb1, (0x35,'N'), None, False, 0),
  152. ce('Novacoin', 'NVC', 0x88, (0x08,'4'), (0x14,'9'), False, 1),
  153. ce('OKCash', 'OK', 0xb7, (0x37,'P'), (0x1c,'C'), False, 1),
  154. ce('Omnicoin', 'OMC', 0xf3, (0x73,'o'), None, False, 1),
  155. ce('Omni', 'OMNI', 0xf3, (0x73,'o'), None, False, 0),
  156. ce('Onix', 'ONX', 0x80, (0x8a,'x'), None, False, 0),
  157. ce('PandaCoin', 'PND', 0xb7, (0x37,'P'), (0x16,('9','A')), False, 1),
  158. ce('ParkByte', 'PKB', 0xb7, (0x37,'P'), (0x1c,'C'), False, 1),
  159. ce('Particl', 'PART', 0x6c, (0x38,'P'), None, False, 0),
  160. ce('Paycoin', 'CON', 0xb7, (0x37,'P'), None, False, 1),
  161. ce('Peercoin', 'PPC', 0xb7, (0x37,'P'), (0x75,'p'), False, 1),
  162. ce('PesetaCoin', 'PTC', 0xaf, (0x2f,('K','L')), None, False, 1),
  163. ce('PhoenixCoin', 'PXC', 0xb8, (0x38,'P'), None, False, 0),
  164. ce('PinkCoin', 'PINK', 0x83, (0x03,'2'), None, False, 1),
  165. ce('PIVX', 'PIVX', 0xd4, (0x1e,'D'), None, False, 0),
  166. ce('PokeChain', 'XPOKE', 0x9c, (0x1c,'C'), None, False, 0),
  167. ce('Potcoin', 'POT', 0xb7, (0x37,'P'), (0x05,'3'), False, 1),
  168. ce('Primecoin', 'XPM', 0x97, (0x17,'A'), (0x53,'a'), False, 1),
  169. ce('Quark', 'QRK', 0xba, (0x3a,'Q'), None, False, 0),
  170. ce('ReddCoin', 'RDD', 0xbd, (0x3d,'R'), None, False, 1),
  171. ce('Riecoin', 'RIC', 0x80, (0x3c,'R'), (0x05,'3'), False, 2),
  172. ce('Rimbit', 'RBT', 0xbc, (0x3c,'R'), None, False, 0),
  173. ce('Rubycoin', 'RBY', 0xbd, (0x3d,'R'), (0x55,'b'), False, 1),
  174. ce('ShadowCash', 'SDC', 0xbf, (0x3f,'S'), (0x7d,'s'), False, 1),
  175. ce('Sibcoin', 'SIB', 0x80, (0x3f,'S'), None, False, 0),
  176. ce('SixEleven', '611', 0x80, (0x34,('M','N')), None, False, 0),
  177. ce('SmileyCoin', 'SMLY', 0x99, (0x19,'B'), None, False, 0),
  178. ce('Songcoin', 'SONG', 0xbf, (0x3f,'S'), None, False, 0),
  179. ce('Spreadcoin', 'SPR', 0xbf, (0x3f,'S'), None, False, 1),
  180. ce('Startcoin', 'START', 0xfd, (0x7d,'s'), (0x05,'3'), False, 1),
  181. ce('StealthCoin', 'XST', 0xbe, (0x3e,('R','S')), None, False, 0),
  182. ce('SwagBucks', 'BUCKS', 0x99, (0x3f,'S'), None, False, 0),
  183. ce('SysCoin', 'SYS', 0x80, (0x00,'1'), None, False, 0),
  184. ce('TajCoin', 'TAJ', 0x6f, (0x41,'T'), None, False, 0),
  185. ce('Templecoin', 'TPC', 0xc1, (0x41,'T'), (0x05,'3'), False, 1),
  186. ce('Terracoin', 'TRC', 0x80, (0x00,'1'), None, False, 0),
  187. ce('Titcoin', 'TIT', 0x80, (0x00,'1'), None, False, 0),
  188. ce('TittieCoin', 'TTC', 0xc1, (0x41,'T'), None, False, 0),
  189. ce('Transfer', 'TX', 0x99, (0x42,'T'), None, False, 0),
  190. ce('Unobtanium', 'UNO', 0xe0, (0x82,'u'), (0x1e,'D'), False, 2),
  191. ce('Vcash', 'XVC', 0xc7, (0x47,'V'), None, False, 0),
  192. ce('Vertcoin', 'VTC', 0xc7, (0x47,'V'), (0x05,'3'), False, 1),
  193. ce('Viacoin', 'VIA', 0xc7, (0x47,'V'), (0x21,'E'), False, 2),
  194. ce('VpnCoin', 'VPN', 0xc7, (0x47,'V'), (0x05,'3'), False, 1),
  195. ce('WankCoin', 'WKC', 0x80, (0x00,'1'), None, False, 1),
  196. ce('WashingtonCoin', 'WASH', 0xc9, (0x49,'W'), None, False, 0),
  197. ce('WeAreSatoshi', 'WSX', 0x97, (0x87,'w'), None, False, 0),
  198. ce('WisdomCoin', 'WISC', 0x87, (0x49,'W'), None, False, 0),
  199. ce('WorldCoin', 'WDC', 0xc9, (0x49,'W'), None, False, 1),
  200. ce('XRealEstateDevcoin', 'XRED', 0x80, (0x00,'1'), None, False, 0),
  201. ce('ZetaCoin', 'ZET', 0xe0, (0x50,'Z'), None, False, 0),
  202. ce('ZiftrCoin', 'ZRC', 0xd0, (0x50,'Z'), (0x05,'3'), False, 1),
  203. ce('ZLiteQubit', 'ZLQ', 0xe0, (0x26,'G'), None, False, 0),
  204. ce('Zoomcoin', 'ZOOM', 0xe7, (0x67,'i'), (0x5c,'e'), False, 1),
  205. )
  206. coin_constants['testnet'] = (
  207. ce('Bitcoin', 'BTC', 0xef, (0x6f,('m','n')), (0xc4,'2'), True, 5),
  208. ce('BitcoinCashNode','BCH',0xef, (0x6f,('m','n')), (0xc4,'2'), True, 5),
  209. ce('BitcoinGold', 'BCG', 0xef, (0x6f,('m','n')), (0xc4,'2'), True, -1),
  210. ce('Dash', 'DASH', 0xef, (0x8c,'y'), (0x13,('8','9')), False, 1),
  211. ce('Decred', 'DCR', 0x230e, (0x0f21,'T'), (0x0e6c,'S'), False, 1),
  212. ce('Dogecoin', 'DOGE', 0xf1, (0x71,'n'), (0xc4,'2'), False, 2),
  213. ce('Feathercoin', 'FTC', 0xc1, (0x41,'T'), (0xc4,'2'), False, 2),
  214. ce('Viacoin', 'VIA', 0xff, (0x7f,'t'), (0xc4,'2'), False, 2),
  215. ce('Emercoin', 'EMC', 0xef, (0x6f,('m','n')), (0xc4,'2'), False, 2),
  216. ce('Litecoin', 'LTC', 0xef, (0x6f,('m','n')), (0x3a,'Q'), True, 5), # old p2sh: 0xc4
  217. )
  218. coin_sources = (
  219. ('BTC', 'https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.cpp'),
  220. ('EMC', 'https://github.com/emercoin/emercoin/blob/master/src/chainparams.cpp'), # checked mn,tn
  221. ('LTC', 'https://github.com/litecoin-project/litecoin/blob/master-0.10/src/chainparams.cpp'),
  222. ('DOGE', 'https://github.com/dogecoin/dogecoin/blob/master/src/chainparams.cpp'),
  223. ('RDD', 'https://github.com/reddcoin-project/reddcoin/blob/master/src/base58.h'),
  224. ('DASH', 'https://github.com/dashpay/dash/blob/master/src/chainparams.cpp'),
  225. ('PPC', 'https://github.com/belovachap/peercoin/blob/master/src/base58.h'),
  226. ('NMC', 'https://github.com/domob1812/namecore/blob/master/src/chainparams.cpp'),
  227. ('FTC', 'https://github.com/FeatherCoin/Feathercoin/blob/master-0.8/src/base58.h'),
  228. ('BLK', 'https://github.com/rat4/blackcoin/blob/master/src/chainparams.cpp'),
  229. ('NSR', 'https://nubits.com/nushares/introduction'),
  230. ('NBT', 'https://bitbucket.org/JordanLeePeershares/nubit/NuBit / src /base58.h'),
  231. ('MZC', 'https://github.com/MazaCoin/MazaCoin/blob/master/src/chainparams.cpp'),
  232. ('VIA', 'https://github.com/viacoin/viacoin/blob/master/src/chainparams.cpp'),
  233. ('RBY', 'https://github.com/rubycoinorg/rubycoin/blob/master/src/base58.h'),
  234. ('GRS', 'https://github.com/GroestlCoin/groestlcoin/blob/master/src/groestlcoin.cpp'),
  235. ('DGC', 'https://github.com/DGCDev/digitalcoin/blob/master/src/chainparams.cpp'),
  236. ('CCN', 'https://github.com/Cannacoin-Project/Cannacoin/blob/Proof-of-Stake/src/base58.h'),
  237. ('DGB', 'https://github.com/digibyte/digibyte/blob/master/src/chainparams.cpp'),
  238. ('MONA', 'https://github.com/monacoinproject/monacoin/blob/master-0.10/src/chainparams.cpp'),
  239. ('CLAM', 'https://github.com/nochowderforyou/clams/blob/master/src/chainparams.cpp'),
  240. ('XPM', 'https://github.com/primecoin/primecoin/blob/master/src/base58.h'),
  241. ('NEOS', 'https://github.com/bellacoin/neoscoin/blob/master/src/chainparams.cpp'),
  242. ('JBS', 'https://github.com/jyap808/jumbucks/blob/master/src/base58.h'),
  243. ('ZRC', 'https://github.com/ZiftrCOIN/ziftrcoin/blob/master/src/chainparams.cpp'),
  244. ('VTC', 'https://github.com/vertcoin/vertcoin/blob/master/src/base58.h'),
  245. ('NXT', 'https://bitbucket.org/JeanLucPicard/nxt/src and unofficial at https://github.com/Blackcomb/nxt'),
  246. ('MUE', 'https://github.com/MonetaryUnit/MUE-Src/blob/master/src/chainparams.cpp'),
  247. ('ZOOM', 'https://github.com/zoom-c/zoom/blob/master/src/base58.h'),
  248. ('VPN', 'https://github.com/Bit-Net/VpnCoin/blob/master/src/base58.h'),
  249. ('CDN', 'https://github.com/ThisIsOurCoin/canadaecoin/blob/master/src/base58.h'),
  250. ('SDC', 'https://github.com/ShadowProject/shadow/blob/master/src/chainparams.cpp'),
  251. ('PKB', 'https://github.com/parkbyte/ParkByte/blob/master/src/base58.h'),
  252. ('PND', 'https://github.com/coinkeeper/2015-04-19_21-22_pandacoin/blob/master/src/base58.h'),
  253. ('START', 'https://github.com/startcoin-project/startcoin/blob/master/src/base58.h'),
  254. ('GCR', 'https://github.com/globalcurrencyreserve/gcr/blob/master/src/chainparams.cpp'),
  255. ('NVC', 'https://github.com/novacoin-project/novacoin/blob/master/src/base58.h'),
  256. ('AC', 'https://github.com/AsiaCoin/AsiaCoinFix/blob/master/src/base58.h'),
  257. ('BTCD', 'https://github.com/jl777/btcd/blob/master/src/base58.h'),
  258. ('DOPE', 'https://github.com/dopecoin-dev/DopeCoinV3/blob/master/src/base58.h'),
  259. ('TPC', 'https://github.com/9cat/templecoin/blob/templecoin/src/base58.h'),
  260. ('OK', 'https://github.com/okcashpro/okcash/blob/master/src/chainparams.cpp'),
  261. ('DOGED', 'https://github.com/doged/dogedsource/blob/master/src/base58.h'),
  262. ('EFL', 'https://github.com/Electronic-Gulden-Foundation/egulden/blob/master/src/base58.h'),
  263. ('POT', 'https://github.com/potcoin/Potcoin/blob/master/src/base58.h'),
  264. )
  265. # Sources (see above) that are in agreement for these coins
  266. # No check for segwit, p2sh check skipped if source doesn't support it
  267. cross_checks = {
  268. '2GIVE': ['wn'],
  269. '42': ['vg','wn'],
  270. '611': ['wn'],
  271. 'AC': ['lb','vg'],
  272. 'ACOIN': ['wn'],
  273. 'ALF': ['wn'],
  274. 'ANC': ['vg','wn'],
  275. 'APEX': ['wn'],
  276. 'ARCO': ['wn'],
  277. 'ARG': ['pc'],
  278. 'AUR': ['vg','wn'],
  279. 'BCH': ['wn'],
  280. 'BLK': ['lb','vg','wn'],
  281. 'BQC': ['vg','wn'],
  282. 'BSTY': ['wn'],
  283. 'BTC': ['lb','vg','wn'],
  284. 'BTCD': ['lb','vg','wn'],
  285. 'BUCKS': ['wn'],
  286. 'CASH': ['wn'],
  287. 'CBX': ['wn'],
  288. 'CCN': ['lb','vg','wn'],
  289. 'CDN': ['lb','vg','wn'],
  290. 'CHC': ['wn'],
  291. 'CLAM': ['lb','vg'],
  292. 'CON': ['vg','wn'],
  293. 'CPC': ['wn'],
  294. 'DASH': ['lb','pc','vg','wn'],
  295. 'DCR': ['pc'],
  296. 'DFC': ['pc'],
  297. 'DGB': ['lb','vg'],
  298. 'DGC': ['lb','vg','wn'],
  299. 'DOGE': ['lb','pc','vg','wn'],
  300. 'DOGED': ['lb','vg','wn'],
  301. 'DOPE': ['lb','vg'],
  302. 'DVC': ['vg','wn'],
  303. 'EFL': ['lb','vg','wn'],
  304. 'EMC': ['vg'],
  305. 'EMD': ['wn'],
  306. 'ESP': ['wn'],
  307. 'FAI': ['pc'],
  308. 'FC2': ['wn'],
  309. 'FIBRE': ['wn'],
  310. 'FJC': ['wn'],
  311. 'FLO': ['wn'],
  312. 'FLT': ['wn'],
  313. 'FST': ['wn'],
  314. 'FTC': ['lb','pc','vg','wn'],
  315. 'GCR': ['lb','vg'],
  316. 'GOOD': ['wn'],
  317. 'GRC': ['vg','wn'],
  318. 'GUN': ['vg','wn'],
  319. 'HAM': ['vg','wn'],
  320. 'HTML5': ['wn'],
  321. 'HYP': ['wn'],
  322. 'ICASH': ['wn'],
  323. 'INFX': ['wn'],
  324. 'IPC': ['wn'],
  325. 'JBS': ['lb','pc','vg','wn'],
  326. 'JUDGE': ['wn'],
  327. 'LANA': ['wn'],
  328. 'LAT': ['wn'],
  329. 'LDOGE': ['wn'],
  330. 'LMC': ['wn'],
  331. 'LTC': ['lb','vg','wn'],
  332. 'MARS': ['wn'],
  333. 'MEC': ['pc','wn'],
  334. 'MINT': ['wn'],
  335. 'MOBI': ['wn'],
  336. 'MONA': ['lb','vg'],
  337. 'MOON': ['wn'],
  338. 'MUE': ['lb','vg'],
  339. 'MXT': ['wn'],
  340. 'MYR': ['pc'],
  341. 'MYRIAD': ['vg','wn'],
  342. 'MZC': ['lb','pc','vg','wn'],
  343. 'NEOS': ['lb','vg'],
  344. 'NEVA': ['wn'],
  345. 'NKA': ['wn'],
  346. 'NLG': ['vg','wn'],
  347. 'NMC': ['lb','vg'],
  348. 'NVC': ['lb','vg','wn'],
  349. 'OK': ['lb','vg'],
  350. 'OMC': ['vg','wn'],
  351. 'ONION': ['vg','wn'],
  352. 'PART': ['wn'],
  353. 'PINK': ['vg','wn'],
  354. 'PIVX': ['wn'],
  355. 'PKB': ['lb','vg','wn'],
  356. 'PND': ['lb','vg','wn'],
  357. 'POT': ['lb','vg','wn'],
  358. 'PPC': ['lb','vg','wn'],
  359. 'PTC': ['vg','wn'],
  360. 'PXC': ['wn'],
  361. 'QRK': ['wn'],
  362. 'RAIN': ['wn'],
  363. 'RBT': ['wn'],
  364. 'RBY': ['lb','vg'],
  365. 'RDD': ['vg','wn'],
  366. 'RIC': ['pc','vg','wn'],
  367. 'SDC': ['lb','vg'],
  368. 'SIB': ['wn'],
  369. 'SMLY': ['wn'],
  370. 'SONG': ['wn'],
  371. 'SPR': ['vg','wn'],
  372. 'START': ['lb','vg'],
  373. 'SYS': ['wn'],
  374. 'TAJ': ['wn'],
  375. 'TIT': ['wn'],
  376. 'TPC': ['lb','vg'],
  377. 'TRC': ['wn'],
  378. 'TTC': ['wn'],
  379. 'TX': ['wn'],
  380. 'UNO': ['pc','vg','wn'],
  381. 'VIA': ['lb','pc','vg','wn'],
  382. 'VPN': ['lb','vg'],
  383. 'VTC': ['lb','vg','wn'],
  384. 'WDC': ['vg','wn'],
  385. 'WISC': ['wn'],
  386. 'WKC': ['vg','wn'],
  387. 'WSX': ['wn'],
  388. 'XCN': ['wn'],
  389. 'XGB': ['wn'],
  390. 'XPM': ['lb','vg','wn'],
  391. 'XST': ['wn'],
  392. 'XVC': ['wn'],
  393. 'ZET': ['wn'],
  394. 'ZOOM': ['lb','vg'],
  395. 'ZRC': ['lb','vg']
  396. }
  397. @classmethod
  398. def verify_leading_symbols(cls,quiet=False,verbose=False):
  399. for network in ('mainnet','testnet'):
  400. for coin in [e.symbol for e in cls.coin_constants[network]]:
  401. e = cls.get_entry(coin,network)
  402. cdata = (network,coin,e,'Computed value',verbose)
  403. if not quiet:
  404. msg('{} {}'.format(coin,network))
  405. vn_info = e.p2pkh_info
  406. ret = cls.find_addr_leading_symbol(vn_info[0])
  407. test_equal('P2PKH leading symbol',vn_info[1],ret,*cdata)
  408. vn_info = e.p2sh_info
  409. if vn_info:
  410. ret = cls.find_addr_leading_symbol(vn_info[0])
  411. test_equal('P2SH leading symbol',vn_info[1],ret,*cdata)
  412. @classmethod
  413. def verify_core_coin_data(cls,quiet=False,verbose=False):
  414. from mmgen.protocol import CoinProtocol,init_proto
  415. for network in ('mainnet','testnet'):
  416. for coin in CoinProtocol.core_coins:
  417. e = cls.get_entry(coin,network)
  418. if e:
  419. proto = init_proto(coin,testnet=network=='testnet')
  420. cdata = (network,coin,e,type(proto).__name__,verbose)
  421. if not quiet:
  422. msg('Verifying {} {}'.format(coin.upper(),network))
  423. if coin != 'bch': # TODO
  424. test_equal('coin name',e.name,proto.name,*cdata)
  425. if e.trust_level != -1:
  426. test_equal('Trust level',e.trust_level,CoinProtocol.coins[coin].trust_level,*cdata)
  427. test_equal(
  428. 'WIF version number',
  429. e.wif_ver_num,
  430. int.from_bytes(bytes.fromhex(proto.wif_ver_num['std']),'big'),
  431. *cdata )
  432. test_equal(
  433. 'P2PKH version number',
  434. e.p2pkh_info[0],
  435. int.from_bytes(proto.addr_fmt_to_ver_bytes('p2pkh'),'big'),
  436. *cdata )
  437. test_equal(
  438. 'P2SH version number',
  439. e.p2sh_info[0],
  440. int.from_bytes(proto.addr_fmt_to_ver_bytes('p2sh'),'big'),
  441. *cdata )
  442. @classmethod
  443. def get_supported_coins(cls,network):
  444. return [e for e in cls.coin_constants[network] if e.trust_level != -1]
  445. @classmethod
  446. def get_entry(cls,coin,network):
  447. try:
  448. idx = [e.symbol for e in cls.coin_constants[network]].index(coin.upper())
  449. except:
  450. return None
  451. return cls.coin_constants[network][idx]
  452. # Data is one of the coin_constants lists above. Normalize ints to hex of correct width, add
  453. # missing leading letters, set trust level from external_tests.
  454. # Insert a coin entry from outside source, set version info leading letters to '?' and trust level
  455. # to 0, then run CoinInfo.fix_table(data). 'has_segwit' field is updated manually for now.
  456. @classmethod
  457. def fix_table(cls,data):
  458. import re
  459. def myhex(n):
  460. return '0x{:0{}x}'.format(n,2 if n < 256 else 4)
  461. def fix_ver_info(e,k):
  462. e[k] = list(e[k])
  463. e[k][0] = myhex(e[k][0])
  464. s1 = cls.find_addr_leading_symbol(int(e[k][0][2:],16))
  465. m = 'Fixing leading address letter for coin {} ({!r} --> {})'.format(e['symbol'],e[k][1],s1)
  466. if e[k][1] != '?':
  467. assert s1 == e[k][1],'First letters do not match! {}'.format(m)
  468. else:
  469. msg(m)
  470. e[k][1] = s1
  471. e[k] = tuple(e[k])
  472. old_sym = None
  473. for sym in sorted([e.symbol for e in data]):
  474. if sym == old_sym:
  475. msg("'{}': duplicate coin symbol in data!".format(sym))
  476. sys.exit(2)
  477. old_sym = sym
  478. tt = cls.create_trust_table()
  479. name_w = max(len(e.name) for e in data)
  480. fs = '\t({:%s} {:10} {:7} {:17} {:17} {:6} {}),' % (name_w+3)
  481. for e in data:
  482. e = e._asdict()
  483. e['wif_ver_num'] = myhex(e['wif_ver_num'])
  484. sym,trust = e['symbol'],e['trust_level']
  485. fix_ver_info(e,'p2pkh_info')
  486. if type(e['p2sh_info']) == tuple:
  487. fix_ver_info(e,'p2sh_info')
  488. for k in e.keys():
  489. e[k] = repr(e[k])
  490. e[k] = re.sub(r"'0x(..)'",r'0x\1',e[k])
  491. e[k] = re.sub(r"'0x(....)'",r'0x\1',e[k])
  492. e[k] = re.sub(r' ',r'',e[k]) + ('',',')[k != 'trust_level']
  493. if trust != -1:
  494. if sym in tt:
  495. src = tt[sym]
  496. if src != trust:
  497. msg("Updating trust for coin '{}': {} -> {}".format(sym,trust,src))
  498. e['trust_level'] = src
  499. else:
  500. if trust != 0:
  501. msg("Downgrading trust for coin '{}': {} -> {}".format(sym,trust,0))
  502. e['trust_level'] = 0
  503. if sym in cls.cross_checks:
  504. if int(e['trust_level']) == 0 and len(cls.cross_checks[sym]) > 1:
  505. msg("Upgrading trust for coin '{}': {} -> {}".format(sym,e['trust_level'],1))
  506. e['trust_level'] = 1
  507. print(fs.format(*e.values()))
  508. msg('Processed {} entries'.format(len(data)))
  509. @classmethod
  510. def find_addr_leading_symbol(cls,ver_num,verbose=False):
  511. if ver_num == 0:
  512. return '1'
  513. def phash2addr(ver_num,pk_hash):
  514. from mmgen.protocol import _b58chk_encode
  515. bl = ver_num.bit_length()
  516. ver_bytes = int.to_bytes(ver_num,bl//8 + bool(bl%8),'big')
  517. return _b58chk_encode(ver_bytes + pk_hash)
  518. low = phash2addr(ver_num,b'\x00'*20)
  519. high = phash2addr(ver_num,b'\xff'*20)
  520. if verbose:
  521. print('low address: ' + low)
  522. print('high address: ' + high)
  523. l1,h1 = low[0],high[0]
  524. return (l1,h1) if l1 != h1 else l1
  525. @classmethod
  526. def print_symbols(cls,include_names=False,reverse=False):
  527. for e in cls.coin_constants['mainnet']:
  528. if reverse:
  529. print('{:6} {}'.format(e.symbol,e.name))
  530. else:
  531. name_w = max(len(e.name) for e in cls.coin_constants['mainnet'])
  532. print(('{:{}} '.format(e.name,name_w) if include_names else '') + e.symbol)
  533. @classmethod
  534. def create_trust_table(cls):
  535. tt = {}
  536. mn = cls.external_tests['mainnet']
  537. for ext_prog in mn:
  538. assert len(set(mn[ext_prog])) == len(mn[ext_prog]),"Duplicate entry in '{}'!".format(ext_prog)
  539. for coin in mn[ext_prog]:
  540. if coin in tt:
  541. tt[coin] += 1
  542. else:
  543. tt[coin] = 1
  544. for k in cls.trust_override:
  545. tt[k] = cls.trust_override[k]
  546. return tt
  547. trust_override = {'BTC':3,'BCH':3,'LTC':3,'DASH':1,'EMC':2}
  548. @classmethod
  549. def get_test_support(cls,coin,addr_type,network,tool=None,verbose=False):
  550. """
  551. If requested tool supports coin/addr_type/network triplet, return tool name.
  552. If 'tool' is None, return tool that supports coin/addr_type/network triplet.
  553. Return None on failure.
  554. """
  555. tool_arg = tool
  556. all_tools = [tool] if tool else list(cls.external_tests[network].keys())
  557. coin = coin.upper()
  558. for tool in all_tools:
  559. if coin in cls.external_tests[network][tool]:
  560. break
  561. else:
  562. if verbose:
  563. m1 = 'Requested tool {t!r} does not support coin {c} on network {n}'
  564. m2 = 'No test tool found for coin {c} on network {n}'
  565. m = m1 if tool_arg else m2
  566. msg(m.format(t=tool,c=coin,n=network))
  567. return None
  568. if addr_type == 'zcash_z':
  569. if tool_arg in (None,'zcash-mini'):
  570. return 'zcash-mini'
  571. else:
  572. if verbose:
  573. m = "Address type {a!r} supported only by tool 'zcash-mini'"
  574. msg(m.format(a=addr_type))
  575. return None
  576. try:
  577. assert (
  578. cls.external_tests_blacklist[addr_type][tool] == True
  579. or coin in cls.external_tests_blacklist[addr_type][tool] )
  580. except:
  581. pass
  582. else:
  583. if verbose:
  584. m = 'Tool {t!r} blacklisted for coin {c}, addr_type {a!r}'
  585. msg(m.format(t=tool,c=coin,a=addr_type))
  586. return None
  587. if tool_arg: # skip whitelists
  588. return tool
  589. if addr_type in ('segwit','bech32'):
  590. st = cls.external_tests_segwit_whitelist
  591. if addr_type in st and coin in st[addr_type]:
  592. return tool
  593. else:
  594. if verbose:
  595. m1 = 'Requested tool {t!r} does not support coin {c}, addr_type {a!r}, on network {n}'
  596. m2 = 'No test tool found supporting coin {c}, addr_type {a!r}, on network {n}'
  597. m = m1 if tool_arg else m2
  598. msg(m.format(t=tool,c=coin,n=network,a=addr_type))
  599. return None
  600. return tool
  601. external_tests = {
  602. 'mainnet': {
  603. # List in order of preference.
  604. # If 'tool' is not specified, the first tool supporting the coin will be selected.
  605. 'pycoin': (
  606. 'DASH', # only compressed
  607. 'BCH',
  608. 'BTC','LTC','VIA','FTC','DOGE','MEC',
  609. 'JBS','MZC','RIC','DFC','FAI','ARG','ZEC','DCR'),
  610. 'keyconv': (
  611. 'BCH',
  612. # broken: PIVX
  613. '42','AC','AIB','ANC','ARS','ATMOS','AUR','BLK','BQC','BTC','TEST','BTCD','CCC','CCN','CDN',
  614. 'CLAM','CNC','CNOTE','CON','CRW','DEEPONION','DGB','DGC','DMD','DOGED','DOGE','DOPE',
  615. 'DVC','EFL','EMC','EXCL','FAIR','FLOZ','FTC','GAME','GAP','GCR','GRC','GRS','GUN','HAM','HODL',
  616. 'IXC','JBS','LBRY','LEAF','LTC','MMC','MONA','MUE','MYRIAD','MZC','NEOS','NLG','NMC','NVC',
  617. 'NYAN','OK','OMC','PIGGY','PINK','PKB','PND','POT','PPC','PTC','PTS','QTUM','RBY','RDD',
  618. 'RIC','SCA','SDC','SKC','SPR','START','SXC','TPC','UIS','UNO','VIA','VPN','VTC','WDC','WKC',
  619. 'WUBS', 'XC', 'XPM', 'YAC', 'ZOOM', 'ZRC'),
  620. 'ethkey': ('ETH','ETC'),
  621. 'zcash-mini': ('ZEC',),
  622. 'moneropy': ('XMR',),
  623. },
  624. 'testnet': {
  625. 'pycoin': {
  626. 'DASH':'tDASH', # only compressed
  627. 'BCH':'XTN',
  628. 'BTC':'XTN','LTC':'XLT','VIA':'TVI','FTC':'FTX','DOGE':'XDT','DCR':'DCRT'
  629. },
  630. 'ethkey': {},
  631. 'keyconv': {}
  632. }
  633. }
  634. external_tests_segwit_whitelist = {
  635. # Whitelists apply to the *first* tool in cls.external_tests supporting the given coin/addr_type.
  636. # They're ignored if specific tool is requested.
  637. 'segwit': ('BTC',), # LTC Segwit broken on pycoin: uses old fmt
  638. 'bech32': ('BTC','LTC'),
  639. 'compressed': (
  640. 'BTC','LTC','VIA','FTC','DOGE','DASH','MEC','MYR','UNO',
  641. 'JBS','MZC','RIC','DFC','FAI','ARG','ZEC','DCR','ZEC'
  642. ),
  643. }
  644. external_tests_blacklist = {
  645. # Unconditionally block testing of the given coin/addr_type with given tool, or all coins if True
  646. 'legacy': { 'pycoin': ('DASH',) },
  647. 'segwit': { 'pycoin': ('LTC',), 'keyconv': True },
  648. 'bech32': { 'keyconv': True },
  649. }
  650. if __name__ == '__main__':
  651. quiet = '--quiet' in sys.argv
  652. verbose = '--verbose' in sys.argv
  653. if verbose:
  654. quiet = False
  655. msg('Checking CoinInfo WIF/P2PKH/P2SH version numbers and trust levels against protocol.py')
  656. CoinInfo.verify_core_coin_data(quiet=quiet,verbose=verbose)
  657. msg('Checking CoinInfo address leading symbols')
  658. CoinInfo.verify_leading_symbols(quiet=quiet,verbose=verbose)