test.py 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515
  1. #!/usr/bin/python
  2. # Chdir to repo root.
  3. # Since script is not in repo root, fix sys.path so that modules are
  4. # imported from repo, not system.
  5. import sys,os
  6. pn = os.path.dirname(sys.argv[0])
  7. os.chdir(os.path.join(pn,os.pardir))
  8. sys.path.__setitem__(0,os.path.abspath(os.curdir))
  9. import mmgen.globalvars as g
  10. import mmgen.opt as opt
  11. from mmgen.util import mmsg,mdie,Msg,die
  12. from mmgen.test import *
  13. hincog_fn = "rand_data"
  14. hincog_bytes = 1024*1024
  15. hincog_offset = 98765
  16. hincog_seedlen = 256
  17. incog_id_fn = "incog_id"
  18. non_mmgen_fn = "btckey"
  19. ref_dir = os.path.join("test","ref")
  20. ref_wallet_brainpass = "abc"
  21. ref_wallet_hash_preset = "1"
  22. ref_wallet_incog_offset = 123
  23. ref_bw_hash_preset = "1"
  24. ref_bw_file = "brainwallet"
  25. ref_bw_file_spc = "brainwallet-spaced"
  26. ref_kafile_pass = "kafile password"
  27. ref_kafile_hash_preset = "1"
  28. ref_enc_fn = "sample-text.mmenc"
  29. tool_enc_passwd = "Scrypt it, don't hash it!"
  30. sample_text = \
  31. "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks\n"
  32. cfgs = {
  33. '6': {
  34. 'name': "reference wallet check (128-bit)",
  35. 'seed_len': 128,
  36. 'seed_id': "FE3C6545",
  37. 'ref_bw_seed_id': "33F10310",
  38. 'addrfile_chk': "B230 7526 638F 38CB 8FDC 8B76",
  39. 'keyaddrfile_chk': "CF83 32FB 8A8B 08E2 0F00 D601",
  40. 'wpasswd': "reference password",
  41. 'ref_wallet': "FE3C6545-D782B529[128,1].mmdat",
  42. 'ic_wallet': "FE3C6545-E29303EA-5E229E30[128,1].mmincog",
  43. 'ic_wallet_hex': "FE3C6545-BC4BE3F2-32586837[128,1].mmincox",
  44. 'hic_wallet': "FE3C6545-161E495F-BEB7548E[128:1].incog-offset123",
  45. 'hic_wallet_old': "FE3C6545-161E495F-9860A85B[128:1].incog-old.offset123",
  46. 'tmpdir': os.path.join("test","tmp6"),
  47. 'kapasswd': "",
  48. 'addr_idx_list': "1010,500-501,31-33,1,33,500,1011", # 8 addresses
  49. 'dep_generators': {
  50. 'mmdat': "refwalletgen1",
  51. 'addrs': "refaddrgen1",
  52. 'akeys.mmenc': "refkeyaddrgen1"
  53. },
  54. },
  55. '7': {
  56. 'name': "reference wallet check (192-bit)",
  57. 'seed_len': 192,
  58. 'seed_id': "1378FC64",
  59. 'ref_bw_seed_id': "CE918388",
  60. 'addrfile_chk': "8C17 A5FA 0470 6E89 3A87 8182",
  61. 'keyaddrfile_chk': "9648 5132 B98E 3AD9 6FC3 C5AD",
  62. 'wpasswd': "reference password",
  63. 'ref_wallet': "1378FC64-6F0F9BB4[192,1].mmdat",
  64. 'ic_wallet': "1378FC64-2907DE97-F980D21F[192,1].mmincog",
  65. 'ic_wallet_hex': "1378FC64-4DCB5174-872806A7[192,1].mmincox",
  66. 'hic_wallet': "1378FC64-B55E9958-77256FC1[192:1].incog.offset123",
  67. 'hic_wallet_old': "1378FC64-B55E9958-D85FF20C[192:1].incog-old.offset123",
  68. 'tmpdir': os.path.join("test","tmp7"),
  69. 'kapasswd': "",
  70. 'addr_idx_list': "1010,500-501,31-33,1,33,500,1011", # 8 addresses
  71. 'dep_generators': {
  72. 'mmdat': "refwalletgen2",
  73. 'addrs': "refaddrgen2",
  74. 'akeys.mmenc': "refkeyaddrgen2"
  75. },
  76. },
  77. '8': {
  78. 'name': "reference wallet check (256-bit)",
  79. 'seed_len': 256,
  80. 'seed_id': "98831F3A",
  81. 'ref_bw_seed_id': "B48CD7FC",
  82. 'addrfile_chk': "6FEF 6FB9 7B13 5D91 854A 0BD3",
  83. 'keyaddrfile_chk': "9F2D D781 1812 8BAD C396 9DEB",
  84. 'wpasswd': "reference password",
  85. 'ref_wallet': "98831F3A-27F2BF93[256,1].mmdat",
  86. 'ref_addrfile': "98831F3A[1,31-33,500-501,1010-1011].addrs",
  87. 'ref_keyaddrfile': "98831F3A[1,31-33,500-501,1010-1011].akeys.mmenc",
  88. 'ref_addrfile_chksum': "6FEF 6FB9 7B13 5D91 854A 0BD3",
  89. 'ref_keyaddrfile_chksum': "9F2D D781 1812 8BAD C396 9DEB",
  90. # 'ref_fake_unspent_data':"98831F3A_unspent.json",
  91. 'ref_tx_file': "tx_FFB367[1.234].raw",
  92. 'ic_wallet': "98831F3A-5482381C-18460FB1[256,1].mmincog",
  93. 'ic_wallet_hex': "98831F3A-1630A9F2-870376A9[256,1].mmincox",
  94. 'hic_wallet': "98831F3A-F59B07A0-559CEF19[256:1].incog.offset123",
  95. 'hic_wallet_old': "98831F3A-F59B07A0-848535F3[256:1].incog-old.offset123",
  96. 'tmpdir': os.path.join("test","tmp8"),
  97. 'kapasswd': "",
  98. 'addr_idx_list': "1010,500-501,31-33,1,33,500,1011", # 8 addresses
  99. 'dep_generators': {
  100. 'mmdat': "refwalletgen3",
  101. 'addrs': "refaddrgen3",
  102. 'akeys.mmenc': "refkeyaddrgen3"
  103. },
  104. },
  105. '1': {
  106. 'tmpdir': os.path.join("test","tmp1"),
  107. 'wpasswd': "Dorian",
  108. 'kapasswd': "Grok the blockchain",
  109. 'addr_idx_list': "12,99,5-10,5,12", # 8 addresses
  110. 'dep_generators': {
  111. 'mmdat': "walletgen",
  112. 'addrs': "addrgen",
  113. 'raw': "txcreate",
  114. 'sig': "txsign",
  115. 'mmwords': "export_mnemonic",
  116. 'mmseed': "export_seed",
  117. 'mmincog': "export_incog",
  118. 'mmincox': "export_incog_hex",
  119. hincog_fn: "export_incog_hidden",
  120. incog_id_fn: "export_incog_hidden",
  121. 'akeys.mmenc': "keyaddrgen"
  122. },
  123. },
  124. '2': {
  125. 'tmpdir': os.path.join("test","tmp2"),
  126. 'wpasswd': "Hodling away",
  127. 'addr_idx_list': "37,45,3-6,22-23", # 8 addresses
  128. 'seed_len': 128,
  129. 'dep_generators': {
  130. 'mmdat': "walletgen2",
  131. 'addrs': "addrgen2",
  132. 'raw': "txcreate2",
  133. 'sig': "txsign2",
  134. 'mmwords': "export_mnemonic2",
  135. },
  136. },
  137. '3': {
  138. 'tmpdir': os.path.join("test","tmp3"),
  139. 'wpasswd': "Major miner",
  140. 'addr_idx_list': "73,54,1022-1023,2-5", # 8 addresses
  141. 'dep_generators': {
  142. 'mmdat': "walletgen3",
  143. 'addrs': "addrgen3",
  144. 'raw': "txcreate3",
  145. 'sig': "txsign3"
  146. },
  147. },
  148. '4': {
  149. 'tmpdir': os.path.join("test","tmp4"),
  150. 'wpasswd': "Hashrate rising",
  151. 'addr_idx_list': "63,1004,542-544,7-9", # 8 addresses
  152. 'seed_len': 192,
  153. 'dep_generators': {
  154. 'mmdat': "walletgen4",
  155. 'mmbrain': "walletgen4",
  156. 'addrs': "addrgen4",
  157. 'raw': "txcreate4",
  158. 'sig': "txsign4",
  159. },
  160. 'bw_filename': "brainwallet.mmbrain",
  161. 'bw_params': "192,1",
  162. },
  163. '5': {
  164. 'tmpdir': os.path.join("test","tmp5"),
  165. 'wpasswd': "My changed password",
  166. 'dep_generators': {
  167. 'mmdat': "passchg",
  168. },
  169. },
  170. '9': {
  171. 'tmpdir': os.path.join("test","tmp9"),
  172. 'tool_enc_infn': "tool_encrypt.in",
  173. # 'tool_enc_ref_infn': "tool_encrypt_ref.in",
  174. 'dep_generators': {
  175. 'tool_encrypt.in': "tool_encrypt",
  176. 'tool_encrypt.in.mmenc': "tool_encrypt",
  177. # 'tool_encrypt_ref.in': "tool_encrypt_ref",
  178. # 'tool_encrypt_ref.in.mmenc': "tool_encrypt_ref",
  179. },
  180. },
  181. }
  182. from copy import deepcopy
  183. for a,b in ('6','11'),('7','12'),('8','13'):
  184. cfgs[b] = deepcopy(cfgs[a])
  185. cfgs[b]['tmpdir'] = os.path.join("test","tmp"+b)
  186. from collections import OrderedDict
  187. cmd_data = OrderedDict([
  188. # test description depends
  189. ['walletgen', (1,'wallet generation', [[[],1]])],
  190. # ['walletchk', (1,'wallet check', [[["mmdat"],1]])],
  191. ['passchg', (5,'password, label and hash preset change',[[["mmdat"],1]])],
  192. ['walletchk_newpass',(5,'wallet check with new pw, label and hash preset',[[["mmdat"],5]])],
  193. ['addrgen', (1,'address generation', [[["mmdat"],1]])],
  194. ['addrimport', (1,'address import', [[["addrs"],1]])],
  195. ['txcreate', (1,'transaction creation', [[["addrs"],1]])],
  196. ['txsign', (1,'transaction signing', [[["mmdat","raw"],1]])],
  197. ['txsend', (1,'transaction sending', [[["sig"],1]])],
  198. ['export_seed', (1,'seed export to mmseed format', [[["mmdat"],1]])],
  199. ['export_mnemonic', (1,'seed export to mmwords format', [[["mmdat"],1]])],
  200. ['export_incog', (1,'seed export to mmincog format', [[["mmdat"],1]])],
  201. ['export_incog_hex',(1,'seed export to mmincog hex format', [[["mmdat"],1]])],
  202. ['export_incog_hidden',(1,'seed export to hidden mmincog format', [[["mmdat"],1]])],
  203. ['addrgen_seed', (1,'address generation from mmseed file', [[["mmseed","addrs"],1]])],
  204. ['addrgen_mnemonic',(1,'address generation from mmwords file',[[["mmwords","addrs"],1]])],
  205. ['addrgen_incog', (1,'address generation from mmincog file',[[["mmincog","addrs"],1]])],
  206. ['addrgen_incog_hex',(1,'address generation from mmincog hex file',[[["mmincox","addrs"],1]])],
  207. ['addrgen_incog_hidden',(1,'address generation from hidden mmincog file', [[[hincog_fn,"addrs"],1]])],
  208. ['keyaddrgen', (1,'key-address file generation', [[["mmdat"],1]])],
  209. ['txsign_keyaddr',(1,'transaction signing with key-address file', [[["akeys.mmenc","raw"],1]])],
  210. ['walletgen2',(2,'wallet generation (2), 128-bit seed', [])],
  211. ['addrgen2', (2,'address generation (2)', [[["mmdat"],2]])],
  212. ['txcreate2', (2,'transaction creation (2)', [[["addrs"],2]])],
  213. ['txsign2', (2,'transaction signing, two transactions',[[["mmdat","raw"],1],[["mmdat","raw"],2]])],
  214. ['export_mnemonic2', (2,'seed export to mmwords format (2)',[[["mmdat"],2]])],
  215. ['walletgen3',(3,'wallet generation (3)', [])],
  216. ['addrgen3', (3,'address generation (3)', [[["mmdat"],3]])],
  217. ['txcreate3', (3,'tx creation with inputs and outputs from two wallets', [[["addrs"],1],[["addrs"],3]])],
  218. ['txsign3', (3,'tx signing with inputs and outputs from two wallets',[[["mmdat"],1],[["mmdat","raw"],3]])],
  219. ['walletgen4',(4,'wallet generation (4) (brainwallet)', [])],
  220. ['addrgen4', (4,'address generation (4)', [[["mmdat"],4]])],
  221. ['txcreate4', (4,'tx creation with inputs and outputs from four seed sources, plus non-MMGen inputs and outputs', [[["addrs"],1],[["addrs"],2],[["addrs"],3],[["addrs"],4]])],
  222. ['txsign4', (4,'tx signing with inputs and outputs from incog file, mnemonic file, wallet and brainwallet, plus non-MMGen inputs and outputs', [[["mmincog"],1],[["mmwords"],2],[["mmdat"],3],[["mmbrain","raw"],4]])],
  223. ['tool_encrypt', (9,"'mmgen-tool encrypt' (random data)", [])],
  224. ['tool_decrypt', (9,"'mmgen-tool decrypt' (random data)", [[[cfgs['9']['tool_enc_infn'],cfgs['9']['tool_enc_infn']+".mmenc"],9]])],
  225. # ['tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])],
  226. ['tool_find_incog_data', (9,"'mmgen-tool find_incog_data'", [[[hincog_fn],1],[[incog_id_fn],1]])],
  227. ])
  228. # saved reference data
  229. cmd_data_ref = (
  230. # reading
  231. ('ref_wallet_chk', ([],'saved reference wallet')),
  232. ('ref_seed_chk', ([],'saved seed file')),
  233. ('ref_mn_chk', ([],'saved mnemonic file')),
  234. ('ref_hincog_chk', ([],'saved hidden incog reference wallet')),
  235. ('ref_brain_chk', ([],'saved brainwallet')),
  236. # generating new reference ('abc' brainwallet) files:
  237. ('refwalletgen', ([],'gen new refwallet')),
  238. ('refaddrgen', (["mmdat"],'new refwallet addr chksum')),
  239. ('refkeyaddrgen', (["mmdat"],'new refwallet key-addr chksum'))
  240. )
  241. # misc. saved reference data
  242. cmd_data_ref_other = (
  243. ('ref_addrfile_chk', 'saved reference address file'),
  244. ('ref_keyaddrfile_chk','saved reference key-address file'),
  245. # Create the fake inputs:
  246. # ('txcreate8', 'transaction creation (8)'),
  247. ('ref_tx_chk', 'saved reference tx file'),
  248. ('ref_brain_chk_spc3', 'saved brainwallet (non-standard spacing)'),
  249. ('ref_tool_decrypt', 'decryption of saved MMGen-encrypted file'),
  250. )
  251. # mmgen-walletconv:
  252. cmd_data_conv_in = ( # reading
  253. ('ref_wallet_conv', 'conversion of saved reference wallet'),
  254. ('ref_mn_conv', 'conversion of saved mnemonic'),
  255. ('ref_seed_conv', 'conversion of saved seed file'),
  256. ('ref_brain_conv', 'conversion of ref brainwallet'),
  257. ('ref_incog_conv', 'conversion of saved incog wallet'),
  258. ('ref_incox_conv', 'conversion of saved hex incog wallet'),
  259. ('ref_hincog_conv', 'conversion of saved hidden incog wallet'),
  260. ('ref_hincog_conv_old','conversion of saved hidden incog wallet (old format)')
  261. )
  262. cmd_data_conv_out = ( # writing
  263. ('ref_wallet_conv_out', 'ref seed conversion to wallet'),
  264. ('ref_mn_conv_out', 'ref seed conversion to mnemonic'),
  265. ('ref_seed_conv_out', 'ref seed conversion to seed'),
  266. ('ref_incog_conv_out', 'ref seed conversion to incog data'),
  267. ('ref_incox_conv_out', 'ref seed conversion to hex incog data'),
  268. ('ref_hincog_conv_out', 'ref seed conversion to hidden incog data')
  269. )
  270. cmd_groups = OrderedDict([
  271. ('main', cmd_data.keys()),
  272. ('ref', [c[0]+str(i) for c in cmd_data_ref for i in (1,2,3)]),
  273. ('ref_other', [c[0] for c in cmd_data_ref_other]),
  274. ('conv_in', [c[0]+str(i) for c in cmd_data_conv_in for i in (1,2,3)]),
  275. ('conv_out', [c[0]+str(i) for c in cmd_data_conv_out for i in (1,2,3)]),
  276. ])
  277. for a,b in cmd_data_ref:
  278. for i,j in (1,128),(2,192),(3,256):
  279. cmd_data[a+str(i)] = (5+i,"%s (%s-bit)" % (b[1],j),[[b[0],5+i]])
  280. for a,b in cmd_data_ref_other:
  281. cmd_data[a] = (8,b,[[[],8]])
  282. for a,b in cmd_data_conv_in:
  283. for i,j in (1,128),(2,192),(3,256):
  284. cmd_data[a+str(i)] = (10+i,"%s (%s-bit)" % (b,j),[[[],10+i]])
  285. for a,b in cmd_data_conv_out:
  286. for i,j in (1,128),(2,192),(3,256):
  287. cmd_data[a+str(i)] = (10+i,"%s (%s-bit)" % (b,j),[[[],10+i]])
  288. utils = {
  289. 'check_deps': 'check dependencies for specified command',
  290. 'clean': 'clean specified tmp dir(s) 1,2,3,4,5 or 6 (no arg = all dirs)',
  291. }
  292. addrs_per_wallet = 8
  293. # total of two outputs must be < 10 BTC
  294. for k in cfgs.keys():
  295. cfgs[k]['amts'] = [0,0]
  296. for idx,mod in (0,6),(1,4):
  297. cfgs[k]['amts'][idx] = "%s.%s" % ((getrandnum(2) % mod), str(getrandnum(4))[:5])
  298. meta_cmds = OrderedDict([
  299. ['ref1', ("refwalletgen1","refaddrgen1","refkeyaddrgen1")],
  300. ['ref2', ("refwalletgen2","refaddrgen2","refkeyaddrgen2")],
  301. ['ref3', ("refwalletgen3","refaddrgen3","refkeyaddrgen3")],
  302. ['gen', ("walletgen","addrgen")],
  303. ['pass', ("passchg","walletchk_newpass")],
  304. ['tx', ("addrimport","txcreate","txsign","txsend")],
  305. ['export', [k for k in cmd_data if k[:7] == "export_" and cmd_data[k][0] == 1]],
  306. ['gen_sp', [k for k in cmd_data if k[:8] == "addrgen_" and cmd_data[k][0] == 1]],
  307. ['online', ("keyaddrgen","txsign_keyaddr")],
  308. ['2', [k for k in cmd_data if cmd_data[k][0] == 2]],
  309. ['3', [k for k in cmd_data if cmd_data[k][0] == 3]],
  310. ['4', [k for k in cmd_data if cmd_data[k][0] == 4]],
  311. ['tool', ("tool_encrypt","tool_decrypt","tool_find_incog_data")],
  312. ['saved_ref1', [c[0]+"1" for c in cmd_data_ref]],
  313. ['saved_ref2', [c[0]+"2" for c in cmd_data_ref]],
  314. ['saved_ref3', [c[0]+"3" for c in cmd_data_ref]],
  315. ['saved_ref_other', [c[0] for c in cmd_data_ref_other]],
  316. ['saved_ref_conv_in1', [c[0]+"1" for c in cmd_data_conv_in]],
  317. ['saved_ref_conv_in2', [c[0]+"2" for c in cmd_data_conv_in]],
  318. ['saved_ref_conv_in3', [c[0]+"3" for c in cmd_data_conv_in]],
  319. ['saved_ref_conv_out1', [c[0]+"1" for c in cmd_data_conv_out]],
  320. ['saved_ref_conv_out2', [c[0]+"2" for c in cmd_data_conv_out]],
  321. ['saved_ref_conv_out3', [c[0]+"3" for c in cmd_data_conv_out]],
  322. ])
  323. opts_data = {
  324. 'desc': "Test suite for the MMGen suite",
  325. 'usage':"[options] [command(s) or metacommand(s)]",
  326. 'options': """
  327. -h, --help Print this help message
  328. -b, --buf-keypress Use buffered keypresses as with real human input
  329. -d, --debug-scripts Turn on debugging output in executed scripts
  330. -D, --direct-exec Bypass pexpect and execute a command directly (for
  331. debugging only)
  332. -e, --exact-output Show the exact output of the MMGen script(s) being run
  333. -l, --list-cmds List and describe the tests and commands in the test suite
  334. -p, --pause Pause between tests, resuming on keypress
  335. -q, --quiet Produce minimal output. Suppress dependency info
  336. -s, --system Test scripts and modules installed on system rather than
  337. those in the repo root
  338. -v, --verbose Produce more verbose output
  339. """,
  340. 'notes': """
  341. If no command is given, the whole suite of tests is run.
  342. """
  343. }
  344. cmd_args = opt.opts.init(opts_data)
  345. if opt.system: sys.path.pop(0)
  346. if opt.debug_scripts: os.environ["MMGEN_DEBUG"] = "1"
  347. if opt.buf_keypress:
  348. send_delay = 0.3
  349. else:
  350. send_delay = 0
  351. os.environ["MMGEN_DISABLE_HOLD_PROTECT"] = "1"
  352. if opt.exact_output:
  353. def msg(s): pass
  354. vmsg = vmsg_r = msg_r = msg
  355. else:
  356. def msg(s): sys.stderr.write(s+"\n")
  357. def vmsg(s):
  358. if opt.verbose: sys.stderr.write(s+"\n")
  359. def msg_r(s): sys.stderr.write(s)
  360. def vmsg_r(s):
  361. if opt.verbose: sys.stderr.write(s)
  362. stderr_save = sys.stderr
  363. def silence():
  364. if not (opt.verbose or opt.exact_output):
  365. sys.stderr = open("/dev/null","a")
  366. def end_silence():
  367. if not (opt.verbose or opt.exact_output):
  368. sys.stderr = stderr_save
  369. def errmsg(s): stderr_save.write(s+"\n")
  370. def errmsg_r(s): stderr_save.write(s)
  371. if opt.list_cmds:
  372. fs = " {:<{w}} - {}"
  373. Msg("AVAILABLE COMMANDS:")
  374. w = max([len(i) for i in cmd_data])
  375. for cmd in cmd_data:
  376. Msg(fs.format(cmd,cmd_data[cmd][1],w=w))
  377. w = max([len(i) for i in meta_cmds])
  378. Msg("\nAVAILABLE METACOMMANDS:")
  379. for cmd in meta_cmds:
  380. Msg(fs.format(cmd," ".join(meta_cmds[cmd]),w=w))
  381. w = max([len(i) for i in cmd_groups.keys()])
  382. Msg("\nAVAILABLE COMMAND GROUPS:")
  383. for g in cmd_groups.keys():
  384. Msg(fs.format(g," ".join(cmd_groups[g]),w=w))
  385. Msg("\nAVAILABLE UTILITIES:")
  386. w = max([len(i) for i in utils])
  387. for cmd in sorted(utils):
  388. Msg(fs.format(cmd,utils[cmd],w=w))
  389. sys.exit()
  390. import pexpect,time,re
  391. from mmgen.util import get_data_from_file,write_to_file,get_lines_from_file
  392. def my_send(p,t,delay=send_delay,s=False):
  393. if delay: time.sleep(delay)
  394. ret = p.send(t) # returns num bytes written
  395. if delay: time.sleep(delay)
  396. if opt.verbose:
  397. ls = "" if opt.debug or not s else " "
  398. es = "" if s else " "
  399. msg("%sSEND %s%s" % (ls,es,yellow("'%s'"%t.replace('\n',r'\n'))))
  400. return ret
  401. def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False):
  402. quo = "'" if type(s) == str else ""
  403. if opt.verbose: msg_r("EXPECT %s" % yellow(quo+str(s)+quo))
  404. else: msg_r("+")
  405. try:
  406. if s == '': ret = 0
  407. else:
  408. f = p.expect if regex else p.expect_exact
  409. ret = f(s,timeout=3)
  410. except pexpect.TIMEOUT:
  411. errmsg(red("\nERROR. Expect %s%s%s timed out. Exiting" % (quo,s,quo)))
  412. sys.exit(1)
  413. if opt.debug or (opt.verbose and type(s) != str): msg_r(" ==> %s " % ret)
  414. if ret == -1:
  415. errmsg("Error. Expect returned %s" % ret)
  416. sys.exit(1)
  417. else:
  418. if t == '':
  419. if not nonl: vmsg("")
  420. else:
  421. my_send(p,t,delay,s)
  422. return ret
  423. def get_file_with_ext(ext,mydir,delete=True):
  424. flist = [os.path.join(mydir,f) for f in os.listdir(mydir)
  425. if f == ext or f[-(len(ext)+1):] == "."+ext]
  426. if not flist: return False
  427. if len(flist) > 1:
  428. if delete:
  429. if not opt.quiet:
  430. msg("Multiple *.%s files in '%s' - deleting" % (ext,mydir))
  431. for f in flist: os.unlink(f)
  432. return False
  433. else:
  434. return flist[0]
  435. def get_addrfile_checksum(display=False):
  436. addrfile = get_file_with_ext("addrs",cfg['tmpdir'])
  437. silence()
  438. from mmgen.addr import AddrInfo
  439. chk = AddrInfo(addrfile).checksum
  440. if opt.verbose and display: msg("Checksum: %s" % cyan(chk))
  441. end_silence()
  442. return chk
  443. def verify_checksum_or_exit(checksum,chk):
  444. if checksum != chk:
  445. errmsg(red("Checksum error: %s" % chk))
  446. sys.exit(1)
  447. vmsg(green("Checksums match: %s") % (cyan(chk)))
  448. class MMGenExpect(object):
  449. def __init__(self,name,mmgen_cmd,cmd_args=[],extra_desc=""):
  450. if not opt.system:
  451. mmgen_cmd = os.path.join(os.curdir,mmgen_cmd)
  452. desc = cmd_data[name][1]
  453. if extra_desc: desc += " " + extra_desc
  454. if opt.verbose or opt.exact_output:
  455. sys.stderr.write(
  456. green("Testing %s\nExecuting " % desc) +
  457. cyan("'%s %s'\n" % (mmgen_cmd," ".join(cmd_args)))
  458. )
  459. else:
  460. msg_r("Testing %s " % (desc+":"))
  461. if opt.direct_exec:
  462. os.system(" ".join([mmgen_cmd] + cmd_args))
  463. sys.exit()
  464. else:
  465. self.p = pexpect.spawn(mmgen_cmd,cmd_args)
  466. if opt.exact_output: self.p.logfile = sys.stdout
  467. def license(self):
  468. p = "'w' for conditions and warranty info, or 'c' to continue: "
  469. my_expect(self.p,p,'c')
  470. def usr_rand(self,num_chars):
  471. rand_chars = list(getrandstr(num_chars,no_space=True))
  472. my_expect(self.p,'symbols left: ','x')
  473. try:
  474. vmsg_r("SEND ")
  475. while self.p.expect('left: ',0.1) == 0:
  476. ch = rand_chars.pop(0)
  477. msg_r(yellow(ch)+" " if opt.verbose else "+")
  478. self.p.send(ch)
  479. except:
  480. vmsg("EOT")
  481. my_expect(self.p,"ENTER to continue: ",'\n')
  482. def passphrase_new(self,desc,passphrase):
  483. my_expect(self.p,("Enter passphrase for %s: " % desc), passphrase+"\n")
  484. my_expect(self.p,"Repeat passphrase: ", passphrase+"\n")
  485. def passphrase(self,desc,passphrase,pwtype=""):
  486. if pwtype: pwtype += " "
  487. my_expect(self.p,("Enter %spassphrase for %s.*?: " % (pwtype,desc)),
  488. passphrase+"\n",regex=True)
  489. def hash_preset(self,desc,preset=''):
  490. my_expect(self.p,("Enter hash preset for %s," % desc))
  491. my_expect(self.p,("or hit ENTER .*?:"), str(preset)+"\n",regex=True)
  492. def written_to_file(self,desc,overwrite_unlikely=False,query="Overwrite? ",oo=False):
  493. s1 = "%s written to file " % desc
  494. s2 = query + "Type uppercase 'YES' to confirm: "
  495. ret = my_expect(self.p,s1 if overwrite_unlikely else [s1,s2])
  496. if ret == 1:
  497. my_send(self.p,"YES\n")
  498. if oo:
  499. outfile = self.expect_getend("Overwriting file '").rstrip("'")
  500. return outfile
  501. else:
  502. ret = my_expect(self.p,s1)
  503. outfile = self.p.readline().strip().strip("'")
  504. vmsg("%s file: %s" % (desc,cyan(outfile.replace("'",""))))
  505. return outfile
  506. def no_overwrite(self):
  507. self.expect("Overwrite? Type uppercase 'YES' to confirm: ","\n")
  508. self.expect("Exiting at user request")
  509. def tx_view(self):
  510. my_expect(self.p,r"View .*?transaction.*? \(y\)es, \(N\)o, pager \(v\)iew.*?: ","\n",regex=True)
  511. def expect_getend(self,s,regex=False):
  512. ret = self.expect(s,regex=regex,nonl=True)
  513. end = self.readline().strip()
  514. vmsg(" ==> %s" % cyan(end))
  515. return end
  516. def interactive(self):
  517. return self.p.interact()
  518. def logfile(self,arg):
  519. self.p.logfile = arg
  520. def expect(self,*args,**kwargs):
  521. return my_expect(self.p,*args,**kwargs)
  522. def send(self,*args,**kwargs):
  523. return my_send(self.p,*args,**kwargs)
  524. def readline(self):
  525. return self.p.readline()
  526. def close(self):
  527. return self.p.close()
  528. def readlines(self):
  529. return [l.rstrip()+"\n" for l in self.p.readlines()]
  530. def read(self,n=None):
  531. return self.p.read(n)
  532. from mmgen.rpc.data import TransactionInfo
  533. from decimal import Decimal
  534. from mmgen.bitcoin import verify_addr
  535. def add_fake_unspent_entry(out,address,comment):
  536. out.append(TransactionInfo(
  537. account = unicode(comment),
  538. vout = int(getrandnum(4) % 8),
  539. txid = unicode(hexlify(os.urandom(32))),
  540. amount = Decimal("%s.%s" % (10+(getrandnum(4) % 40), getrandnum(4) % 100000000)),
  541. address = address,
  542. spendable = False,
  543. scriptPubKey = ("76a914"+verify_addr(address,return_hex=True)+"88ac"),
  544. confirmations = getrandnum(4) % 500
  545. ))
  546. def create_fake_unspent_data(adata,unspent_data_file,tx_data,non_mmgen_input=''):
  547. out = []
  548. for s in tx_data.keys():
  549. sid = tx_data[s]['sid']
  550. a = adata.addrinfo(sid)
  551. for idx,btcaddr in a.addrpairs():
  552. add_fake_unspent_entry(out,btcaddr,"%s:%s Test Wallet" % (sid,idx))
  553. if non_mmgen_input:
  554. from mmgen.bitcoin import privnum2addr,hextowif
  555. privnum = getrandnum(32)
  556. btcaddr = privnum2addr(privnum,compressed=True)
  557. of = os.path.join(cfgs[non_mmgen_input]['tmpdir'],non_mmgen_fn)
  558. write_to_file(of, hextowif("{:064x}".format(privnum),
  559. compressed=True)+"\n","compressed bitcoin key")
  560. add_fake_unspent_entry(out,btcaddr,"Non-MMGen address")
  561. # msg("\n".join([repr(o) for o in out])); sys.exit()
  562. write_to_file(unspent_data_file,repr(out),"Unspent outputs",verbose=True)
  563. def add_comments_to_addr_file(addrfile,tfile):
  564. silence()
  565. msg(green("Adding comments to address file '%s'" % addrfile))
  566. from mmgen.addr import AddrInfo
  567. a = AddrInfo(addrfile)
  568. for i in a.idxs(): a.set_comment(idx,"Test address %s" % idx)
  569. write_to_file(tfile,a.fmt_data(),{})
  570. end_silence()
  571. def make_brainwallet_file(fn):
  572. # Print random words with random whitespace in between
  573. from mmgen.mn_tirosh import words
  574. wl = words.split("\n")
  575. nwords,ws_list,max_spaces = 10," \n",5
  576. def rand_ws_seq():
  577. nchars = getrandnum(1) % max_spaces + 1
  578. return "".join([ws_list[getrandnum(1)%len(ws_list)] for i in range(nchars)])
  579. rand_pairs = [wl[getrandnum(4) % len(wl)] + rand_ws_seq() for i in range(nwords)]
  580. d = "".join(rand_pairs).rstrip() + "\n"
  581. if opt.verbose: msg_r("Brainwallet password:\n%s" % cyan(d))
  582. write_to_file(fn,d,"brainwallet password")
  583. def do_between():
  584. if opt.pause:
  585. from mmgen.util import keypress_confirm
  586. if keypress_confirm(green("Continue?"),default_yes=True):
  587. if opt.verbose or opt.exact_output: sys.stderr.write("\n")
  588. else:
  589. errmsg("Exiting at user request")
  590. sys.exit()
  591. elif opt.verbose or opt.exact_output:
  592. sys.stderr.write("\n")
  593. rebuild_list = OrderedDict()
  594. def check_needs_rerun(ts,cmd,build=False,root=True,force_delete=False,dpy=False):
  595. rerun = True if root else False # force_delete is not passed to recursive call
  596. fns = []
  597. if force_delete or not root:
  598. # does cmd produce a needed dependency(ies)?
  599. ret = ts.get_num_exts_for_cmd(cmd,dpy)
  600. if ret:
  601. for ext in ret[1]:
  602. fn = get_file_with_ext(ext,cfgs[ret[0]]['tmpdir'],delete=build)
  603. if fn:
  604. if force_delete: os.unlink(fn)
  605. else: fns.append(fn)
  606. else: rerun = True
  607. fdeps = ts.generate_file_deps(cmd)
  608. cdeps = ts.generate_cmd_deps(fdeps)
  609. for fn in fns:
  610. my_age = os.stat(fn).st_mtime
  611. for num,ext in fdeps:
  612. f = get_file_with_ext(ext,cfgs[num]['tmpdir'],delete=build)
  613. if f and os.stat(f).st_mtime > my_age: rerun = True
  614. for cdep in cdeps:
  615. if check_needs_rerun(ts,cdep,build=build,root=False,dpy=cmd): rerun = True
  616. if build:
  617. if rerun:
  618. for fn in fns:
  619. if not root: os.unlink(fn)
  620. ts.do_cmd(cmd)
  621. if not root: do_between()
  622. else:
  623. # If prog produces multiple files:
  624. if cmd not in rebuild_list or rerun == True:
  625. rebuild_list[cmd] = (rerun,fns[0] if fns else "") # FIX
  626. return rerun
  627. def refcheck(desc,chk,refchk):
  628. vmsg("Comparing %s '%s' to stored reference" % (desc,chk))
  629. if chk == refchk:
  630. ok()
  631. else:
  632. if not opt.verbose: errmsg("")
  633. errmsg(red("""
  634. Fatal error - %s '%s' does not match reference value '%s'. Aborting test
  635. """.strip() % (desc,chk,refchk)))
  636. sys.exit(3)
  637. def check_deps(cmds):
  638. if len(cmds) != 1:
  639. msg("Usage: %s check_deps <command>" % g.prog_name)
  640. sys.exit(1)
  641. cmd = cmds[0]
  642. if cmd not in cmd_data:
  643. msg("'%s': unrecognized command" % cmd)
  644. sys.exit(1)
  645. if not opt.quiet:
  646. msg("Checking dependencies for '%s'" % (cmd))
  647. check_needs_rerun(ts,cmd,build=False)
  648. w = max(len(i) for i in rebuild_list) + 1
  649. for cmd in rebuild_list:
  650. c = rebuild_list[cmd]
  651. m = "Rebuild" if (c[0] and c[1]) else "Build" if c[0] else "OK"
  652. msg("cmd {:<{w}} {}".format(cmd+":", m, w=w))
  653. # mmsg(cmd,c)
  654. def clean(dirs=[]):
  655. ts = MMGenTestSuite()
  656. dirlist = ts.list_tmp_dirs()
  657. if not dirs: dirs = dirlist.keys()
  658. for d in sorted(dirs):
  659. if d in dirlist:
  660. cleandir(dirlist[d])
  661. else:
  662. msg("%s: invalid directory number" % d)
  663. sys.exit(1)
  664. class MMGenTestSuite(object):
  665. def __init__(self):
  666. pass
  667. def list_tmp_dirs(self):
  668. d = {}
  669. for k in cfgs: d[k] = cfgs[k]['tmpdir']
  670. return d
  671. def get_num_exts_for_cmd(self,cmd,dpy=False): # dpy ignored here
  672. num = str(cmd_data[cmd][0])
  673. dgl = cfgs[num]['dep_generators']
  674. # mmsg(num,cmd,dgl)
  675. if cmd in dgl.values():
  676. exts = [k for k in dgl if dgl[k] == cmd]
  677. return (num,exts)
  678. else:
  679. return None
  680. def do_cmd(self,cmd):
  681. d = [(str(num),ext) for exts,num in cmd_data[cmd][2] for ext in exts]
  682. al = [get_file_with_ext(ext,cfgs[num]['tmpdir']) for num,ext in d]
  683. global cfg
  684. cfg = cfgs[str(cmd_data[cmd][0])]
  685. self.__class__.__dict__[cmd](*([self,cmd] + al))
  686. def generate_file_deps(self,cmd):
  687. return [(str(n),e) for exts,n in cmd_data[cmd][2] for e in exts]
  688. def generate_cmd_deps(self,fdeps):
  689. return [cfgs[str(n)]['dep_generators'][ext] for n,ext in fdeps]
  690. def walletgen(self,name,brain=False,seed_len=None):
  691. args = ["-d",cfg['tmpdir'],"-p1","-r10"]
  692. if seed_len: args += ["-l",str(seed_len)]
  693. # if 'seed_len' in cfg: args += ["-l",cfg['seed_len']]
  694. if brain:
  695. bwf = os.path.join(cfg['tmpdir'],cfg['bw_filename'])
  696. args += ["-b",cfg['bw_params'],bwf]
  697. make_brainwallet_file(bwf)
  698. t = MMGenExpect(name,"mmgen-walletgen", args)
  699. t.license()
  700. if brain:
  701. t.expect(
  702. "A brainwallet will be secure only if you really know what you're doing")
  703. t.expect("Type uppercase 'YES' to confirm: ","YES\n")
  704. t.usr_rand(10)
  705. for s in "user-supplied entropy","saved user-supplied entropy":
  706. t.expect("Generating encryption key from OS random data plus %s" % s)
  707. if brain: break
  708. t.passphrase_new("new MMGen wallet",cfg['wpasswd'])
  709. t.written_to_file("Wallet")
  710. ok()
  711. def refwalletgen(self,name):
  712. label = "test.py ref. wallet (pw '%s', seed len %s)" \
  713. % (ref_wallet_brainpass,cfg['seed_len'])
  714. bw_arg = "-b%s,%s" % (cfg['seed_len'], ref_wallet_hash_preset)
  715. args = ["-d",cfg['tmpdir'],"-p1","-r10",bw_arg,"-L",label]
  716. d = " (%s-bit seed)" % cfg['seed_len']
  717. t = MMGenExpect(name,"mmgen-walletgen", args)
  718. t.license()
  719. t.expect("Type uppercase 'YES' to confirm: ","YES\n")
  720. t.expect("passphrase: ",ref_wallet_brainpass+"\n")
  721. t.usr_rand(10)
  722. t.passphrase_new("new MMGen wallet",cfg['wpasswd'])
  723. seed_id = t.written_to_file("Wallet").split("-")[0].split("/")[-1]
  724. refcheck("seed ID",seed_id,cfg['seed_id'])
  725. refwalletgen1 = refwalletgen2 = refwalletgen3 = refwalletgen
  726. def passchg(self,name,walletfile):
  727. t = MMGenExpect(name,"mmgen-passchg",
  728. ["-d",cfg['tmpdir'],"-p","2","-L","New Label","-r","16",walletfile])
  729. t.passphrase("MMGen wallet",cfgs['1']['wpasswd'],pwtype="old")
  730. t.expect_getend("Label changed: ")
  731. t.expect_getend("Hash preset changed: ")
  732. t.passphrase("MMGen wallet",cfg['wpasswd'],pwtype="new")
  733. t.expect("Repeat passphrase: ",cfg['wpasswd']+"\n")
  734. t.usr_rand(16)
  735. t.expect_getend("Key ID changed: ")
  736. t.written_to_file("Wallet")
  737. ok()
  738. def walletchk_beg(self,name,args):
  739. t = MMGenExpect(name,"mmgen-walletchk", args)
  740. t.expect("Getting MMGen wallet data from file '%s'" % args[-1])
  741. t.passphrase("MMGen wallet",cfg['wpasswd'])
  742. t.expect("Passphrase is OK")
  743. t.expect("Wallet is OK")
  744. return t
  745. def walletchk(self,name,walletfile):
  746. self.walletchk_beg(name,[walletfile])
  747. ok()
  748. walletchk_newpass = walletchk
  749. def addrgen(self,name,walletfile,check_ref=False):
  750. t = MMGenExpect(name,"mmgen-addrgen",["-d",cfg['tmpdir'],walletfile,cfg['addr_idx_list']])
  751. t.license()
  752. t.passphrase("MMGen wallet",cfg['wpasswd'])
  753. t.expect("Passphrase is OK")
  754. t.expect("[0-9]+ addresses generated",regex=True)
  755. chk = t.expect_getend(r"Checksum for address data .*?: ",regex=True)
  756. if check_ref:
  757. refcheck("address data checksum",chk,cfg['addrfile_chk'])
  758. return
  759. t.written_to_file("Addresses")
  760. ok()
  761. def refaddrgen(self,name,walletfile):
  762. d = " (%s-bit seed)" % cfg['seed_len']
  763. self.addrgen(name,walletfile,check_ref=True)
  764. refaddrgen1 = refaddrgen2 = refaddrgen3 = refaddrgen
  765. def addrimport(self,name,addrfile):
  766. outfile = os.path.join(cfg['tmpdir'],"addrfile_w_comments")
  767. add_comments_to_addr_file(addrfile,outfile)
  768. t = MMGenExpect(name,"mmgen-addrimport",[outfile])
  769. t.expect_getend(r"Checksum for address data .*\[.*\]: ",regex=True)
  770. t.expect_getend("Validating addresses...OK. ")
  771. t.expect("Type uppercase 'YES' to confirm: ","\n")
  772. vmsg("This is a simulation, so no addresses were actually imported into the tracking\nwallet")
  773. ok()
  774. def txcreate(self,name,addrfile):
  775. self.txcreate_common(name,sources=['1'])
  776. def txcreate_common(self,name,sources=['1'],non_mmgen_input=''):
  777. if opt.verbose or opt.exact_output:
  778. sys.stderr.write(green("Generating fake transaction info\n"))
  779. silence()
  780. from mmgen.addr import AddrInfo,AddrInfoList
  781. tx_data,ail = {},AddrInfoList()
  782. from mmgen.util import parse_addr_idxs
  783. for s in sources:
  784. afile = get_file_with_ext("addrs",cfgs[s]["tmpdir"])
  785. ai = AddrInfo(afile)
  786. ail.add(ai)
  787. aix = parse_addr_idxs(cfgs[s]['addr_idx_list'])
  788. if len(aix) != addrs_per_wallet:
  789. errmsg(red("Address index list length != %s: %s" %
  790. (addrs_per_wallet,repr(aix))))
  791. sys.exit()
  792. tx_data[s] = {
  793. 'addrfile': afile,
  794. 'chk': ai.checksum,
  795. 'sid': ai.seed_id,
  796. 'addr_idxs': aix[-2:],
  797. }
  798. unspent_data_file = os.path.join(cfg['tmpdir'],"unspent.json")
  799. create_fake_unspent_data(ail,unspent_data_file,tx_data,non_mmgen_input)
  800. # make the command line
  801. from mmgen.bitcoin import privnum2addr
  802. btcaddr = privnum2addr(getrandnum(32),compressed=True)
  803. cmd_args = ["-d",cfg['tmpdir']]
  804. for num in tx_data.keys():
  805. s = tx_data[num]
  806. cmd_args += [
  807. "%s:%s,%s" % (s['sid'],s['addr_idxs'][0],cfgs[num]['amts'][0]),
  808. ]
  809. # + one BTC address
  810. # + one change address and one BTC address
  811. if num is tx_data.keys()[-1]:
  812. cmd_args += ["%s:%s" % (s['sid'],s['addr_idxs'][1])]
  813. cmd_args += ["%s,%s" % (btcaddr,cfgs[num]['amts'][1])]
  814. for num in tx_data: cmd_args += [tx_data[num]['addrfile']]
  815. os.environ["MMGEN_BOGUS_WALLET_DATA"] = unspent_data_file
  816. end_silence()
  817. if opt.verbose or opt.exact_output: sys.stderr.write("\n")
  818. t = MMGenExpect(name,"mmgen-txcreate",cmd_args)
  819. t.license()
  820. for num in tx_data.keys():
  821. t.expect_getend("Getting address data from file ")
  822. chk=t.expect_getend(r"Checksum for address data .*?: ",regex=True)
  823. verify_checksum_or_exit(tx_data[num]['chk'],chk)
  824. # not in tracking wallet warning, (1 + num sources) times
  825. if t.expect(["Continue anyway? (y/N): ",
  826. "Unable to connect to bitcoind"]) == 0:
  827. t.send("y")
  828. else:
  829. errmsg(red("Error: unable to connect to bitcoind. Exiting"))
  830. sys.exit(1)
  831. for num in tx_data.keys():
  832. t.expect("Continue anyway? (y/N): ","y")
  833. t.expect(r"'q' = quit sorting, .*?: ","M", regex=True)
  834. t.expect(r"'q' = quit sorting, .*?: ","q", regex=True)
  835. outputs_list = [addrs_per_wallet*i + 1 for i in range(len(tx_data))]
  836. if non_mmgen_input: outputs_list.append(len(tx_data)*addrs_per_wallet + 1)
  837. t.expect("Enter a range or space-separated list of outputs to spend: ",
  838. " ".join([str(i) for i in outputs_list])+"\n")
  839. if non_mmgen_input: t.expect("Accept? (y/N): ","y")
  840. t.expect("OK? (Y/n): ","y")
  841. t.expect("Add a comment to transaction? (y/N): ","\n")
  842. t.tx_view()
  843. t.expect("Save transaction? (y/N): ","y")
  844. t.written_to_file("Transaction")
  845. ok()
  846. def txsign_end(self,t,tnum=None):
  847. t.expect("Signing transaction")
  848. t.expect("Edit transaction comment? (y/N): ","\n")
  849. t.expect("Save signed transaction? (y/N): ","y")
  850. add = " #" + tnum if tnum else ""
  851. t.written_to_file("Signed transaction" + add)
  852. def txsign(self,name,txfile,walletfile,save=True):
  853. t = MMGenExpect(name,"mmgen-txsign",
  854. ["-d",cfg['tmpdir'],txfile,walletfile])
  855. t.license()
  856. t.tx_view()
  857. t.passphrase("MMGen wallet",cfg['wpasswd'])
  858. if save:
  859. self.txsign_end(t)
  860. else:
  861. t.expect("Edit transaction comment? (y/N): ","\n")
  862. t.expect("Save signed transaction? (y/N): ","\n")
  863. t.expect("Signed transaction not saved")
  864. ok()
  865. def txsend(self,name,sigfile):
  866. t = MMGenExpect(name,"mmgen-txsend", ["-d",cfg['tmpdir'],sigfile])
  867. t.license()
  868. t.tx_view()
  869. t.expect("Edit transaction comment? (y/N): ","\n")
  870. t.expect("broadcast this transaction to the network?")
  871. t.expect("'YES, I REALLY WANT TO DO THIS' to confirm: ","\n")
  872. t.expect("Exiting at user request")
  873. vmsg("This is a simulation; no transaction was sent")
  874. ok()
  875. def export_seed(self,name,walletfile):
  876. t = self.walletchk_beg(name,["-s","-d",cfg['tmpdir'],walletfile])
  877. f = t.written_to_file("Seed data")
  878. silence()
  879. msg("Seed data: %s" % cyan(get_data_from_file(f,"seed data")))
  880. end_silence()
  881. ok()
  882. def export_mnemonic(self,name,walletfile):
  883. t = self.walletchk_beg(name,["-m","-d",cfg['tmpdir'],walletfile])
  884. f = t.written_to_file("Mnemonic data")
  885. silence()
  886. msg_r("Mnemonic data: %s" % cyan(get_data_from_file(f,"mnemonic data")))
  887. end_silence()
  888. ok()
  889. def export_incog(self,name,walletfile,args=["-g"]):
  890. t = MMGenExpect(name,"mmgen-walletchk",args+["-d",cfg['tmpdir'],"-r","10",walletfile])
  891. t.passphrase("MMGen wallet",cfg['wpasswd'])
  892. t.usr_rand(10)
  893. incog_id = t.expect_getend("Incog ID: ")
  894. write_to_tmpfile(cfg,incog_id_fn,incog_id+"\n")
  895. if args[0] == "-G": return t
  896. t.written_to_file("Incognito wallet data",overwrite_unlikely=True)
  897. ok()
  898. def export_incog_hex(self,name,walletfile):
  899. self.export_incog(name,walletfile,args=["-X"])
  900. # TODO: make outdir and hidden incog compatible (ignore --outdir and warn user?)
  901. def export_incog_hidden(self,name,walletfile):
  902. rf,rd = os.path.join(cfg['tmpdir'],hincog_fn),os.urandom(hincog_bytes)
  903. vmsg(green("Writing %s bytes of data to file '%s'" % (hincog_bytes,rf)))
  904. write_to_file(rf,rd,verbose=opt.verbose)
  905. t = self.export_incog(name,walletfile,args=["-G","%s,%s"%(rf,hincog_offset)])
  906. t.written_to_file("Data",query="")
  907. ok()
  908. def addrgen_seed(self,name,walletfile,foo,desc="seed data",arg="-s"):
  909. t = MMGenExpect(name,"mmgen-addrgen",
  910. [arg,"-d",cfg['tmpdir'],walletfile,cfg['addr_idx_list']])
  911. t.license()
  912. t.expect_getend("Valid %s for seed ID " % desc)
  913. vmsg("Comparing generated checksum with checksum from previous address file")
  914. chk = t.expect_getend(r"Checksum for address data .*?: ",regex=True)
  915. verify_checksum_or_exit(get_addrfile_checksum(),chk)
  916. t.no_overwrite()
  917. ok()
  918. def addrgen_mnemonic(self,name,walletfile,foo):
  919. self.addrgen_seed(name,walletfile,foo,desc="mnemonic",arg="-m")
  920. def addrgen_incog(self,name,walletfile,foo,args=["-g"]):
  921. t = MMGenExpect(name,"mmgen-addrgen",args+["-d",
  922. cfg['tmpdir'],walletfile,cfg['addr_idx_list']])
  923. t.license()
  924. t.expect_getend("Incog ID: ")
  925. t.passphrase("incognito wallet data \w{8}", cfg['wpasswd'])
  926. t.hash_preset("incog wallet",'1')
  927. vmsg("Comparing generated checksum with checksum from address file")
  928. chk = t.expect_getend(r"Checksum for address data .*?: ",regex=True)
  929. verify_checksum_or_exit(get_addrfile_checksum(),chk)
  930. t.no_overwrite()
  931. ok()
  932. def addrgen_incog_hex(self,name,walletfile,foo):
  933. self.addrgen_incog(name,walletfile,foo,args=["-X"])
  934. def addrgen_incog_hidden(self,name,walletfile,foo):
  935. rf = os.path.join(cfg['tmpdir'],hincog_fn)
  936. self.addrgen_incog(name,walletfile,foo,
  937. args=["-G","%s,%s,%s"%(rf,hincog_offset,hincog_seedlen)])
  938. def keyaddrgen(self,name,walletfile,check_ref=False):
  939. t = MMGenExpect(name,"mmgen-keygen",
  940. ["-d",cfg['tmpdir'],walletfile,cfg['addr_idx_list']])
  941. t.license()
  942. t.expect("Type uppercase 'YES' to confirm: ","YES\n")
  943. t.passphrase("MMGen wallet",cfg['wpasswd'])
  944. chk = t.expect_getend(r"Checksum for key-address data .*?: ",regex=True)
  945. if check_ref:
  946. refcheck("key-address data checksum",chk,cfg['keyaddrfile_chk'])
  947. return
  948. t.expect("Encrypt key list? (y/N): ","y")
  949. t.hash_preset("new key list",'1')
  950. t.passphrase_new("new key list",cfg['kapasswd'])
  951. t.written_to_file("Keys")
  952. ok()
  953. def refkeyaddrgen(self,name,walletfile):
  954. self.keyaddrgen(name,walletfile,check_ref=True)
  955. refkeyaddrgen1 = refkeyaddrgen2 = refkeyaddrgen3 = refkeyaddrgen
  956. def txsign_keyaddr(self,name,keyaddr_file,txfile):
  957. t = MMGenExpect(name,"mmgen-txsign", ["-d",cfg['tmpdir'],"-M",keyaddr_file,txfile])
  958. t.license()
  959. t.hash_preset("key-address file",'1')
  960. t.passphrase("key-address file",cfg['kapasswd'])
  961. t.expect("Check key-to-address validity? (y/N): ","y")
  962. t.tx_view()
  963. self.txsign_end(t)
  964. ok()
  965. def walletgen2(self,name):
  966. self.walletgen(name,seed_len=128)
  967. def addrgen2(self,name,walletfile):
  968. self.addrgen(name,walletfile)
  969. def txcreate2(self,name,addrfile):
  970. self.txcreate_common(name,sources=['2'])
  971. def txsign2(self,name,txf1,wf1,txf2,wf2):
  972. t = MMGenExpect(name,"mmgen-txsign", ["-d",cfg['tmpdir'],txf1,wf1,txf2,wf2])
  973. t.license()
  974. for cnum in ('1','2'):
  975. t.tx_view()
  976. t.passphrase("MMGen wallet",cfgs[cnum]['wpasswd'])
  977. self.txsign_end(t,cnum)
  978. ok()
  979. def export_mnemonic2(self,name,walletfile):
  980. self.export_mnemonic(name,walletfile)
  981. def walletgen3(self,name):
  982. self.walletgen(name)
  983. def addrgen3(self,name,walletfile):
  984. self.addrgen(name,walletfile)
  985. def txcreate3(self,name,addrfile1,addrfile2):
  986. self.txcreate_common(name,sources=['1','3'])
  987. def txsign3(self,name,wf1,wf2,txf2):
  988. t = MMGenExpect(name,"mmgen-txsign", ["-d",cfg['tmpdir'],wf1,wf2,txf2])
  989. t.license()
  990. t.tx_view()
  991. for cnum in ('1','3'):
  992. t.expect_getend("Getting MMGen wallet data from file ")
  993. t.passphrase("MMGen wallet",cfgs[cnum]['wpasswd'])
  994. self.txsign_end(t)
  995. ok()
  996. def walletgen4(self,name):
  997. self.walletgen(name,brain=True)
  998. def addrgen4(self,name,walletfile):
  999. self.addrgen(name,walletfile)
  1000. def txcreate4(self,name,f1,f2,f3,f4):
  1001. self.txcreate_common(name,sources=['1','2','3','4'],non_mmgen_input='4')
  1002. def txsign4(self,name,f1,f2,f3,f4,f5):
  1003. non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
  1004. t = MMGenExpect(name,"mmgen-txsign",
  1005. ["-d",cfg['tmpdir'],"-b",cfg['bw_params'],"-k",non_mm_fn,f1,f2,f3,f4,f5])
  1006. t.license()
  1007. t.tx_view()
  1008. for cnum,desc,app in ('1',"incognito","incognito"),('3',"MMGen","MMGen"):
  1009. t.expect_getend("Getting %s wallet data from file " % desc)
  1010. t.passphrase("%s wallet"%app,cfgs[cnum]['wpasswd'])
  1011. if cnum == '1':
  1012. t.hash_preset("incog wallet",'1')
  1013. self.txsign_end(t)
  1014. ok()
  1015. def tool_encrypt(self,name,infile=""):
  1016. if infile:
  1017. infn = infile
  1018. else:
  1019. d = os.urandom(1033)
  1020. tmp_fn = cfg['tool_enc_infn']
  1021. write_to_tmpfile(cfg,tmp_fn,d)
  1022. infn = get_tmpfile_fn(cfg,tmp_fn)
  1023. t = MMGenExpect(name,"mmgen-tool",["-d",cfg['tmpdir'],"encrypt",infn])
  1024. t.hash_preset("user data",'1')
  1025. t.passphrase_new("user data",tool_enc_passwd)
  1026. t.written_to_file("Encrypted data")
  1027. ok()
  1028. # Generate the reference mmenc file
  1029. # def tool_encrypt_ref(self,name):
  1030. # infn = get_tmpfile_fn(cfg,cfg['tool_enc_ref_infn'])
  1031. # write_to_file(infn,cfg['tool_enc_reftext'],silent=True)
  1032. # self.tool_encrypt(name,infn)
  1033. def tool_decrypt(self,name,f1,f2):
  1034. of = name + ".out"
  1035. t = MMGenExpect(name,"mmgen-tool",
  1036. ["-d",cfg['tmpdir'],"decrypt",f2,"outfile="+of,"hash_preset=1"])
  1037. t.passphrase("user data",tool_enc_passwd)
  1038. t.written_to_file("Decrypted data")
  1039. d1 = read_from_file(f1)
  1040. d2 = read_from_file(get_tmpfile_fn(cfg,of))
  1041. cmp_or_die(d1,d2)
  1042. def tool_find_incog_data(self,name,f1,f2):
  1043. i_id = read_from_file(f2).rstrip()
  1044. vmsg("Incog ID: %s" % cyan(i_id))
  1045. t = MMGenExpect(name,"mmgen-tool",
  1046. ["-d",cfg['tmpdir'],"find_incog_data",f1,i_id])
  1047. o = t.expect_getend("Incog data for ID \w{8} found at offset ",regex=True)
  1048. cmp_or_die(hincog_offset,int(o))
  1049. def walletconv_out(self,name,desc,out_fmt="w",uopts=[],uopts_chk=[],pw=False):
  1050. opts = ["-d",cfg['tmpdir'],"-r10","-p1","-o",out_fmt] + uopts
  1051. infile = os.path.join(ref_dir,cfg['seed_id']+".mmwords")
  1052. d = "(convert)"
  1053. t = MMGenExpect(name,"mmgen-walletconv",opts+[infile],extra_desc=d)
  1054. t.license()
  1055. if pw:
  1056. t.passphrase_new("new "+desc,cfg['wpasswd'])
  1057. t.usr_rand(10)
  1058. if desc == "hidden incognito data":
  1059. ret = t.expect(["Create? (Y/n): ","'YES' to confirm: "],"YES\n")
  1060. if ret == 0:
  1061. t.expect("Enter file size: ","1234\n")
  1062. wf = t.written_to_file(desc[0].upper()+desc[1:],oo=True)
  1063. ok()
  1064. d = "(check)"
  1065. if desc == "hidden incognito data":
  1066. self.keygen_chksum_chk_hincog(name,cfg['seed_id'],uopts_chk)
  1067. # elif pw:
  1068. # self.walletchk_chksum_chk(name,wf,cfg['seed_id'],uopts=uopts_chk)
  1069. else:
  1070. self.keygen_chksum_chk(name,wf,cfg['seed_id'],pw=pw)
  1071. def walletconv_in(self,name,infile,desc,uopts=[],pw=False,oo=False):
  1072. opts = ["-d",cfg['tmpdir'],"-o","words","-r10"]
  1073. if_arg = [infile] if infile else []
  1074. d = "(convert)"
  1075. t = MMGenExpect(name,"mmgen-walletconv",opts+uopts+if_arg,extra_desc=d)
  1076. t.license()
  1077. if desc == "brainwallet":
  1078. t.expect("Enter brainwallet: ",ref_wallet_brainpass+"\n")
  1079. if pw:
  1080. t.passphrase(desc,cfg['wpasswd'])
  1081. if name[:19] == "ref_hincog_conv_old":
  1082. t.expect("Is the seed ID correct? (Y/n): ","\n")
  1083. else:
  1084. t.expect(["Passphrase is OK"," are correct"])
  1085. # Output
  1086. wf = t.written_to_file("Mnemonic data",oo=oo)
  1087. t.close()
  1088. ok()
  1089. # back check of result
  1090. d = "(check)"
  1091. self.keygen_chksum_chk(name,wf,cfg['seed_id'])
  1092. # Saved reference file tests
  1093. def ref_wallet_conv(self,name):
  1094. wf = os.path.join(ref_dir,cfg['ref_wallet'])
  1095. self.walletconv_in(name,wf,"MMGen wallet",pw=True,oo=True)
  1096. def ref_mn_conv(self,name,ext="mmwords",desc="Mnemonic data"):
  1097. wf = os.path.join(ref_dir,cfg['seed_id']+"."+ext)
  1098. self.walletconv_in(name,wf,desc,oo=True)
  1099. def ref_seed_conv(self,name):
  1100. self.ref_mn_conv(name,ext="mmseed",desc="Seed data")
  1101. def ref_brain_conv(self,name):
  1102. uopts = ["-i","b","-p","1","-l",str(cfg['seed_len'])]
  1103. self.walletconv_in(name,None,"brainwallet",uopts,oo=True)
  1104. def ref_incog_conv(self,name,wfk="ic_wallet",in_fmt="i",desc="incognito data"):
  1105. uopts = ["-i",in_fmt,"-p","1","-l",str(cfg['seed_len'])]
  1106. wf = os.path.join(ref_dir,cfg[wfk])
  1107. self.walletconv_in(name,wf,desc,uopts,oo=True,pw=True)
  1108. def ref_incox_conv(self,name):
  1109. self.ref_incog_conv(name,in_fmt="xi",wfk="ic_wallet_hex",desc="hex incognito data")
  1110. def ref_hincog_conv(self,name,wfk='hic_wallet',add_uopts=[]):
  1111. ic_f = os.path.join(ref_dir,cfg[wfk])
  1112. uopts = ["-i","hi","-p","1","-l",str(cfg['seed_len'])] + add_uopts
  1113. hi_opt = ["-H","%s,%s" % (ic_f,ref_wallet_incog_offset)]
  1114. self.walletconv_in(name,None,"hidden incognito data",uopts+hi_opt,oo=True,pw=True)
  1115. def ref_hincog_conv_old(self,name):
  1116. self.ref_hincog_conv(name,wfk='hic_wallet_old',add_uopts=["-O"])
  1117. def ref_wallet_conv_out(self,name):
  1118. self.walletconv_out(name,"MMGen wallet","w",pw=True)
  1119. def ref_mn_conv_out(self,name):
  1120. self.walletconv_out(name,"mnemonic data","mn")
  1121. def ref_seed_conv_out(self,name):
  1122. self.walletconv_out(name,"seed data","seed")
  1123. def ref_incog_conv_out(self,name):
  1124. self.walletconv_out(name,"incognito data",out_fmt="i",pw=True)
  1125. def ref_incox_conv_out(self,name):
  1126. self.walletconv_out(name,"hex incognito data",out_fmt="xi",pw=True)
  1127. def ref_hincog_conv_out(self,name,extra_uopts=[]):
  1128. ic_f = os.path.join(cfg['tmpdir'],"rand.data")
  1129. hi_parms = "%s,%s" % (ic_f,ref_wallet_incog_offset)
  1130. hi_parms_legacy = "%s,%s,%s"%(ic_f,ref_wallet_incog_offset,cfg['seed_len'])
  1131. self.walletconv_out(name,
  1132. "hidden incognito data", "hi",
  1133. uopts=["-J",hi_parms] + extra_uopts,
  1134. uopts_chk=["-G",hi_parms_legacy],
  1135. pw=True
  1136. )
  1137. ref_wallet_conv1 = ref_wallet_conv2 = ref_wallet_conv3 = ref_wallet_conv
  1138. ref_mn_conv1 = ref_mn_conv2 = ref_mn_conv3 = ref_mn_conv
  1139. ref_seed_conv1 = ref_seed_conv2 = ref_seed_conv3 = ref_seed_conv
  1140. ref_brain_conv1 = ref_brain_conv2 = ref_brain_conv3 = ref_brain_conv
  1141. ref_incog_conv1 = ref_incog_conv2 = ref_incog_conv3 = ref_incog_conv
  1142. ref_incox_conv1 = ref_incox_conv2 = ref_incox_conv3 = ref_incox_conv
  1143. ref_hincog_conv1 = ref_hincog_conv2 = ref_hincog_conv3 = ref_hincog_conv
  1144. ref_hincog_conv_old1 = ref_hincog_conv_old2 = ref_hincog_conv_old3 = ref_hincog_conv_old
  1145. ref_wallet_conv_out1 = ref_wallet_conv_out2 = ref_wallet_conv_out3 = ref_wallet_conv_out
  1146. ref_mn_conv_out1 = ref_mn_conv_out2 = ref_mn_conv_out3 = ref_mn_conv_out
  1147. ref_seed_conv_out1 = ref_seed_conv_out2 = ref_seed_conv_out3 = ref_seed_conv_out
  1148. ref_incog_conv_out1 = ref_incog_conv_out2 = ref_incog_conv_out3 = ref_incog_conv_out
  1149. ref_incox_conv_out1 = ref_incox_conv_out2 = ref_incox_conv_out3 = ref_incox_conv_out
  1150. ref_hincog_conv_out1 = ref_hincog_conv_out2 = ref_hincog_conv_out3 = ref_hincog_conv_out
  1151. def ref_wallet_chk(self,name):
  1152. wf = os.path.join(ref_dir,cfg['ref_wallet'])
  1153. self.walletchk(name,wf)
  1154. ref_wallet_chk1 = ref_wallet_chk2 = ref_wallet_chk3 = ref_wallet_chk
  1155. def ref_seed_chk(self,name,ext=g.seed_ext):
  1156. wf = os.path.join(ref_dir,"%s.%s" % (cfg['seed_id'],ext))
  1157. desc = "seed data" if ext == g.seed_ext else "mnemonic"
  1158. self.keygen_chksum_chk(name,wf,cfg['seed_id'])
  1159. ref_seed_chk1 = ref_seed_chk2 = ref_seed_chk3 = ref_seed_chk
  1160. def ref_mn_chk(self,name): self.ref_seed_chk(name,ext=g.mn_ext)
  1161. ref_mn_chk1 = ref_mn_chk2 = ref_mn_chk3 = ref_mn_chk
  1162. def ref_brain_chk(self,name,bw_file=ref_bw_file):
  1163. wf = os.path.join(ref_dir,bw_file)
  1164. arg = "-b%s,%s" % (cfg['seed_len'],ref_bw_hash_preset)
  1165. self.keygen_chksum_chk(name,wf,cfg['ref_bw_seed_id'],[arg])
  1166. def keygen_chksum_chk_hincog(self,name,seed_id,hincog_parm):
  1167. t = MMGenExpect(name,"mmgen-keygen", ["-p1","-q","-S","-A"]+hincog_parm+["1"],extra_desc="(check)")
  1168. t.passphrase("",cfg['wpasswd'])
  1169. t.expect("Encrypt key list? (y/N): ","\n")
  1170. t.expect("any printable ASCII symbol.\r\n")
  1171. chk = t.readline()[:8]
  1172. vmsg("Seed ID: %s" % cyan(chk))
  1173. cmp_or_die(seed_id,chk)
  1174. def keygen_chksum_chk(self,name,wf,seed_id,args=[],pw=False):
  1175. hp_arg = ["-p1"] if pw else []
  1176. t = MMGenExpect(name,"mmgen-keygen", ["-q","-S","-A"]+args+hp_arg+[wf,"1"],extra_desc="(check)")
  1177. if pw:
  1178. t.passphrase("",cfg['wpasswd'])
  1179. t.expect("Encrypt key list? (y/N): ","\n")
  1180. t.expect("any printable ASCII symbol.\r\n")
  1181. chk = t.readline()[:8]
  1182. vmsg("Seed ID: %s" % cyan(chk))
  1183. cmp_or_die(seed_id,chk)
  1184. # Use this for encrypted wallets instead of keygen_chksum_chk()
  1185. def walletchk_chksum_chk(self,name,wf,seed_id,uopts=[]):
  1186. t = MMGenExpect(name,"mmgen-walletchk",["-v", wf]+uopts,
  1187. extra_desc="(check)")
  1188. t.passphrase("",cfg['wpasswd'])
  1189. chk = t.expect_getend("Seed ID checksum OK (")[:8]
  1190. t.close()
  1191. cmp_or_die(seed_id,chk)
  1192. ref_brain_chk1 = ref_brain_chk2 = ref_brain_chk3 = ref_brain_chk
  1193. def ref_brain_chk_spc3(self,name):
  1194. self.ref_brain_chk(name,bw_file=ref_bw_file_spc)
  1195. def ref_hincog_chk(self,name):
  1196. for wtype,desc,earg in ('hic_wallet','',[]), \
  1197. ('hic_wallet_old','(old format)',["-o"]):
  1198. ic_arg = "%s,%s,%s" % (
  1199. os.path.join(ref_dir,cfg[wtype]),
  1200. ref_wallet_incog_offset,cfg['seed_len']
  1201. )
  1202. t = MMGenExpect(name,"mmgen-keygen",
  1203. ["-q","-A"]+earg+["-G"]+[ic_arg]+['1'],extra_desc=desc)
  1204. t.passphrase("incognito wallet",cfg['wpasswd'])
  1205. t.hash_preset("incog wallet","1")
  1206. if wtype == 'hic_wallet_old':
  1207. t.expect("Is the seed ID correct? (Y/n): ","\n")
  1208. chk = t.expect_getend("Valid incog data for seed ID ")
  1209. t.close()
  1210. cmp_or_die(cfg['seed_id'],chk)
  1211. ref_hincog_chk1 = ref_hincog_chk2 = ref_hincog_chk3 = ref_hincog_chk
  1212. def ref_addrfile_chk(self,name,ftype="addr"):
  1213. wf = os.path.join(ref_dir,cfg['ref_'+ftype+'file'])
  1214. t = MMGenExpect(name,"mmgen-tool",[ftype+"file_chksum",wf])
  1215. if ftype == "keyaddr":
  1216. w = "key-address file"
  1217. t.hash_preset(w,ref_kafile_hash_preset)
  1218. t.passphrase(w,ref_kafile_pass)
  1219. t.expect("Check key-to-address validity? (y/N): ","y")
  1220. o = t.expect_getend("Checksum for .*address data .*: ",regex=True)
  1221. cmp_or_die(cfg['ref_'+ftype+'file_chksum'],o)
  1222. def ref_keyaddrfile_chk(self,name):
  1223. self.ref_addrfile_chk(name,ftype="keyaddr")
  1224. # def txcreate8(self,name,addrfile):
  1225. # self.txcreate_common(name,sources=['8'])
  1226. def ref_tx_chk(self,name):
  1227. tf = os.path.join(ref_dir,cfg['ref_tx_file'])
  1228. wf = os.path.join(ref_dir,cfg['ref_wallet'])
  1229. self.txsign(name,tf,wf,save=False)
  1230. def ref_tool_decrypt(self,name):
  1231. f = os.path.join(ref_dir,ref_enc_fn)
  1232. t = MMGenExpect(name,"mmgen-tool",
  1233. ["-q","decrypt",f,"outfile=-","hash_preset=1"])
  1234. t.passphrase("user data",tool_enc_passwd)
  1235. t.readline()
  1236. import re
  1237. o = re.sub('\r\n','\n',t.read())
  1238. cmp_or_die(sample_text,o)
  1239. # main()
  1240. if opt.pause:
  1241. import termios,atexit
  1242. fd = sys.stdin.fileno()
  1243. old = termios.tcgetattr(fd)
  1244. def at_exit():
  1245. termios.tcsetattr(fd, termios.TCSADRAIN, old)
  1246. atexit.register(at_exit)
  1247. start_time = int(time.time())
  1248. ts = MMGenTestSuite()
  1249. for cfg in sorted(cfgs): mk_tmpdir(cfgs[cfg])
  1250. try:
  1251. if cmd_args:
  1252. for arg in cmd_args:
  1253. if arg in utils:
  1254. globals()[arg](cmd_args[cmd_args.index(arg)+1:])
  1255. sys.exit()
  1256. elif arg in meta_cmds:
  1257. for cmd in meta_cmds[arg]:
  1258. check_needs_rerun(ts,cmd,build=True)
  1259. elif arg in cmd_groups.keys():
  1260. for cmd in cmd_groups[arg]:
  1261. check_needs_rerun(ts,cmd,build=True)
  1262. elif arg in cmd_data:
  1263. check_needs_rerun(ts,arg,build=True)
  1264. else:
  1265. die(1,"%s: unrecognized command" % arg)
  1266. else:
  1267. clean()
  1268. for cmd in cmd_data:
  1269. ts.do_cmd(cmd)
  1270. if cmd is not cmd_data.keys()[-1]: do_between()
  1271. except:
  1272. sys.stderr = stderr_save
  1273. raise
  1274. t = int(time.time()) - start_time
  1275. sys.stderr.write(green(
  1276. "All requested tests finished OK, elapsed time: %02i:%02i\n"
  1277. % (t/60,t%60)))