test.py 159 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2019 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. test/test.py: Test suite for the MMGen suite
  20. """
  21. import sys,os,subprocess,shutil,time,re,json
  22. from decimal import Decimal
  23. repo_root = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]),os.pardir)))
  24. os.chdir(repo_root)
  25. sys.path.__setitem__(0,repo_root)
  26. try: os.unlink(os.path.join(repo_root,'my.err'))
  27. except: pass
  28. # Import these _after_ local path's been added to sys.path
  29. from mmgen.common import *
  30. from mmgen.test import *
  31. from mmgen.protocol import CoinProtocol,init_coin
  32. def omsg(s): sys.stderr.write(s+'\n')
  33. def omsg_r(s): sys.stderr.write(s)
  34. class TestSuiteException(Exception): pass
  35. class TestSuiteFatalException(Exception): pass
  36. set_debug_all()
  37. g.quiet = False # if 'quiet' was set in config file, disable here
  38. os.environ['MMGEN_QUIET'] = '0' # and for the spawned scripts
  39. log_file = 'test.py_log'
  40. hincog_fn = 'rand_data'
  41. hincog_bytes = 1024*1024
  42. hincog_offset = 98765
  43. hincog_seedlen = 256
  44. incog_id_fn = 'incog_id'
  45. non_mmgen_fn = 'coinkey'
  46. pwfile = 'passwd_file'
  47. ref_dir = os.path.join('test','ref')
  48. rt_pw = 'abc-α'
  49. ref_wallet_brainpass = 'abc'
  50. ref_wallet_hash_preset = '1'
  51. ref_wallet_incog_offset = 123
  52. from mmgen.obj import MMGenTXLabel,PrivKey,ETHAmt
  53. from mmgen.addr import AddrGenerator,KeyGenerator,AddrList,AddrData,AddrIdxList
  54. ref_tx_label_jp = '必要なのは、信用ではなく暗号化された証明に基づく電子取引システムであり、これにより希望する二者が信用できる第三者機関を介さずに直接取引できるよう' # 72 chars ('W'ide)
  55. ref_tx_label_zh = '所以,我們非常需要這樣一種電子支付系統,它基於密碼學原理而不基於信用,使得任何達成一致的雙方,能夠直接進行支付,從而不需要協力廠商仲介的參與。。' # 72 chars ('F'ull + 'W'ide)
  56. ref_tx_label_lat_cyr_gr = ''.join(map(chr,
  57. list(range(65,91)) +
  58. list(range(1040,1072)) + # cyrillic
  59. list(range(913,939)) + # greek
  60. list(range(97,123))))[:MMGenTXLabel.max_len] # 72 chars
  61. ref_bw_hash_preset = '1'
  62. ref_bw_file = 'wallet.mmbrain'
  63. ref_bw_file_spc = 'wallet-spaced.mmbrain'
  64. ref_kafile_pass = 'kafile password'
  65. ref_kafile_hash_preset = '1'
  66. ref_enc_fn = 'sample-text.mmenc'
  67. tool_enc_passwd = "Scrypt it, don't hash it!"
  68. sample_text = \
  69. 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks\n'
  70. chksum_pat = r'\b[A-F0-9]{4} [A-F0-9]{4} [A-F0-9]{4} [A-F0-9]{4}\b'
  71. # Laggy flash media cause pexpect to crash, so create a temporary directory
  72. # under '/dev/shm' and put datadir and temp files here.
  73. shortopts = ''.join([e[1:] for e in sys.argv if len(e) > 1 and e[0] == '-' and e[1] != '-'])
  74. shortopts = ['-'+e for e in list(shortopts)]
  75. data_dir_basename = 'data_dir' + ('','-α')[bool(os.getenv('MMGEN_DEBUG_UTF8'))]
  76. data_dir = os.path.join('test',data_dir_basename)
  77. trash_dir = os.path.join('test','trash')
  78. if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts):
  79. if g.platform == 'win':
  80. for tdir in (data_dir,trash_dir):
  81. try: os.listdir(tdir)
  82. except: pass
  83. else:
  84. try: shutil.rmtree(tdir)
  85. except: # we couldn't remove data dir - perhaps regtest daemon is running
  86. try: subprocess.call(['python3',os.path.join('cmds','mmgen-regtest'),'stop'])
  87. except: rdie(1,"Unable to remove {!r}!".format(tdir))
  88. else:
  89. time.sleep(2)
  90. shutil.rmtree(tdir)
  91. os.mkdir(tdir,0o755)
  92. else:
  93. d,pfx = '/dev/shm','mmgen-test-'
  94. try:
  95. subprocess.call('rm -rf {}/{}*'.format(d,pfx),shell=True)
  96. except Exception as e:
  97. die(2,'Unable to delete directory tree {}/{}* ({})'.format(d,pfx,e.args[0]))
  98. try:
  99. import tempfile
  100. shm_dir = str(tempfile.mkdtemp('',pfx,d))
  101. except Exception as e:
  102. die(2,'Unable to create temporary directory in {} ({})'.format(d,e.args[0]))
  103. for tdir in (data_dir,trash_dir):
  104. dd = os.path.join(shm_dir,os.path.basename(tdir))
  105. os.mkdir(dd,0o755)
  106. try: os.unlink(tdir)
  107. except: pass
  108. os.symlink(dd,tdir)
  109. opts_data = lambda: {
  110. 'desc': 'Test suite for the MMGen suite',
  111. 'usage':'[options] [command(s) or metacommand(s)]',
  112. 'options': """
  113. -h, --help Print this help message
  114. --, --longhelp Print help message for long options (common options)
  115. -B, --bech32 Generate and use Bech32 addresses
  116. -b, --buf-keypress Use buffered keypresses as with real human input
  117. (often required on slow systems, or under emulation)
  118. -c, --print-cmdline Print the command line of each spawned command
  119. -C, --coverage Produce code coverage info using trace module
  120. -x, --debug-pexpect Produce debugging output for pexpect calls
  121. -D, --no-daemon-stop Don't stop auto-started daemons after running tests
  122. -E, --direct-exec Bypass pexpect and execute a command directly (for
  123. debugging only)
  124. -e, --exact-output Show the exact output of the MMGen script(s) being run
  125. -l, --list-cmds List and describe the commands in the test suite
  126. -L, --list-cmd-groups Output a list of command groups, with no descriptions
  127. -n, --names Display command names instead of descriptions
  128. -o, --log Log commands to file {lf}
  129. -O, --popen-spawn Use pexpect's popen_spawn instead of popen
  130. -p, --pause Pause between tests, resuming on keypress
  131. -P, --profile Record the execution time of each script
  132. -q, --quiet Produce minimal output. Suppress dependency info
  133. -r, --resume=c Resume at command 'c' after interrupted run
  134. -s, --system Test scripts and modules installed on system rather
  135. than those in the repo root
  136. -S, --skip-deps Skip dependency checking for command
  137. -u, --usr-random Get random data interactively from user
  138. -t, --traceback Run the command inside the '{tbc}' script
  139. -v, --verbose Produce more verbose output
  140. -W, --no-dw-delete Don't remove default wallet from data dir after dw tests are done
  141. -X, --exit-after=C Exit after command 'C'
  142. -y, --segwit Generate and use Segwit addresses
  143. -Y, --segwit-random Generate and use a random mix of Segwit and Legacy addrs
  144. """.format(tbc='scripts/traceback_run.py',lf=log_file),
  145. 'notes': """
  146. If no command is given, the whole suite of tests is run.
  147. """
  148. }
  149. sys.argv = [sys.argv[0]] + ['--data-dir',data_dir] + sys.argv[1:]
  150. cmd_args = opts.init(opts_data)
  151. # Under python3, with PopenSpawn we can no longer imitate cbreak mode with sys.stdin.read(1)
  152. # opt.popen_spawn = True # popen has issues, so use popen_spawn always
  153. if not opt.system: os.environ['PYTHONPATH'] = repo_root
  154. lbl_id = ('account','label')[g.coin=='BTC'] # update as other coins adopt Core's label API
  155. ref_subdir = '' if g.proto.base_coin == 'BTC' else 'ethereum_classic' if g.coin == 'ETC' else g.proto.name
  156. altcoin_pfx = '' if g.proto.base_coin == 'BTC' else '-'+g.proto.base_coin
  157. tn_ext = ('','.testnet')[g.testnet]
  158. coin_sel = g.coin.lower()
  159. if g.coin.lower() in ('eth','etc'): coin_sel = 'btc'
  160. fork = {'bch':'btc','btc':'btc','ltc':'ltc'}[coin_sel]
  161. tx_fee = {'btc':'0.0001','bch':'0.001','ltc':'0.01'}[coin_sel]
  162. txbump_fee = {'btc':'123s','bch':'567s','ltc':'12345s'}[coin_sel]
  163. rtFundAmt = {'btc':'500','bch':'500','ltc':'5500'}[coin_sel]
  164. rtFee = {
  165. 'btc': ('20s','10s','60s','31s','10s','20s'),
  166. 'bch': ('20s','10s','60s','0.0001','10s','20s'),
  167. 'ltc': ('1000s','500s','1500s','0.05','400s','1000s')
  168. }[coin_sel]
  169. rtBals = {
  170. 'btc': ('499.9999488','399.9998282','399.9998147','399.9996877',
  171. '52.99990000','946.99933647','999.99923647','52.9999','946.99933647'),
  172. 'bch': ('499.9999484','399.9999194','399.9998972','399.9997692',
  173. '46.78900000','953.20966920','999.99866920','46.789','953.2096692'),
  174. 'ltc': ('5499.99744','5399.994425','5399.993885','5399.987535',
  175. '52.99000000','10946.93753500','10999.92753500','52.99','10946.937535'),
  176. }[coin_sel]
  177. rtBals_gb = {
  178. 'btc': ('116.77629233','283.22339537'),
  179. 'bch': ('116.77637483','283.22339437'),
  180. 'ltc': ('5116.77036263','283.21717237')
  181. }[coin_sel]
  182. rtBobOp3 = {'btc':'S:2','bch':'L:3','ltc':'S:2'}[coin_sel]
  183. if opt.segwit and 'S' not in g.proto.mmtypes:
  184. die(1,'--segwit option incompatible with {}'.format(g.proto.__name__))
  185. if opt.bech32 and 'B' not in g.proto.mmtypes:
  186. die(1,'--bech32 option incompatible with {}'.format(g.proto.__name__))
  187. def randbool():
  188. return hexlify(os.urandom(1))[1] in b'12345678'
  189. def get_segwit_bool():
  190. return randbool() if opt.segwit_random else True if opt.segwit or opt.bech32 else False
  191. def disable_debug():
  192. global save_debug
  193. save_debug = {}
  194. for k in g.env_opts:
  195. if k[:11] == 'MMGEN_DEBUG':
  196. save_debug[k] = os.getenv(k)
  197. os.environ[k] = ''
  198. def restore_debug():
  199. for k in save_debug:
  200. os.environ[k] = save_debug[k] or ''
  201. cfgs = {
  202. '15': {
  203. 'tmpdir': os.path.join('test','tmp15'),
  204. 'wpasswd': 'Dorian-α',
  205. 'kapasswd': 'Grok the blockchain',
  206. 'addr_idx_list': '12,99,5-10,5,12', # 8 addresses
  207. 'dep_generators': {
  208. pwfile: 'walletgen_dfl_wallet',
  209. 'addrs': 'addrgen_dfl_wallet',
  210. 'rawtx': 'txcreate_dfl_wallet',
  211. 'sigtx': 'txsign_dfl_wallet',
  212. 'mmseed': 'export_seed_dfl_wallet',
  213. 'del_dw_run': 'delete_dfl_wallet',
  214. },
  215. 'segwit': get_segwit_bool()
  216. },
  217. '16': {
  218. 'tmpdir': os.path.join('test','tmp16'),
  219. 'wpasswd': 'My changed password',
  220. 'hash_preset': '2',
  221. 'dep_generators': {
  222. pwfile: 'passchg_dfl_wallet',
  223. },
  224. 'segwit': get_segwit_bool()
  225. },
  226. '17': { 'tmpdir': os.path.join('test','tmp17') },
  227. '18': { 'tmpdir': os.path.join('test','tmp18') },
  228. # '19': { 'tmpdir': os.path.join(u'test',u'tmp19'), 'wpasswd':'abc' }, B2X
  229. '31': { 'tmpdir': os.path.join('test','tmp31'), # L
  230. 'addr_idx_list':'1-2', 'segwit': False,
  231. 'dep_generators': {'addrs':'ref_tx_addrgen1'} },
  232. '32': { 'tmpdir': os.path.join('test','tmp32'), # C
  233. 'addr_idx_list':'1-2', 'segwit': False,
  234. 'dep_generators': {'addrs':'ref_tx_addrgen2'} },
  235. '33': { 'tmpdir': os.path.join('test','tmp33'), # S
  236. 'addr_idx_list':'1-2', 'segwit': True,
  237. 'dep_generators': {'addrs':'ref_tx_addrgen3'} },
  238. '34': { 'tmpdir': os.path.join('test','tmp34'), # B
  239. 'addr_idx_list':'1-2', 'segwit': True,
  240. 'dep_generators': {'addrs':'ref_tx_addrgen4'} },
  241. '1': {
  242. 'tmpdir': os.path.join('test','tmp1'),
  243. 'wpasswd': 'Dorian-α',
  244. 'kapasswd': 'Grok the blockchain',
  245. 'addr_idx_list': '12,99,5-10,5,12', # 8 addresses
  246. 'dep_generators': {
  247. pwfile: 'walletgen',
  248. 'mmdat': 'walletgen',
  249. 'addrs': 'addrgen',
  250. 'rawtx': 'txcreate',
  251. 'txbump': 'txbump',
  252. 'sigtx': 'txsign',
  253. 'mmwords': 'export_mnemonic',
  254. 'mmseed': 'export_seed',
  255. 'mmhex': 'export_hex',
  256. 'mmincog': 'export_incog',
  257. 'mmincox': 'export_incog_hex',
  258. hincog_fn: 'export_incog_hidden',
  259. incog_id_fn: 'export_incog_hidden',
  260. 'akeys.mmenc': 'keyaddrgen'
  261. },
  262. 'segwit': get_segwit_bool()
  263. },
  264. '2': {
  265. 'tmpdir': os.path.join('test','tmp2'),
  266. 'wpasswd': 'Hodling away',
  267. 'addr_idx_list': '37,45,3-6,22-23', # 8 addresses
  268. 'seed_len': 128,
  269. 'dep_generators': {
  270. 'mmdat': 'walletgen2',
  271. 'addrs': 'addrgen2',
  272. 'rawtx': 'txcreate2',
  273. 'sigtx': 'txsign2',
  274. 'mmwords': 'export_mnemonic2',
  275. },
  276. 'segwit': get_segwit_bool()
  277. },
  278. '20': {
  279. 'tmpdir': os.path.join('test','tmp20'),
  280. 'wpasswd': 'Vsize it',
  281. 'addr_idx_list': '1-8', # 8 addresses
  282. 'seed_len': 256,
  283. 'dep_generators': {
  284. 'mmdat': 'walletgen5',
  285. 'addrs': 'addrgen5',
  286. 'rawtx': 'txcreate5',
  287. 'sigtx': 'txsign5',
  288. },
  289. 'segwit': get_segwit_bool()
  290. },
  291. '21': {
  292. 'tmpdir': os.path.join('test','tmp21'),
  293. 'wpasswd': 'Vsize it',
  294. 'addr_idx_list': '1-8', # 8 addresses
  295. 'seed_len': 256,
  296. 'dep_generators': {
  297. 'mmdat': 'walletgen6',
  298. 'addrs': 'addrgen6',
  299. 'rawtx': 'txcreate6',
  300. 'sigtx': 'txsign6',
  301. },
  302. 'segwit': get_segwit_bool()
  303. },
  304. '22': {
  305. 'tmpdir': os.path.join('test','tmp22'),
  306. 'parity_pidfile': 'parity.pid',
  307. 'parity_keyfile': 'parity.devkey',
  308. },
  309. '3': {
  310. 'tmpdir': os.path.join('test','tmp3'),
  311. 'wpasswd': 'Major miner',
  312. 'addr_idx_list': '73,54,1022-1023,2-5', # 8 addresses
  313. 'dep_generators': {
  314. 'mmdat': 'walletgen3',
  315. 'addrs': 'addrgen3',
  316. 'rawtx': 'txcreate3',
  317. 'sigtx': 'txsign3'
  318. },
  319. 'segwit': get_segwit_bool()
  320. },
  321. '4': {
  322. 'tmpdir': os.path.join('test','tmp4'),
  323. 'wpasswd': 'Hashrate good',
  324. 'addr_idx_list': '63,1004,542-544,7-9', # 8 addresses
  325. 'seed_len': 192,
  326. 'dep_generators': {
  327. 'mmdat': 'walletgen4',
  328. 'mmbrain': 'walletgen4',
  329. 'addrs': 'addrgen4',
  330. 'rawtx': 'txcreate4',
  331. 'sigtx': 'txsign4',
  332. 'txdo': 'txdo4',
  333. },
  334. 'bw_filename': 'brainwallet.mmbrain',
  335. 'bw_params': '192,1',
  336. 'segwit': get_segwit_bool()
  337. },
  338. '14': {
  339. 'kapasswd': 'Maxwell',
  340. 'tmpdir': os.path.join('test','tmp14'),
  341. 'wpasswd': 'The Halving',
  342. 'addr_idx_list': '61,998,502-504,7-9', # 8 addresses
  343. 'seed_len': 256,
  344. 'dep_generators': {
  345. 'mmdat': 'walletgen14',
  346. 'addrs': 'addrgen14',
  347. 'akeys.mmenc': 'keyaddrgen14',
  348. },
  349. 'segwit': get_segwit_bool()
  350. },
  351. '5': {
  352. 'tmpdir': os.path.join('test','tmp5'),
  353. 'wpasswd': 'My changed password-α',
  354. 'hash_preset': '2',
  355. 'dep_generators': {
  356. 'mmdat': 'passchg',
  357. pwfile: 'passchg',
  358. },
  359. 'segwit': get_segwit_bool()
  360. },
  361. '6': {
  362. 'name': 'reference wallet check (128-bit)',
  363. 'seed_len': 128,
  364. 'seed_id': 'FE3C6545',
  365. 'ref_bw_seed_id': '33F10310',
  366. 'addrfile_chk': {
  367. 'btc': ('B230 7526 638F 38CB','A9DC 5A13 12CB 1317'),
  368. 'ltc': ('2B23 5E97 848A B961','AEC3 E774 0B21 0202'),
  369. },
  370. 'addrfile_segwit_chk': {
  371. 'btc': ('9914 6D10 2307 F348','83C8 A6B6 ADA8 25B2'),
  372. 'ltc': ('CC09 A190 B7DF B7CD','0425 7893 C6F1 ECA3'),
  373. },
  374. 'addrfile_bech32_chk': {
  375. 'btc': ('C529 D686 31AA ACD4','21D0 26AD 3A22 5465'),
  376. 'ltc': ('3DFB CFCC E180 DC9D','8C72 D5C2 07E0 5F7B'),
  377. },
  378. 'addrfile_compressed_chk': {
  379. 'btc': ('95EB 8CC0 7B3B 7856','16E6 6170 154D 2202'),
  380. 'ltc': ('35D5 8ECA 9A42 46C3','15B3 5492 D3D3 6854'),
  381. },
  382. 'keyaddrfile_chk': {
  383. 'btc': ('CF83 32FB 8A8B 08E2','1F67 B73A FF8C 5D15'),
  384. 'ltc': ('1896 A26C 7F14 2D01','FA0E CD4E ADAF DBF4'),
  385. },
  386. 'keyaddrfile_segwit_chk': {
  387. 'btc': ('C13B F717 D4E8 CF59','BB71 175C 5416 19D8'),
  388. 'ltc': ('054B 9794 55B4 5D82','DE85 3CF3 9636 FE2E'),
  389. },
  390. 'keyaddrfile_bech32_chk': {
  391. 'btc': ('934F 1C33 6C06 B18C','A283 5BAB 7AF3 3EA4'),
  392. 'ltc': ('A6AD DF53 5968 7B6A','9572 43E0 A4DC 0B2E'),
  393. },
  394. 'keyaddrfile_compressed_chk': {
  395. 'btc': ('E43A FA46 5751 720A','FDEE 8E45 1C0A 02AD'),
  396. 'ltc': ('7603 2FE3 2145 FFAD','3FE0 5A8E 5FBE FF3E'),
  397. },
  398. 'passfile_chk': 'EB29 DC4F 924B 289F',
  399. 'passfile32_chk': '37B6 C218 2ABC 7508',
  400. 'passfilehex_chk': '523A F547 0E69 8323',
  401. 'wpasswd': 'reference password',
  402. 'ref_wallet': 'FE3C6545-D782B529[128,1].mmdat',
  403. 'ic_wallet': 'FE3C6545-E29303EA-5E229E30[128,1].mmincog',
  404. 'ic_wallet_hex': 'FE3C6545-BC4BE3F2-32586837[128,1].mmincox',
  405. 'hic_wallet': 'FE3C6545-161E495F-BEB7548E[128,1].incog-offset123',
  406. 'hic_wallet_old': 'FE3C6545-161E495F-9860A85B[128,1].incog-old.offset123',
  407. 'tmpdir': os.path.join('test','tmp6'),
  408. 'kapasswd': '',
  409. 'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
  410. 'pass_idx_list': '1,4,9-11,1100',
  411. 'dep_generators': {
  412. 'mmdat': 'refwalletgen1',
  413. pwfile: 'refwalletgen1',
  414. 'addrs': 'refaddrgen1',
  415. 'akeys.mmenc': 'refkeyaddrgen1'
  416. },
  417. 'segwit': get_segwit_bool()
  418. },
  419. '7': {
  420. 'name': 'reference wallet check (192-bit)',
  421. 'seed_len': 192,
  422. 'seed_id': '1378FC64',
  423. 'ref_bw_seed_id': 'CE918388',
  424. 'addrfile_chk': {
  425. 'btc': ('8C17 A5FA 0470 6E89','764C 66F9 7502 AAEA'),
  426. 'ltc': ('2B77 A009 D5D0 22AD','51D1 979D 0A35 F24B'),
  427. },
  428. 'addrfile_segwit_chk': {
  429. 'btc': ('91C4 0414 89E4 2089','BF9F C67F ED22 A47B'),
  430. 'ltc': ('8F12 FA7B 9F12 594C','2609 8494 A23C F836'),
  431. },
  432. 'addrfile_bech32_chk': {
  433. 'btc': ('2AA3 78DF B965 82EB','027B 1C1F 7FB2 D859'),
  434. 'ltc': ('951C 8FB2 FCA5 87D1','4A5D 67E0 8210 FEF2'),
  435. },
  436. 'addrfile_compressed_chk': {
  437. 'btc': ('2615 8401 2E98 7ECA','A386 EE07 A356 906D'),
  438. 'ltc': ('197C C48C 3C37 AB0F','8DDC 5FE3 BFF9 1226'),
  439. },
  440. 'keyaddrfile_chk': {
  441. 'btc': ('9648 5132 B98E 3AD9','1BD3 5A36 D51C 256D'),
  442. 'ltc': ('DBD4 FAB6 7E46 CD07','8822 3FDF FEC0 6A8C'),
  443. },
  444. 'keyaddrfile_segwit_chk': {
  445. 'btc': ('C98B DF08 A3D5 204B','7E7F DF50 FE04 6F68'),
  446. 'ltc': ('1829 7FE7 2567 CB91','BE92 D19C 7589 EF30'),
  447. },
  448. 'keyaddrfile_bech32_chk': {
  449. 'btc': ('4A6B 3762 DF30 9368','12DD 1888 36BA 85F7'),
  450. 'ltc': ('5C12 FDD4 17AB F179','E195 B28C 59C4 C5EC'),
  451. },
  452. 'keyaddrfile_compressed_chk': {
  453. 'btc': ('6D6D 3D35 04FD B9C3','94BF 4BCF 10B2 394B'),
  454. 'ltc': ('F5DA 9D60 6798 C4E9','7918 88DE 9096 DD7A'),
  455. },
  456. 'passfile_chk': 'ADEA 0083 094D 489A',
  457. 'passfile32_chk': '2A28 C5C7 36EC 217A',
  458. 'passfilehex_chk': 'B11C AC6A 1464 608D',
  459. 'wpasswd': 'reference password',
  460. 'ref_wallet': '1378FC64-6F0F9BB4[192,1].mmdat',
  461. 'ic_wallet': '1378FC64-2907DE97-F980D21F[192,1].mmincog',
  462. 'ic_wallet_hex': '1378FC64-4DCB5174-872806A7[192,1].mmincox',
  463. 'hic_wallet': '1378FC64-B55E9958-77256FC1[192,1].incog.offset123',
  464. 'hic_wallet_old': '1378FC64-B55E9958-D85FF20C[192,1].incog-old.offset123',
  465. 'tmpdir': os.path.join('test','tmp7'),
  466. 'kapasswd': '',
  467. 'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
  468. 'pass_idx_list': '1,4,9-11,1100',
  469. 'dep_generators': {
  470. 'mmdat': 'refwalletgen2',
  471. pwfile: 'refwalletgen2',
  472. 'addrs': 'refaddrgen2',
  473. 'akeys.mmenc': 'refkeyaddrgen2'
  474. },
  475. 'segwit': get_segwit_bool()
  476. },
  477. '8': {
  478. 'name': 'reference wallet check (256-bit)',
  479. 'seed_len': 256,
  480. 'seed_id': '98831F3A',
  481. 'ref_bw_seed_id': 'B48CD7FC',
  482. 'addrfile_chk': {
  483. 'btc': ('6FEF 6FB9 7B13 5D91','424E 4326 CFFE 5F51'),
  484. 'ltc': ('AD52 C3FE 8924 AAF0','4EBE 2E85 E969 1B30'),
  485. },
  486. 'addrfile_segwit_chk': {
  487. 'btc': ('06C1 9C87 F25C 4EE6','072C 8B07 2730 CB7A'),
  488. 'ltc': ('63DF E42A 0827 21C3','5DD1 D186 DBE1 59F2'),
  489. },
  490. 'addrfile_bech32_chk': {
  491. 'btc': ('9D2A D4B6 5117 F02E','0527 9C39 6C1B E39A'),
  492. 'ltc': ('FF1C 7939 5967 AB82','ED3D 8AA4 BED4 0B40'),
  493. },
  494. 'addrfile_compressed_chk': {
  495. 'btc': ('A33C 4FDE F515 F5BC','6C48 AA57 2056 C8C8'),
  496. 'ltc': ('3FC0 8F03 C2D6 BD19','4C0A 49B6 2DD1 1BE0'),
  497. },
  498. 'keyaddrfile_chk': {
  499. 'btc': ('9F2D D781 1812 8BAD','88CC 5120 9A91 22C2'),
  500. 'ltc': ('B804 978A 8796 3ED4','98B5 AC35 F334 0398'),
  501. },
  502. 'keyaddrfile_segwit_chk': {
  503. 'btc': ('A447 12C2 DD14 5A9B','C770 7391 C415 21F9'),
  504. 'ltc': ('E8A3 9F6E E164 A521','D3D5 BFDD F5D5 20BD'),
  505. },
  506. 'keyaddrfile_bech32_chk': {
  507. 'btc': ('D0DD BDE3 87BE 15AE','7552 D70C AAB8 DEAA'),
  508. 'ltc': ('74A0 7DD5 963B 6326','2CDA A007 4B9F E9A5'),
  509. },
  510. 'keyaddrfile_compressed_chk': {
  511. 'btc': ('420A 8EB5 A9E2 7814','F43A CB4A 81F3 F735'),
  512. 'ltc': ('8D1C 781F EB7F 44BC','05F3 5C68 FD31 FCEF'),
  513. },
  514. 'passfile_chk': '2D6D 8FBA 422E 1315',
  515. 'passfile32_chk': 'F6C1 CDFB 97D9 FCAE',
  516. 'passfilehex_chk': 'BD4F A0AC 8628 4BE4',
  517. 'wpasswd': 'reference password',
  518. 'ref_wallet': '98831F3A-{}[256,1].mmdat'.format(('27F2BF93','E2687906')[g.testnet]),
  519. 'ref_addrfile': '98831F3A{}[1,31-33,500-501,1010-1011]{}.addrs',
  520. 'ref_segwitaddrfile':'98831F3A{}-S[1,31-33,500-501,1010-1011]{}.addrs',
  521. 'ref_bech32addrfile':'98831F3A{}-B[1,31-33,500-501,1010-1011]{}.addrs',
  522. 'ref_keyaddrfile': '98831F3A{}[1,31-33,500-501,1010-1011]{}.akeys.mmenc',
  523. 'ref_passwdfile': '98831F3A-фубар@crypto.org-b58-20[1,4,9-11,1100].pws',
  524. 'ref_addrfile_chksum': {
  525. 'btc': ('6FEF 6FB9 7B13 5D91','424E 4326 CFFE 5F51'),
  526. 'ltc': ('AD52 C3FE 8924 AAF0','4EBE 2E85 E969 1B30'),
  527. },
  528. 'ref_segwitaddrfile_chksum': {
  529. 'btc': ('06C1 9C87 F25C 4EE6','072C 8B07 2730 CB7A'),
  530. 'ltc': ('63DF E42A 0827 21C3','5DD1 D186 DBE1 59F2'),
  531. },
  532. 'ref_bech32addrfile_chksum': {
  533. 'btc': ('9D2A D4B6 5117 F02E','0527 9C39 6C1B E39A'),
  534. 'ltc': ('FF1C 7939 5967 AB82','ED3D 8AA4 BED4 0B40'),
  535. },
  536. 'ref_keyaddrfile_chksum': {
  537. 'btc': ('9F2D D781 1812 8BAD','88CC 5120 9A91 22C2'),
  538. 'ltc': ('B804 978A 8796 3ED4','98B5 AC35 F334 0398'),
  539. },
  540. 'ref_addrfile_chksum_zec': '903E 7225 DD86 6E01',
  541. 'ref_addrfile_chksum_zec_z': '9C7A 72DC 3D4A B3AF',
  542. 'ref_addrfile_chksum_xmr': '4369 0253 AC2C 0E38',
  543. 'ref_addrfile_chksum_dash':'FBC1 6B6A 0988 4403',
  544. 'ref_addrfile_chksum_eth': 'E554 076E 7AF6 66A3',
  545. 'ref_addrfile_chksum_etc': 'E97A D796 B495 E8BC',
  546. 'ref_keyaddrfile_chksum_zec': 'F05A 5A5C 0C8E 2617',
  547. 'ref_keyaddrfile_chksum_zec_z': '6B87 9B2D 0D8D 8D1E',
  548. 'ref_keyaddrfile_chksum_xmr': 'E0D7 9612 3D67 404A',
  549. 'ref_keyaddrfile_chksum_dash': 'E83D 2C63 FEA2 4142',
  550. 'ref_keyaddrfile_chksum_eth': 'E400 70D9 0AE3 C7C2',
  551. 'ref_keyaddrfile_chksum_etc': 'EF49 967D BD6C FE45',
  552. 'ref_passwdfile_chksum': 'A983 DAB9 5514 27FB',
  553. 'ref_tx_file': {
  554. 'btc': ('0B8D5A[15.31789,14,tl=1320969600].rawtx',
  555. '0C7115[15.86255,14,tl=1320969600].testnet.rawtx'),
  556. 'bch': ('460D4D-BCH[10.19764,tl=1320969600].rawtx',
  557. '359FD5-BCH[6.68868,tl=1320969600].testnet.rawtx'),
  558. 'ltc': ('AF3CDF-LTC[620.76194,1453,tl=1320969600].rawtx',
  559. 'A5A1E0-LTC[1454.64322,1453,tl=1320969600].testnet.rawtx'),
  560. 'eth': ('88FEFD-ETH[23.45495,40000].rawtx',
  561. 'B472BD-ETH[23.45495,40000].testnet.rawtx'),
  562. 'erc20': ('5881D2-MM1[1.23456,50000].rawtx',
  563. '6BDB25-MM1[1.23456,50000].testnet.rawtx'),
  564. 'etc': ('ED3848-ETC[1.2345,40000].rawtx','')
  565. },
  566. 'ic_wallet': '98831F3A-5482381C-18460FB1[256,1].mmincog',
  567. 'ic_wallet_hex': '98831F3A-1630A9F2-870376A9[256,1].mmincox',
  568. 'hic_wallet': '98831F3A-F59B07A0-559CEF19[256,1].incog.offset123',
  569. 'hic_wallet_old': '98831F3A-F59B07A0-848535F3[256,1].incog-old.offset123',
  570. 'tmpdir': os.path.join('test','tmp8'),
  571. 'kapasswd': '',
  572. 'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
  573. 'pass_idx_list': '1,4,9-11,1100',
  574. 'dep_generators': {
  575. 'mmdat': 'refwalletgen3',
  576. pwfile: 'refwalletgen3',
  577. 'addrs': 'refaddrgen3',
  578. 'akeys.mmenc': 'refkeyaddrgen3'
  579. },
  580. 'segwit': get_segwit_bool()
  581. },
  582. '9': {
  583. 'tmpdir': os.path.join('test','tmp9'),
  584. 'tool_enc_infn': 'tool_encrypt.in',
  585. # 'tool_enc_ref_infn': 'tool_encrypt_ref.in',
  586. 'wpasswd': 'reference password',
  587. 'dep_generators': {
  588. 'tool_encrypt.in': 'tool_encrypt',
  589. 'tool_encrypt.in.mmenc': 'tool_encrypt',
  590. # 'tool_encrypt_ref.in': 'tool_encrypt_ref',
  591. # 'tool_encrypt_ref.in.mmenc': 'tool_encrypt_ref',
  592. },
  593. },
  594. }
  595. dfl_words = os.path.join(ref_dir,cfgs['8']['seed_id']+'.mmwords')
  596. eth_rem_addrs = ('4','1')
  597. if g.coin in ('ETH','ETC'):
  598. # The Parity dev address with lots of coins. Create with "ethkey -b info ''":
  599. eth_addr = '00a329c0648769a73afac7f9381e08fb43dbea72'
  600. eth_addr_chk = '00a329c0648769A73afAc7F9381E08FB43dBEA72'
  601. eth_key = '4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7'
  602. eth_burn_addr = 'deadbeef'*5
  603. eth_amt1 = '999999.12345689012345678'
  604. eth_amt2 = '888.111122223333444455'
  605. # Token sends require varying amounts of gas, depending on compiler version
  606. solc_ver = re.search(r'Version:\s*(.*)',
  607. subprocess.Popen(['solc','--version'],stdout=subprocess.PIPE
  608. ).stdout.read().decode()).group(1)
  609. if re.match(r'\b0.5.1\b',solc_ver): # Raspbian Stretch
  610. vbal1 = '1.2288337'
  611. vbal2 = '99.997085083'
  612. vbal3 = '1.23142165'
  613. vbal4 = '127.0287837'
  614. elif re.match(r'\b0.5.3\b',solc_ver): # Ubuntu Bionic
  615. vbal1 = '1.2288487'
  616. vbal2 = '99.997092733'
  617. vbal3 = '1.23142915'
  618. vbal4 = '127.0287987'
  619. eth_bals = {
  620. '1': [ ('98831F3A:E:1','123.456')],
  621. '2': [ ('98831F3A:E:1','123.456'),('98831F3A:E:11','1.234')],
  622. '3': [ ('98831F3A:E:1','123.456'),('98831F3A:E:11','1.234'),('98831F3A:E:21','2.345')],
  623. '4': [ ('98831F3A:E:1','100'),
  624. ('98831F3A:E:2','23.45495'),
  625. ('98831F3A:E:11','1.234'),
  626. ('98831F3A:E:21','2.345')],
  627. '5': [ ('98831F3A:E:1','100'),
  628. ('98831F3A:E:2','23.45495'),
  629. ('98831F3A:E:11','1.234'),
  630. ('98831F3A:E:21','2.345'),
  631. (eth_burn_addr + '\s+Non-MMGen',eth_amt1)],
  632. '8': [ ('98831F3A:E:1','0'),
  633. ('98831F3A:E:2','23.45495'),
  634. ('98831F3A:E:11',vbal1,'a'),
  635. ('98831F3A:E:12','99.99895'),
  636. ('98831F3A:E:21','2.345'),
  637. (eth_burn_addr + '\s+Non-MMGen',eth_amt1)],
  638. '9': [ ('98831F3A:E:1','0'),
  639. ('98831F3A:E:2','23.45495'),
  640. ('98831F3A:E:11',vbal1,'a'),
  641. ('98831F3A:E:12',vbal2),
  642. ('98831F3A:E:21','2.345'),
  643. (eth_burn_addr + '\s+Non-MMGen',eth_amt1)]
  644. }
  645. eth_token_bals = {
  646. '1': [ ('98831F3A:E:11','1000','1.234')],
  647. '2': [ ('98831F3A:E:11','998.76544',vbal3,'a'),
  648. ('98831F3A:E:12','1.23456','0')],
  649. '3': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
  650. ('98831F3A:E:12','1.23456','0')],
  651. '4': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
  652. ('98831F3A:E:12','1.23456','0'),
  653. (eth_burn_addr + '\s+Non-MMGen',eth_amt2,eth_amt1)],
  654. '5': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
  655. ('98831F3A:E:12','1.23456','99.99895'),
  656. (eth_burn_addr + '\s+Non-MMGen',eth_amt2,eth_amt1)],
  657. '6': [ ('98831F3A:E:11','110.654317776666555545',vbal1,'a'),
  658. ('98831F3A:E:12','0',vbal2),
  659. ('98831F3A:E:13','1.23456','0'),
  660. (eth_burn_addr + '\s+Non-MMGen',eth_amt2,eth_amt1)]
  661. }
  662. eth_token_bals_getbalance = {
  663. '1': (vbal4,'999999.12345689012345678'),
  664. '2': ('111.888877776666555545','888.111122223333444455')
  665. }
  666. def eth_args():
  667. if g.coin not in ('ETH','ETC'):
  668. raise TestSuiteException('for ethdev tests, --coin must be set to either ETH or ETC')
  669. return ['--outdir={}'.format(cfgs['22']['tmpdir']),'--rpc-port=8549','--quiet']
  670. from copy import deepcopy
  671. for a,b in (('6','11'),('7','12'),('8','13')):
  672. cfgs[b] = deepcopy(cfgs[a])
  673. cfgs[b]['tmpdir'] = os.path.join('test','tmp'+b)
  674. if g.debug_utf8:
  675. for k in cfgs: cfgs[k]['tmpdir'] += '-α'
  676. from collections import OrderedDict
  677. cmd_group = OrderedDict()
  678. cmd_group['help'] = OrderedDict([
  679. # test description depends
  680. ['helpscreens', (1,'help screens', [])],
  681. ['longhelpscreens', (1,'help screens (--longhelp)',[])],
  682. ])
  683. cmd_group['dfl_wallet'] = OrderedDict([
  684. ['walletgen_dfl_wallet', (15,'wallet generation (default wallet)',[[[],15]])],
  685. ['export_seed_dfl_wallet',(15,'seed export to mmseed format (default wallet)',[[[pwfile],15]])],
  686. ['addrgen_dfl_wallet',(15,'address generation (default wallet)',[[[pwfile],15]])],
  687. ['txcreate_dfl_wallet',(15,'transaction creation (default wallet)',[[['addrs'],15]])],
  688. ['txsign_dfl_wallet',(15,'transaction signing (default wallet)',[[['rawtx',pwfile],15]])],
  689. ['passchg_dfl_wallet',(16,'password, label and hash preset change (default wallet)',[[[pwfile],15]])],
  690. ['walletchk_newpass_dfl_wallet',(16,'wallet check with new pw, label and hash preset',[[[pwfile],16]])],
  691. ['delete_dfl_wallet',(15,'delete default wallet',[[[pwfile],15]])],
  692. ])
  693. cmd_group['main'] = OrderedDict([
  694. ['walletgen', (1,'wallet generation', [[['del_dw_run'],15]])],
  695. # ['walletchk', (1,'wallet check', [[['mmdat'],1]])],
  696. ['passchg', (5,'password, label and hash preset change',[[['mmdat',pwfile],1]])],
  697. ['passchg_keeplabel',(5,'password, label and hash preset change (keep label)',[[['mmdat',pwfile],1]])],
  698. ['passchg_usrlabel',(5,'password, label and hash preset change (interactive label)',[[['mmdat',pwfile],1]])],
  699. ['walletchk_newpass',(5,'wallet check with new pw, label and hash preset',[[['mmdat',pwfile],5]])],
  700. ['addrgen', (1,'address generation', [[['mmdat',pwfile],1]])],
  701. ['txcreate', (1,'transaction creation', [[['addrs'],1]])],
  702. ['txbump', (1,'transaction fee bumping (no send)',[[['rawtx'],1]])],
  703. ['txsign', (1,'transaction signing', [[['mmdat','rawtx',pwfile,'txbump'],1]])],
  704. ['txsend', (1,'transaction sending', [[['sigtx'],1]])],
  705. # txdo must go after txsign
  706. ['txdo', (1,'online transaction', [[['sigtx','mmdat'],1]])],
  707. ['export_hex', (1,'seed export to hexadecimal format', [[['mmdat'],1]])],
  708. ['export_seed', (1,'seed export to mmseed format', [[['mmdat'],1]])],
  709. ['export_mnemonic', (1,'seed export to mmwords format', [[['mmdat'],1]])],
  710. ['export_incog', (1,'seed export to mmincog format', [[['mmdat'],1]])],
  711. ['export_incog_hex',(1,'seed export to mmincog hex format', [[['mmdat'],1]])],
  712. ['export_incog_hidden',(1,'seed export to hidden mmincog format', [[['mmdat'],1]])],
  713. ['addrgen_hex', (1,'address generation from mmhex file', [[['mmhex','addrs'],1]])],
  714. ['addrgen_seed', (1,'address generation from mmseed file', [[['mmseed','addrs'],1]])],
  715. ['addrgen_mnemonic',(1,'address generation from mmwords file',[[['mmwords','addrs'],1]])],
  716. ['addrgen_incog', (1,'address generation from mmincog file',[[['mmincog','addrs'],1]])],
  717. ['addrgen_incog_hex',(1,'address generation from mmincog hex file',[[['mmincox','addrs'],1]])],
  718. ['addrgen_incog_hidden',(1,'address generation from hidden mmincog file', [[[hincog_fn,'addrs'],1]])],
  719. ['keyaddrgen', (1,'key-address file generation', [[['mmdat',pwfile],1]])],
  720. ['txsign_keyaddr',(1,'transaction signing with key-address file', [[['akeys.mmenc','rawtx'],1]])],
  721. ['txcreate_ni', (1,'transaction creation (non-interactive)', [[['addrs'],1]])],
  722. ['walletgen2',(2,'wallet generation (2), 128-bit seed', [[['del_dw_run'],15]])],
  723. ['addrgen2', (2,'address generation (2)', [[['mmdat'],2]])],
  724. ['txcreate2', (2,'transaction creation (2)', [[['addrs'],2]])],
  725. ['txsign2', (2,'transaction signing, two transactions',[[['mmdat','rawtx'],1],[['mmdat','rawtx'],2]])],
  726. ['export_mnemonic2', (2,'seed export to mmwords format (2)',[[['mmdat'],2]])],
  727. ['walletgen3',(3,'wallet generation (3)', [[['del_dw_run'],15]])],
  728. ['addrgen3', (3,'address generation (3)', [[['mmdat'],3]])],
  729. ['txcreate3', (3,'tx creation with inputs and outputs from two wallets', [[['addrs'],1],[['addrs'],3]])],
  730. ['txsign3', (3,'tx signing with inputs and outputs from two wallets',[[['mmdat'],1],[['mmdat','rawtx'],3]])],
  731. ['walletgen14', (14,'wallet generation (14)', [[['del_dw_run'],15]],14)],
  732. ['addrgen14', (14,'address generation (14)', [[['mmdat'],14]])],
  733. ['keyaddrgen14',(14,'key-address file generation (14)', [[['mmdat'],14]],14)],
  734. ['walletgen4',(4,'wallet generation (4) (brainwallet)', [[['del_dw_run'],15]])],
  735. ['addrgen4', (4,'address generation (4)', [[['mmdat'],4]])],
  736. ['txcreate4', (4,'tx creation with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['addrs'],1],[['addrs'],2],[['addrs'],3],[['addrs'],4],[['addrs','akeys.mmenc'],14]])],
  737. ['txsign4', (4,'tx signing with inputs and outputs from incog file, mnemonic file, wallet, brainwallet, key-address file and non-MMGen inputs and outputs', [[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['mmbrain','rawtx'],4],[['akeys.mmenc'],14]])],
  738. ['txdo4', (4,'tx creation,signing and sending with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['addrs'],1],[['addrs'],2],[['addrs'],3],[['addrs'],4],[['addrs','akeys.mmenc'],14],[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['mmbrain','rawtx'],4],[['akeys.mmenc'],14]])], # must go after txsign4
  739. ['txbump4', (4,'tx fee bump + send with inputs and outputs from four seed sources, key-address file and non-MMGen inputs and outputs', [[['akeys.mmenc'],14],[['mmincog'],1],[['mmwords'],2],[['mmdat'],3],[['akeys.mmenc'],14],[['mmbrain','sigtx','mmdat','txdo'],4]])], # must go after txsign4
  740. ['walletgen5',(20,'wallet generation (5)', [[['del_dw_run'],15]],20)],
  741. ['addrgen5', (20,'address generation (5)', [[['mmdat'],20]])],
  742. ['txcreate5', (20,'transaction creation with bad vsize (5)', [[['addrs'],20]])],
  743. ['txsign5', (20,'transaction signing with bad vsize', [[['mmdat','rawtx'],20]])],
  744. ['walletgen6',(21,'wallet generation (6)', [[['del_dw_run'],15]],21)],
  745. ['addrgen6', (21,'address generation (6)', [[['mmdat'],21]])],
  746. ['txcreate6', (21,'transaction creation with corrected vsize (6)', [[['addrs'],21]])],
  747. ['txsign6', (21,'transaction signing with corrected vsize', [[['mmdat','rawtx'],21]])],
  748. ])
  749. cmd_group['tool'] = OrderedDict([
  750. ['tool_encrypt', (9,"'mmgen-tool encrypt' (random data)", [])],
  751. ['tool_decrypt', (9,"'mmgen-tool decrypt' (random data)", [[[cfgs['9']['tool_enc_infn'],cfgs['9']['tool_enc_infn']+'.mmenc'],9]])],
  752. # ['tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])],
  753. ['tool_find_incog_data', (9,"'mmgen-tool find_incog_data'", [[[hincog_fn],1],[[incog_id_fn],1]])],
  754. # ['pywallet', (9,"'mmgen-pywallet'", [])],
  755. ])
  756. # generated reference data
  757. cmd_group['ref'] = (
  758. # reading
  759. ('ref_wallet_chk', ([],'saved reference wallet')),
  760. ('ref_seed_chk', ([],'saved seed file')),
  761. ('ref_hex_chk', ([],'saved mmhex file')),
  762. ('ref_mn_chk', ([],'saved mnemonic file')),
  763. ('ref_hincog_chk', ([],'saved hidden incog reference wallet')),
  764. ('ref_brain_chk', ([],'saved brainwallet')),
  765. # generating new reference ('abc' brainwallet) files:
  766. ('refwalletgen', ([],'gen new refwallet')),
  767. ('refaddrgen', (['mmdat',pwfile],'new refwallet addr chksum')),
  768. ('refkeyaddrgen', (['mmdat',pwfile],'new refwallet key-addr chksum')),
  769. ('refaddrgen_compressed', (['mmdat',pwfile],'new refwallet addr chksum (compressed)')),
  770. ('refkeyaddrgen_compressed', (['mmdat',pwfile],'new refwallet key-addr chksum (compressed)')),
  771. ('refpasswdgen', (['mmdat',pwfile],'new refwallet passwd file chksum')),
  772. ('ref_b32passwdgen',(['mmdat',pwfile],'new refwallet passwd file chksum (base32)')),
  773. ('ref_hexpasswdgen',(['mmdat',pwfile],'new refwallet passwd file chksum (base32)')),
  774. )
  775. # reference files
  776. cmd_group['ref_files'] = (
  777. ('ref_addrfile_chk', 'saved reference address file'),
  778. ('ref_segwitaddrfile_chk','saved reference address file (segwit)'),
  779. ('ref_bech32addrfile_chk','saved reference address file (bech32)'),
  780. ('ref_keyaddrfile_chk','saved reference key-address file'),
  781. ('ref_passwdfile_chk', 'saved reference password file'),
  782. # Create the fake inputs:
  783. # ('txcreate8', 'transaction creation (8)'),
  784. ('ref_tx_chk', 'saved reference tx file'),
  785. ('ref_brain_chk_spc3', 'saved brainwallet (non-standard spacing)'),
  786. ('ref_tool_decrypt', 'decryption of saved MMGen-encrypted file'),
  787. )
  788. # mmgen-walletconv:
  789. cmd_group['conv_in'] = ( # reading
  790. ('ref_wallet_conv', 'conversion of saved reference wallet'),
  791. ('ref_mn_conv', 'conversion of saved mnemonic'),
  792. ('ref_seed_conv', 'conversion of saved seed file'),
  793. ('ref_hex_conv', 'conversion of saved hexadecimal seed file'),
  794. ('ref_brain_conv', 'conversion of ref brainwallet'),
  795. ('ref_incog_conv', 'conversion of saved incog wallet'),
  796. ('ref_incox_conv', 'conversion of saved hex incog wallet'),
  797. ('ref_hincog_conv', 'conversion of saved hidden incog wallet'),
  798. ('ref_hincog_conv_old','conversion of saved hidden incog wallet (old format)')
  799. )
  800. cmd_group['conv_out'] = ( # writing
  801. ('ref_wallet_conv_out', 'ref seed conversion to wallet'),
  802. ('ref_mn_conv_out', 'ref seed conversion to mnemonic'),
  803. ('ref_hex_conv_out', 'ref seed conversion to hex seed'),
  804. ('ref_seed_conv_out', 'ref seed conversion to seed'),
  805. ('ref_incog_conv_out', 'ref seed conversion to incog data'),
  806. ('ref_incox_conv_out', 'ref seed conversion to hex incog data'),
  807. ('ref_hincog_conv_out', 'ref seed conversion to hidden incog data'),
  808. ('ref_hincog_blkdev_conv_out', 'ref seed conversion to hidden incog data on block device')
  809. )
  810. cmd_group['regtest'] = (
  811. ('regtest_setup', 'regtest (Bob and Alice) mode setup'),
  812. ('regtest_walletgen_bob', 'wallet generation (Bob)'),
  813. ('regtest_walletgen_alice', 'wallet generation (Alice)'),
  814. ('regtest_addrgen_bob', 'address generation (Bob)'),
  815. ('regtest_addrgen_alice', 'address generation (Alice)'),
  816. ('regtest_addrimport_bob', "importing Bob's addresses"),
  817. ('regtest_addrimport_alice', "importing Alice's addresses"),
  818. ('regtest_fund_bob', "funding Bob's wallet"),
  819. ('regtest_fund_alice', "funding Alice's wallet"),
  820. ('regtest_bob_bal1', "Bob's balance"),
  821. ('regtest_bob_add_label', "adding a 40-character UTF-8 encoded label"),
  822. ('regtest_bob_split1', "splitting Bob's funds"),
  823. ('regtest_generate', 'mining a block'),
  824. ('regtest_bob_bal2', "Bob's balance"),
  825. ('regtest_bob_bal2a', "Bob's balance (show_days=1)"),
  826. ('regtest_bob_bal2b', "Bob's balance (show_age=1)"),
  827. ('regtest_bob_bal2c', "Bob's balance (showempty=1 show_age=1 minconf=2)"),
  828. ('regtest_bob_bal2d', "Bob's balance (show_age=1 minconf=2)"),
  829. ('regtest_bob_bal2e', "Bob's balance (showempty=1 show_age=1 sort=age)"),
  830. ('regtest_bob_bal2f', "Bob's balance (showempty=1 show_age=1 sort=age,reverse)"),
  831. ('regtest_bob_rbf_send', 'sending funds to Alice (RBF)'),
  832. ('regtest_get_mempool1', 'mempool (before RBF bump)'),
  833. ('regtest_bob_rbf_bump', 'bumping RBF transaction'),
  834. ('regtest_get_mempool2', 'mempool (after RBF bump)'),
  835. ('regtest_generate', 'mining a block'),
  836. ('regtest_bob_bal3', "Bob's balance"),
  837. ('regtest_bob_pre_import', 'sending to non-imported address'),
  838. ('regtest_generate', 'mining a block'),
  839. ('regtest_bob_import_addr', 'importing non-MMGen address with --rescan'),
  840. ('regtest_bob_bal4', "Bob's balance (after import with rescan)"),
  841. ('regtest_bob_import_list', 'importing flat address list'),
  842. ('regtest_bob_split2', "splitting Bob's funds"),
  843. ('regtest_generate', 'mining a block'),
  844. ('regtest_bob_bal5', "Bob's balance"),
  845. ('regtest_bob_bal5_getbalance',"Bob's balance"),
  846. ('regtest_bob_send_non_mmgen', 'sending funds to Alice (from non-MMGen addrs)'),
  847. ('regtest_generate', 'mining a block'),
  848. ('regtest_alice_add_label1', 'adding a label'),
  849. ('regtest_alice_chk_label1', 'the label'),
  850. ('regtest_alice_add_label2', 'adding a label'),
  851. ('regtest_alice_chk_label2', 'the label'),
  852. ('regtest_alice_edit_label1', 'editing a label'),
  853. ('regtest_alice_chk_label3', 'the label'),
  854. ('regtest_alice_remove_label1','removing a label'),
  855. ('regtest_alice_chk_label4', 'the label'),
  856. ('regtest_alice_add_label_coinaddr','adding a label using the coin address'),
  857. ('regtest_alice_chk_label_coinaddr','the label'),
  858. ('regtest_alice_add_label_badaddr1','adding a label with invalid address'),
  859. ('regtest_alice_add_label_badaddr2','adding a label with invalid address for this chain'),
  860. ('regtest_alice_add_label_badaddr3','adding a label with wrong MMGen address'),
  861. ('regtest_alice_add_label_badaddr4','adding a label with wrong coin address'),
  862. ('regtest_alice_bal_rpcfail','RPC failure code'),
  863. ('regtest_alice_send_estimatefee','tx creation with no fee on command line'),
  864. ('regtest_generate', 'mining a block'),
  865. ('regtest_bob_bal6', "Bob's balance"),
  866. ('regtest_bob_alice_bal', "Bob and Alice's balances"),
  867. ('regtest_alice_bal2', "Alice's balance"),
  868. ('regtest_stop', 'stopping regtest daemon'),
  869. )
  870. cmd_group['regtest_split'] = (
  871. ('regtest_split_setup', 'regtest forking scenario setup'),
  872. ('regtest_walletgen_bob', "generating Bob's wallet"),
  873. ('regtest_addrgen_bob', "generating Bob's addresses"),
  874. ('regtest_addrimport_bob', "importing Bob's addresses"),
  875. ('regtest_fund_bob', "funding Bob's wallet"),
  876. ('regtest_split_fork', 'regtest split fork'),
  877. ('regtest_split_start_btc', 'start regtest daemon (BTC)'),
  878. ('regtest_split_start_b2x', 'start regtest daemon (B2X)'),
  879. ('regtest_split_gen_btc', 'mining a block (BTC)'),
  880. ('regtest_split_gen_b2x', 'mining 100 blocks (B2X)'),
  881. ('regtest_split_do_split', 'creating coin splitting transactions'),
  882. ('regtest_split_sign_b2x', 'signing B2X split transaction'),
  883. ('regtest_split_sign_btc', 'signing BTC split transaction'),
  884. ('regtest_split_send_b2x', 'sending B2X split transaction'),
  885. ('regtest_split_send_btc', 'sending BTC split transaction'),
  886. ('regtest_split_gen_btc', 'mining a block (BTC)'),
  887. ('regtest_split_gen_b2x2', 'mining a block (B2X)'),
  888. ('regtest_split_txdo_timelock_bad_btc', 'sending transaction with bad locktime (BTC)'),
  889. ('regtest_split_txdo_timelock_good_btc','sending transaction with good locktime (BTC)'),
  890. ('regtest_split_txdo_timelock_bad_b2x', 'sending transaction with bad locktime (B2X)'),
  891. ('regtest_split_txdo_timelock_good_b2x','sending transaction with good locktime (B2X)'),
  892. )
  893. cmd_group['ethdev'] = (
  894. ('ethdev_setup', 'Ethereum Parity dev mode tests for coin {} (start parity)'.format(g.coin)),
  895. ('ethdev_addrgen', 'generating addresses'),
  896. ('ethdev_addrimport', 'importing addresses'),
  897. ('ethdev_addrimport_dev_addr', "importing Parity dev address 'Ox00a329c..'"),
  898. ('ethdev_txcreate1', 'creating a transaction (spend from dev address to address :1)'),
  899. ('ethdev_txsign1', 'signing the transaction'),
  900. ('ethdev_txsign1_ni', 'signing the transaction (non-interactive)'),
  901. ('ethdev_txsend1', 'sending the transaction'),
  902. ('ethdev_bal1', 'the {} balance'.format(g.coin)),
  903. ('ethdev_txcreate2', 'creating a transaction (spend from dev address to address :11)'),
  904. ('ethdev_txsign2', 'signing the transaction'),
  905. ('ethdev_txsend2', 'sending the transaction'),
  906. ('ethdev_bal2', 'the {} balance'.format(g.coin)),
  907. ('ethdev_txcreate3', 'creating a transaction (spend from dev address to address :21)'),
  908. ('ethdev_txsign3', 'signing the transaction'),
  909. ('ethdev_txsend3', 'sending the transaction'),
  910. ('ethdev_bal3', 'the {} balance'.format(g.coin)),
  911. ('ethdev_tx_status1', 'getting the transaction status'),
  912. ('ethdev_txcreate4', 'creating a transaction (spend from MMGen address, low TX fee)'),
  913. ('ethdev_txbump', 'bumping the transaction fee'),
  914. ('ethdev_txsign4', 'signing the transaction'),
  915. ('ethdev_txsend4', 'sending the transaction'),
  916. ('ethdev_bal4', 'the {} balance'.format(g.coin)),
  917. ('ethdev_txcreate5', 'creating a transaction (fund burn address)'),
  918. ('ethdev_txsign5', 'signing the transaction'),
  919. ('ethdev_txsend5', 'sending the transaction'),
  920. ('ethdev_addrimport_burn_addr',"importing burn address"),
  921. ('ethdev_bal5', 'the {} balance'.format(g.coin)),
  922. ('ethdev_add_label', 'adding a UTF-8 label'),
  923. ('ethdev_chk_label', 'the label'),
  924. ('ethdev_remove_label', 'removing the label'),
  925. ('ethdev_token_compile1', 'compiling ERC20 token #1'),
  926. ('ethdev_token_deploy1a', 'deploying ERC20 token #1 (SafeMath)'),
  927. ('ethdev_token_deploy1b', 'deploying ERC20 token #1 (Owned)'),
  928. ('ethdev_token_deploy1c', 'deploying ERC20 token #1 (Token)'),
  929. ('ethdev_tx_status2', 'getting the transaction status'),
  930. ('ethdev_bal6', 'the {} balance'.format(g.coin)),
  931. ('ethdev_token_compile2', 'compiling ERC20 token #2'),
  932. ('ethdev_token_deploy2a', 'deploying ERC20 token #2 (SafeMath)'),
  933. ('ethdev_token_deploy2b', 'deploying ERC20 token #2 (Owned)'),
  934. ('ethdev_token_deploy2c', 'deploying ERC20 token #2 (Token)'),
  935. ('ethdev_contract_deploy', 'deploying contract (create,sign,send)'),
  936. ('ethdev_token_fund_users', 'transferring token funds from dev to user'),
  937. ('ethdev_token_user_bals', 'show balances after transfer'),
  938. ('ethdev_token_addrgen', 'generating token addresses'),
  939. ('ethdev_token_addrimport_badaddr1','importing token addresses (no token address)'),
  940. ('ethdev_token_addrimport_badaddr2','importing token addresses (bad token address)'),
  941. ('ethdev_token_addrimport', 'importing token addresses'),
  942. ('ethdev_bal7', 'the {} balance'.format(g.coin)),
  943. ('ethdev_token_bal1', 'the {} balance and token balance'.format(g.coin)),
  944. ('ethdev_token_txcreate1', 'creating a token transaction'),
  945. ('ethdev_token_txsign1', 'signing the transaction'),
  946. ('ethdev_token_txsend1', 'sending the transaction'),
  947. ('ethdev_token_bal2', 'the {} balance and token balance'.format(g.coin)),
  948. ('ethdev_token_txcreate2', 'creating a token transaction (to burn address)'),
  949. ('ethdev_token_txbump', 'bumping the transaction fee'),
  950. ('ethdev_token_txsign2', 'signing the transaction'),
  951. ('ethdev_token_txsend2', 'sending the transaction'),
  952. ('ethdev_token_bal3', 'the {} balance and token balance'.format(g.coin)),
  953. ('ethdev_del_dev_addr', "deleting the dev address"),
  954. ('ethdev_bal1_getbalance', 'the {} balance (getbalance)'.format(g.coin)),
  955. ('ethdev_addrimport_token_burn_addr',"importing the token burn address"),
  956. ('ethdev_token_bal4', 'the {} balance and token balance'.format(g.coin)),
  957. ('ethdev_token_bal_getbalance','the token balance (getbalance)'),
  958. ('ethdev_txcreate_noamt', 'creating a transaction (full amount send)'),
  959. ('ethdev_txsign_noamt', 'signing the transaction'),
  960. ('ethdev_txsend_noamt', 'sending the transaction'),
  961. ('ethdev_bal8', 'the {} balance'.format(g.coin)),
  962. ('ethdev_token_bal5', 'the token balance'),
  963. ('ethdev_token_txcreate_noamt', 'creating a token transaction (full amount send)'),
  964. ('ethdev_token_txsign_noamt', 'signing the transaction'),
  965. ('ethdev_token_txsend_noamt', 'sending the transaction'),
  966. ('ethdev_bal9', 'the {} balance'.format(g.coin)),
  967. ('ethdev_token_bal6', 'the token balance'),
  968. ('ethdev_listaddresses1', 'listaddresses'),
  969. ('ethdev_listaddresses2', 'listaddresses minconf=999999999 (ignored)'),
  970. ('ethdev_listaddresses3', 'listaddresses sort=age (ignored)'),
  971. ('ethdev_listaddresses4', 'listaddresses showempty=1 sort=age (ignored)'),
  972. ('ethdev_token_listaddresses1','listaddresses --token=mm1'),
  973. ('ethdev_token_listaddresses2','listaddresses --token=mm1 showempty=1'),
  974. ('ethdev_twview1','twview'),
  975. ('ethdev_twview2','twview wide=1'),
  976. ('ethdev_twview3','twview wide=1 sort=age (ignored)'),
  977. ('ethdev_twview4','twview wide=1 minconf=999999999 (ignored)'),
  978. ('ethdev_twview5','twview wide=1 minconf=0 (ignored)'),
  979. ('ethdev_twview6','twview show_days=0 (ignored)'),
  980. ('ethdev_token_twview1','twview --token=mm1'),
  981. ('ethdev_token_twview2','twview --token=mm1 wide=1'),
  982. ('ethdev_token_twview3','twview --token=mm1 wide=1 sort=age (ignored)'),
  983. ('ethdev_edit_label1','adding label to addr #{} in {} tracking wallet'.format(eth_rem_addrs[0],g.coin)),
  984. ('ethdev_edit_label2','adding label to addr #{} in {} tracking wallet'.format(eth_rem_addrs[1],g.coin)),
  985. ('ethdev_edit_label3','removing label from addr #{} in {} tracking wallet'.format(eth_rem_addrs[0],g.coin)),
  986. ('ethdev_remove_addr1','removing addr #{} from {} tracking wallet'.format(eth_rem_addrs[0],g.coin)),
  987. ('ethdev_remove_addr2','removing addr #{} from {} tracking wallet'.format(eth_rem_addrs[1],g.coin)),
  988. ('ethdev_remove_token_addr1','removing addr #{} from {} token tracking wallet'.format(eth_rem_addrs[0],g.coin)),
  989. ('ethdev_remove_token_addr2','removing addr #{} from {} token tracking wallet'.format(eth_rem_addrs[1],g.coin)),
  990. ('ethdev_stop', 'stopping parity'),
  991. )
  992. cmd_group['autosign'] = (
  993. ('autosign', 'transaction autosigning (BTC,BCH,LTC,ETH,ETC)'),
  994. )
  995. cmd_group['autosign_minimal'] = (
  996. ('autosign_minimal', 'transaction autosigning (BTC,ETH,ETC)'),
  997. )
  998. cmd_group['autosign_live'] = (
  999. ('autosign_live', 'transaction autosigning (BTC,ETH,ETC - test device insertion/removal + LED)'),
  1000. )
  1001. cmd_group['ref_alt'] = (
  1002. ('ref_addrfile_gen_eth', 'generate address file (ETH)'),
  1003. ('ref_addrfile_gen_etc', 'generate address file (ETC)'),
  1004. ('ref_addrfile_gen_dash', 'generate address file (DASH)'),
  1005. ('ref_addrfile_gen_zec', 'generate address file (ZEC-T)'),
  1006. ('ref_addrfile_gen_zec_z','generate address file (ZEC-Z)'),
  1007. ('ref_addrfile_gen_xmr', 'generate address file (XMR)'),
  1008. # we test the old ed25519 library in test-release.sh, so skip this
  1009. # ('ref_addrfile_gen_xmr_old','generate address file (XMR - old (slow) ed25519 library)'),
  1010. ('ref_keyaddrfile_gen_eth', 'generate key-address file (ETH)'),
  1011. ('ref_keyaddrfile_gen_etc', 'generate key-address file (ETC)'),
  1012. ('ref_keyaddrfile_gen_dash', 'generate key-address file (DASH)'),
  1013. ('ref_keyaddrfile_gen_zec', 'generate key-address file (ZEC-T)'),
  1014. ('ref_keyaddrfile_gen_zec_z','generate key-address file (ZEC-Z)'),
  1015. ('ref_keyaddrfile_gen_xmr', 'generate key-address file (XMR)'),
  1016. ('ref_addrfile_chk_eth', 'reference address file (ETH)'),
  1017. ('ref_addrfile_chk_etc', 'reference address file (ETC)'),
  1018. ('ref_addrfile_chk_dash','reference address file (DASH)'),
  1019. ('ref_addrfile_chk_zec', 'reference address file (ZEC-T)'),
  1020. ('ref_addrfile_chk_zec_z','reference address file (ZEC-Z)'),
  1021. ('ref_addrfile_chk_xmr', 'reference address file (XMR)'),
  1022. ('ref_keyaddrfile_chk_eth', 'reference key-address file (ETH)'),
  1023. ('ref_keyaddrfile_chk_etc', 'reference key-address file (ETC)'),
  1024. ('ref_keyaddrfile_chk_dash','reference key-address file (DASH)'),
  1025. ('ref_keyaddrfile_chk_zec', 'reference key-address file (ZEC-T)'),
  1026. ('ref_keyaddrfile_chk_zec_z','reference key-address file (ZEC-Z)'),
  1027. ('ref_keyaddrfile_chk_xmr', 'reference key-address file (XMR)'),
  1028. )
  1029. # undocumented admin cmds - precede with 'admin'
  1030. cmd_group_admin = OrderedDict()
  1031. cmd_group_admin['create_ref_tx'] = OrderedDict([
  1032. ['ref_tx_addrgen1', (31,'address generation (legacy)', [[[],1]])],
  1033. ['ref_tx_addrgen2', (32,'address generation (compressed)', [[[],1]])],
  1034. ['ref_tx_addrgen3', (33,'address generation (segwit)', [[[],1]])],
  1035. ['ref_tx_addrgen4', (34,'address generation (bech32)', [[[],1]])],
  1036. ['ref_tx_txcreate', (31,'transaction creation', [[['addrs'],31],[['addrs'],32],[['addrs'],33],[['addrs'],34]])],
  1037. ])
  1038. cmd_list_admin = OrderedDict()
  1039. for k in cmd_group_admin: cmd_list_admin[k] = []
  1040. cmd_data_admin = OrderedDict()
  1041. for k,v in [('create_ref_tx',('reference transaction creation',[31,32,33,34]))]:
  1042. cmd_data_admin['info_'+k] = v
  1043. for i in cmd_group_admin[k]:
  1044. cmd_list_admin[k].append(i)
  1045. cmd_data_admin[i] = cmd_group_admin[k][i]
  1046. cmd_data_admin['info_create_ref_tx'] = 'create reference tx',[8]
  1047. cmd_list = OrderedDict()
  1048. for k in cmd_group: cmd_list[k] = []
  1049. cmd_data = OrderedDict()
  1050. for k,v in (
  1051. ('help', ('help screens',[])),
  1052. ('dfl_wallet', ('basic operations with default wallet',[15,16])),
  1053. ('main', ('basic operations',[1,2,3,4,5,6,15,16])),
  1054. ('tool', ('tools',[9]))
  1055. ):
  1056. cmd_data['info_'+k] = v
  1057. for i in cmd_group[k]:
  1058. cmd_list[k].append(i)
  1059. cmd_data[i] = cmd_group[k][i]
  1060. cmd_data['info_ref'] = 'generated reference data',[6,7,8]
  1061. for a,b in cmd_group['ref']:
  1062. for i,j in ((1,128),(2,192),(3,256)):
  1063. k = a+str(i)
  1064. cmd_list['ref'].append(k)
  1065. cmd_data[k] = (5+i,'{} ({}-bit)'.format(b[1],j),[[b[0],5+i]])
  1066. cmd_data['info_ref_files'] = 'reference files',[8]
  1067. for a,b in cmd_group['ref_files']:
  1068. cmd_list['ref_files'].append(a)
  1069. cmd_data[a] = (8,b,[[[],8]])
  1070. cmd_data['info_conv_in'] = 'wallet conversion from reference data',[11,12,13]
  1071. for a,b in cmd_group['conv_in']:
  1072. for i,j in ((1,128),(2,192),(3,256)):
  1073. k = a+str(i)
  1074. cmd_list['conv_in'].append(k)
  1075. cmd_data[k] = (10+i,'{} ({}-bit)'.format(b,j),[[[],10+i]])
  1076. cmd_data['info_conv_out'] = 'wallet conversion to reference data',[11,12,13]
  1077. for a,b in cmd_group['conv_out']:
  1078. for i,j in ((1,128),(2,192),(3,256)):
  1079. k = a+str(i)
  1080. cmd_list['conv_out'].append(k)
  1081. cmd_data[k] = (10+i,'{} ({}-bit)'.format(b,j),[[[],10+i]])
  1082. cmd_data['info_regtest'] = 'regtest mode',[17]
  1083. for a,b in cmd_group['regtest']:
  1084. cmd_list['regtest'].append(a)
  1085. cmd_data[a] = (17,b,[[[],17]])
  1086. cmd_data['info_ethdev'] = 'Ethereum tracking wallet and transaction ops',[22]
  1087. for a,b in cmd_group['ethdev']:
  1088. cmd_list['ethdev'].append(a)
  1089. cmd_data[a] = (22,b,[[[],22]])
  1090. cmd_data['info_autosign'] = 'autosign',[18]
  1091. for a,b in cmd_group['autosign']:
  1092. cmd_list['autosign'].append(a)
  1093. cmd_data[a] = (18,b,[[[],18]])
  1094. cmd_data['info_autosign_minimal'] = 'autosign_minimal',[18]
  1095. for a,b in cmd_group['autosign_minimal']:
  1096. cmd_list['autosign_minimal'].append(a)
  1097. cmd_data[a] = (18,b,[[[],18]])
  1098. cmd_data['info_autosign_live'] = 'autosign_live',[18]
  1099. for a,b in cmd_group['autosign_live']:
  1100. cmd_list['autosign_live'].append(a)
  1101. cmd_data[a] = (18,b,[[[],18]])
  1102. cmd_data['info_ref_alt'] = 'altcoin reference files',[8]
  1103. for a,b in cmd_group['ref_alt']:
  1104. cmd_list['ref_alt'].append(a)
  1105. cmd_data[a] = (8,b,[[[],8]])
  1106. utils = {
  1107. 'check_deps': 'check dependencies for specified command',
  1108. 'clean': 'clean specified tmp dir(s) 1,2,3,4,5 or 6 (no arg = all dirs)',
  1109. }
  1110. addrs_per_wallet = 8
  1111. meta_cmds = OrderedDict([
  1112. ['gen', ('walletgen','addrgen')],
  1113. ['pass', ('passchg','walletchk_newpass')],
  1114. ['tx', ('txcreate','txsign','txsend')],
  1115. ['export', [k for k in cmd_data if k[:7] == 'export_' and cmd_data[k][0] == 1]],
  1116. ['gen_sp', [k for k in cmd_data if k[:8] == 'addrgen_' and cmd_data[k][0] == 1]],
  1117. ['online', ('keyaddrgen','txsign_keyaddr')],
  1118. ['2', [k for k in cmd_data if cmd_data[k][0] == 2]],
  1119. ['3', [k for k in cmd_data if cmd_data[k][0] == 3]],
  1120. ['4', [k for k in cmd_data if cmd_data[k][0] == 4]],
  1121. ['5', [k for k in cmd_data if cmd_data[k][0] == 20]],
  1122. ['6', [k for k in cmd_data if cmd_data[k][0] == 21]],
  1123. ['ref1', [c[0]+'1' for c in cmd_group['ref']]],
  1124. ['ref2', [c[0]+'2' for c in cmd_group['ref']]],
  1125. ['ref3', [c[0]+'3' for c in cmd_group['ref']]],
  1126. ['conv_in1', [c[0]+'1' for c in cmd_group['conv_in']]],
  1127. ['conv_in2', [c[0]+'2' for c in cmd_group['conv_in']]],
  1128. ['conv_in3', [c[0]+'3' for c in cmd_group['conv_in']]],
  1129. ['conv_out1', [c[0]+'1' for c in cmd_group['conv_out']]],
  1130. ['conv_out2', [c[0]+'2' for c in cmd_group['conv_out']]],
  1131. ['conv_out3', [c[0]+'3' for c in cmd_group['conv_out']]],
  1132. ])
  1133. del cmd_group
  1134. if opt.profile: opt.names = True
  1135. if opt.resume: opt.skip_deps = True
  1136. log_fd = None
  1137. if opt.log:
  1138. log_fd = open(log_file,'a')
  1139. log_fd.write('\nLog started: {}\n'.format(make_timestr()))
  1140. usr_rand_chars = (5,30)[bool(opt.usr_random)]
  1141. usr_rand_arg = '-r{}'.format(usr_rand_chars)
  1142. cmd_total = 0
  1143. # Disable color in spawned scripts so pexpect can parse their output
  1144. os.environ['MMGEN_DISABLE_COLOR'] = '1'
  1145. os.environ['MMGEN_NO_LICENSE'] = '1'
  1146. os.environ['MMGEN_MIN_URANDCHARS'] = '3'
  1147. os.environ['MMGEN_BOGUS_SEND'] = '1'
  1148. # Tell spawned programs they're running in the test suite
  1149. os.environ['MMGEN_TEST_SUITE'] = '1'
  1150. def get_segwit_arg(cfg):
  1151. return ['--type='+('segwit','bech32')[bool(opt.bech32)]] if cfg['segwit'] else []
  1152. if opt.exact_output:
  1153. def imsg(s): os.write(2,s.encode() + b'\n')
  1154. def imsg_r(s): os.write(2,s.encode())
  1155. def msg(s): pass
  1156. qmsg = qmsg_r = vmsg = vmsg_r = msg_r = msg
  1157. else:
  1158. def imsg(s): pass
  1159. def imsg_r(s): pass
  1160. devnull_fh = open('/dev/null','w')
  1161. def silence():
  1162. if not (opt.verbose or opt.exact_output):
  1163. g.stderr_fileno = g.stdout_fileno = devnull_fh.fileno()
  1164. def end_silence():
  1165. if not (opt.verbose or opt.exact_output):
  1166. g.stderr_fileno = 2
  1167. g.stdout_fileno = 1
  1168. if opt.list_cmd_groups:
  1169. Msg(' '.join(cmd_list))
  1170. sys.exit(0)
  1171. if opt.list_cmds:
  1172. from mmgen.term import get_terminal_size
  1173. tw = get_terminal_size()[0]
  1174. fs = ' {:<{w}} - {}'
  1175. Msg(green('AVAILABLE COMMANDS:'))
  1176. w = max(map(len,cmd_data))
  1177. for cmd in cmd_data:
  1178. if cmd[:5] == 'info_':
  1179. Msg(green(' {}:'.format(capfirst(cmd_data[cmd][0]))))
  1180. continue
  1181. Msg(' '+fs.format(cmd,cmd_data[cmd][1],w=w))
  1182. for cl,lbl in ((meta_cmds,'METACOMMANDS'),(cmd_list,'COMMAND GROUPS')):
  1183. w = max(map(len,cl))
  1184. Msg('\n'+green('AVAILABLE {}:'.format(lbl)))
  1185. for cmd in cl:
  1186. ft = format_par(' '.join(cl[cmd]),width=tw,indent=4,as_list=True)
  1187. sep = '' if not ft else ' ' if len(ft[0]) + len(cmd) < tw - 4 else '\n '
  1188. Msg(' {}{}{}'.format(yellow(cmd+':'),sep,'\n'.join(ft).lstrip()))
  1189. Msg('\n'+green('AVAILABLE UTILITIES:'))
  1190. w = max(map(len,utils))
  1191. for cmd in sorted(utils):
  1192. Msg(fs.format(cmd,utils[cmd],w=w))
  1193. sys.exit(0)
  1194. NL = ('\r\n','\n')[g.platform=='linux' and bool(opt.popen_spawn)]
  1195. def get_file_with_ext(ext,mydir,delete=True,no_dot=False,return_list=False,delete_all=False):
  1196. dot = ('.','')[bool(no_dot)]
  1197. flist = [os.path.join(mydir,f) for f in os.listdir(mydir) if f == ext or f[-len(dot+ext):] == dot+ext]
  1198. if not flist: return False
  1199. if return_list: return flist
  1200. if len(flist) > 1 or delete_all:
  1201. if delete or delete_all:
  1202. if not opt.quiet:
  1203. msg("Multiple *.{} files in '{}' - deleting".format(ext,mydir))
  1204. for f in flist:
  1205. os.unlink(f)
  1206. return False
  1207. else:
  1208. return flist[0]
  1209. def find_generated_exts(cmd):
  1210. out = []
  1211. for k in cfgs:
  1212. for ext,prog in list(cfgs[k]['dep_generators'].items()):
  1213. if prog == cmd:
  1214. out.append((ext,cfgs[k]['tmpdir']))
  1215. return out
  1216. def get_addrfile_checksum(display=False):
  1217. addrfile = get_file_with_ext('addrs',cfg['tmpdir'])
  1218. silence()
  1219. chk = AddrList(addrfile).chksum
  1220. if opt.verbose and display: msg('Checksum: {}'.format(cyan(chk)))
  1221. end_silence()
  1222. return chk
  1223. def verify_checksum_or_exit(checksum,chk):
  1224. if checksum != chk:
  1225. raise TestSuiteFatalException('Checksum error: {}'.format(chk))
  1226. vmsg(green('Checksums match: ') + cyan(chk))
  1227. from test.mmgen_pexpect import MMGenPexpect
  1228. class MMGenExpect(MMGenPexpect):
  1229. def __init__(self,name,mmgen_cmd,cmd_args=[],extra_desc='',no_output=False,msg_only=False,no_msg=False):
  1230. desc = ((cmd_data[name][1],name)[bool(opt.names)] + (' ' + extra_desc)).strip()
  1231. passthru_args = ['testnet','rpc_host','rpc_port','regtest','coin']
  1232. if not opt.system:
  1233. mmgen_cmd = os.path.relpath(os.path.join(repo_root,'cmds',mmgen_cmd))
  1234. elif g.platform == 'win':
  1235. mmgen_cmd = os.path.join('/mingw64','opt','bin',mmgen_cmd)
  1236. return MMGenPexpect.__init__(
  1237. self,
  1238. name,
  1239. mmgen_cmd,
  1240. cmd_args,
  1241. desc,
  1242. no_output=no_output,
  1243. passthru_args=passthru_args,
  1244. msg_only=msg_only,
  1245. no_msg=no_msg,
  1246. log_fd=log_fd)
  1247. def create_fake_unspent_entry(coinaddr,al_id=None,idx=None,lbl=None,non_mmgen=False,segwit=False):
  1248. if 'S' not in g.proto.mmtypes: segwit = False
  1249. if lbl: lbl = ' ' + lbl
  1250. k = coinaddr.addr_fmt
  1251. if not segwit and k == 'p2sh': k = 'p2pkh'
  1252. s_beg,s_end = { 'p2pkh': ('76a914','88ac'),
  1253. 'p2sh': ('a914','87'),
  1254. 'bech32': (g.proto.witness_vernum_hex.decode()+'14','') }[k]
  1255. amt1,amt2 = {'btc':(10,40),'bch':(10,40),'ltc':(1000,4000)}[coin_sel]
  1256. ret = {
  1257. lbl_id: '{}:{}'.format(g.proto.base_coin.lower(),coinaddr) if non_mmgen \
  1258. else ('{}:{}{}'.format(al_id,idx,lbl)),
  1259. 'vout': int(getrandnum(4) % 8),
  1260. 'txid': hexlify(os.urandom(32)),
  1261. 'amount': g.proto.coin_amt('{}.{}'.format(amt1 + getrandnum(4) % amt2, getrandnum(4) % 100000000)),
  1262. 'address': coinaddr,
  1263. 'spendable': False,
  1264. 'scriptPubKey': '{}{}{}'.format(s_beg,coinaddr.hex.decode(),s_end).encode(),
  1265. 'confirmations': getrandnum(3) // 2 # max: 8388608 (7 digits)
  1266. }
  1267. return ret
  1268. labels = [
  1269. "Automotive",
  1270. "Travel expenses",
  1271. "Healthcare",
  1272. ref_tx_label_jp[:40],
  1273. ref_tx_label_zh[:40],
  1274. "Alice's allowance",
  1275. "Bob's bequest",
  1276. "House purchase",
  1277. "Real estate fund",
  1278. "Job 1",
  1279. "XYZ Corp.",
  1280. "Eddie's endowment",
  1281. "Emergency fund",
  1282. "Real estate fund",
  1283. "Ian's inheritance",
  1284. "",
  1285. "Rainy day",
  1286. "Fred's funds",
  1287. "Job 2",
  1288. "Carl's capital",
  1289. ]
  1290. def get_label(do_shuffle=False):
  1291. from random import shuffle
  1292. global label_iter
  1293. try:
  1294. return str(next(label_iter))
  1295. except:
  1296. if do_shuffle: shuffle(labels)
  1297. label_iter = iter(labels)
  1298. return str(next(label_iter))
  1299. def create_fake_unspent_data(adata,tx_data,non_mmgen_input='',non_mmgen_input_compressed=True):
  1300. out = []
  1301. for d in tx_data.values():
  1302. al = adata.addrlist(d['al_id'])
  1303. for n,(idx,coinaddr) in enumerate(al.addrpairs()):
  1304. lbl = get_label(do_shuffle=True)
  1305. out.append(create_fake_unspent_entry(coinaddr,d['al_id'],idx,lbl,segwit=d['segwit']))
  1306. if n == 0: # create a duplicate address. This means addrs_per_wallet += 1
  1307. out.append(create_fake_unspent_entry(coinaddr,d['al_id'],idx,lbl,segwit=d['segwit']))
  1308. if non_mmgen_input:
  1309. privkey = PrivKey(os.urandom(32),compressed=non_mmgen_input_compressed,pubkey_type='std')
  1310. rand_coinaddr = AddrGenerator('p2pkh').to_addr(KeyGenerator('std').to_pubhex(privkey))
  1311. of = os.path.join(cfgs[non_mmgen_input]['tmpdir'],non_mmgen_fn)
  1312. write_data_to_file(of, privkey.wif+'\n','compressed {} key'.format(g.proto.name),
  1313. silent=True,ignore_opt_outdir=True)
  1314. out.append(create_fake_unspent_entry(rand_coinaddr,non_mmgen=True,segwit=False))
  1315. # msg('\n'.join([repr(o) for o in out])); sys.exit(0)
  1316. return out
  1317. def write_fake_data_to_file(d):
  1318. unspent_data_file = os.path.join(cfg['tmpdir'],'unspent.json')
  1319. write_data_to_file(unspent_data_file,d,'Unspent outputs',silent=True,ignore_opt_outdir=True)
  1320. os.environ['MMGEN_BOGUS_WALLET_DATA'] = unspent_data_file
  1321. bwd_msg = 'MMGEN_BOGUS_WALLET_DATA={}'.format(unspent_data_file)
  1322. if opt.print_cmdline: msg(bwd_msg)
  1323. if opt.log: log_fd.write(bwd_msg + ' ')
  1324. if opt.verbose or opt.exact_output:
  1325. sys.stderr.write("Fake transaction wallet data written to file {!r}\n".format(unspent_data_file))
  1326. def create_tx_data(sources,addrs_per_wallet=addrs_per_wallet):
  1327. tx_data,ad = {},AddrData()
  1328. for s in sources:
  1329. afile = get_file_with_ext('addrs',cfgs[s]['tmpdir'])
  1330. al = AddrList(afile)
  1331. ad.add(al)
  1332. aix = AddrIdxList(fmt_str=cfgs[s]['addr_idx_list'])
  1333. if len(aix) != addrs_per_wallet:
  1334. raise TestSuiteFatalException(
  1335. 'Address index list length != {}: {}'.format(addrs_per_wallet,repr(aix)))
  1336. tx_data[s] = {
  1337. 'addrfile': afile,
  1338. 'chk': al.chksum,
  1339. 'al_id': al.al_id,
  1340. 'addr_idxs': aix[-2:],
  1341. 'segwit': cfgs[s]['segwit']
  1342. }
  1343. return ad,tx_data
  1344. def make_txcreate_cmdline(tx_data):
  1345. privkey = PrivKey(os.urandom(32),compressed=True,pubkey_type='std')
  1346. t = ('p2pkh','segwit')['S' in g.proto.mmtypes]
  1347. rand_coinaddr = AddrGenerator(t).to_addr(KeyGenerator('std').to_pubhex(privkey))
  1348. # total of two outputs must be < 10 BTC (<1000 LTC)
  1349. mods = {'btc':(6,4),'bch':(6,4),'ltc':(600,400)}[coin_sel]
  1350. for k in cfgs:
  1351. cfgs[k]['amts'] = [None,None]
  1352. for idx,mod in enumerate(mods):
  1353. cfgs[k]['amts'][idx] = '{}.{}'.format(getrandnum(4) % mod, str(getrandnum(4))[:5])
  1354. cmd_args = ['--outdir='+cfg['tmpdir']]
  1355. for num in tx_data:
  1356. s = tx_data[num]
  1357. cmd_args += [
  1358. '{}:{},{}'.format(s['al_id'],s['addr_idxs'][0],cfgs[num]['amts'][0]),
  1359. ]
  1360. # + one change address and one BTC address
  1361. if num is list(tx_data.keys())[-1]:
  1362. cmd_args += ['{}:{}'.format(s['al_id'],s['addr_idxs'][1])]
  1363. cmd_args += ['{},{}'.format(rand_coinaddr,cfgs[num]['amts'][1])]
  1364. return cmd_args + [tx_data[num]['addrfile'] for num in tx_data]
  1365. def add_comments_to_addr_file(addrfile,outfile,use_labels=False):
  1366. silence()
  1367. gmsg("Adding comments to address file '{}'".format(addrfile))
  1368. a = AddrList(addrfile)
  1369. for n,idx in enumerate(a.idxs(),1):
  1370. if use_labels:
  1371. a.set_comment(idx,get_label())
  1372. else:
  1373. if n % 2: a.set_comment(idx,'Test address {}'.format(n))
  1374. a.format(enable_comments=True)
  1375. write_data_to_file(outfile,a.fmt_data,silent=True,ignore_opt_outdir=True)
  1376. end_silence()
  1377. # 100 words chosen randomly from here:
  1378. # https://github.com/bitcoin/bips/pull/432/files/6332230d63149a950d05db78964a03bfd344e6b0
  1379. rwords = """
  1380. алфавит алый амнезия амфора артист баян белый биатлон брат бульвар веревка вернуть весть возраст
  1381. восток горло горный десяток дятел ежевика жест жизнь жрать заговор здание зона изделие итог кабина
  1382. кавалер каждый канал керосин класс клятва князь кривой крыша крючок кузнец кукла ландшафт мальчик
  1383. масса масштаб матрос мрак муравей мычать негодяй носок ночной нрав оборот оружие открытие оттенок
  1384. палуба пароход период пехота печать письмо позор полтора понятие поцелуй почему приступ пруд пятно
  1385. ранее режим речь роса рынок рябой седой сердце сквозь смех снимок сойти соперник спичка стон
  1386. сувенир сугроб суть сцена театр тираж толк удивить улыбка фирма читатель эстония эстрада юность
  1387. """
  1388. def make_brainwallet_file(fn):
  1389. # Print random words with random whitespace in between
  1390. wl = rwords.split()
  1391. nwords,ws_list,max_spaces = 10,' \n',5
  1392. def rand_ws_seq():
  1393. nchars = getrandnum(1) % max_spaces + 1
  1394. return ''.join([ws_list[getrandnum_range(1,200) % len(ws_list)] for i in range(nchars)])
  1395. rand_pairs = [wl[getrandnum_range(1,200) % len(wl)] + rand_ws_seq() for i in range(nwords)]
  1396. d = ''.join(rand_pairs).rstrip() + '\n'
  1397. if opt.verbose: msg_r('Brainwallet password:\n{}'.format(cyan(d)))
  1398. write_data_to_file(fn,d,'brainwallet password',silent=True,ignore_opt_outdir=True)
  1399. def confirm_continue():
  1400. if keypress_confirm(blue('Continue?'),default_yes=True):
  1401. if opt.verbose or opt.exact_output: sys.stderr.write('\n')
  1402. else:
  1403. raise KeyboardInterrupt('Exiting at user request')
  1404. def do_between():
  1405. if opt.pause:
  1406. confirm_continue()
  1407. elif opt.verbose or opt.exact_output:
  1408. sys.stderr.write('\n')
  1409. rebuild_list = OrderedDict()
  1410. def check_needs_rerun(
  1411. ts,
  1412. cmd,
  1413. build=False,
  1414. root=True,
  1415. force_delete=False,
  1416. dpy=False
  1417. ):
  1418. rerun = (False,True)[root] # force_delete is not passed to recursive call
  1419. fns = []
  1420. if force_delete or not root:
  1421. # does cmd produce a needed dependency(ies)?
  1422. ret = ts.get_num_exts_for_cmd(cmd,dpy)
  1423. if ret:
  1424. for ext in ret[1]:
  1425. fn = get_file_with_ext(ext,cfgs[ret[0]]['tmpdir'],delete=build)
  1426. if fn:
  1427. if force_delete: os.unlink(fn)
  1428. else: fns.append(fn)
  1429. else: rerun = True
  1430. fdeps = ts.generate_file_deps(cmd)
  1431. cdeps = ts.generate_cmd_deps(fdeps)
  1432. # print 'cmd,fdeps,cdeps,fns: ',cmd,fdeps,cdeps,fns # DEBUG
  1433. for fn in fns:
  1434. my_age = os.stat(fn).st_mtime
  1435. for num,ext in fdeps:
  1436. f = get_file_with_ext(ext,cfgs[num]['tmpdir'],delete=build)
  1437. if f and os.stat(f).st_mtime > my_age:
  1438. rerun = True
  1439. for cdep in cdeps:
  1440. if check_needs_rerun(ts,cdep,build=build,root=False,dpy=cmd):
  1441. rerun = True
  1442. if build:
  1443. if rerun:
  1444. for fn in fns:
  1445. if not root: os.unlink(fn)
  1446. if not (dpy and opt.skip_deps):
  1447. ts.do_cmd(cmd)
  1448. if not root: do_between()
  1449. else:
  1450. # If prog produces multiple files:
  1451. if cmd not in rebuild_list or rerun == True:
  1452. rebuild_list[cmd] = (rerun,fns[0] if fns else '') # FIX
  1453. return rerun
  1454. def refcheck(desc,chk,refchk):
  1455. vmsg("Comparing {} '{}' to stored reference".format(desc,chk))
  1456. if chk == refchk:
  1457. ok()
  1458. else:
  1459. m = "\nFatal error - {} '{}' does not match reference value '{}'. Aborting test"
  1460. raise TestSuiteFatalException(m.format(desc,chk,refchk))
  1461. def check_deps(cmds):
  1462. if len(cmds) != 1:
  1463. die(1,'Usage: {} check_deps <command>'.format(g.prog_name))
  1464. cmd = cmds[0]
  1465. if cmd not in cmd_data:
  1466. die(1,"'{}': unrecognized command".format(cmd))
  1467. if not opt.quiet:
  1468. msg("Checking dependencies for '{}'".format(cmd))
  1469. check_needs_rerun(ts,cmd,build=False)
  1470. w = max(map(len,rebuild_list)) + 1
  1471. for cmd in rebuild_list:
  1472. c = rebuild_list[cmd]
  1473. m = 'Rebuild' if (c[0] and c[1]) else 'Build' if c[0] else 'OK'
  1474. msg('cmd {:<{w}} {}'.format(cmd+':', m, w=w))
  1475. # mmsg(cmd,c)
  1476. def clean(usr_dirs=[]):
  1477. if opt.skip_deps: return
  1478. all_dirs = MMGenTestSuite().list_tmp_dirs()
  1479. dirnums = (usr_dirs or all_dirs)
  1480. for d in sorted(dirnums):
  1481. if str(d) in all_dirs:
  1482. cleandir(all_dirs[str(d)])
  1483. else:
  1484. die(1,'{}: invalid directory number'.format(d))
  1485. cleandir(data_dir)
  1486. cleandir(trash_dir)
  1487. def skip_for_win():
  1488. if g.platform == 'win':
  1489. import traceback
  1490. f = traceback.extract_stack()[-2][-2]
  1491. msg("Skipping test '{}': not supported on Windows platform".format(f))
  1492. return True
  1493. else:
  1494. return False
  1495. class MMGenTestSuite(object):
  1496. def __init__(self):
  1497. pass
  1498. def list_tmp_dirs(self):
  1499. d = {}
  1500. for k in cfgs: d[k] = cfgs[k]['tmpdir']
  1501. return d
  1502. def get_num_exts_for_cmd(self,cmd,dpy=False): # dpy ignored here
  1503. num = str(cmd_data[cmd][0])
  1504. dgl = cfgs[num]['dep_generators']
  1505. # mmsg(num,cmd,dgl)
  1506. if cmd in dgl.values():
  1507. exts = [k for k in dgl if dgl[k] == cmd]
  1508. return (num,exts)
  1509. else:
  1510. return None
  1511. def do_cmd(self,cmd):
  1512. # delete files produced by this cmd
  1513. # for ext,tmpdir in find_generated_exts(cmd):
  1514. # print cmd, get_file_with_ext(ext,tmpdir)
  1515. d = [(str(num),ext) for exts,num in cmd_data[cmd][2] for ext in exts]
  1516. # delete files depended on by this cmd
  1517. al = [get_file_with_ext(ext,cfgs[num]['tmpdir']) for num,ext in d]
  1518. global cfg
  1519. cfg = cfgs[str(cmd_data[cmd][0])]
  1520. if opt.resume:
  1521. if cmd == opt.resume:
  1522. ymsg("Resuming at '{}'".format(cmd))
  1523. opt.resume = False
  1524. opt.skip_deps = False
  1525. else:
  1526. return
  1527. if opt.profile: start = time.time()
  1528. self.__class__.__dict__[cmd](*([self,cmd] + al))
  1529. if opt.profile:
  1530. msg('\r\033[50C{:.4f}'.format(time.time() - start))
  1531. global cmd_total
  1532. cmd_total += 1
  1533. if cmd == opt.exit_after:
  1534. sys.exit(0)
  1535. def generate_file_deps(self,cmd):
  1536. return [(str(n),e) for exts,n in cmd_data[cmd][2] for e in exts]
  1537. def generate_cmd_deps(self,fdeps):
  1538. return [cfgs[str(n)]['dep_generators'][ext] for n,ext in fdeps]
  1539. def helpscreens(self,name,arg='--help'):
  1540. scripts = (
  1541. 'walletgen','walletconv','walletchk','txcreate','txsign','txsend','txdo','txbump',
  1542. 'addrgen','addrimport','keygen','passchg','tool','passgen','regtest','autosign')
  1543. for s in scripts:
  1544. t = MMGenExpect(name,('mmgen-'+s),[arg],extra_desc='(mmgen-{})'.format(s),no_output=True)
  1545. t.ok()
  1546. def longhelpscreens(self,name): self.helpscreens(name,arg='--longhelp')
  1547. def walletgen(self,name,del_dw_run='dummy',seed_len=None,gen_dfl_wallet=False):
  1548. write_to_tmpfile(cfg,pwfile,cfg['wpasswd']+'\n')
  1549. args = ['-p1']
  1550. if not gen_dfl_wallet: args += ['-d',cfg['tmpdir']]
  1551. if seed_len: args += ['-l',str(seed_len)]
  1552. t = MMGenExpect(name,'mmgen-walletgen', args + [usr_rand_arg])
  1553. t.license()
  1554. t.usr_rand(usr_rand_chars)
  1555. t.expect('Generating')
  1556. t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
  1557. t.label()
  1558. global have_dfl_wallet
  1559. if not have_dfl_wallet and gen_dfl_wallet:
  1560. t.expect('move it to the data directory? (Y/n): ','y')
  1561. have_dfl_wallet = True
  1562. t.written_to_file('MMGen wallet')
  1563. t.ok()
  1564. def walletgen_dfl_wallet(self,name,seed_len=None):
  1565. self.walletgen(name,seed_len=seed_len,gen_dfl_wallet=True)
  1566. def brainwalletgen_ref(self,name):
  1567. sl_arg = '-l{}'.format(cfg['seed_len'])
  1568. hp_arg = '-p{}'.format(ref_wallet_hash_preset)
  1569. label = "test.py ref. wallet (pw '{}', seed len {}) α".format(ref_wallet_brainpass,cfg['seed_len'])
  1570. bf = 'ref.mmbrain'
  1571. args = ['-d',cfg['tmpdir'],hp_arg,sl_arg,'-ib','-L',label]
  1572. write_to_tmpfile(cfg,bf,ref_wallet_brainpass)
  1573. write_to_tmpfile(cfg,pwfile,cfg['wpasswd'])
  1574. t = MMGenExpect(name,'mmgen-walletconv', args + [usr_rand_arg])
  1575. t.license()
  1576. t.expect('Enter brainwallet: ', ref_wallet_brainpass+'\n')
  1577. t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
  1578. t.usr_rand(usr_rand_chars)
  1579. sid = os.path.basename(t.written_to_file('MMGen wallet')).split('-')[0]
  1580. refcheck('Seed ID',sid,cfg['seed_id'])
  1581. def refwalletgen(self,name): self.brainwalletgen_ref(name)
  1582. def passchg(self,name,wf,pf,label_action='cmdline'):
  1583. silence()
  1584. write_to_tmpfile(cfg,pwfile,get_data_from_file(pf))
  1585. end_silence()
  1586. add_args = {'cmdline': ['-d',cfg['tmpdir'],'-L','Changed label (UTF-8) α'],
  1587. 'keep': ['-d',trash_dir,'--keep-label'],
  1588. 'user': ['-d',trash_dir]
  1589. }[label_action]
  1590. t = MMGenExpect(name,'mmgen-passchg', add_args + [usr_rand_arg, '-p2'] + ([],[wf])[bool(wf)])
  1591. t.license()
  1592. t.passphrase('MMGen wallet',cfgs['1']['wpasswd'],pwtype='old')
  1593. t.expect_getend('Hash preset changed to ')
  1594. t.passphrase('MMGen wallet',cfg['wpasswd'],pwtype='new') # reuse passphrase?
  1595. t.expect('Repeat passphrase: ',cfg['wpasswd']+'\n')
  1596. t.usr_rand(usr_rand_chars)
  1597. if label_action == 'user':
  1598. t.expect('Enter a wallet label.*: ','Interactive Label (UTF-8) α\n',regex=True)
  1599. t.expect_getend(('Label changed to ','Reusing label ')[label_action=='keep'])
  1600. # t.expect_getend('Key ID changed: ')
  1601. if not wf:
  1602. t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
  1603. t.written_to_file('New wallet')
  1604. t.expect('Securely deleting old wallet')
  1605. # t.expect('Okay to WIPE 1 regular file ? (Yes/No)','Yes\n')
  1606. t.expect('Wallet passphrase has changed')
  1607. t.expect_getend('has been changed to ')
  1608. else:
  1609. t.written_to_file('MMGen wallet')
  1610. t.ok()
  1611. def passchg_keeplabel(self,name,wf,pf):
  1612. return self.passchg(name,wf,pf,label_action='keep')
  1613. def passchg_usrlabel(self,name,wf,pf):
  1614. return self.passchg(name,wf,pf,label_action='user')
  1615. def passchg_dfl_wallet(self,name,pf):
  1616. return self.passchg(name=name,wf=None,pf=pf)
  1617. def walletchk(self,name,wf,pf,desc='MMGen wallet',add_args=[],sid=None,pw=False,extra_desc=''):
  1618. args = []
  1619. hp = cfg['hash_preset'] if 'hash_preset' in cfg else '1'
  1620. wf_arg = [wf] if wf else []
  1621. t = MMGenExpect(name,'mmgen-walletchk',
  1622. add_args+args+['-p',hp]+wf_arg,
  1623. extra_desc=extra_desc)
  1624. if desc != 'hidden incognito data':
  1625. t.expect("Getting {} from file '".format(desc))
  1626. if pw:
  1627. t.passphrase(desc,cfg['wpasswd'])
  1628. t.expect(['Passphrase is OK', 'Passphrase.* are correct'],regex=True)
  1629. chk = t.expect_getend('Valid {} for Seed ID '.format(desc))[:8]
  1630. if sid: t.cmp_or_die(chk,sid)
  1631. else: t.ok()
  1632. def walletchk_newpass(self,name,wf,pf):
  1633. return self.walletchk(name,wf,pf,pw=True)
  1634. def walletchk_newpass_dfl_wallet(self,name,pf):
  1635. return self.walletchk_newpass(name,wf=None,pf=pf)
  1636. def delete_dfl_wallet(self,name,pf):
  1637. with open(os.path.join(cfg['tmpdir'],'del_dw_run'),'w') as f: pass
  1638. if opt.no_dw_delete: return True
  1639. for wf in [f for f in os.listdir(g.data_dir) if f[-6:]=='.mmdat']:
  1640. os.unlink(os.path.join(g.data_dir,wf))
  1641. MMGenExpect(name,'',msg_only=True)
  1642. global have_dfl_wallet
  1643. have_dfl_wallet = False
  1644. ok()
  1645. def addrgen(self,name,wf,pf=None,check_ref=False,ftype='addr',id_str=None,extra_args=[],mmtype=None):
  1646. if ftype[:4] != 'pass' and not mmtype:
  1647. if cfg['segwit']: mmtype = ('segwit','bech32')[bool(opt.bech32)]
  1648. cmd_pfx = (ftype,'pass')[ftype[:4]=='pass']
  1649. t = MMGenExpect(name,'mmgen-{}gen'.format(cmd_pfx),
  1650. ['-d',cfg['tmpdir']] +
  1651. extra_args +
  1652. ([],['--type='+str(mmtype)])[bool(mmtype)] +
  1653. ([],[wf])[bool(wf)] +
  1654. ([id_str] if id_str else []) +
  1655. [cfg['{}_idx_list'.format(cmd_pfx)]],
  1656. extra_desc='({})'.format(mmtype) if mmtype in ('segwit','bech32') else '')
  1657. t.license()
  1658. t.passphrase('MMGen wallet',cfg['wpasswd'])
  1659. t.expect('Passphrase is OK')
  1660. desc = ('address','password')[ftype[:4]=='pass']
  1661. chk = t.expect_getend(r'Checksum for {} data .*?: '.format(desc),regex=True)
  1662. if ftype[:4] == 'pass':
  1663. t.expect('Encrypt password list? (y/N): ','\n')
  1664. t.written_to_file('Password list',oo=True)
  1665. else:
  1666. t.written_to_file('Addresses',oo=True)
  1667. if check_ref:
  1668. try: k = { 'pass32': 'passfile32_chk',
  1669. 'passhex': 'passfilehex_chk',
  1670. 'pass': 'passfile_chk'}[ftype]
  1671. except: k = '{}file{}_chk'.format(ftype,'_'+mmtype if mmtype else '')
  1672. chk_ref = cfg[k] if ftype[:4] == 'pass' else cfg[k][fork][g.testnet]
  1673. refcheck('{}list data checksum'.format(ftype),chk,chk_ref)
  1674. else:
  1675. t.ok()
  1676. def addrgen_dfl_wallet(self,name,pf=None,check_ref=False):
  1677. return self.addrgen(name,wf=None,pf=pf,check_ref=check_ref)
  1678. def refaddrgen(self,name,wf,pf):
  1679. self.addrgen(name,wf,pf=pf,check_ref=True)
  1680. def refaddrgen_compressed(self,name,wf,pf):
  1681. if opt.segwit or opt.bech32:
  1682. msg('Skipping non-Segwit address generation'); return True
  1683. self.addrgen(name,wf,pf=pf,check_ref=True,mmtype='compressed')
  1684. def txcreate_ui_common(self,t,name,
  1685. menu=[],inputs='1',
  1686. file_desc='Transaction',
  1687. input_sels_prompt='to spend',
  1688. bad_input_sels=False,non_mmgen_inputs=0,
  1689. interactive_fee='',
  1690. fee_desc='transaction fee',fee_res=None,eth_fee_res=None,
  1691. add_comment='',view='t',save=True,no_ok=False):
  1692. for choice in menu + ['q']:
  1693. t.expect(r'\[q\]uit view, .*?:.',choice,regex=True)
  1694. if bad_input_sels:
  1695. for r in ('x','3-1','9999'):
  1696. t.expect(input_sels_prompt+': ',r+'\n')
  1697. t.expect(input_sels_prompt+': ',inputs+'\n')
  1698. if not name[:4] == 'txdo':
  1699. for i in range(non_mmgen_inputs):
  1700. t.expect('Accept? (y/N): ','y')
  1701. have_est_fee = t.expect([fee_desc+': ','OK? (Y/n): ']) == 1
  1702. if have_est_fee and not interactive_fee:
  1703. t.send('y')
  1704. else:
  1705. if have_est_fee: t.send('n')
  1706. if eth_fee_res:
  1707. t.expect('or gas price: ',interactive_fee+'\n')
  1708. else:
  1709. t.send(interactive_fee+'\n')
  1710. if fee_res: t.expect(fee_res)
  1711. t.expect('OK? (Y/n): ','y')
  1712. t.expect('(Y/n): ','\n') # chg amt OK?
  1713. t.do_comment(add_comment)
  1714. t.view_tx(view)
  1715. if not name[:4] == 'txdo':
  1716. t.expect('(y/N): ',('n','y')[save])
  1717. t.written_to_file(file_desc)
  1718. if not no_ok: t.ok()
  1719. def txsign_ui_common(self,t,name, view='t',add_comment='',
  1720. ni=False,save=True,do_passwd=False,
  1721. file_desc='Signed transaction',no_ok=False,has_label=False):
  1722. txdo = name[:4] == 'txdo'
  1723. if do_passwd:
  1724. t.passphrase('MMGen wallet',cfg['wpasswd'])
  1725. if not ni and not txdo:
  1726. t.view_tx(view)
  1727. t.do_comment(add_comment,has_label=has_label)
  1728. t.expect('(Y/n): ',('n','y')[save])
  1729. t.written_to_file(file_desc)
  1730. if not txdo and not no_ok: t.ok()
  1731. def do_confirm_send(self,t,quiet=False,confirm_send=True):
  1732. t.expect('Are you sure you want to broadcast this')
  1733. m = ('YES, I REALLY WANT TO DO THIS','YES')[quiet]
  1734. t.expect("'{}' to confirm: ".format(m),('',m)[confirm_send]+'\n')
  1735. def txsend_ui_common(self,t,name, view='n',add_comment='',
  1736. confirm_send=True,bogus_send=True,quiet=False,
  1737. file_desc='Sent transaction',no_ok=False,has_label=False):
  1738. txdo = name[:4] == 'txdo'
  1739. if not txdo:
  1740. t.license() # MMGEN_NO_LICENSE is set, so does nothing
  1741. t.view_tx(view)
  1742. t.do_comment(add_comment,has_label=has_label)
  1743. self.do_confirm_send(t,quiet=quiet,confirm_send=confirm_send)
  1744. if bogus_send:
  1745. txid = ''
  1746. t.expect('BOGUS transaction NOT sent')
  1747. else:
  1748. txid = t.expect_getend('Transaction sent: ')
  1749. assert len(txid) == 64,"'{}': Incorrect txid length!".format(txid)
  1750. t.written_to_file(file_desc)
  1751. if not txdo and not no_ok: t.ok()
  1752. return txid
  1753. def txcreate_common(self,name,
  1754. sources=['1'],
  1755. non_mmgen_input='',
  1756. do_label=False,
  1757. txdo_args=[],
  1758. add_args=[],
  1759. view='n',
  1760. addrs_per_wallet=addrs_per_wallet,
  1761. non_mmgen_input_compressed=True,
  1762. cmdline_inputs=False):
  1763. if opt.verbose or opt.exact_output:
  1764. sys.stderr.write(green('Generating fake tracking wallet info\n'))
  1765. silence()
  1766. ad,tx_data = create_tx_data(sources,addrs_per_wallet)
  1767. dfake = create_fake_unspent_data(ad,tx_data,non_mmgen_input,non_mmgen_input_compressed)
  1768. write_fake_data_to_file(repr(dfake))
  1769. cmd_args = make_txcreate_cmdline(tx_data)
  1770. if cmdline_inputs:
  1771. from mmgen.tx import TwLabel
  1772. cmd_args = ['--inputs={},{},{},{},{},{}'.format(
  1773. TwLabel(dfake[0][lbl_id]).mmid,dfake[1]['address'],
  1774. TwLabel(dfake[2][lbl_id]).mmid,dfake[3]['address'],
  1775. TwLabel(dfake[4][lbl_id]).mmid,dfake[5]['address']
  1776. ),'--outdir='+trash_dir] + cmd_args[1:]
  1777. end_silence()
  1778. if opt.verbose or opt.exact_output: sys.stderr.write('\n')
  1779. t = MMGenExpect(name,
  1780. 'mmgen-'+('txcreate','txdo')[bool(txdo_args)],
  1781. ([],['--rbf'])[g.proto.cap('rbf')] +
  1782. ['-f',tx_fee,'-B'] + add_args + cmd_args + txdo_args)
  1783. if t.expect([('Get','Transac')[cmdline_inputs],'Unable to connect to \S+'],regex=True) == 1:
  1784. raise TestSuiteException('\n'+t.p.after)
  1785. if cmdline_inputs:
  1786. t.written_to_file('tion')
  1787. t.ok()
  1788. return
  1789. t.license()
  1790. if txdo_args and add_args: # txdo4
  1791. t.do_decrypt_ka_data(hp='1',pw=cfgs['14']['kapasswd'])
  1792. for num in tx_data:
  1793. t.expect_getend('ting address data from file ')
  1794. chk=t.expect_getend(r'Checksum for address data .*?: ',regex=True)
  1795. verify_checksum_or_exit(tx_data[num]['chk'],chk)
  1796. # not in tracking wallet warning, (1 + num sources) times
  1797. for num in range(len(tx_data) + 1):
  1798. t.expect('Continue anyway? (y/N): ','y')
  1799. outputs_list = [(addrs_per_wallet+1)*i + 1 for i in range(len(tx_data))]
  1800. if non_mmgen_input: outputs_list.append(len(tx_data)*(addrs_per_wallet+1) + 1)
  1801. self.txcreate_ui_common(t,name,
  1802. menu=(['M'],['M','D','m','g'])[name=='txcreate'],
  1803. inputs=' '.join(map(str,outputs_list)),
  1804. add_comment=('',ref_tx_label_lat_cyr_gr)[do_label],
  1805. non_mmgen_inputs=(0,1)[bool(non_mmgen_input and not txdo_args)],
  1806. view=view)
  1807. return t
  1808. def txcreate(self,name,addrfile):
  1809. self.txcreate_common(name,sources=['1'],add_args=['--vsize-adj=1.01'])
  1810. def txcreate_ni(self,name,addrfile):
  1811. self.txcreate_common(name,sources=['1'],cmdline_inputs=True,add_args=['--yes'])
  1812. def txbump(self,name,txfile,prepend_args=[],seed_args=[]):
  1813. if not g.proto.cap('rbf'):
  1814. msg('Skipping RBF'); return True
  1815. args = prepend_args + ['--quiet','--outdir='+cfg['tmpdir'],txfile] + seed_args
  1816. t = MMGenExpect(name,'mmgen-txbump',args)
  1817. if seed_args:
  1818. t.do_decrypt_ka_data(hp='1',pw=cfgs['14']['kapasswd'])
  1819. t.expect('deduct the fee from (Hit ENTER for the change output): ','1\n')
  1820. # Fee must be > tx_fee + network relay fee (currently 0.00001)
  1821. t.expect('OK? (Y/n): ','\n')
  1822. t.expect('Enter transaction fee: ',txbump_fee+'\n')
  1823. t.expect('OK? (Y/n): ','\n')
  1824. if seed_args: # sign and send
  1825. t.do_comment(False,has_label=True)
  1826. for cnum,desc in (('1','incognito data'),('3','MMGen wallet'),('4','MMGen wallet')):
  1827. t.passphrase(desc,cfgs[cnum]['wpasswd'])
  1828. self.do_confirm_send(t,quiet=not g.debug,confirm_send=True)
  1829. if g.debug:
  1830. t.written_to_file('Transaction')
  1831. else:
  1832. t.do_comment(False)
  1833. t.expect('Save transaction? (y/N): ','y')
  1834. t.written_to_file('Transaction')
  1835. os.unlink(txfile) # our tx file replaces the original
  1836. cmd = 'touch ' + os.path.join(cfg['tmpdir'],'txbump')
  1837. os.system(cmd.encode())
  1838. t.ok()
  1839. def txdo(self,name,addrfile,wallet):
  1840. t = self.txcreate_common(name,sources=['1'],txdo_args=[wallet])
  1841. self.txsign_ui_common(t,name,view='n',do_passwd=True)
  1842. self.txsend_ui_common(t,name)
  1843. t.ok()
  1844. def txcreate_dfl_wallet(self,name,addrfile):
  1845. self.txcreate_common(name,sources=['15'])
  1846. def txsign_end(self,t,tnum=None,has_label=False):
  1847. t.expect('Signing transaction')
  1848. t.do_comment(False,has_label=has_label)
  1849. t.expect('Save signed transaction.*?\? \(Y/n\): ','y',regex=True)
  1850. t.written_to_file('Signed transaction' + (' #' + tnum if tnum else ''), oo=True)
  1851. def txsign(self,name,txfile,wf,pf='',bumpf='',save=True,has_label=False,do_passwd=True,extra_opts=[]):
  1852. t = MMGenExpect(name,'mmgen-txsign', extra_opts + ['-d',cfg['tmpdir'],txfile]+([],[wf])[bool(wf)])
  1853. t.license()
  1854. t.view_tx('n')
  1855. if do_passwd: t.passphrase('MMGen wallet',cfg['wpasswd'])
  1856. if save:
  1857. self.txsign_end(t,has_label=has_label)
  1858. t.ok()
  1859. else:
  1860. t.do_comment(False,has_label=has_label)
  1861. t.expect('Save signed transaction? (Y/n): ','n')
  1862. t.ok(exit_val=1)
  1863. def txsign_dfl_wallet(self,name,txfile,pf='',save=True,has_label=False):
  1864. return self.txsign(name,txfile,wf=None,pf=pf,save=save,has_label=has_label)
  1865. def txsend(self,name,sigfile,bogus_send=True,extra_opts=[]):
  1866. if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = ''
  1867. t = MMGenExpect(name,'mmgen-txsend', extra_opts + ['-d',cfg['tmpdir'],sigfile])
  1868. if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = '1'
  1869. self.txsend_ui_common(t,name,view='t',add_comment='')
  1870. def walletconv_export(self,name,wf,desc,uargs=[],out_fmt='w',pf=None,out_pw=False):
  1871. opts = ['-d',cfg['tmpdir'],'-o',out_fmt] + uargs + \
  1872. ([],[wf])[bool(wf)] + ([],['-P',pf])[bool(pf)]
  1873. t = MMGenExpect(name,'mmgen-walletconv',opts)
  1874. t.license()
  1875. if not pf:
  1876. t.passphrase('MMGen wallet',cfg['wpasswd'])
  1877. if out_pw:
  1878. t.passphrase_new('new '+desc,cfg['wpasswd'])
  1879. t.usr_rand(usr_rand_chars)
  1880. if ' '.join(desc.split()[-2:]) == 'incognito data':
  1881. m = 'Generating encryption key from OS random data '
  1882. t.expect(m); t.expect(m)
  1883. ic_id = t.expect_getend('New Incog Wallet ID: ')
  1884. t.expect(m)
  1885. if desc == 'hidden incognito data':
  1886. write_to_tmpfile(cfg,incog_id_fn,ic_id)
  1887. ret = t.expect(['Create? (Y/n): ',"'YES' to confirm: "])
  1888. if ret == 0:
  1889. t.send('\n')
  1890. t.expect('Enter file size: ',str(hincog_bytes)+'\n')
  1891. else:
  1892. t.send('YES\n')
  1893. if out_fmt == 'w': t.label()
  1894. return t.written_to_file(capfirst(desc),oo=True),t
  1895. def export_seed(self,name,wf,desc='seed data',out_fmt='seed',pf=None):
  1896. f,t = self.walletconv_export(name,wf,desc=desc,out_fmt=out_fmt,pf=pf)
  1897. silence()
  1898. msg('{}: {}'.format(capfirst(desc),cyan(get_data_from_file(f,desc))))
  1899. end_silence()
  1900. t.ok()
  1901. def export_hex(self,name,wf,desc='hexadecimal seed data',out_fmt='hex',pf=None):
  1902. self.export_seed(name,wf,desc=desc,out_fmt=out_fmt,pf=pf)
  1903. def export_seed_dfl_wallet(self,name,pf,desc='seed data',out_fmt='seed'):
  1904. self.export_seed(name,wf=None,desc=desc,out_fmt=out_fmt,pf=pf)
  1905. def export_mnemonic(self,name,wf):
  1906. self.export_seed(name,wf,desc='mnemonic data',out_fmt='words')
  1907. def export_incog(self,name,wf,desc='incognito data',out_fmt='i',add_args=[]):
  1908. uargs = ['-p1',usr_rand_arg] + add_args
  1909. f,t = self.walletconv_export(name,wf,desc=desc,out_fmt=out_fmt,uargs=uargs,out_pw=True)
  1910. t.ok()
  1911. def export_incog_hex(self,name,wf):
  1912. self.export_incog(name,wf,desc='hex incognito data',out_fmt='xi')
  1913. # TODO: make outdir and hidden incog compatible (ignore --outdir and warn user?)
  1914. def export_incog_hidden(self,name,wf):
  1915. rf = os.path.join(cfg['tmpdir'],hincog_fn)
  1916. add_args = ['-J','{},{}'.format(rf,hincog_offset)]
  1917. self.export_incog(
  1918. name,wf,desc='hidden incognito data',out_fmt='hi',add_args=add_args)
  1919. def addrgen_seed(self,name,wf,foo,desc='seed data',in_fmt='seed'):
  1920. stdout = (False,True)[desc=='seed data'] #capture output to screen once
  1921. add_args = ([],['-S'])[bool(stdout)] + get_segwit_arg(cfg)
  1922. t = MMGenExpect(name,'mmgen-addrgen', add_args +
  1923. ['-i'+in_fmt,'-d',cfg['tmpdir'],wf,cfg['addr_idx_list']])
  1924. t.license()
  1925. t.expect_getend('Valid {} for Seed ID '.format(desc))
  1926. vmsg('Comparing generated checksum with checksum from previous address file')
  1927. chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
  1928. if stdout: t.read()
  1929. verify_checksum_or_exit(get_addrfile_checksum(),chk)
  1930. if in_fmt == 'seed':
  1931. t.ok()
  1932. else:
  1933. t.no_overwrite()
  1934. t.ok(exit_val=1)
  1935. def addrgen_hex(self,name,wf,foo,desc='hexadecimal seed data',in_fmt='hex'):
  1936. self.addrgen_seed(name,wf,foo,desc=desc,in_fmt=in_fmt)
  1937. def addrgen_mnemonic(self,name,wf,foo):
  1938. self.addrgen_seed(name,wf,foo,desc='mnemonic data',in_fmt='words')
  1939. def addrgen_incog(self,name,wf=[],foo='',in_fmt='i',desc='incognito data',args=[]):
  1940. t = MMGenExpect(name,'mmgen-addrgen', args + get_segwit_arg(cfg) + ['-i'+in_fmt,'-d',cfg['tmpdir']]+
  1941. ([],[wf])[bool(wf)] + [cfg['addr_idx_list']])
  1942. t.license()
  1943. t.expect_getend('Incog Wallet ID: ')
  1944. t.hash_preset(desc,'1')
  1945. t.passphrase('{} \w{{8}}'.format(desc),cfg['wpasswd'])
  1946. vmsg('Comparing generated checksum with checksum from address file')
  1947. chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
  1948. verify_checksum_or_exit(get_addrfile_checksum(),chk)
  1949. t.no_overwrite()
  1950. t.ok(exit_val=1)
  1951. def addrgen_incog_hex(self,name,wf,foo):
  1952. self.addrgen_incog(name,wf,'',in_fmt='xi',desc='hex incognito data')
  1953. def addrgen_incog_hidden(self,name,wf,foo):
  1954. rf = os.path.join(cfg['tmpdir'],hincog_fn)
  1955. self.addrgen_incog(name,[],'',in_fmt='hi',desc='hidden incognito data',
  1956. args=['-H','{},{}'.format(rf,hincog_offset),'-l',str(hincog_seedlen)])
  1957. def keyaddrgen(self,name,wf,pf=None,check_ref=False,mmtype=None):
  1958. if cfg['segwit'] and not mmtype:
  1959. mmtype = ('segwit','bech32')[bool(opt.bech32)]
  1960. args = ['-d',cfg['tmpdir'],usr_rand_arg,wf,cfg['addr_idx_list']]
  1961. t = MMGenExpect(name,'mmgen-keygen',
  1962. ([],['--type='+str(mmtype)])[bool(mmtype)] + args,
  1963. extra_desc='({})'.format(mmtype) if mmtype in ('segwit','bech32') else '')
  1964. t.license()
  1965. t.passphrase('MMGen wallet',cfg['wpasswd'])
  1966. chk = t.expect_getend(r'Checksum for key-address data .*?: ',regex=True)
  1967. if check_ref:
  1968. k = 'keyaddrfile{}_chk'.format('_'+mmtype if mmtype else '')
  1969. refcheck('key-address data checksum',chk,cfg[k][fork][g.testnet])
  1970. return
  1971. t.expect('Encrypt key list? (y/N): ','y')
  1972. t.usr_rand(usr_rand_chars)
  1973. t.hash_preset('new key list','1')
  1974. t.passphrase_new('new key list',cfg['kapasswd'])
  1975. t.written_to_file('Encrypted secret keys',oo=True)
  1976. t.ok()
  1977. def refkeyaddrgen(self,name,wf,pf):
  1978. self.keyaddrgen(name,wf,pf,check_ref=True)
  1979. def refkeyaddrgen_compressed(self,name,wf,pf):
  1980. if opt.segwit or opt.bech32:
  1981. msg('Skipping non-Segwit key-address generation'); return True
  1982. self.keyaddrgen(name,wf,pf,check_ref=True,mmtype='compressed')
  1983. def refpasswdgen(self,name,wf,pf):
  1984. self.addrgen(name,wf,pf,check_ref=True,ftype='pass',id_str='alice@crypto.org')
  1985. def ref_b32passwdgen(self,name,wf,pf):
  1986. ea = ['--base32','--passwd-len','17']
  1987. self.addrgen(name,wf,pf,check_ref=True,ftype='pass32',id_str='фубар@crypto.org',extra_args=ea)
  1988. def ref_hexpasswdgen(self,name,wf,pf):
  1989. ea = ['--hex']
  1990. self.addrgen(name,wf,pf,check_ref=True,ftype='passhex',id_str='фубар@crypto.org',extra_args=ea)
  1991. def txsign_keyaddr(self,name,keyaddr_file,txfile):
  1992. t = MMGenExpect(name,'mmgen-txsign', ['-d',cfg['tmpdir'],'-M',keyaddr_file,txfile])
  1993. t.license()
  1994. t.do_decrypt_ka_data(hp='1',pw=cfg['kapasswd'])
  1995. t.view_tx('n')
  1996. self.txsign_end(t)
  1997. t.ok()
  1998. def walletgen2(self,name,del_dw_run='dummy'):
  1999. self.walletgen(name,seed_len=128)
  2000. def addrgen2(self,name,wf):
  2001. self.addrgen(name,wf,pf='')
  2002. def txcreate2(self,name,addrfile):
  2003. self.txcreate_common(name,sources=['2'])
  2004. def txsign2(self,name,txf1,wf1,txf2,wf2):
  2005. t = MMGenExpect(name,'mmgen-txsign', ['-d',cfg['tmpdir'],txf1,wf1,txf2,wf2])
  2006. t.license()
  2007. for cnum in ('1','2'):
  2008. t.view_tx('n')
  2009. t.passphrase('MMGen wallet',cfgs[cnum]['wpasswd'])
  2010. self.txsign_end(t,cnum)
  2011. t.ok()
  2012. def export_mnemonic2(self,name,wf):
  2013. self.export_mnemonic(name,wf)
  2014. def walletgen3(self,name,del_dw_run='dummy'):
  2015. self.walletgen(name)
  2016. def addrgen3(self,name,wf):
  2017. self.addrgen(name,wf,pf='')
  2018. def txcreate3(self,name,addrfile1,addrfile2):
  2019. self.txcreate_common(name,sources=['1','3'])
  2020. def txsign3(self,name,wf1,wf2,txf2):
  2021. t = MMGenExpect(name,'mmgen-txsign', ['-d',cfg['tmpdir'],wf1,wf2,txf2])
  2022. t.license()
  2023. t.view_tx('n')
  2024. for cnum in ('1','3'):
  2025. t.passphrase('MMGen wallet',cfgs[cnum]['wpasswd'])
  2026. self.txsign_end(t)
  2027. t.ok()
  2028. def walletgen4(self,name,del_dw_run='dummy'):
  2029. bwf = os.path.join(cfg['tmpdir'],cfg['bw_filename'])
  2030. make_brainwallet_file(bwf)
  2031. seed_len = str(cfg['seed_len'])
  2032. args = ['-d',cfg['tmpdir'],'-p1',usr_rand_arg,'-l'+seed_len,'-ib']
  2033. t = MMGenExpect(name,'mmgen-walletconv', args + [bwf])
  2034. t.license()
  2035. t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
  2036. t.usr_rand(usr_rand_chars)
  2037. t.label()
  2038. t.written_to_file('MMGen wallet')
  2039. t.ok()
  2040. def addrgen4(self,name,wf):
  2041. self.addrgen(name,wf,pf='')
  2042. def txcreate4(self,name,f1,f2,f3,f4,f5,f6):
  2043. self.txcreate_common(name,sources=['1','2','3','4','14'],non_mmgen_input='4',do_label=True,view='y')
  2044. def txdo4(self,name,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12):
  2045. non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
  2046. add_args = ['-d',cfg['tmpdir'],'-i','brain','-b'+cfg['bw_params'],'-p1','-k',non_mm_fn,'-M',f12]
  2047. get_file_with_ext('sigtx',cfg['tmpdir'],delete_all=True) # delete tx signed by txsign4
  2048. t = self.txcreate_common(name,sources=['1','2','3','4','14'],
  2049. non_mmgen_input='4',do_label=True,txdo_args=[f7,f8,f9,f10],add_args=add_args)
  2050. for cnum,desc in (('1','incognito data'),('3','MMGen wallet')):
  2051. t.passphrase('{}'.format(desc),cfgs[cnum]['wpasswd'])
  2052. self.txsign_ui_common(t,name)
  2053. self.txsend_ui_common(t,name)
  2054. cmd = 'touch ' + os.path.join(cfg['tmpdir'],'txdo')
  2055. os.system(cmd.encode())
  2056. t.ok()
  2057. def txsign4(self,name,f1,f2,f3,f4,f5,f6):
  2058. non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
  2059. a = ['-d',cfg['tmpdir'],'-i','brain','-b'+cfg['bw_params'],'-p1','-k',non_mm_fn,'-M',f6,f1,f2,f3,f4,f5]
  2060. t = MMGenExpect(name,'mmgen-txsign',a)
  2061. t.license()
  2062. t.do_decrypt_ka_data(hp='1',pw=cfgs['14']['kapasswd'])
  2063. t.view_tx('t')
  2064. for cnum,desc in (('1','incognito data'),('3','MMGen wallet')):
  2065. t.passphrase('{}'.format(desc),cfgs[cnum]['wpasswd'])
  2066. self.txsign_end(t,has_label=True)
  2067. t.ok()
  2068. def txbump4(self,name,f1,f2,f3,f4,f5,f6,f7,f8,f9): # f7:txfile,f9:'txdo'
  2069. non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
  2070. self.txbump(name,f7,prepend_args=['-p1','-k',non_mm_fn,'-M',f1],seed_args=[f2,f3,f4,f5,f6,f8])
  2071. def walletgen5(self,name,del_dw_run='dummy'):
  2072. self.walletgen(name)
  2073. def addrgen5(self,name,wf):
  2074. self.addrgen(name,wf,pf='')
  2075. def txcreate5(self,name,addrfile):
  2076. self.txcreate_common(name,sources=['20'],non_mmgen_input='20',non_mmgen_input_compressed=False)
  2077. def txsign5(self,name,txf,wf,bad_vsize=True,add_args=[]):
  2078. non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
  2079. t = MMGenExpect(name,'mmgen-txsign', add_args + ['-d',cfg['tmpdir'],'-k',non_mm_fn,txf,wf])
  2080. t.license()
  2081. t.view_tx('n')
  2082. t.passphrase('MMGen wallet',cfgs['20']['wpasswd'])
  2083. if bad_vsize:
  2084. t.expect('Estimated transaction vsize')
  2085. t.expect('1 transaction could not be signed')
  2086. exit_val = 2
  2087. else:
  2088. t.do_comment(False)
  2089. t.expect('Save signed transaction? (Y/n): ','y')
  2090. exit_val = 0
  2091. t.read()
  2092. t.ok(exit_val=exit_val)
  2093. def walletgen6(self,name,del_dw_run='dummy'):
  2094. self.walletgen(name)
  2095. def addrgen6(self,name,wf):
  2096. self.addrgen(name,wf,pf='')
  2097. def txcreate6(self,name,addrfile):
  2098. self.txcreate_common(
  2099. name,sources=['21'],non_mmgen_input='21',non_mmgen_input_compressed=False,add_args=['--vsize-adj=1.08'])
  2100. def txsign6(self,name,txf,wf):
  2101. return self.txsign5(name,txf,wf,bad_vsize=False,add_args=['--vsize-adj=1.08'])
  2102. def tool_encrypt(self,name,infile=''):
  2103. if infile:
  2104. infn = infile
  2105. else:
  2106. d = os.urandom(1033)
  2107. tmp_fn = cfg['tool_enc_infn']
  2108. write_to_tmpfile(cfg,tmp_fn,d,binary=True)
  2109. infn = get_tmpfile_fn(cfg,tmp_fn)
  2110. t = MMGenExpect(name,'mmgen-tool',['-d',cfg['tmpdir'],usr_rand_arg,'encrypt',infn])
  2111. t.usr_rand(usr_rand_chars)
  2112. t.hash_preset('user data','1')
  2113. t.passphrase_new('user data',tool_enc_passwd)
  2114. t.written_to_file('Encrypted data')
  2115. t.ok()
  2116. # Generate the reference mmenc file
  2117. # def tool_encrypt_ref(self,name):
  2118. # infn = get_tmpfile_fn(cfg,cfg['tool_enc_ref_infn'])
  2119. # write_data_to_file(infn,cfg['tool_enc_reftext'],silent=True)
  2120. # self.tool_encrypt(name,infn)
  2121. def tool_decrypt(self,name,f1,f2):
  2122. of = name + '.out'
  2123. pre = []
  2124. t = MMGenExpect(name,'mmgen-tool',
  2125. pre+['-d',cfg['tmpdir'],'decrypt',f2,'outfile='+of,'hash_preset=1'])
  2126. t.passphrase('user data',tool_enc_passwd)
  2127. t.written_to_file('Decrypted data')
  2128. d1 = read_from_file(f1,binary=True)
  2129. d2 = read_from_file(get_tmpfile_fn(cfg,of),binary=True)
  2130. cmp_or_die(d1,d2,skip_ok=False)
  2131. def tool_find_incog_data(self,name,f1,f2):
  2132. i_id = read_from_file(f2).rstrip()
  2133. vmsg('Incog ID: {}'.format(cyan(i_id)))
  2134. t = MMGenExpect(name,'mmgen-tool',
  2135. ['-d',cfg['tmpdir'],'find_incog_data',f1,i_id])
  2136. o = t.expect_getend('Incog data for ID {} found at offset '.format(i_id))
  2137. os.unlink(f1)
  2138. cmp_or_die(hincog_offset,int(o))
  2139. def autosign_live(self,name):
  2140. return self.autosign_minimal(name,live=True)
  2141. def autosign_minimal(self,name,live=False):
  2142. return self.autosign(name,
  2143. coins=['btc','eth'],
  2144. txfiles=['btc','eth','erc20','etc'],
  2145. txcount=7,
  2146. live=live)
  2147. # tests everything except device detection, mount/unmount
  2148. def autosign( self,name,
  2149. coins=['btc','bch','ltc','eth'],
  2150. txfiles=['btc','bch','ltc','eth','erc20','etc'],
  2151. txcount=11,
  2152. live=False):
  2153. if skip_for_win(): return
  2154. def make_wallet(opts):
  2155. t = MMGenExpect(name,'mmgen-autosign',opts+['gen_key'],extra_desc='(gen_key)')
  2156. t.expect_getend('Wrote key file ')
  2157. t.ok()
  2158. t = MMGenExpect(name,'mmgen-autosign',opts+['setup'],extra_desc='(setup)')
  2159. t.expect('words: ','3')
  2160. t.expect('OK? (Y/n): ','\n')
  2161. mn_fn = os.path.join(ref_dir,cfgs['8']['seed_id']+'.mmwords') # 98831F3A
  2162. mn = read_from_file(mn_fn).strip().split()
  2163. mn = ['foo'] + mn[:5] + ['realiz','realized'] + mn[5:]
  2164. wnum = 1
  2165. max_wordlen = 12
  2166. def get_pad_chars(n):
  2167. ret = ''
  2168. for i in range(n):
  2169. m = int(hexlify(os.urandom(1)),16) % 32
  2170. ret += r'123579!@#$%^&*()_+-=[]{}"?/,.<>|'[m]
  2171. return ret
  2172. for i in range(len(mn)):
  2173. w = mn[i]
  2174. if len(w) > 5:
  2175. w = w + '\n'
  2176. else:
  2177. w = get_pad_chars(3 if randbool() else 0) + w[0] + get_pad_chars(3) + w[1:] + get_pad_chars(7)
  2178. w = w[:max_wordlen+1]
  2179. em,rm = 'Enter word #{}: ','Repeat word #{}: '
  2180. ret = t.expect((em.format(wnum),rm.format(wnum-1)))
  2181. if ret == 0: wnum += 1
  2182. for j in range(len(w)):
  2183. t.send(w[j])
  2184. time.sleep(0.005)
  2185. wf = t.written_to_file('Autosign wallet')
  2186. t.ok()
  2187. def copy_files(mountpoint,remove_signed_only=False,include_bad_tx=True):
  2188. fdata_in = (('btc',''),
  2189. ('bch',''),
  2190. ('ltc','litecoin'),
  2191. ('eth','ethereum'),
  2192. ('erc20','ethereum'),
  2193. ('etc','ethereum_classic'))
  2194. fdata = [e for e in fdata_in if e[0] in txfiles]
  2195. tfns = [cfgs['8']['ref_tx_file'][c][1] for c,d in fdata] + \
  2196. [cfgs['8']['ref_tx_file'][c][0] for c,d in fdata]
  2197. tfs = [os.path.join(ref_dir,d[1],fn) for d,fn in zip(fdata+fdata,tfns)]
  2198. for f,fn in zip(tfs,tfns):
  2199. if fn: # use empty fn to skip file
  2200. target = os.path.join(mountpoint,'tx',fn)
  2201. remove_signed_only or shutil.copyfile(f,target)
  2202. try: os.unlink(target.replace('.rawtx','.sigtx'))
  2203. except: pass
  2204. # make a bad tx file
  2205. bad_tx = os.path.join(mountpoint,'tx','bad.rawtx')
  2206. if include_bad_tx and not remove_signed_only:
  2207. with open(bad_tx,'w') as f:
  2208. f.write('bad tx data')
  2209. if not include_bad_tx:
  2210. try: os.unlink(bad_tx)
  2211. except: pass
  2212. def do_autosign_live(opts,mountpoint,led_opts=[],gen_wallet=True):
  2213. def do_mount():
  2214. try: subprocess.check_call(['mount',mountpoint])
  2215. except: pass
  2216. def do_unmount():
  2217. try: subprocess.check_call(['umount',mountpoint])
  2218. except: pass
  2219. omsg_r(blue('\nRemove removable device and then hit ENTER '))
  2220. input()
  2221. if gen_wallet: make_wallet(opts)
  2222. else: do_mount()
  2223. copy_files(mountpoint,include_bad_tx=not led_opts)
  2224. desc = '(sign)'
  2225. m1 = "Running 'mmgen-autosign wait'"
  2226. m2 = 'Insert removable device '
  2227. if led_opts:
  2228. if led_opts == ['--led']:
  2229. m1 = "Running 'mmgen-autosign wait' with --led. The LED should start blinking slowly now"
  2230. elif led_opts == ['--stealth-led']:
  2231. m1 = "Running 'mmgen-autosign wait' with --stealth-led. You should see no LED activity now"
  2232. m2 = 'Insert removable device and watch for fast LED activity during signing'
  2233. desc = '(sign - {})'.format(led_opts[0])
  2234. def do_loop():
  2235. omsg(blue(m2))
  2236. t.expect('{} transactions signed'.format(txcount))
  2237. if not led_opts:
  2238. t.expect('1 transaction failed to sign')
  2239. t.expect('Waiting')
  2240. do_unmount()
  2241. omsg(green(m1))
  2242. t = MMGenExpect(name,'mmgen-autosign',opts+led_opts+['wait'],extra_desc=desc)
  2243. if not opt.exact_output: omsg('')
  2244. do_loop()
  2245. do_mount() # race condition due to device insertion detection
  2246. copy_files(mountpoint,remove_signed_only=True,include_bad_tx=not led_opts)
  2247. do_unmount()
  2248. do_loop()
  2249. t.kill(2)
  2250. t.ok(exit_val=1)
  2251. def do_autosign(opts,mountpoint):
  2252. make_wallet(opts)
  2253. copy_files(mountpoint,include_bad_tx=True)
  2254. t = MMGenExpect(name,'mmgen-autosign',opts+['wait'],extra_desc='(sign)')
  2255. t.expect('{} transactions signed'.format(txcount))
  2256. t.expect('1 transaction failed to sign')
  2257. t.expect('Waiting')
  2258. t.kill(2)
  2259. t.ok(exit_val=1)
  2260. if live:
  2261. mountpoint = '/mnt/tx'
  2262. if not os.path.ismount(mountpoint):
  2263. try:
  2264. subprocess.check_call(['mount',mountpoint])
  2265. imsg("Mounted '{}'".format(mountpoint))
  2266. except:
  2267. imsg("Could not mount '{}'! Exiting".format(mountpoint))
  2268. return
  2269. txdir = os.path.join(mountpoint,'tx')
  2270. if not os.path.isdir(txdir):
  2271. imsg("Directory '{}' does not exist! Exiting".format(mountpoint))
  2272. return
  2273. opts = ['--coins='+','.join(coins)]
  2274. led_files = { 'opi': ('/sys/class/leds/orangepi:red:status/brightness',),
  2275. 'rpi': ('/sys/class/leds/led0/brightness','/sys/class/leds/led0/trigger') }
  2276. for k in ('opi','rpi'):
  2277. if os.path.exists(led_files[k][0]):
  2278. led_support = k
  2279. break
  2280. else:
  2281. led_support = None
  2282. if led_support:
  2283. for fn in (led_files[led_support]):
  2284. subprocess.check_call(['sudo','chmod','0666',fn])
  2285. omsg(purple('Running autosign test with no LED'))
  2286. do_autosign_live(opts,mountpoint)
  2287. omsg(purple("Running autosign test with '--led'"))
  2288. do_autosign_live(opts,mountpoint,led_opts=['--led'],gen_wallet=False)
  2289. omsg(purple("Running autosign test with '--stealth-led'"))
  2290. do_autosign_live(opts,mountpoint,led_opts=['--stealth-led'],gen_wallet=False)
  2291. else:
  2292. do_autosign_live(opts,mountpoint)
  2293. else:
  2294. mountpoint = cfg['tmpdir']
  2295. opts = ['--no-insert-check','--mountpoint='+mountpoint,'--coins='+','.join(coins)]
  2296. try: os.mkdir(os.path.join(mountpoint,'tx'))
  2297. except: pass
  2298. do_autosign(opts,mountpoint)
  2299. # Saved reference file tests
  2300. def ref_wallet_conv(self,name):
  2301. wf = os.path.join(ref_dir,cfg['ref_wallet'])
  2302. self.walletconv_in(name,wf,'MMGen wallet',pw=True,oo=True)
  2303. def ref_mn_conv(self,name,ext='mmwords',desc='Mnemonic data'):
  2304. wf = os.path.join(ref_dir,cfg['seed_id']+'.'+ext)
  2305. self.walletconv_in(name,wf,desc,oo=True)
  2306. def ref_seed_conv(self,name):
  2307. self.ref_mn_conv(name,ext='mmseed',desc='Seed data')
  2308. def ref_hex_conv(self,name):
  2309. self.ref_mn_conv(name,ext='mmhex',desc='Hexadecimal seed data')
  2310. def ref_brain_conv(self,name):
  2311. uopts = ['-i','b','-p','1','-l',str(cfg['seed_len'])]
  2312. self.walletconv_in(name,None,'brainwallet',uopts,oo=True)
  2313. def ref_incog_conv(self,name,wfk='ic_wallet',in_fmt='i',desc='incognito data'):
  2314. uopts = ['-i',in_fmt,'-p','1','-l',str(cfg['seed_len'])]
  2315. wf = os.path.join(ref_dir,cfg[wfk])
  2316. self.walletconv_in(name,wf,desc,uopts,oo=True,pw=True)
  2317. def ref_incox_conv(self,name):
  2318. self.ref_incog_conv(name,in_fmt='xi',wfk='ic_wallet_hex',desc='hex incognito data')
  2319. def ref_hincog_conv(self,name,wfk='hic_wallet',add_uopts=[]):
  2320. ic_f = os.path.join(ref_dir,cfg[wfk])
  2321. uopts = ['-i','hi','-p','1','-l',str(cfg['seed_len'])] + add_uopts
  2322. hi_opt = ['-H','{},{}'.format(ic_f,ref_wallet_incog_offset)]
  2323. self.walletconv_in(name,None,'hidden incognito data',uopts+hi_opt,oo=True,pw=True)
  2324. def ref_hincog_conv_old(self,name):
  2325. self.ref_hincog_conv(name,wfk='hic_wallet_old',add_uopts=['-O'])
  2326. def ref_wallet_conv_out(self,name):
  2327. self.walletconv_out(name,'MMGen wallet','w',pw=True)
  2328. def ref_mn_conv_out(self,name):
  2329. self.walletconv_out(name,'mnemonic data','mn')
  2330. def ref_seed_conv_out(self,name):
  2331. self.walletconv_out(name,'seed data','seed')
  2332. def ref_hex_conv_out(self,name):
  2333. self.walletconv_out(name,'hexadecimal seed data','hexseed')
  2334. def ref_incog_conv_out(self,name):
  2335. self.walletconv_out(name,'incognito data',out_fmt='i',pw=True)
  2336. def ref_incox_conv_out(self,name):
  2337. self.walletconv_out(name,'hex incognito data',out_fmt='xi',pw=True)
  2338. def ref_hincog_conv_out(self,name,ic_f=None):
  2339. if not ic_f: ic_f = os.path.join(cfg['tmpdir'],hincog_fn)
  2340. hi_parms = '{},{}'.format(ic_f,ref_wallet_incog_offset)
  2341. sl_parm = '-l' + str(cfg['seed_len'])
  2342. self.walletconv_out(name,
  2343. 'hidden incognito data', 'hi',
  2344. uopts=['-J',hi_parms,sl_parm],
  2345. uopts_chk=['-H',hi_parms,sl_parm],
  2346. pw=True
  2347. )
  2348. def ref_hincog_blkdev_conv_out(self,name):
  2349. imsg('Creating block device image file')
  2350. ic_img = os.path.join(cfg['tmpdir'],'hincog_blkdev_img')
  2351. subprocess.check_output(['dd','if=/dev/zero','of='+ic_img,'bs=1K','count=1'],stderr=subprocess.PIPE)
  2352. ic_dev = subprocess.check_output(['losetup','-f']).strip().decode()
  2353. ic_dev_mode_orig = '{:o}'.format(os.stat(ic_dev).st_mode & 0xfff)
  2354. ic_dev_mode = '0666'
  2355. imsg("Changing permissions on loop device to '{}'".format(ic_dev_mode))
  2356. subprocess.check_output(['sudo','chmod',ic_dev_mode,ic_dev],stderr=subprocess.PIPE)
  2357. imsg("Attaching loop device '{}'".format(ic_dev))
  2358. subprocess.check_output(['losetup',ic_dev,ic_img])
  2359. self.ref_hincog_conv_out(name,ic_f=ic_dev)
  2360. imsg("Detaching loop device '{}'".format(ic_dev))
  2361. subprocess.check_output(['losetup','-d',ic_dev])
  2362. imsg("Resetting permissions on loop device to '{}'".format(ic_dev_mode_orig))
  2363. subprocess.check_output(['sudo','chmod',ic_dev_mode_orig,ic_dev],stderr=subprocess.PIPE)
  2364. def ref_wallet_chk(self,name):
  2365. wf = os.path.join(ref_dir,cfg['ref_wallet'])
  2366. self.walletchk(name,wf,pf=None,pw=True,sid=cfg['seed_id'])
  2367. def ref_ss_chk(self,name,ss=None):
  2368. wf = os.path.join(ref_dir,'{}.{}'.format(cfg['seed_id'],ss.ext))
  2369. self.walletchk(name,wf,pf=None,desc=ss.desc,sid=cfg['seed_id'])
  2370. def ref_seed_chk(self,name):
  2371. from mmgen.seed import SeedFile
  2372. self.ref_ss_chk(name,ss=SeedFile)
  2373. def ref_hex_chk(self,name):
  2374. from mmgen.seed import HexSeedFile
  2375. self.ref_ss_chk(name,ss=HexSeedFile)
  2376. def ref_mn_chk(self,name):
  2377. from mmgen.seed import Mnemonic
  2378. self.ref_ss_chk(name,ss=Mnemonic)
  2379. def ref_brain_chk(self,name,bw_file=ref_bw_file):
  2380. wf = os.path.join(ref_dir,bw_file)
  2381. add_args = ['-l{}'.format(cfg['seed_len']), '-p'+ref_bw_hash_preset]
  2382. self.walletchk(name,wf,pf=None,add_args=add_args,
  2383. desc='brainwallet',sid=cfg['ref_bw_seed_id'])
  2384. def ref_brain_chk_spc3(self,name):
  2385. self.ref_brain_chk(name,bw_file=ref_bw_file_spc)
  2386. def ref_hincog_chk(self,name,desc='hidden incognito data'):
  2387. for wtype,edesc,of_arg in ('hic_wallet','',[]), \
  2388. ('hic_wallet_old','(old format)',['-O']):
  2389. ic_arg = ['-H{},{}'.format(os.path.join(ref_dir,cfg[wtype]),ref_wallet_incog_offset)]
  2390. slarg = ['-l{} '.format(cfg['seed_len'])]
  2391. hparg = ['-p1']
  2392. if wtype == 'hic_wallet_old' and opt.profile: msg('')
  2393. t = MMGenExpect(name,'mmgen-walletchk',
  2394. slarg + hparg + of_arg + ic_arg,
  2395. extra_desc=edesc)
  2396. t.passphrase(desc,cfg['wpasswd'])
  2397. if wtype == 'hic_wallet_old':
  2398. t.expect('Is the Seed ID correct? (Y/n): ','\n')
  2399. chk = t.expect_getend('Seed ID: ')
  2400. t.close()
  2401. cmp_or_die(cfg['seed_id'],chk)
  2402. def ref_addrfile_chk(self,name,ftype='addr',coin=None,subdir=None,pfx=None,mmtype=None,add_args=[]):
  2403. af_key = 'ref_{}file'.format(ftype)
  2404. af_fn = cfg[af_key].format(pfx or altcoin_pfx,'' if coin else tn_ext)
  2405. af = os.path.join(ref_dir,(subdir or ref_subdir,'')[ftype=='passwd'],af_fn)
  2406. coin_arg = [] if coin == None else ['--coin='+coin]
  2407. tool_cmd = ftype.replace('segwit','').replace('bech32','')+'file_chksum'
  2408. t = MMGenExpect(name,'mmgen-tool',coin_arg+[tool_cmd,af]+add_args)
  2409. if ftype == 'keyaddr':
  2410. t.do_decrypt_ka_data(hp=ref_kafile_hash_preset,pw=ref_kafile_pass)
  2411. rc = cfg[ 'ref_' + ftype + 'file_chksum' +
  2412. ('_'+coin.lower() if coin else '') +
  2413. ('_'+mmtype if mmtype else '')]
  2414. ref_chksum = rc if (ftype == 'passwd' or coin) else rc[g.proto.base_coin.lower()][g.testnet]
  2415. t.expect(chksum_pat,regex=True)
  2416. m = t.p.match.group(0)
  2417. t.read()
  2418. cmp_or_die(ref_chksum,m)
  2419. def ref_altcoin_addrgen(self,name,coin,mmtype,gen_what='addr',coin_suf='',add_args=[]):
  2420. wf = os.path.join(ref_dir,cfg['seed_id']+'.mmwords')
  2421. t = MMGenExpect(name,'mmgen-{}gen'.format(gen_what),
  2422. ['-Sq','--coin='+coin] +
  2423. (['--type='+mmtype] if mmtype else []) +
  2424. add_args +
  2425. [wf,cfg['addr_idx_list']])
  2426. if gen_what == 'key':
  2427. t.expect('Encrypt key list? (y/N): ','N')
  2428. chk = t.expect_getend(r'.* data checksum for \S*: ',regex=True)
  2429. chk_ref = cfg['ref_{}addrfile_chksum_{}{}'.format(('','key')[gen_what=='key'],coin.lower(),coin_suf)]
  2430. t.read()
  2431. refcheck('{}list data checksum'.format(gen_what),chk,chk_ref)
  2432. def ref_addrfile_gen_eth(self,name):
  2433. self.ref_altcoin_addrgen(name,coin='ETH',mmtype='ethereum')
  2434. def ref_addrfile_gen_etc(self,name):
  2435. self.ref_altcoin_addrgen(name,coin='ETC',mmtype='ethereum')
  2436. def ref_addrfile_gen_dash(self,name):
  2437. self.ref_altcoin_addrgen(name,coin='DASH',mmtype='compressed')
  2438. def ref_addrfile_gen_zec(self,name):
  2439. self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='compressed')
  2440. def ref_addrfile_gen_zec_z(self,name):
  2441. self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='zcash_z',coin_suf='_z')
  2442. def ref_addrfile_gen_xmr(self,name):
  2443. self.ref_altcoin_addrgen(name,coin='XMR',mmtype='monero')
  2444. def ref_addrfile_gen_xmr_old(self,name):
  2445. self.ref_altcoin_addrgen(name,coin='XMR',mmtype='monero',add_args=['--use-old-ed25519'])
  2446. def ref_keyaddrfile_gen_eth(self,name):
  2447. self.ref_altcoin_addrgen(name,coin='ETH',mmtype='ethereum',gen_what='key')
  2448. def ref_keyaddrfile_gen_etc(self,name):
  2449. self.ref_altcoin_addrgen(name,coin='ETC',mmtype='ethereum',gen_what='key')
  2450. def ref_keyaddrfile_gen_dash(self,name):
  2451. self.ref_altcoin_addrgen(name,coin='DASH',mmtype='compressed',gen_what='key')
  2452. def ref_keyaddrfile_gen_zec(self,name):
  2453. self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='compressed',gen_what='key')
  2454. def ref_keyaddrfile_gen_zec_z(self,name):
  2455. self.ref_altcoin_addrgen(name,coin='ZEC',mmtype='zcash_z',coin_suf='_z',gen_what='key')
  2456. def ref_keyaddrfile_gen_xmr(self,name):
  2457. self.ref_altcoin_addrgen(name,coin='XMR',mmtype='monero',gen_what='key')
  2458. def ref_addrfile_chk_eth(self,name):
  2459. self.ref_addrfile_chk(name,ftype='addr',coin='ETH',subdir='ethereum',pfx='-ETH')
  2460. def ref_addrfile_chk_etc(self,name):
  2461. self.ref_addrfile_chk(name,ftype='addr',coin='ETC',subdir='ethereum_classic',pfx='-ETC')
  2462. def ref_addrfile_chk_dash(self,name):
  2463. self.ref_addrfile_chk(name,ftype='addr',coin='DASH',subdir='dash',pfx='-DASH-C')
  2464. def ref_addrfile_chk_zec(self,name):
  2465. self.ref_addrfile_chk(name,ftype='addr',coin='ZEC',subdir='zcash',pfx='-ZEC-C')
  2466. def ref_addrfile_chk_zec_z(self,name):
  2467. if skip_for_win(): return
  2468. self.ref_addrfile_chk(name,ftype='addr',coin='ZEC',subdir='zcash',pfx='-ZEC-Z',
  2469. mmtype='z',add_args=['mmtype=zcash_z'])
  2470. def ref_addrfile_chk_xmr(self,name):
  2471. self.ref_addrfile_chk(name,ftype='addr',coin='XMR',subdir='monero',pfx='-XMR-M')
  2472. def ref_keyaddrfile_chk_eth(self,name):
  2473. self.ref_addrfile_chk(name,ftype='keyaddr',coin='ETH',subdir='ethereum',pfx='-ETH')
  2474. def ref_keyaddrfile_chk_etc(self,name):
  2475. self.ref_addrfile_chk(name,ftype='keyaddr',coin='ETC',subdir='ethereum_classic',pfx='-ETC')
  2476. def ref_keyaddrfile_chk_dash(self,name):
  2477. self.ref_addrfile_chk(name,ftype='keyaddr',coin='DASH',subdir='dash',pfx='-DASH-C')
  2478. def ref_keyaddrfile_chk_zec(self,name):
  2479. self.ref_addrfile_chk(name,ftype='keyaddr',coin='ZEC',subdir='zcash',pfx='-ZEC-C')
  2480. def ref_keyaddrfile_chk_zec_z(self,name):
  2481. if skip_for_win(): return
  2482. self.ref_addrfile_chk(name,ftype='keyaddr',coin='ZEC',subdir='zcash',pfx='-ZEC-Z',
  2483. mmtype='z',add_args=['mmtype=zcash_z'])
  2484. def ref_keyaddrfile_chk_xmr(self,name):
  2485. self.ref_addrfile_chk(name,ftype='keyaddr',coin='XMR',subdir='monero',pfx='-XMR-M')
  2486. def ref_keyaddrfile_chk(self,name):
  2487. self.ref_addrfile_chk(name,ftype='keyaddr')
  2488. def ref_passwdfile_chk(self,name):
  2489. self.ref_addrfile_chk(name,ftype='passwd')
  2490. def ref_segwitaddrfile_chk(self,name):
  2491. if not 'S' in g.proto.mmtypes:
  2492. msg_r('Skipping {} (not supported)'.format(name)); ok()
  2493. else:
  2494. self.ref_addrfile_chk(name,ftype='segwitaddr')
  2495. def ref_bech32addrfile_chk(self,name):
  2496. if not 'B' in g.proto.mmtypes:
  2497. msg_r('Skipping {} (not supported)'.format(name)); ok()
  2498. else:
  2499. self.ref_addrfile_chk(name,ftype='bech32addr')
  2500. # def txcreate8(self,name,addrfile):
  2501. # self.txcreate_common(name,sources=['8'])
  2502. def ref_tx_chk(self,name):
  2503. fn = cfg['ref_tx_file'][g.coin.lower()][bool(tn_ext)]
  2504. if not fn: return
  2505. tf = os.path.join(ref_dir,ref_subdir,fn)
  2506. wf = dfl_words
  2507. write_to_tmpfile(cfg,pwfile,cfg['wpasswd'])
  2508. pf = get_tmpfile_fn(cfg,pwfile)
  2509. self.txsign(name,tf,wf,pf,save=False,has_label=True,do_passwd=False)
  2510. def ref_tool_decrypt(self,name):
  2511. f = os.path.join(ref_dir,ref_enc_fn)
  2512. disable_debug()
  2513. t = MMGenExpect(name,'mmgen-tool', ['-q','decrypt',f,'outfile=-','hash_preset=1'])
  2514. restore_debug()
  2515. t.passphrase('user data',tool_enc_passwd)
  2516. t.expect(NL,nonl=True)
  2517. t.expect('to confirm: ','YES\n')
  2518. import re
  2519. o = t.read()
  2520. o = re.sub('YES\r\n','',o).split('\n')[0]
  2521. o = re.sub('\r','\n',o)
  2522. cmp_or_die(sample_text,o)
  2523. # wallet conversion tests
  2524. def walletconv_in(self,name,infile,desc,uopts=[],pw=False,oo=False):
  2525. opts = ['-d',cfg['tmpdir'],'-o','words',usr_rand_arg]
  2526. if_arg = [infile] if infile else []
  2527. d = '(convert)'
  2528. t = MMGenExpect(name,'mmgen-walletconv',opts+uopts+if_arg,extra_desc=d)
  2529. t.license()
  2530. if desc == 'brainwallet':
  2531. t.expect('Enter brainwallet: ',ref_wallet_brainpass+'\n')
  2532. if pw:
  2533. t.passphrase(desc,cfg['wpasswd'])
  2534. if name[:19] == 'ref_hincog_conv_old':
  2535. t.expect('Is the Seed ID correct? (Y/n): ','\n')
  2536. else:
  2537. t.expect(['Passphrase is OK',' are correct'])
  2538. # Output
  2539. wf = t.written_to_file('Mnemonic data',oo=oo)
  2540. t.p.wait()
  2541. t.ok()
  2542. # back check of result
  2543. if opt.profile: msg('')
  2544. self.walletchk(name,wf,pf=None,
  2545. desc='mnemonic data',
  2546. sid=cfg['seed_id'],
  2547. extra_desc='(check)'
  2548. )
  2549. def walletconv_out(self,name,desc,out_fmt='w',uopts=[],uopts_chk=[],pw=False):
  2550. opts = ['-d',cfg['tmpdir'],'-p1','-o',out_fmt] + uopts
  2551. infile = os.path.join(ref_dir,cfg['seed_id']+'.mmwords')
  2552. t = MMGenExpect(name,'mmgen-walletconv',[usr_rand_arg]+opts+[infile],extra_desc='(convert)')
  2553. add_args = ['-l{}'.format(cfg['seed_len'])]
  2554. t.license()
  2555. if pw:
  2556. t.passphrase_new('new '+desc,cfg['wpasswd'])
  2557. t.usr_rand(usr_rand_chars)
  2558. if ' '.join(desc.split()[-2:]) == 'incognito data':
  2559. for i in (1,2,3):
  2560. t.expect('Generating encryption key from OS random data ')
  2561. if desc == 'hidden incognito data':
  2562. ret = t.expect(['Create? (Y/n): ',"'YES' to confirm: "])
  2563. if ret == 0:
  2564. t.send('\n')
  2565. t.expect('Enter file size: ',str(hincog_bytes)+'\n')
  2566. else:
  2567. t.send('YES\n')
  2568. if out_fmt == 'w': t.label()
  2569. wf = t.written_to_file(capfirst(desc),oo=True)
  2570. pf = None
  2571. t.ok()
  2572. if desc == 'hidden incognito data':
  2573. add_args += uopts_chk
  2574. wf = None
  2575. if opt.profile: msg('')
  2576. self.walletchk(name,wf,pf=pf,
  2577. desc=desc,sid=cfg['seed_id'],pw=pw,
  2578. add_args=add_args,
  2579. extra_desc='(check)')
  2580. def regtest_setup(self,name):
  2581. os.environ['MMGEN_BOGUS_WALLET_DATA'] = ''
  2582. if g.testnet:
  2583. die(2,'--testnet option incompatible with regtest test suite')
  2584. try: shutil.rmtree(os.path.join(data_dir,'regtest'))
  2585. except: pass
  2586. os.environ['MMGEN_TEST_SUITE'] = '' # mnemonic is piped to stdin, so stop being a terminal
  2587. t = MMGenExpect(name,'mmgen-regtest',['-n','setup'])
  2588. os.environ['MMGEN_TEST_SUITE'] = '1'
  2589. for s in 'Starting setup','Creating','Mined','Creating','Creating','Setup complete':
  2590. t.expect(s)
  2591. t.ok()
  2592. def regtest_walletgen(self,name,user):
  2593. t = MMGenExpect(name,'mmgen-walletgen',['-q','-r0','-p1','--'+user])
  2594. t.passphrase_new('new MMGen wallet',rt_pw)
  2595. t.label()
  2596. t.expect('move it to the data directory? (Y/n): ','y')
  2597. t.written_to_file('MMGen wallet')
  2598. t.ok()
  2599. def regtest_walletgen_bob(self,name): return self.regtest_walletgen(name,'bob')
  2600. def regtest_walletgen_alice(self,name): return self.regtest_walletgen(name,'alice')
  2601. @staticmethod
  2602. def regtest_user_dir(user,coin=None):
  2603. return os.path.join(data_dir,'regtest',coin or g.coin.lower(),user)
  2604. def regtest_user_sid(self,user):
  2605. return os.path.basename(get_file_with_ext('mmdat',self.regtest_user_dir(user)))[:8]
  2606. def regtest_addrgen(self,name,user,wf=None,passwd=rt_pw,addr_range='1-5'):
  2607. from mmgen.addr import MMGenAddrType
  2608. for mmtype in g.proto.mmtypes:
  2609. t = MMGenExpect(name,'mmgen-addrgen',
  2610. ['--quiet','--'+user,'--type='+mmtype,'--outdir={}'.format(self.regtest_user_dir(user))] +
  2611. ([],[wf])[bool(wf)] + [addr_range],
  2612. extra_desc='({})'.format(MMGenAddrType.mmtypes[mmtype]['name']))
  2613. t.passphrase('MMGen wallet',passwd)
  2614. t.written_to_file('Addresses')
  2615. t.ok()
  2616. def regtest_addrgen_bob(self,name): self.regtest_addrgen(name,'bob')
  2617. def regtest_addrgen_alice(self,name): self.regtest_addrgen(name,'alice')
  2618. def regtest_addrimport(self,name,user,sid=None,addr_range='1-5',num_addrs=5):
  2619. id_strs = { 'legacy':'', 'compressed':'-C', 'segwit':'-S', 'bech32':'-B' }
  2620. if not sid: sid = self.regtest_user_sid(user)
  2621. from mmgen.addr import MMGenAddrType
  2622. for mmtype in g.proto.mmtypes:
  2623. desc = MMGenAddrType.mmtypes[mmtype]['name']
  2624. fn = os.path.join(self.regtest_user_dir(user),
  2625. '{}{}{}[{}]{x}.testnet.addrs'.format(
  2626. sid,altcoin_pfx,id_strs[desc],addr_range,
  2627. x='-α' if g.debug_utf8 else ''))
  2628. if mmtype == g.proto.mmtypes[0] and user == 'bob':
  2629. psave = g.proto
  2630. g.proto = CoinProtocol(g.coin,True)
  2631. add_comments_to_addr_file(fn,fn,use_labels=True)
  2632. g.proto = psave
  2633. t = MMGenExpect(name,'mmgen-addrimport', ['--quiet','--'+user,'--batch',fn],extra_desc='('+desc+')')
  2634. if g.debug:
  2635. t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
  2636. t.expect('Importing')
  2637. t.expect('{} addresses imported'.format(num_addrs))
  2638. t.ok()
  2639. def regtest_addrimport_bob(self,name): self.regtest_addrimport(name,'bob')
  2640. def regtest_addrimport_alice(self,name): self.regtest_addrimport(name,'alice')
  2641. def regtest_fund_wallet(self,name,user,mmtype,amt,sid=None,addr_range='1-5'):
  2642. if not sid: sid = self.regtest_user_sid(user)
  2643. addr = self.get_addr_from_regtest_addrlist(user,sid,mmtype,0,addr_range=addr_range)
  2644. t = MMGenExpect(name,'mmgen-regtest', ['send',str(addr),str(amt)])
  2645. t.expect('Sending {} {}'.format(amt,g.coin))
  2646. t.expect('Mined 1 block')
  2647. t.ok()
  2648. def regtest_fund_bob(self,name): self.regtest_fund_wallet(name,'bob','C',rtFundAmt)
  2649. def regtest_fund_alice(self,name): self.regtest_fund_wallet(name,'alice',('L','S')[g.proto.cap('segwit')],rtFundAmt)
  2650. def regtest_user_bal(self,name,user,bal,args=['showempty=1'],skip_check=False,exit_val=0):
  2651. t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses'] + args)
  2652. if skip_check:
  2653. t.read()
  2654. t.ok(exit_val=exit_val)
  2655. else:
  2656. total = t.expect_getend('TOTAL: ')
  2657. cmp_or_die('{} {}'.format(bal,g.coin),total)
  2658. def regtest_alice_bal1(self,name):
  2659. return self.regtest_user_bal(name,'alice',rtFundAmt)
  2660. def regtest_alice_bal2(self,name):
  2661. return self.regtest_user_bal(name,'alice',rtBals[8])
  2662. def regtest_bob_bal1(self,name):
  2663. return self.regtest_user_bal(name,'bob',rtFundAmt)
  2664. def regtest_bob_bal2(self,name):
  2665. return self.regtest_user_bal(name,'bob',rtBals[0])
  2666. def regtest_bob_bal2a(self,name):
  2667. return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','show_days=1'])
  2668. def regtest_bob_bal2b(self,name):
  2669. return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','show_age=1'])
  2670. def regtest_bob_bal2c(self,name):
  2671. return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','show_age=1','minconf=2'],skip_check=True)
  2672. def regtest_bob_bal2d(self,name):
  2673. return self.regtest_user_bal(name,'bob',rtBals[0],args=['show_age=1','minconf=2'],skip_check=True)
  2674. def regtest_bob_bal2e(self,name):
  2675. return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','show_age=1','sort=age'])
  2676. def regtest_bob_bal2f(self,name):
  2677. return self.regtest_user_bal(name,'bob',rtBals[0],args=['showempty=1','show_age=1','sort=age,reverse'])
  2678. def regtest_bob_bal3(self,name):
  2679. return self.regtest_user_bal(name,'bob',rtBals[1])
  2680. def regtest_bob_bal4(self,name):
  2681. return self.regtest_user_bal(name,'bob',rtBals[2])
  2682. def regtest_bob_bal5(self,name):
  2683. return self.regtest_user_bal(name,'bob',rtBals[3])
  2684. def regtest_bob_bal6(self,name):
  2685. return self.regtest_user_bal(name,'bob',rtBals[7])
  2686. def regtest_bob_bal5_getbalance(self,name):
  2687. t_ext,t_mmgen = rtBals_gb[0],rtBals_gb[1]
  2688. assert Decimal(t_ext) + Decimal(t_mmgen) == Decimal(rtBals[3])
  2689. t = MMGenExpect(name,'mmgen-tool',['--bob','getbalance'])
  2690. t.expect(r'\n[0-9A-F]{8}: .* '+t_mmgen,regex=True)
  2691. t.expect(r'\nNon-MMGen: .* '+t_ext,regex=True)
  2692. t.expect(r'\nTOTAL: .* '+rtBals[3],regex=True)
  2693. t.read()
  2694. t.ok()
  2695. def regtest_bob_alice_bal(self,name):
  2696. t = MMGenExpect(name,'mmgen-regtest',['get_balances'])
  2697. t.expect('Switching')
  2698. ret = t.expect_getend("Bob's balance:").strip()
  2699. cmp_or_die(rtBals[4],ret,skip_ok=True)
  2700. ret = t.expect_getend("Alice's balance:").strip()
  2701. cmp_or_die(rtBals[5],ret,skip_ok=True)
  2702. ret = t.expect_getend("Total balance:").strip()
  2703. cmp_or_die(rtBals[6],ret,skip_ok=True)
  2704. t.ok()
  2705. def regtest_user_txdo( self,name,user,fee,
  2706. outputs_cl,
  2707. outputs_list,
  2708. extra_args=[],
  2709. wf=None,
  2710. pw=rt_pw,
  2711. do_label=False,
  2712. bad_locktime=False,
  2713. full_tx_view=False):
  2714. os.environ['MMGEN_BOGUS_SEND'] = ''
  2715. t = MMGenExpect(name,'mmgen-txdo',
  2716. ['-d',cfg['tmpdir'],'-B','--'+user] +
  2717. (['--tx-fee='+fee] if fee else []) +
  2718. extra_args + ([],[wf])[bool(wf)] + outputs_cl)
  2719. os.environ['MMGEN_BOGUS_SEND'] = '1'
  2720. self.txcreate_ui_common(t,'txdo',
  2721. menu=['M'],inputs=outputs_list,
  2722. file_desc='Signed transaction',
  2723. interactive_fee=(tx_fee,'')[bool(fee)],
  2724. add_comment=ref_tx_label_jp,
  2725. view='t',save=True)
  2726. t.passphrase('MMGen wallet',pw)
  2727. t.written_to_file('Signed transaction')
  2728. self.do_confirm_send(t)
  2729. s,exit_val = (('Transaction sent',0),("can't be included",1))[bad_locktime]
  2730. t.expect(s)
  2731. t.ok(exit_val)
  2732. def regtest_bob_split1(self,name):
  2733. sid = self.regtest_user_sid('bob')
  2734. outputs_cl = [sid+':C:1,100', sid+':L:2,200',sid+':'+rtBobOp3]
  2735. return self.regtest_user_txdo(name,'bob',rtFee[0],outputs_cl,'1',do_label=True,full_tx_view=True)
  2736. def get_addr_from_regtest_addrlist(self,user,sid,mmtype,idx,addr_range='1-5'):
  2737. id_str = { 'L':'', 'S':'-S', 'C':'-C', 'B':'-B' }[mmtype]
  2738. ext = '{}{}{}[{}]{x}.testnet.addrs'.format(
  2739. sid,altcoin_pfx,id_str,addr_range,x='-α' if g.debug_utf8 else '')
  2740. fn = get_file_with_ext(ext,self.regtest_user_dir(user),no_dot=True)
  2741. psave = g.proto
  2742. g.proto = CoinProtocol(g.coin,True)
  2743. if hasattr(g.proto,'bech32_hrp_rt'):
  2744. g.proto.bech32_hrp = g.proto.bech32_hrp_rt
  2745. silence()
  2746. addr = AddrList(fn).data[idx].addr
  2747. end_silence()
  2748. g.proto = psave
  2749. return addr
  2750. def create_tx_outputs(self,user,data):
  2751. sid = self.regtest_user_sid(user)
  2752. return [self.get_addr_from_regtest_addrlist(user,sid,mmtype,idx-1)+amt_str for mmtype,idx,amt_str in data]
  2753. def regtest_bob_rbf_send(self,name):
  2754. outputs_cl = self.create_tx_outputs('alice',(('L',1,',60'),('C',1,',40'))) # alice_sid:L:1, alice_sid:C:1
  2755. outputs_cl += [self.regtest_user_sid('bob')+':'+rtBobOp3]
  2756. return self.regtest_user_txdo(name,'bob',rtFee[1],outputs_cl,'3',
  2757. extra_args=([],['--rbf'])[g.proto.cap('rbf')])
  2758. def regtest_bob_send_non_mmgen(self,name):
  2759. outputs_cl = self.create_tx_outputs('alice',(
  2760. (('L','S')[g.proto.cap('segwit')],2,',10'),
  2761. (('L','S')[g.proto.cap('segwit')],3,'')
  2762. )) # alice_sid:S:2, alice_sid:S:3
  2763. fn = os.path.join(cfg['tmpdir'],'non-mmgen.keys')
  2764. return self.regtest_user_txdo(name,'bob',rtFee[3],outputs_cl,'1,4-10',
  2765. extra_args=['--keys-from-file='+fn,'--vsize-adj=1.02'])
  2766. def regtest_alice_send_estimatefee(self,name):
  2767. outputs_cl = self.create_tx_outputs('bob',(('L',1,''),)) # bob_sid:L:1
  2768. return self.regtest_user_txdo(name,'alice',None,outputs_cl,'1') # fee=None
  2769. def regtest_user_txbump(self,name,user,txfile,fee,red_op):
  2770. if not g.proto.cap('rbf'):
  2771. msg('Skipping RBF'); return True
  2772. os.environ['MMGEN_BOGUS_SEND'] = ''
  2773. t = MMGenExpect(name,'mmgen-txbump',
  2774. ['-d',cfg['tmpdir'],'--send','--'+user,'--tx-fee='+fee,'--output-to-reduce='+red_op] + [txfile])
  2775. os.environ['MMGEN_BOGUS_SEND'] = '1'
  2776. t.expect('OK? (Y/n): ','y') # output OK?
  2777. t.expect('OK? (Y/n): ','y') # fee OK?
  2778. t.do_comment(False,has_label=True)
  2779. t.passphrase('MMGen wallet',rt_pw)
  2780. t.written_to_file('Signed transaction')
  2781. self.txsend_ui_common(t,'txdo',bogus_send=False,file_desc='Signed transaction')
  2782. t.read()
  2783. t.ok()
  2784. def regtest_bob_rbf_bump(self,name):
  2785. ext = ',{}]{x}.testnet.sigtx'.format(rtFee[1][:-1],x='-α' if g.debug_utf8 else '')
  2786. txfile = get_file_with_ext(ext,cfg['tmpdir'],delete=False,no_dot=True)
  2787. return self.regtest_user_txbump(name,'bob',txfile,rtFee[2],'c')
  2788. def regtest_generate(self,name,coin=None,num_blocks=1):
  2789. int(num_blocks)
  2790. if coin: opt.coin = coin
  2791. t = MMGenExpect(name,'mmgen-regtest',['generate',str(num_blocks)])
  2792. t.expect('Mined {} block'.format(num_blocks))
  2793. t.ok()
  2794. def regtest_get_mempool(self,name):
  2795. disable_debug()
  2796. ret = MMGenExpect(name,'mmgen-regtest',['show_mempool']).read()
  2797. restore_debug()
  2798. from ast import literal_eval
  2799. return literal_eval(ret.split('\n')[0]) # allow for extra output by handler at end
  2800. def regtest_get_mempool1(self,name):
  2801. mp = self.regtest_get_mempool(name)
  2802. if len(mp) != 1:
  2803. rdie(2,'Mempool has more or less than one TX!')
  2804. write_to_tmpfile(cfg,'rbf_txid',mp[0]+'\n')
  2805. ok()
  2806. def regtest_get_mempool2(self,name):
  2807. if not g.proto.cap('rbf'):
  2808. msg('Skipping post-RBF mempool check'); return True
  2809. mp = self.regtest_get_mempool(name)
  2810. if len(mp) != 1:
  2811. rdie(2,'Mempool has more or less than one TX!')
  2812. chk = read_from_tmpfile(cfg,'rbf_txid')
  2813. if chk.strip() == mp[0]:
  2814. rdie(2,'TX in mempool has not changed! RBF bump failed')
  2815. ok()
  2816. @staticmethod
  2817. def gen_pairs(n):
  2818. disable_debug()
  2819. ret = [subprocess.check_output(
  2820. ['python3',os.path.join('cmds','mmgen-tool'),'--testnet=1'] +
  2821. (['--type=compressed'],[])[i==0] +
  2822. ['-r0','randpair']
  2823. ).decode().split() for i in range(n)]
  2824. restore_debug()
  2825. return ret
  2826. def regtest_bob_pre_import(self,name):
  2827. pairs = self.gen_pairs(5)
  2828. write_to_tmpfile(cfg,'non-mmgen.keys','\n'.join([a[0] for a in pairs])+'\n')
  2829. write_to_tmpfile(cfg,'non-mmgen.addrs','\n'.join([a[1] for a in pairs])+'\n')
  2830. return self.regtest_user_txdo(name,'bob',rtFee[4],[pairs[0][1]],'3')
  2831. def regtest_user_import(self,name,user,args):
  2832. t = MMGenExpect(name,'mmgen-addrimport',['--quiet','--'+user]+args)
  2833. if g.debug:
  2834. t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
  2835. t.expect('Importing')
  2836. t.expect('OK')
  2837. t.ok()
  2838. def regtest_bob_import_addr(self,name):
  2839. addr = read_from_tmpfile(cfg,'non-mmgen.addrs').split()[0]
  2840. return self.regtest_user_import(name,'bob',['--rescan','--address='+addr])
  2841. def regtest_bob_import_list(self,name):
  2842. fn = os.path.join(cfg['tmpdir'],'non-mmgen.addrs')
  2843. return self.regtest_user_import(name,'bob',['--addrlist',fn])
  2844. def regtest_bob_split2(self,name):
  2845. addrs = read_from_tmpfile(cfg,'non-mmgen.addrs').split()
  2846. amts = (1.12345678,2.87654321,3.33443344,4.00990099,5.43214321)
  2847. outputs1 = list(map('{},{}'.format,addrs,amts))
  2848. sid = self.regtest_user_sid('bob')
  2849. l1,l2 = (':S',':B') if 'B' in g.proto.mmtypes else (':S',':S') if g.proto.cap('segwit') else (':L',':L')
  2850. outputs2 = [sid+':C:2,6.333', sid+':L:3,6.667',sid+l1+':4,0.123',sid+l2+':5']
  2851. return self.regtest_user_txdo(name,'bob',rtFee[5],outputs1+outputs2,'1-2')
  2852. def regtest_user_add_label(self,name,user,addr,label):
  2853. t = MMGenExpect(name,'mmgen-tool',['--'+user,'add_label',addr,label])
  2854. t.expect('Added label.*in tracking wallet',regex=True)
  2855. t.ok()
  2856. def regtest_user_remove_label(self,name,user,addr):
  2857. t = MMGenExpect(name,'mmgen-tool',['--'+user,'remove_label',addr])
  2858. t.expect('Removed label.*in tracking wallet',regex=True)
  2859. t.ok()
  2860. # utf8_label = u'Edited label (40 characters, UTF8/JP) 月へ' # '\xe6\x9c\x88\xe3\x81\xb8' (Jp.)
  2861. # utf8_label_pat = ur'Edited label \(40 characters, UTF8/JP\) ......'
  2862. utf8_label = ref_tx_label_zh[:40]
  2863. utf8_label_pat = utf8_label
  2864. def regtest_bob_add_label(self,name):
  2865. sid = self.regtest_user_sid('bob')
  2866. return self.regtest_user_add_label(name,'bob',sid+':C:1',self.utf8_label)
  2867. def regtest_alice_add_label1(self,name):
  2868. sid = self.regtest_user_sid('alice')
  2869. return self.regtest_user_add_label(name,'alice',sid+':C:1','Original Label - 月へ')
  2870. def regtest_alice_add_label2(self,name):
  2871. sid = self.regtest_user_sid('alice')
  2872. return self.regtest_user_add_label(name,'alice',sid+':C:1','Replacement Label')
  2873. def regtest_alice_add_label_coinaddr(self,name):
  2874. mmaddr = self.regtest_user_sid('alice') + ':C:2'
  2875. t = MMGenExpect(name,'mmgen-tool',['--alice','listaddress',mmaddr],no_msg=True)
  2876. btcaddr = [i for i in t.read().splitlines() if i.lstrip()[0:len(mmaddr)] == mmaddr][0].split()[1]
  2877. return self.regtest_user_add_label(name,'alice',btcaddr,'Label added using coin address')
  2878. def regtest_alice_chk_label_coinaddr(self,name):
  2879. sid = self.regtest_user_sid('alice')
  2880. return self.regtest_user_chk_label(name,'alice',sid+':C:2','Label added using coin address')
  2881. def regtest_alice_add_label_badaddr(self,name,addr,reply):
  2882. t = MMGenExpect(name,'mmgen-tool',['--alice','add_label',addr,'(none)'])
  2883. t.expect(reply,regex=True)
  2884. t.ok()
  2885. def regtest_alice_add_label_badaddr1(self,name):
  2886. return self.regtest_alice_add_label_badaddr(name,rt_pw,'Invalid coin address for this chain: '+rt_pw)
  2887. def regtest_alice_add_label_badaddr2(self,name):
  2888. addr = g.proto.pubhash2addr(b'00'*20,False) # mainnet zero address
  2889. return self.regtest_alice_add_label_badaddr(name,addr,'Invalid coin address for this chain: '+addr)
  2890. def regtest_alice_add_label_badaddr3(self,name):
  2891. addr = self.regtest_user_sid('alice') + ':C:123'
  2892. return self.regtest_alice_add_label_badaddr(name,addr,
  2893. "MMGen address '{}' not found in tracking wallet".format(addr))
  2894. def regtest_alice_add_label_badaddr4(self,name):
  2895. addr = CoinProtocol(g.coin,True).pubhash2addr(b'00'*20,False) # testnet zero address
  2896. return self.regtest_alice_add_label_badaddr(name,addr,
  2897. "Address '{}' not found in tracking wallet".format(addr))
  2898. def regtest_alice_bal_rpcfail(self,name):
  2899. addr = self.regtest_user_sid('alice') + ':C:2'
  2900. os.environ['MMGEN_RPC_FAIL_ON_COMMAND'] = 'listunspent'
  2901. t = MMGenExpect(name,'mmgen-tool',['--alice','getbalance'])
  2902. os.environ['MMGEN_RPC_FAIL_ON_COMMAND'] = ''
  2903. t.expect('Method not found')
  2904. t.read()
  2905. ok()
  2906. def regtest_alice_remove_label1(self,name):
  2907. sid = self.regtest_user_sid('alice')
  2908. return self.regtest_user_remove_label(name,'alice',sid+':C:1')
  2909. def regtest_user_chk_label(self,name,user,addr,label,label_pat=None):
  2910. t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','all_labels=1'])
  2911. t.expect(r'{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,(label_pat or label)),regex=True)
  2912. t.ok()
  2913. def regtest_alice_chk_label1(self,name):
  2914. sid = self.regtest_user_sid('alice')
  2915. return self.regtest_user_chk_label(name,'alice',sid+':C:1','Original Label - 月へ')
  2916. def regtest_alice_chk_label2(self,name):
  2917. sid = self.regtest_user_sid('alice')
  2918. return self.regtest_user_chk_label(name,'alice',sid+':C:1','Replacement Label')
  2919. def regtest_alice_edit_label1(self,name):
  2920. return self.regtest_user_edit_label(name,'alice','1',self.utf8_label)
  2921. def regtest_alice_chk_label3(self,name):
  2922. sid = self.regtest_user_sid('alice')
  2923. return self.regtest_user_chk_label(name,'alice',sid+':C:1',self.utf8_label,label_pat=self.utf8_label_pat)
  2924. def regtest_alice_chk_label4(self,name):
  2925. sid = self.regtest_user_sid('alice')
  2926. return self.regtest_user_chk_label(name,'alice',sid+':C:1','-')
  2927. def regtest_user_edit_label(self,name,user,output,label):
  2928. t = MMGenExpect(name,'mmgen-txcreate',['-B','--'+user,'-i'])
  2929. t.expect(r'add \[l\]abel:.','M',regex=True)
  2930. t.expect(r'add \[l\]abel:.','l',regex=True)
  2931. t.expect(r"Enter unspent.*return to main menu\):.",output+'\n',regex=True)
  2932. t.expect(r"Enter label text.*return to main menu\):.",label+'\n',regex=True)
  2933. t.expect(r'\[q\]uit view, .*?:.','q',regex=True)
  2934. t.ok()
  2935. def regtest_stop(self,name):
  2936. if opt.no_daemon_stop:
  2937. MMGenExpect(name,'',msg_only=True)
  2938. msg_r('(leaving daemon running by user request)')
  2939. ok()
  2940. else:
  2941. t = MMGenExpect(name,'mmgen-regtest',['stop'])
  2942. t.ok()
  2943. def regtest_split_setup(self,name):
  2944. if g.coin != 'BTC': die(1,'Test valid only for coin BTC')
  2945. opt.coin = 'BTC'
  2946. return self.regtest_setup(name)
  2947. def regtest_split_fork(self,name):
  2948. opt.coin = 'B2X'
  2949. t = MMGenExpect(name,'mmgen-regtest',['fork','btc'])
  2950. t.expect('Creating fork from coin')
  2951. t.expect('successfully created')
  2952. t.ok()
  2953. def regtest_split_start(self,name,coin):
  2954. opt.coin = coin
  2955. t = MMGenExpect(name,'mmgen-regtest',['bob'])
  2956. t.expect('Starting')
  2957. t.expect('done')
  2958. t.ok()
  2959. def regtest_split_start_btc(self,name): self.regtest_split_start(name,coin='BTC')
  2960. def regtest_split_start_b2x(self,name): self.regtest_split_start(name,coin='B2X')
  2961. def regtest_split_gen_btc(self,name): self.regtest_generate(name,coin='BTC')
  2962. def regtest_split_gen_b2x(self,name): self.regtest_generate(name,coin='B2X',num_blocks=100)
  2963. def regtest_split_gen_b2x2(self,name): self.regtest_generate(name,coin='B2X')
  2964. def regtest_split_do_split(self,name):
  2965. opt.coin = 'B2X'
  2966. sid = self.regtest_user_sid('bob')
  2967. t = MMGenExpect(name,'mmgen-split',[
  2968. '--bob',
  2969. '--outdir='+cfg['tmpdir'],
  2970. '--tx-fees=0.0001,0.0003',
  2971. sid+':S:1',sid+':S:2'])
  2972. t.expect(r'\[q\]uit view, .*?:.','q', regex=True)
  2973. t.expect('outputs to spend: ','1\n')
  2974. for tx in ('timelocked','split'):
  2975. for q in ('fee','change'): t.expect('OK? (Y/n): ','y')
  2976. t.do_comment(False)
  2977. t.view_tx('t')
  2978. t.written_to_file('Long chain (timelocked) transaction')
  2979. t.written_to_file('Short chain transaction')
  2980. t.ok()
  2981. def regtest_split_sign(self,name,coin,ext):
  2982. wf = get_file_with_ext('mmdat',self.regtest_user_dir('bob',coin=coin.lower()))
  2983. txfile = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
  2984. opt.coin = coin
  2985. self.txsign(name,txfile,wf,extra_opts=['--bob'])
  2986. def regtest_split_sign_b2x(self,name):
  2987. return self.regtest_split_sign(name,coin='B2X',ext='533].rawtx')
  2988. def regtest_split_sign_btc(self,name):
  2989. return self.regtest_split_sign(name,coin='BTC',ext='9997].rawtx')
  2990. def regtest_split_send(self,name,coin,ext):
  2991. opt.coin = coin
  2992. txfile = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
  2993. self.txsend(name,txfile,bogus_send=False,extra_opts=['--bob'])
  2994. def regtest_split_send_b2x(self,name):
  2995. return self.regtest_split_send(name,coin='B2X',ext='533].sigtx')
  2996. def regtest_split_send_btc(self,name):
  2997. return self.regtest_split_send(name,coin='BTC',ext='9997].sigtx')
  2998. def regtest_split_txdo_timelock(self,name,coin,locktime,bad_locktime):
  2999. opt.coin = coin
  3000. sid = self.regtest_user_sid('bob')
  3001. self.regtest_user_txdo(
  3002. name,'bob','0.0001',[sid+':S:5'],'1',pw=rt_pw,
  3003. extra_args=['--locktime='+str(locktime)],
  3004. bad_locktime=bad_locktime)
  3005. def regtest_split_txdo_timelock_bad_btc(self,name):
  3006. self.regtest_split_txdo_timelock(name,'BTC',locktime=8888,bad_locktime=True)
  3007. def regtest_split_txdo_timelock_good_btc(self,name):
  3008. self.regtest_split_txdo_timelock(name,'BTC',locktime=1321009871,bad_locktime=False)
  3009. def regtest_split_txdo_timelock_bad_b2x(self,name):
  3010. self.regtest_split_txdo_timelock(name,'B2X',locktime=8888,bad_locktime=True)
  3011. def regtest_split_txdo_timelock_good_b2x(self,name):
  3012. self.regtest_split_txdo_timelock(name,'B2X',locktime=1321009871,bad_locktime=False)
  3013. def ethdev_setup(self,name):
  3014. MMGenExpect(name,'',msg_only=True)
  3015. os.environ['MMGEN_BOGUS_WALLET_DATA'] = ''
  3016. if subprocess.call(['which','parity'],stdout=subprocess.PIPE) == 0:
  3017. lf_arg = '--log-file=' + os.path.join(data_dir,'parity.log')
  3018. ss = 'parity.*--log-file=test/data_dir.*/parity.log' # allow for UTF8_DEBUG
  3019. try:
  3020. pid = subprocess.check_output(['pgrep','-af',ss]).split()[0]
  3021. os.kill(int(pid),9)
  3022. except: pass
  3023. # '--base-path' doesn't work together with daemon mode, so we have to clobber the main dev chain
  3024. dc_dir = os.path.join(os.environ['HOME'],'.local/share/io.parity.ethereum/chains/DevelopmentChain')
  3025. shutil.rmtree(dc_dir,ignore_errors=True)
  3026. bdir = os.path.join(data_dir,'parity')
  3027. try: os.mkdir(bdir)
  3028. except: pass
  3029. pid_fn = get_tmpfile_fn(cfg,cfg['parity_pidfile'])
  3030. opts = ['--ports-shift=4','--config=dev']
  3031. redir = None if opt.exact_output else subprocess.PIPE
  3032. subprocess.check_call(['parity',lf_arg] + opts + ['daemon',pid_fn],stderr=redir,stdout=redir)
  3033. time.sleep(3) # race condition
  3034. pid = read_from_tmpfile(cfg,cfg['parity_pidfile'])
  3035. elif subprocess.call('netstat -tnl | grep -q 127.0.0.1:8549',shell=True) == 0:
  3036. m1 = 'No parity executable found on system, but port 8549 is active!'
  3037. m2 = 'Before continuing, you should probably run the command'
  3038. m3 = 'test/test.py ethdev_setup'
  3039. m4 = 'on the remote host.'
  3040. sys.stderr.write('{}\n{}\n{} {}\n'.format(m1,m2,cyan(m3),m4))
  3041. confirm_continue()
  3042. else:
  3043. die(1,'No parity executable found!')
  3044. ok()
  3045. def ethdev_addrgen(self,name,addrs='1-3,11-13,21-23'):
  3046. from mmgen.addr import MMGenAddrType
  3047. t = MMGenExpect(name,'mmgen-addrgen', eth_args() + [dfl_words,addrs])
  3048. t.written_to_file('Addresses')
  3049. t.read()
  3050. t.ok()
  3051. def ethdev_addrimport(self,name,ext='21-23]{}.addrs',expect='9/9',add_args=[],bad_input=False):
  3052. ext = ext.format('-α' if g.debug_utf8 else '')
  3053. fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True,delete=False)
  3054. t = MMGenExpect(name,'mmgen-addrimport', eth_args()[1:] + add_args + [fn])
  3055. if bad_input:
  3056. t.read(); t.ok(2); return
  3057. if g.debug: t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
  3058. t.expect('Importing')
  3059. t.expect(expect)
  3060. t.read()
  3061. t.ok()
  3062. def ethdev_addrimport_one_addr(self,name,addr=None,extra_args=[]):
  3063. t = MMGenExpect(name,'mmgen-addrimport', eth_args()[1:] + extra_args + ['--address='+addr])
  3064. t.expect('OK')
  3065. t.ok()
  3066. def ethdev_addrimport_dev_addr(self,name):
  3067. self.ethdev_addrimport_one_addr(name,addr=eth_addr)
  3068. def ethdev_addrimport_burn_addr(self,name):
  3069. self.ethdev_addrimport_one_addr(name,addr=eth_burn_addr)
  3070. def ethdev_txcreate(self,name,args=[],menu=[],acct='1',non_mmgen_inputs=0,
  3071. interactive_fee='50G',
  3072. fee_res='0.00105 {} (50 gas price in Gwei)'.format(g.coin),
  3073. eth_fee_res=None,
  3074. fee_desc = 'gas price'):
  3075. t = MMGenExpect(name,'mmgen-txcreate', eth_args() + ['-B'] + args)
  3076. t.expect(r'add \[l\]abel, .*?:.','p', regex=True)
  3077. t.written_to_file('Account balances listing')
  3078. self.txcreate_ui_common(t,name,
  3079. menu=menu,
  3080. input_sels_prompt='to spend from',
  3081. inputs=acct,file_desc='Ethereum transaction',
  3082. bad_input_sels=True,non_mmgen_inputs=non_mmgen_inputs,
  3083. interactive_fee=interactive_fee,fee_res=fee_res,
  3084. fee_desc=fee_desc,eth_fee_res=eth_fee_res,
  3085. add_comment=ref_tx_label_jp)
  3086. def ethdev_txsign(self,name,ni=False,ext='{}.rawtx',add_args=[]):
  3087. ext = ext.format('-α' if g.debug_utf8 else '')
  3088. key_fn = get_tmpfile_fn(cfg,cfg['parity_keyfile'])
  3089. write_to_tmpfile(cfg,cfg['parity_keyfile'],eth_key+'\n')
  3090. tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
  3091. t = MMGenExpect(name,'mmgen-txsign',eth_args()+add_args + ([],['--yes'])[ni] + ['-k',key_fn,tx_fn,dfl_words])
  3092. self.txsign_ui_common(t,name,ni=ni,has_label=True)
  3093. def ethdev_txsend(self,name,ni=False,bogus_send=False,ext='{}.sigtx',add_args=[]):
  3094. ext = ext.format('-α' if g.debug_utf8 else '')
  3095. tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
  3096. if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = ''
  3097. t = MMGenExpect(name,'mmgen-txsend', eth_args()+add_args + [tx_fn])
  3098. if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = '1'
  3099. self.txsend_ui_common(t,name,quiet=True,bogus_send=bogus_send,has_label=True)
  3100. def ethdev_txcreate1(self,name):
  3101. # valid_keypresses = 'adrMmeqpvwl'
  3102. menu = ['a','d','r','M','D','e','m','m'] # include one invalid keypress, 'D'
  3103. args = ['98831F3A:E:1,123.456']
  3104. return self.ethdev_txcreate(name,args=args,menu=menu,acct='1',non_mmgen_inputs=1)
  3105. def ethdev_txsign1(self,name): self.ethdev_txsign(name)
  3106. def ethdev_txsign1_ni(self,name): self.ethdev_txsign(name,ni=True)
  3107. def ethdev_txsend1(self,name): self.ethdev_txsend(name)
  3108. def ethdev_bal1(self,name): self.ethdev_bal(name,n='1')
  3109. def ethdev_txcreate2(self,name):
  3110. args = ['98831F3A:E:11,1.234']
  3111. return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
  3112. def ethdev_txsign2(self,name): self.ethdev_txsign(name,ni=True,ext='1.234,50000]{}.rawtx')
  3113. def ethdev_txsend2(self,name): self.ethdev_txsend(name,ext='1.234,50000]{}.sigtx')
  3114. def ethdev_bal2(self,name): self.ethdev_bal(name,n='2')
  3115. def ethdev_txcreate3(self,name):
  3116. args = ['98831F3A:E:21,2.345']
  3117. return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
  3118. def ethdev_txsign3(self,name): self.ethdev_txsign(name,ni=True,ext='2.345,50000]{}.rawtx')
  3119. def ethdev_txsend3(self,name): self.ethdev_txsend(name,ext='2.345,50000]{}.sigtx')
  3120. def ethdev_bal3(self,name): self.ethdev_bal(name,n='3')
  3121. def ethdev_tx_status(self,name,ext,expect_str):
  3122. ext = ext.format('-α' if g.debug_utf8 else '')
  3123. tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
  3124. t = MMGenExpect(name,'mmgen-txsend', eth_args() + ['--status',tx_fn])
  3125. t.expect(expect_str)
  3126. t.read()
  3127. t.ok()
  3128. def ethdev_tx_status1(self,name):
  3129. self.ethdev_tx_status(name,ext='2.345,50000]{}.sigtx',expect_str='has 1 confirmation')
  3130. def ethdev_txcreate4(self,name):
  3131. args = ['98831F3A:E:2,23.45495']
  3132. interactive_fee='40G'
  3133. fee_res='0.00084 {} (40 gas price in Gwei)'.format(g.coin)
  3134. return self.ethdev_txcreate(name,args=args,acct='1',non_mmgen_inputs=0,
  3135. interactive_fee=interactive_fee,fee_res=fee_res,eth_fee_res=True)
  3136. def ethdev_txbump(self,name,ext=',40000]{}.rawtx',fee='50G',add_args=[]):
  3137. ext = ext.format('-α' if g.debug_utf8 else '')
  3138. tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
  3139. t = MMGenExpect(name,'mmgen-txbump', eth_args() + add_args + ['--yes',tx_fn])
  3140. t.expect('or gas price: ',fee+'\n')
  3141. t.read()
  3142. t.ok()
  3143. def ethdev_txsign4(self,name): self.ethdev_txsign(name,ni=True,ext='.45495,50000]{}.rawtx')
  3144. def ethdev_txsend4(self,name): self.ethdev_txsend(name,ext='.45495,50000]{}.sigtx')
  3145. def ethdev_bal4(self,name): self.ethdev_bal(name,n='4')
  3146. def ethdev_txcreate5(self,name):
  3147. args = [eth_burn_addr + ','+eth_amt1]
  3148. return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
  3149. def ethdev_txsign5(self,name): self.ethdev_txsign(name,ni=True,ext=eth_amt1+',50000]{}.rawtx')
  3150. def ethdev_txsend5(self,name): self.ethdev_txsend(name,ext=eth_amt1+',50000]{}.sigtx')
  3151. def ethdev_bal5(self,name): self.ethdev_bal(name,n='5')
  3152. bal_corr = Decimal('0.0000032') # gas use for token sends varies between ETH and ETC!
  3153. def ethdev_bal(self,name,n=None):
  3154. t = MMGenExpect(name,'mmgen-tool', eth_args() + ['twview','wide=1'])
  3155. for b in eth_bals[n]:
  3156. addr,amt,adj = b if len(b) == 3 else b + (False,)
  3157. if adj and g.coin == 'ETC': amt = str(Decimal(amt) + self.bal_corr)
  3158. pat = r'{}\s+{}\s'.format(addr,amt.replace('.',r'\.'))
  3159. t.expect(pat,regex=True)
  3160. t.read()
  3161. t.ok()
  3162. def ethdev_token_bal(self,name,n=None):
  3163. t = MMGenExpect(name,'mmgen-tool', eth_args() + ['--token=mm1','twview','wide=1'])
  3164. for b in eth_token_bals[n]:
  3165. addr,amt1,amt2,adj = b if len(b) == 4 else b + (False,)
  3166. if adj and g.coin == 'ETC': amt2 = str(Decimal(amt2) + self.bal_corr)
  3167. pat = r'{}\s+{}\s+{}\s'.format(addr,amt1.replace('.',r'\.'),amt2.replace('.',r'\.'))
  3168. t.expect(pat,regex=True)
  3169. t.read()
  3170. t.ok()
  3171. def ethdev_bal_getbalance(self,name,idx,etc_adj=False,extra_args=[]):
  3172. bal1 = eth_token_bals_getbalance[idx][0]
  3173. bal2 = eth_token_bals_getbalance[idx][1]
  3174. bal1 = Decimal(bal1)
  3175. if etc_adj and g.coin == 'ETC': bal1 += self.bal_corr
  3176. t = MMGenExpect(name,'mmgen-tool', eth_args() + extra_args + ['getbalance'])
  3177. t.expect(r'\n[0-9A-F]{8}: .* '+str(bal1),regex=True)
  3178. t.expect(r'\nNon-MMGen: .* '+bal2,regex=True)
  3179. total = t.expect_getend(r'\nTOTAL:\s+',regex=True).split()[0]
  3180. t.read()
  3181. assert Decimal(bal1) + Decimal(bal2) == Decimal(total)
  3182. t.ok()
  3183. def ethdev_add_label(self,name,addr='98831F3A:E:3',lbl=utf8_label):
  3184. t = MMGenExpect(name,'mmgen-tool', eth_args() + ['add_label',addr,lbl])
  3185. t.expect('Added label.*in tracking wallet',regex=True)
  3186. t.ok()
  3187. def ethdev_chk_label(self,name,addr='98831F3A:E:3',label_pat=utf8_label_pat):
  3188. t = MMGenExpect(name,'mmgen-tool', eth_args() + ['listaddresses','all_labels=1'])
  3189. t.expect(r'{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,(label_pat or label)),regex=True)
  3190. t.ok()
  3191. def ethdev_remove_label(self,name,addr='98831F3A:E:3'):
  3192. t = MMGenExpect(name,'mmgen-tool', eth_args() + ['remove_label',addr])
  3193. t.expect('Removed label.*in tracking wallet',regex=True)
  3194. t.ok()
  3195. def ethdev_rpc_init(self):
  3196. init_coin(g.coin)
  3197. g.proto.rpc_port = 8549
  3198. rpc_init()
  3199. def ethdev_token_compile(self,name,token_data={}):
  3200. MMGenExpect(name,'',msg_only=True)
  3201. cmd_args = ['--{}={}'.format(k,v) for k,v in list(token_data.items())]
  3202. imsg("Compiling solidity token contract '{}' with 'solc'".format(token_data['symbol']))
  3203. cmd = ['scripts/create-token.py','--coin='+g.coin,'--outdir='+cfg['tmpdir']] + cmd_args + [eth_addr_chk]
  3204. imsg("Executing: {}".format(' '.join(cmd)))
  3205. subprocess.check_output(cmd,stderr=subprocess.STDOUT)
  3206. imsg("ERC20 token '{}' compiled".format(token_data['symbol']))
  3207. ok()
  3208. def ethdev_token_compile1(self,name):
  3209. token_data = { 'name':'MMGen Token 1', 'symbol':'MM1', 'supply':10**26, 'decimals':18 }
  3210. self.ethdev_token_compile(name,token_data)
  3211. def ethdev_token_compile2(self,name):
  3212. token_data = { 'name':'MMGen Token 2', 'symbol':'MM2', 'supply':10**18, 'decimals':10 }
  3213. self.ethdev_token_compile(name,token_data)
  3214. def ethdev_token_deploy(self,name,num,key,gas,mmgen_cmd='txdo',tx_fee='8G'):
  3215. self.ethdev_rpc_init()
  3216. key_fn = get_tmpfile_fn(cfg,cfg['parity_keyfile'])
  3217. fn = os.path.join(cfg['tmpdir'],key+'.bin')
  3218. os.environ['MMGEN_BOGUS_SEND'] = ''
  3219. args = ['-B','--tx-fee='+tx_fee,'--tx-gas={}'.format(gas),'--contract-data='+fn,'--inputs='+eth_addr,'--yes']
  3220. if mmgen_cmd == 'txdo': args += ['-k',key_fn]
  3221. t = MMGenExpect(name,'mmgen-'+mmgen_cmd, eth_args() + args)
  3222. if mmgen_cmd == 'txcreate':
  3223. t.written_to_file('Ethereum transaction')
  3224. ext = '[0,8000]{}.rawtx'.format('-α' if g.debug_utf8 else '')
  3225. tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
  3226. t = MMGenExpect(name,'mmgen-txsign', eth_args() + ['--yes','-k',key_fn,tx_fn],no_msg=True)
  3227. self.txsign_ui_common(t,name,ni=True,no_ok=True)
  3228. tx_fn = tx_fn.replace('.rawtx','.sigtx')
  3229. t = MMGenExpect(name,'mmgen-txsend', eth_args() + [tx_fn],no_msg=True)
  3230. os.environ['MMGEN_BOGUS_SEND'] = '1'
  3231. txid = self.txsend_ui_common(t,mmgen_cmd,quiet=True,bogus_send=False,no_ok=True)
  3232. addr = t.expect_getend('Contract address: ')
  3233. from mmgen.altcoins.eth.tx import EthereumMMGenTX as etx
  3234. assert etx.get_exec_status(txid.encode(),True) != 0,(
  3235. "Contract '{}:{}' failed to execute. Aborting".format(num,key))
  3236. if key == 'Token':
  3237. write_to_tmpfile(cfg,'token_addr{}'.format(num),addr+'\n')
  3238. imsg('\nToken #{} ({}) deployed!'.format(num,addr))
  3239. t.ok()
  3240. def ethdev_token_deploy1a(self,name): self.ethdev_token_deploy(name,num=1,key='SafeMath',gas=200000)
  3241. def ethdev_token_deploy1b(self,name): self.ethdev_token_deploy(name,num=1,key='Owned',gas=250000)
  3242. def ethdev_token_deploy1c(self,name): self.ethdev_token_deploy(name,num=1,key='Token',gas=1100000,tx_fee='7G')
  3243. def ethdev_tx_status2(self,name):
  3244. self.ethdev_tx_status(name,ext=g.coin+'[0,7000]{}.sigtx',expect_str='successfully executed')
  3245. def ethdev_bal6(self,name): return self.ethdev_bal5(name)
  3246. def ethdev_token_deploy2a(self,name): self.ethdev_token_deploy(name,num=2,key='SafeMath',gas=200000)
  3247. def ethdev_token_deploy2b(self,name): self.ethdev_token_deploy(name,num=2,key='Owned',gas=250000)
  3248. def ethdev_token_deploy2c(self,name): self.ethdev_token_deploy(name,num=2,key='Token',gas=1100000)
  3249. def ethdev_contract_deploy(self,name): # test create,sign,send
  3250. self.ethdev_token_deploy(name,num=2,key='SafeMath',gas=1100000,mmgen_cmd='txcreate')
  3251. def ethdev_token_transfer_ops(self,name,op,amt=1000):
  3252. MMGenExpect(name,'',msg_only=True)
  3253. sid = cfgs['8']['seed_id']
  3254. from mmgen.tool import MMGenToolCmd
  3255. usr_mmaddrs = ['{}:E:{}'.format(sid,i) for i in (11,21)]
  3256. usr_addrs = [MMGenToolCmd().gen_addr(addr,dfl_words) for addr in usr_mmaddrs]
  3257. self.ethdev_rpc_init()
  3258. from mmgen.altcoins.eth.contract import Token
  3259. from mmgen.altcoins.eth.tx import EthereumMMGenTX as etx
  3260. def do_transfer():
  3261. for i in range(2):
  3262. tk = Token(read_from_tmpfile(cfg,'token_addr{}'.format(i+1)).strip())
  3263. imsg_r('\n'+tk.info())
  3264. imsg('dev token balance (pre-send): {}'.format(tk.balance(eth_addr)))
  3265. imsg('Sending {} {} to address {} ({})'.format(amt,g.coin,usr_addrs[i],usr_mmaddrs[i]))
  3266. txid = tk.transfer(eth_addr,usr_addrs[i],amt,eth_key,
  3267. start_gas=ETHAmt(60000,'wei'),gasPrice=ETHAmt(8,'Gwei'))
  3268. assert etx.get_exec_status(txid,True) != 0,'Transfer of token funds failed. Aborting'
  3269. def show_bals():
  3270. for i in range(2):
  3271. tk = Token(read_from_tmpfile(cfg,'token_addr{}'.format(i+1)).strip())
  3272. imsg('Token: {}'.format(tk.symbol()))
  3273. imsg('dev token balance: {}'.format(tk.balance(eth_addr)))
  3274. imsg('usr token balance: {} ({} {})'.format(
  3275. tk.balance(usr_addrs[i]),usr_mmaddrs[i],usr_addrs[i]))
  3276. silence()
  3277. if op == 'show_bals': show_bals()
  3278. elif op == 'do_transfer': do_transfer()
  3279. end_silence()
  3280. ok()
  3281. def ethdev_token_fund_users(self,name):
  3282. return self.ethdev_token_transfer_ops(name,op='do_transfer')
  3283. def ethdev_token_user_bals(self,name):
  3284. return self.ethdev_token_transfer_ops(name,op='show_bals')
  3285. def ethdev_token_addrgen(self,name):
  3286. self.ethdev_addrgen(name,addrs='11-13')
  3287. self.ethdev_addrgen(name,addrs='21-23')
  3288. def ethdev_token_addrimport_badaddr1(self,name):
  3289. self.ethdev_addrimport(name,ext='[11-13]{}.addrs',add_args=['--token=abc'],bad_input=True)
  3290. def ethdev_token_addrimport_badaddr2(self,name):
  3291. self.ethdev_addrimport(name,ext='[11-13]{}.addrs',add_args=['--token='+'00deadbeef'*4],bad_input=True)
  3292. def ethdev_token_addrimport(self,name):
  3293. for n,r in ('1','11-13'),('2','21-23'):
  3294. tk_addr = read_from_tmpfile(cfg,'token_addr'+n).strip()
  3295. self.ethdev_addrimport(name,ext='['+r+']{}.addrs',expect='3/3',add_args=['--token='+tk_addr])
  3296. def ethdev_bal7(self,name): return self.ethdev_bal5(name)
  3297. def ethdev_token_bal1(self,name): self.ethdev_token_bal(name,n='1')
  3298. def ethdev_token_txcreate(self,name,args=[],token='',inputs='1',fee='50G'):
  3299. t = MMGenExpect(name,'mmgen-txcreate', eth_args() + ['--token='+token,'-B','--tx-fee='+fee] + args)
  3300. self.txcreate_ui_common(t,name,menu=[],
  3301. input_sels_prompt='to spend from',
  3302. inputs=inputs,file_desc='Ethereum token transaction',
  3303. add_comment=ref_tx_label_lat_cyr_gr)
  3304. return t
  3305. def ethdev_token_txsign(self,name,ext='',token=''):
  3306. self.ethdev_txsign(name,ni=True,ext=ext,add_args=['--token='+token])
  3307. def ethdev_token_txsend(self,name,ext='',token=''):
  3308. self.ethdev_txsend(name,ext=ext,add_args=['--token=mm1'])
  3309. def ethdev_token_txcreate1(self,name):
  3310. return self.ethdev_token_txcreate(name,args=['98831F3A:E:12,1.23456'],token='mm1')
  3311. def ethdev_token_txsign1(self,name):
  3312. self.ethdev_token_txsign(name,ext='1.23456,50000]{}.rawtx',token='mm1')
  3313. def ethdev_token_txsend1(self,name):
  3314. self.ethdev_token_txsend(name,ext='1.23456,50000]{}.sigtx',token='mm1')
  3315. def ethdev_token_bal2(self,name): self.ethdev_token_bal(name,n='2')
  3316. def ethdev_twview(self,name,args=[],expect_str='',tool_args=[],exit_val=0):
  3317. t = MMGenExpect(name,'mmgen-tool', eth_args() + args + ['twview'] + tool_args)
  3318. if expect_str:
  3319. t.expect(expect_str,regex=True)
  3320. t.read()
  3321. t.ok(exit_val=exit_val)
  3322. def ethdev_token_txcreate2(self,name):
  3323. return self.ethdev_token_txcreate(name,args=[eth_burn_addr+','+eth_amt2],token='mm1')
  3324. def ethdev_token_txbump(self,name):
  3325. self.ethdev_txbump(name,ext=eth_amt2+',50000]{}.rawtx',fee='56G',add_args=['--token=mm1'])
  3326. def ethdev_token_txsign2(self,name):
  3327. self.ethdev_token_txsign(name,ext=eth_amt2+',50000]{}.rawtx',token='mm1')
  3328. def ethdev_token_txsend2(self,name):
  3329. self.ethdev_token_txsend(name,ext=eth_amt2+',50000]{}.sigtx',token='mm1')
  3330. def ethdev_token_bal3(self,name): self.ethdev_token_bal(name,n='3')
  3331. def ethdev_del_dev_addr(self,name):
  3332. t = MMGenExpect(name,'mmgen-tool', eth_args() + ['remove_address',eth_addr])
  3333. t.read() # TODO
  3334. t.ok()
  3335. def ethdev_bal1_getbalance(self,name):
  3336. self.ethdev_bal_getbalance(name,'1',etc_adj=True)
  3337. def ethdev_addrimport_token_burn_addr(self,name):
  3338. self.ethdev_addrimport_one_addr(name,addr=eth_burn_addr,extra_args=['--token=mm1'])
  3339. def ethdev_token_bal4(self,name): self.ethdev_token_bal(name,n='4')
  3340. def ethdev_token_bal_getbalance(self,name):
  3341. self.ethdev_bal_getbalance(name,'2',extra_args=['--token=mm1'])
  3342. def ethdev_txcreate_noamt(self,name):
  3343. return self.ethdev_txcreate(name,args=['98831F3A:E:12'],eth_fee_res=True)
  3344. def ethdev_txsign_noamt(self,name):
  3345. self.ethdev_txsign(name,ext='99.99895,50000]{}.rawtx')
  3346. def ethdev_txsend_noamt(self,name):
  3347. self.ethdev_txsend(name,ext='99.99895,50000]{}.sigtx')
  3348. def ethdev_bal8(self,name): self.ethdev_bal(name,n='8')
  3349. def ethdev_token_bal5(self,name): self.ethdev_token_bal(name,n='5')
  3350. def ethdev_token_txcreate_noamt(self,name):
  3351. return self.ethdev_token_txcreate(name,args=['98831F3A:E:13'],token='mm1',inputs='2',fee='51G')
  3352. def ethdev_token_txsign_noamt(self,name):
  3353. self.ethdev_token_txsign(name,ext='1.23456,51000]{}.rawtx',token='mm1')
  3354. def ethdev_token_txsend_noamt(self,name):
  3355. self.ethdev_token_txsend(name,ext='1.23456,51000]{}.sigtx',token='mm1')
  3356. def ethdev_bal9(self,name): self.ethdev_bal(name,n='9')
  3357. def ethdev_token_bal6(self,name): self.ethdev_token_bal(name,n='6')
  3358. def ethdev_listaddresses(self,name,args=[],tool_args=['all_labels=1'],exit_val=0):
  3359. t = MMGenExpect(name,'mmgen-tool', eth_args() + args + ['listaddresses'] + tool_args)
  3360. t.read()
  3361. t.ok(exit_val=exit_val)
  3362. def ethdev_listaddresses1(self,name):
  3363. return self.ethdev_listaddresses(name)
  3364. def ethdev_listaddresses2(self,name):
  3365. return self.ethdev_listaddresses(name,tool_args=['minconf=999999999'])
  3366. def ethdev_listaddresses3(self,name):
  3367. return self.ethdev_listaddresses(name,tool_args=['sort=age'])
  3368. def ethdev_listaddresses4(self,name):
  3369. return self.ethdev_listaddresses(name,tool_args=['sort=age','showempty=1'])
  3370. def ethdev_token_listaddresses1(self,name):
  3371. return self.ethdev_listaddresses(name,args=['--token=mm1'])
  3372. def ethdev_token_listaddresses2(self,name):
  3373. return self.ethdev_listaddresses(name,args=['--token=mm1'],tool_args=['showempty=1'])
  3374. def ethdev_twview1(self,name):
  3375. return self.ethdev_twview(name)
  3376. def ethdev_twview2(self,name):
  3377. return self.ethdev_twview(name,tool_args=['wide=1'])
  3378. def ethdev_twview3(self,name):
  3379. return self.ethdev_twview(name,tool_args=['wide=1','sort=age'])
  3380. def ethdev_twview4(self,name):
  3381. return self.ethdev_twview(name,tool_args=['wide=1','minconf=999999999'])
  3382. def ethdev_twview5(self,name):
  3383. return self.ethdev_twview(name,tool_args=['wide=1','minconf=0'])
  3384. def ethdev_twview6(self,name):
  3385. return self.ethdev_twview(name,tool_args=['show_days=0'])
  3386. def ethdev_token_twview1(self,name):
  3387. return self.ethdev_twview(name,args=['--token=mm1'])
  3388. def ethdev_token_twview2(self,name):
  3389. return self.ethdev_twview(name,args=['--token=mm1'],tool_args=['wide=1'])
  3390. def ethdev_token_twview3(self,name):
  3391. return self.ethdev_twview(name,args=['--token=mm1'],tool_args=['wide=1','sort=age'])
  3392. def ethdev_edit_label(self,name,out_num,args=[],action='l',label_text=None):
  3393. t = MMGenExpect(name,'mmgen-txcreate', eth_args() + args + ['-B','-i'])
  3394. p1,p2 = ('emove address:\b','return to main menu): ')
  3395. p3,r3 = (p2,label_text+'\n') if label_text is not None else ('(y/N): ','y')
  3396. p4,r4 = (('(y/N): ',),('y',)) if label_text == '' else ((),())
  3397. for p,r in zip((p1,p1,p2,p3)+p4+(p1,p1),('M',action,out_num+'\n',r3)+r4+('M','q')):
  3398. t.expect(p,r)
  3399. t.ok()
  3400. def ethdev_edit_label1(self,name):
  3401. self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],label_text='First added label-α')
  3402. def ethdev_edit_label2(self,name):
  3403. self.ethdev_edit_label(name,out_num=eth_rem_addrs[1],label_text='Second added label')
  3404. def ethdev_edit_label3(self,name):
  3405. self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],label_text='')
  3406. def ethdev_remove_addr1(self,name):
  3407. self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],action='R')
  3408. def ethdev_remove_addr2(self,name):
  3409. self.ethdev_edit_label(name,out_num=eth_rem_addrs[1],action='R')
  3410. def ethdev_remove_token_addr1(self,name):
  3411. self.ethdev_edit_label(name,out_num=eth_rem_addrs[0],args=['--token=mm1'],action='R')
  3412. def ethdev_remove_token_addr2(self,name):
  3413. self.ethdev_edit_label(name,out_num=eth_rem_addrs[1],args=['--token=mm1'],action='R')
  3414. def ethdev_stop(self,name):
  3415. MMGenExpect(name,'',msg_only=True)
  3416. if subprocess.call(['which','parity'],stdout=subprocess.PIPE) == 0:
  3417. pid = read_from_tmpfile(cfg,cfg['parity_pidfile'])
  3418. if opt.no_daemon_stop:
  3419. msg_r('(leaving daemon running by user request)')
  3420. else:
  3421. subprocess.check_call(['kill',pid])
  3422. else:
  3423. imsg('No parity executable found on system. Ignoring')
  3424. ok()
  3425. # undocumented admin commands
  3426. def ref_tx_addrgen(self,name,atype='L'):
  3427. if atype not in g.proto.mmtypes: return
  3428. t = MMGenExpect(name,'mmgen-addrgen',['--outdir='+cfg['tmpdir'],'--type='+atype,dfl_words,'1-2'])
  3429. t.read()
  3430. def ref_tx_addrgen1(self,name): self.ref_tx_addrgen(name,atype='L')
  3431. def ref_tx_addrgen2(self,name): self.ref_tx_addrgen(name,atype='C')
  3432. def ref_tx_addrgen3(self,name): self.ref_tx_addrgen(name,atype='S')
  3433. def ref_tx_addrgen4(self,name): self.ref_tx_addrgen(name,atype='B')
  3434. def ref_tx_txcreate(self,name,f1,f2,f3,f4):
  3435. sources = ['31','32']
  3436. if 'S' in g.proto.mmtypes: sources += ['33']
  3437. if 'B' in g.proto.mmtypes: sources += ['34']
  3438. self.txcreate_common(name, sources=sources,
  3439. addrs_per_wallet=2,
  3440. add_args=['--locktime=1320969600'],
  3441. do_label=True)
  3442. # END methods
  3443. for k in (
  3444. 'ref_wallet_conv',
  3445. 'ref_mn_conv',
  3446. 'ref_seed_conv',
  3447. 'ref_hex_conv',
  3448. 'ref_brain_conv',
  3449. 'ref_incog_conv',
  3450. 'ref_incox_conv',
  3451. 'ref_hincog_conv',
  3452. 'ref_hincog_conv_old',
  3453. 'ref_wallet_conv_out',
  3454. 'ref_mn_conv_out',
  3455. 'ref_seed_conv_out',
  3456. 'ref_hex_conv_out',
  3457. 'ref_incog_conv_out',
  3458. 'ref_incox_conv_out',
  3459. 'ref_hincog_conv_out',
  3460. 'ref_hincog_blkdev_conv_out',
  3461. 'ref_wallet_chk',
  3462. 'refwalletgen',
  3463. 'ref_seed_chk',
  3464. 'ref_hex_chk',
  3465. 'ref_mn_chk',
  3466. 'ref_brain_chk',
  3467. 'ref_hincog_chk',
  3468. 'refaddrgen',
  3469. 'refkeyaddrgen',
  3470. 'refaddrgen_compressed',
  3471. 'refkeyaddrgen_compressed',
  3472. 'refpasswdgen',
  3473. 'ref_b32passwdgen',
  3474. 'ref_hexpasswdgen'
  3475. ):
  3476. for i in ('1','2','3'):
  3477. locals()[k+i] = locals()[k]
  3478. for k in ('walletgen','addrgen','keyaddrgen'): locals()[k+'14'] = locals()[k]
  3479. # create temporary dirs
  3480. if not opt.resume and not opt.skip_deps:
  3481. if g.platform == 'win':
  3482. for cfg in sorted(cfgs):
  3483. mk_tmpdir(cfgs[cfg]['tmpdir'])
  3484. else:
  3485. for cfg in sorted(cfgs):
  3486. src = os.path.join(shm_dir,cfgs[cfg]['tmpdir'].split('/')[-1])
  3487. mk_tmpdir(src)
  3488. try:
  3489. os.unlink(cfgs[cfg]['tmpdir'])
  3490. except OSError as e:
  3491. if e.errno != 2: raise
  3492. finally:
  3493. os.symlink(src,cfgs[cfg]['tmpdir'])
  3494. have_dfl_wallet = False
  3495. # main()
  3496. if opt.pause:
  3497. import termios,atexit
  3498. fd = sys.stdin.fileno()
  3499. old = termios.tcgetattr(fd)
  3500. def at_exit():
  3501. termios.tcsetattr(fd, termios.TCSADRAIN, old)
  3502. atexit.register(at_exit)
  3503. start_time = int(time.time())
  3504. def end_msg():
  3505. t = int(time.time()) - start_time
  3506. m = '{} test{} performed. Elapsed time: {:02d}:{:02d}\n'
  3507. sys.stderr.write(green(m.format(cmd_total,suf(cmd_total),t//60,t%60)))
  3508. ts = MMGenTestSuite()
  3509. if cmd_args and cmd_args[0] == 'admin':
  3510. cmd_args.pop(0)
  3511. cmd_data = cmd_data_admin
  3512. cmd_list = cmd_list_admin
  3513. if opt.exit_after:
  3514. if opt.exit_after not in cmd_data.keys():
  3515. die(1,"'{}': command not recognized".format(opt.exit_after))
  3516. try:
  3517. if cmd_args:
  3518. for arg in cmd_args:
  3519. if arg in utils:
  3520. globals()[arg](cmd_args[cmd_args.index(arg)+1:])
  3521. sys.exit(0)
  3522. elif 'info_'+arg in cmd_data:
  3523. dirs = cmd_data['info_'+arg][1]
  3524. if dirs: clean(dirs)
  3525. for cmd in cmd_list[arg]:
  3526. check_needs_rerun(ts,cmd,build=True)
  3527. elif arg in meta_cmds:
  3528. for cmd in meta_cmds[arg]:
  3529. check_needs_rerun(ts,cmd,build=True)
  3530. elif arg in cmd_data:
  3531. check_needs_rerun(ts,arg,build=True)
  3532. else:
  3533. die(1,'{}: unrecognized command'.format(arg))
  3534. else:
  3535. clean()
  3536. for cmd in cmd_data:
  3537. if cmd == 'info_regtest': break # don't run everything after this by default
  3538. if cmd[:5] == 'info_':
  3539. gmsg('{}Testing {}'.format(('\n','')[bool(opt.resume)],cmd_data[cmd][0]))
  3540. continue
  3541. ts.do_cmd(cmd)
  3542. if cmd is not list(cmd_data.keys())[-1]: do_between()
  3543. except KeyboardInterrupt:
  3544. die(1,'\nExiting at user request')
  3545. except TestSuiteException as e:
  3546. ydie(1,e.args[0])
  3547. except TestSuiteFatalException as e:
  3548. rdie(1,e.args[0])
  3549. except opt.traceback and Exception:
  3550. import traceback
  3551. print(''.join(traceback.format_exception(*sys.exc_info())))
  3552. try:
  3553. os.stat('my.err')
  3554. with open('my.err') as f:
  3555. t = f.readlines()
  3556. if t: msg_r('\n'+yellow(''.join(t[:-1]))+red(t[-1]))
  3557. except: pass
  3558. die(1,blue('Test script exited with error'))
  3559. except:
  3560. raise
  3561. end_msg()