Minor changes, bugfixes

This commit is contained in:
The MMGen Project 2015-10-25 13:04:30 +03:00
commit 8fc94a8c64
21 changed files with 670 additions and 757 deletions

View file

@ -1,4 +1,3 @@
MMGen is written in Pure Python and runs on MS Windows and Linux.
Instructions for installation and use reside on MMGen's Github wiki:

View file

@ -176,7 +176,7 @@ def _parse_addrfile_body(lines,has_keys=False,check=False):
def _parse_addrfile(fn,buf=[],has_keys=False,exit_on_error=True):
if buf: lines = remove_comments(buf.split("\n"))
if buf: lines = remove_comments(buf.splitlines()) # DOS-safe
else: lines = get_lines_from_file(fn,"address data",trim_comments=True)
try:
@ -190,7 +190,7 @@ def _parse_addrfile(fn,buf=[],has_keys=False,exit_on_error=True):
elif cbrace != '}':
errmsg = "'%s': invalid last line" % cbrace
elif not is_mmgen_seed_id(sid):
errmsg = "'%s': invalid seed ID" % sid
errmsg = "'%s': invalid Seed ID" % sid
else:
ret = _parse_addrfile_body(lines[1:-1],has_keys)
if type(ret) == list: return sid,ret
@ -203,14 +203,9 @@ def _parse_addrfile(fn,buf=[],has_keys=False,exit_on_error=True):
return False
def _parse_keyaddr_file(infile):
d = get_data_from_file(infile,"{pnm} key-address file data".format(pnm=pnm))
enc_ext = get_extension(infile) == g.mmenc_ext
if enc_ext or not is_utf8(d):
m = "Decrypting" if enc_ext else "Attempting to decrypt"
msg("%s key-address file %s" % (m,infile))
from crypto import mmgen_decrypt_retry
d = mmgen_decrypt_retry(d,"key-address file")
def _parse_keyaddr_file(fn):
from mmgen.crypto import mmgen_decrypt_file_maybe
d = mmgen_decrypt_file_maybe(fn,"key-address file")
return _parse_addrfile("",buf=d,has_keys=True,exit_on_error=False)

View file

@ -52,7 +52,7 @@ keystrokes will also be used as a source of randomness.
# Try again? (Y)es, (n)o, (m)ore information:
# """.strip(),
# 'confirm_seed_id': """
# If the seed ID above is correct but you're seeing this message, then you need
# If the Seed ID above is correct but you're seeing this message, then you need
# to exit and re-run the program with the '--old-incog-fmt' option.
# """.strip(),
}
@ -75,7 +75,7 @@ def decrypt_seed(enc_seed, key, seed_id, key_id):
chk2 = make_chksum_8(dec_seed)
if seed_id:
if compare_chksums(seed_id,"seed ID",chk2,"decrypted seed"):
if compare_chksums(seed_id,"Seed ID",chk2,"decrypted seed"):
qmsg("Passphrase is OK")
else:
if not opt.debug:
@ -246,6 +246,15 @@ def mmgen_decrypt(data,desc="data",hash_preset=""):
msg("Incorrect passphrase or hash preset")
return False
def mmgen_decrypt_file_maybe(fn,desc):
d = get_data_from_file(fn,"{} data".format(desc),binary=True)
have_enc_ext = get_extension(fn) == g.mmenc_ext
if have_enc_ext or not is_ascii(d):
m = ("Attempting to decrypt","Decrypting")[int(have_enc_ext)]
msg("%s %s %s" % (m,desc,fn))
d = mmgen_decrypt_retry(d,desc)
return d
def mmgen_decrypt_retry(d,desc="data"):
while True:
d_dec = mmgen_decrypt(d,desc)

View file

@ -92,7 +92,7 @@ FMT CODES:
{f}
""".format(
n=note1,
f="\n ".join(SeedSource.format_fmt_codes().split("\n")),
f="\n ".join(SeedSource.format_fmt_codes().splitlines()),
o=opt.opts
)
}

View file

@ -76,7 +76,7 @@ for e in ai.addrdata:
msg("%s: invalid address" % e.addr)
sys.exit(2)
m = (" from seed ID %s" % ai.seed_id) if ai.seed_id else ""
m = (" from Seed ID %s" % ai.seed_id) if ai.seed_id else ""
qmsg("OK. %s addresses%s" % (ai.num_addrs,m))
g.http_timeout = 3600

View file

@ -61,7 +61,7 @@ import math
import mmgen.globalvars as g
import mmgen.opt as opt
from mmgen.util import msg,mdie,mmsg,write_data_to_file
from mmgen.util import msg
max_version = 60000
addrtype = 0
@ -1664,7 +1664,7 @@ len_arg = "%s" % len(wallet_addrs) \
if len(data) == len(wallet_addrs) or ext == "json" \
else "%s:%s" % (len(data),len(wallet_addrs))
from mmgen.util import make_chksum_8,write_to_file,write_to_stdout
from mmgen.util import make_chksum_8,write_data_to_file
wallet_id = make_chksum_8(str(sorted(wallet_addrs)))
data = "\n".join(data) + "\n"

View file

@ -32,6 +32,7 @@ opts_data = {
'options': """
-d, --outdir= d Specify an alternate directory 'd' for output
-h, --help Print this help message
-P, --passwd-file= f Get passphrase from file 'f'.
-q, --quiet Produce quieter output
-r, --usr-randchars=n Get 'n' characters of additional randomness from
user (min={g.min_urandchars}, max={g.max_urandchars})
@ -45,7 +46,12 @@ command
""".format(tool.cmd_help,g.prog_name)
}
cmd_args = opt.opts.init(opts_data,add_opts=["no_keyconv"])
cmd_args = opt.opts.init(opts_data,
add_opts=[
"no_keyconv",
"hidden_incog_input_params",
"in_fmt"
])
if len(cmd_args) < 1:
opt.opts.usage()

View file

@ -155,7 +155,7 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
from copy import deepcopy
from mmgen.term import get_terminal_size
write_to_file_msg = ""
written_to_file_msg = ""
msg("")
while True:
@ -215,8 +215,8 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
out += [fs % (str(n+1)+")",i.tx,i.vout,i.addr,i.amt,i.age)
for n,i in enumerate(unsp)]
msg("\n".join(out) +"\n\n" + write_to_file_msg + options_msg)
write_to_file_msg = ""
msg("\n".join(out) +"\n\n" + written_to_file_msg + options_msg)
written_to_file_msg = ""
skip_prompt = False
@ -241,8 +241,8 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
elif reply == 'p':
d = format_unspent_outputs_for_printing(unsp,sort_info,total)
of = "listunspent[%s].out" % ",".join(sort_info)
write_to_file(of, d, "",False,False)
write_to_file_msg = "Data written to '%s'\n\n" % of
write_data_to_file(of,d,"unspent outputs listing")
written_to_file_msg = "Data written to '%s'\n\n" % of
elif reply == 'v':
do_pager("\n".join(out))
continue
@ -390,7 +390,8 @@ if g.bogus_wallet_data: # for debugging purposes only
us = eval(get_data_from_file(g.bogus_wallet_data))
else:
us = c.listunspent()
# write_to_file("bogus_unspent.json", repr(us)); sys.exit()
# write_data_to_file("bogus_unspent.json", repr(us), "bogus unspent data")
# sys.exit()
if not us: msg(wmsg['no_spendable_outputs']); sys.exit(2)
for o in us:
@ -470,10 +471,7 @@ b2m_map = make_b2m_map(sel_unspent,tx_out,ail_w,ail_f)
prompt_and_view_tx_data(c,"View decoded transaction?",
sel_unspent,tx_hex,b2m_map,comment,metadata)
if keypress_confirm("Save transaction?",default_yes=False):
outfile = "tx_%s[%s].%s" % (tx_id,amt,g.rawtx_ext)
data = make_tx_data("{} {} {}".format(*metadata),
tx_hex,sel_unspent,b2m_map,comment)
write_to_file(outfile,data,"transaction",False,True)
else:
msg("Transaction not saved")
outfile = "tx_%s[%s].%s" % (tx_id,amt,g.rawtx_ext)
data = make_tx_data("{} {} {}".format(*metadata),
tx_hex,sel_unspent,b2m_map,comment)
write_data_to_file(outfile,data,"transaction",ask_write_default_yes=False)

View file

@ -63,9 +63,7 @@ if keypress_confirm("Edit transaction comment?"):
comment = get_tx_comment_from_user(comment)
data = make_tx_data("{} {} {}".format(*metadata), tx_hex,
inputs_data, b2m_map, comment)
w = "signed transaction with edited comment"
outfile = infile
write_to_file(outfile,data,w,False,True,True)
write_data_to_file(infile,data,"signed transaction with edited comment")
warn = "Once this transaction is sent, there's no taking it back!"
action = "broadcast this transaction to the network"
@ -86,4 +84,4 @@ except:
msg("Transaction sent: %s" % tx_id)
of = "tx_{}[{}].txid".format(*metadata[:2])
write_to_file(of, tx_id+"\n","transaction ID",True,True)
write_data_to_file(of, tx_id+"\n","transaction ID",ask_overwrite=True)

View file

@ -101,7 +101,7 @@ Seed data supplied in files must have the following extensions:
FMT CODES:
{f}
""".format(
f="\n ".join(SeedSource.format_fmt_codes().split("\n")),
f="\n ".join(SeedSource.format_fmt_codes().splitlines()),
g=g,pnm=pnm,pnl=pnl
)
}
@ -126,11 +126,11 @@ def get_seed_for_seed_id(seed_id,infiles,saved_seeds):
if infiles:
ss = SeedSource(infiles.pop(0),ignore_in_fmt=True)
elif opt.in_fmt:
qmsg("Need seed data for seed ID %s" % seed_id)
qmsg("Need seed data for Seed ID %s" % seed_id)
ss = SeedSource()
msg("User input produced seed ID %s" % make_chksum_8(seed))
msg("User input produced Seed ID %s" % make_chksum_8(seed))
else:
msg("ERROR: No seed source found for seed ID: %s" % seed_id)
msg("ERROR: No seed source found for Seed ID: %s" % seed_id)
sys.exit(2)
saved_seeds[ss.seed.sid] = ss.seed.data
@ -229,7 +229,7 @@ for the following non-{pnm} address{suf}:\n {l}""".format(
def parse_mmgen_keyaddr_file():
from mmgen.addr import AddrInfo
ai = AddrInfo(opt.mmgen_keys_from_file,has_keys=True)
vmsg("Found %s wif key%s for seed ID %s" %
vmsg("Found %s wif key%s for Seed ID %s" %
(ai.num_addrs, suf(ai.num_addrs,"k"), ai.seed_id))
# idx: (0=addr, 1=comment 2=wif) -> mmaddr: (0=addr, 1=wif)
return dict(
@ -238,14 +238,10 @@ def parse_mmgen_keyaddr_file():
def parse_keylist(from_file):
fn = opt.keys_from_file
d = get_data_from_file(fn,"non-{pnm} keylist".format(pnm=pnm))
enc_ext = get_extension(fn) == g.mmenc_ext
if enc_ext or not is_utf8(d):
if not enc_ext: qmsg("Keylist file appears to be encrypted")
from crypto import mmgen_decrypt_retry
d = mmgen_decrypt_retry(d,"encrypted keylist")
# Check for duplication with key-address file
keys_all = set(remove_comments(d.split("\n")))
from mmgen.crypto import mmgen_decrypt_file_maybe
dec = mmgen_decrypt_file_maybe(fn,"non-{} keylist file".format(pnm))
# Remove possible dups from key-address file
keys_all = set(remove_comments(dec.splitlines())) # DOS-safe
d = from_file['mmdata']
kawifs = [d[k][1] for k in d.keys()]
keys = [k for k in keys_all if k not in kawifs]
@ -359,7 +355,7 @@ for tx_num,tx_file in enumerate(tx_files,1):
extra_sids = set(saved_seeds.keys()) - sids
if extra_sids:
msg("Unused seed ID%s: %s" %
msg("Unused Seed ID%s: %s" %
(suf(extra_sids,"k")," ".join(extra_sids)))
# Begin signing
@ -378,13 +374,16 @@ for tx_num,tx_file in enumerate(tx_files,1):
if keypress_confirm("Edit transaction comment?"):
comment = get_tx_comment_from_user(comment)
outfile = "tx_%s[%s].%s" % (metadata[0],metadata[1],g.sigtx_ext)
data = make_tx_data("{} {} {t}".format(*metadata[:2], t=make_timestamp()),
sig_tx['hex'], inputs_data, b2m_map, comment)
w = "signed transaction{}".format(tx_num_str)
if keypress_confirm("Save signed transaction?",default_yes=False):
write_to_file(outfile,data,w,(not opt.quiet),True,False)
else:
msg("Signed transaction not saved")
data = make_tx_data(
"{} {} {t}".format(*metadata[:2],
t=make_timestamp()),
sig_tx['hex'], inputs_data, b2m_map, comment
)
write_data_to_file(
outfile,data,
"signed transaction{}".format(tx_num_str),
ask_write_prompt="Save signed transaction?"
)
else:
msg_r("failed\nSome keys were missing. ")
msg("Transaction %scould not be signed." % tx_num_str)

View file

@ -103,7 +103,7 @@ opts_data = {
FMT CODES:
{f}
""".format(
f="\n ".join(SeedSource.format_fmt_codes().split("\n")),
f="\n ".join(SeedSource.format_fmt_codes().splitlines()),
pw_note=pw_note,
bw_note=("","\n\n" + bw_note)[int(bool(bw_note))]
)

View file

@ -1,149 +0,0 @@
#!/usr/bin/env python
#
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
# Copyright (C)2013-2015 Philemon <mmgen-py@yandex.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
mnemonic.py: Mnemonic routines for the MMGen suite
"""
import sys
from binascii import hexlify
from mmgen.util import msg,msg_r,make_chksum_8,Vmsg,Msg
from mmgen.crypto import get_random
import mmgen.globalvars as g
import mmgen.opt as opt
wl_checksums = {
"electrum": '5ca31424',
"tirosh": '1a5faeff'
}
# These are the only base-1626 specific configs:
mn_base = 1626
def mn2hex_pad(mn): return len(mn) * 8 / 3
def hex2mn_pad(hexnum): return len(hexnum) * 3 / 8
# Universal base-conversion routines:
def baseNtohex(base,words,wordlist,pad=0):
deconv = \
[wordlist.index(words[::-1][i])*(base**i) for i in range(len(words))]
ret = ("{:0%sx}" % pad).format(sum(deconv))
return "%s%s" % (('0' if len(ret) % 2 else ''), ret)
def hextobaseN(base,hexnum,wordlist,pad=0):
num,ret = int(hexnum,16),[]
while num:
ret.append(num % base)
num /= base
return [wordlist[n] for n in [0] * (pad-len(ret)) + ret[::-1]]
def get_seed_from_mnemonic(mn,wl,silent=False,label=""):
if len(mn) not in g.mn_lens:
msg("Invalid mnemonic (%i words). Allowed numbers of words: %s" %
(len(mn),", ".join([str(i) for i in g.mn_lens])))
sys.exit(3)
for n,w in enumerate(mn,1):
if w not in wl:
msg("Invalid mnemonic: word #%s is not in the wordlist" % n)
sys.exit(3)
from binascii import unhexlify
hseed = baseNtohex(mn_base,mn,wl,mn2hex_pad(mn))
rev = hextobaseN(mn_base,hseed,wl,hex2mn_pad(hseed))
if rev != mn:
msg("ERROR: mnemonic recomputed from seed not the same as original")
msg("Recomputed mnemonic:\n%s" % " ".join(rev))
sys.exit(3)
if not silent:
msg("Valid mnemonic for seed ID %s" % make_chksum_8(unhexlify(hseed)))
return unhexlify(hseed)
def get_mnemonic_from_seed(seed, wl, label="", verbose=False):
if len(seed)*8 not in g.seed_lens:
msg("%s: invalid seed length" % len(seed))
sys.exit(3)
from binascii import hexlify
hseed = hexlify(seed)
mn = hextobaseN(mn_base,hseed,wl,hex2mn_pad(hseed))
if verbose:
msg("Wordlist: %s" % label.capitalize())
msg("Seed length: %s bits" % (len(seed) * 8))
msg("Seed: %s" % hseed)
msg("mnemonic (%s words):\n%s" % (len(mn), " ".join(mn)))
rev = baseNtohex(mn_base,mn,wl,mn2hex_pad(mn))
if rev != hseed:
msg("ERROR: seed recomputed from wordlist not the same as original seed!")
msg("Original seed: %s" % hseed)
msg("Recomputed seed: %s" % rev)
sys.exit(3)
return mn
def check_wordlist(wl,label):
Msg("Wordlist: %s" % label.capitalize())
from hashlib import sha256
Msg("Length: %i words" % len(wl))
new_chksum = sha256(" ".join(wl)).hexdigest()[:8]
if new_chksum != wl_checksums[label]:
Msg("ERROR: Checksum mismatch. Computed: %s, Saved: %s" % \
(new_chksum,wl_checksums[label]))
sys.exit(3)
Msg("Checksum: %s (matches)" % new_chksum)
if (sorted(wl) == wl):
Msg("List is sorted")
else:
Msg("ERROR: List is not sorted!")
sys.exit(3)
from mmgen.mn_electrum import words as el
from mmgen.mn_tirosh import words as tl
wordlists = sorted(wl_checksums)
def get_wordlist(wordlist):
wordlist = wordlist.lower()
if wordlist not in wordlists:
Msg('"%s": invalid wordlist. Valid choices: %s' %
(wordlist,'"'+'" "'.join(wordlists)+'"'))
sys.exit(1)
return (el if wordlist == "electrum" else tl).strip().split("\n")
def do_random_mn(nbytes,wordlist):
r = get_random(nbytes)
Vmsg("Seed: %s" % hexlify(r))
for wlname in (wordlists if wordlist == "all" else [wordlist]):
wl = get_wordlist(wlname)
mn = get_mnemonic_from_seed(r,wl,wordlist)
Vmsg("%s wordlist mnemonic:" % (wlname.capitalize()))
Msg(" ".join(mn))

View file

@ -104,10 +104,8 @@ class AuthServiceProxy(object):
'Authorization' : self.__authhdr,
'Content-type' : 'application/json' })
except:
from mmgen.util import msg
import sys
msg("Unable to connect to bitcoind")
sys.exit(2)
from mmgen.util import die,red
die(1,red("Unable to connect to bitcoind"))
httpresp = self.__conn.getresponse()
if httpresp is None:

View file

@ -56,6 +56,7 @@ class Seed(MMGenObject):
class SeedSource(MMGenObject):
desc = g.proj_name + " seed source"
file_mode = "text"
stdin_ok = False
ask_tty = True
no_tty = False
@ -64,7 +65,8 @@ class SeedSource(MMGenObject):
class SeedSourceData(MMGenObject): pass
def __new__(cls,fn=None,ss=None,ignore_in_fmt=False,passchg=False):
def __new__(cls,fn=None,ss=None,seed=None,
ignore_in_fmt=False,passchg=False):
def die_on_opt_mismatch(opt,sstype):
opt_sstype = cls.fmt_code_to_sstype(opt)
@ -104,12 +106,13 @@ class SeedSource(MMGenObject):
else: # Called with no inputs - initialize with random seed
sstype = cls.fmt_code_to_sstype(opt.out_fmt)
me = super(cls,cls).__new__(sstype or Wallet) # default: Wallet
me.seed = Seed()
me.seed = Seed(seed_bin=seed or None)
me.op = "new"
return me
def __init__(self,fn=None,ss=None,ignore_in_fmt=False,passchg=False):
def __init__(self,fn=None,ss=None,seed=None,
ignore_in_fmt=False,passchg=False):
self.ssdata = self.SeedSourceData()
self.msg = {}
@ -132,12 +135,13 @@ class SeedSource(MMGenObject):
self._deformat_retry()
self._decrypt_retry()
m = (""," length %s" % self.seed.length)[int(self.seed.length != 256)]
qmsg("Valid %s for seed ID %s%s" % (self.desc,self.seed.sid,m))
m = ("",", seed length %s" % self.seed.length)[int(self.seed.length != 256)]
qmsg("Valid %s for Seed ID %s%s" % (self.desc,self.seed.sid,m))
def _get_data(self):
if hasattr(self,'infile'):
self.fmt_data = get_data_from_file(self.infile.name,self.desc)
self.fmt_data = get_data_from_file(self.infile.name,self.desc,
binary=self.file_mode=="binary")
else:
self.fmt_data = get_data_from_user(self.desc)
@ -204,12 +208,17 @@ class SeedSource(MMGenObject):
] + sorted(d)]
return "\n".join(ret) + "\n"
def get_fmt_data(self):
self._format()
return self.fmt_data
def write_to_file(self):
self._format()
kwargs = {
'desc': self.desc,
'ask_tty': self.ask_tty,
'no_tty': self.no_tty
'no_tty': self.no_tty,
'binary': self.file_mode == "binary"
}
write_data_to_file(self._filename(),self.fmt_data,**kwargs)
@ -358,43 +367,70 @@ class Mnemonic (SeedSourceUnenc):
mn_base = 1626
wordlists = sorted(wl_checksums)
def _mn2hex_pad(self,mn): return len(mn) * 8 / 3
def _hex2mn_pad(self,hexnum): return len(hexnum) * 3 / 8
@staticmethod
def _mn2hex_pad(mn): return len(mn) * 8 / 3
def _baseNtohex(self,base,words,wl,pad=0):
@staticmethod
def _hex2mn_pad(hexnum): return len(hexnum) * 3 / 8
@staticmethod
def baseNtohex(base,words,wl,pad=0):
deconv = [wl.index(words[::-1][i])*(base**i)
for i in range(len(words))]
ret = ("{:0%sx}" % pad).format(sum(deconv))
return ('','0')[len(ret) % 2] + ret
def _hextobaseN(self,base,hexnum,wl,pad=0):
@staticmethod
def hextobaseN(base,hexnum,wl,pad=0):
num,ret = int(hexnum,16),[]
while num:
ret.append(num % base)
num /= base
return [wl[n] for n in [0] * (pad-len(ret)) + ret[::-1]]
def _get_wordlist(self,wordlist=g.default_wordlist):
wordlist = wordlist.lower()
if wordlist not in self.wordlists:
@classmethod
def hex2mn(cls,hexnum,wordlist):
wl = cls.get_wordlist(wordlist)
return cls.hextobaseN(cls.mn_base,hexnum,wl,cls._hex2mn_pad(hexnum))
@classmethod
def mn2hex(cls,mn,wordlist):
wl = cls.get_wordlist(wordlist)
return cls.baseNtohex(cls.mn_base,mn,wl,cls._mn2hex_pad(mn))
@classmethod
def get_wordlist(cls,wordlist=None):
wordlist = wordlist or g.default_wordlist
if wordlist not in cls.wordlists:
die(1,'"%s": invalid wordlist. Valid choices: %s' %
(wordlist,'"'+'" "'.join(self.wordlists)+'"'))
(wordlist,'"'+'" "'.join(cls.wordlists)+'"'))
if wordlist == "electrum":
from mmgen.mn_electrum import words
elif wordlist == "tirosh":
from mmgen.mn_tirosh import words
return __import__("mmgen.mn_"+wordlist,fromlist=["words"]).words.split()
@classmethod
def check_wordlist(cls,wlname):
wl = cls.get_wordlist(wlname)
Msg("Wordlist: %s\nLength: %i words" % (capfirst(wlname),len(wl)))
new_chksum = sha256(" ".join(wl)).hexdigest()[:8]
if (sorted(wl) == wl):
Msg("List is sorted")
else:
die(3,"Internal error: unknown wordlist")
die(3,"ERROR: List is not sorted!")
return words.strip().split("\n")
compare_chksums(
new_chksum,"generated checksum",
cls.wl_checksums[wlname],"saved checksum",
die_on_fail=True)
Msg("Checksum %s matches" % new_chksum)
def _format(self):
wl = self._get_wordlist()
wl = self.get_wordlist()
seed_hex = self.seed.hexdata
mn = self._hextobaseN(self.mn_base,seed_hex,wl,self._hex2mn_pad(seed_hex))
mn = self.hextobaseN(self.mn_base,seed_hex,wl,self._hex2mn_pad(seed_hex))
ret = self._baseNtohex(self.mn_base,mn,wl,self._mn2hex_pad(mn))
ret = self.baseNtohex(self.mn_base,mn,wl,self._mn2hex_pad(mn))
# Internal error, so just die on fail
compare_or_die(ret,"recomputed seed",
seed_hex,"original",e="Internal error")
@ -405,7 +441,7 @@ class Mnemonic (SeedSourceUnenc):
def _deformat(self):
mn = self.fmt_data.split()
wl = self._get_wordlist()
wl = self.get_wordlist()
if len(mn) not in g.mn_lens:
msg("Invalid mnemonic (%i words). Allowed numbers of words: %s" %
@ -417,9 +453,9 @@ class Mnemonic (SeedSourceUnenc):
msg("Invalid mnemonic: word #%s is not in the wordlist" % n)
return False
seed_hex = self._baseNtohex(self.mn_base,mn,wl,self._mn2hex_pad(mn))
seed_hex = self.baseNtohex(self.mn_base,mn,wl,self._mn2hex_pad(mn))
ret = self._hextobaseN(self.mn_base,seed_hex,wl,self._hex2mn_pad(seed_hex))
ret = self.hextobaseN(self.mn_base,seed_hex,wl,self._hex2mn_pad(seed_hex))
# Internal error, so just die
compare_or_die(" ".join(ret),"recomputed mnemonic",
@ -580,7 +616,7 @@ class Wallet (SeedSourceEnc):
return True
lines = self.fmt_data.rstrip().split("\n")
lines = self.fmt_data.splitlines()
if not check_master_chksum(lines,self.desc): return False
d = self.ssdata
@ -723,6 +759,7 @@ class Brainwallet (SeedSourceEnc):
class IncogWallet (SeedSourceEnc):
file_mode = "binary"
fmt_codes = "mmincog","incog","icg","i"
desc = "incognito data"
ext = "mmincog"
@ -742,7 +779,7 @@ Incorrect passphrase, hash preset, or maybe old-format incog wallet.
Try again? (Y)es, (n)o, (m)ore information:
""".strip(),
'confirm_seed_id': """
If the seed ID above is correct but you're seeing this message, then you need
If the Seed ID above is correct but you're seeing this message, then you need
to exit and re-run the program with the '--old-incog-fmt' option.
""".strip(),
'dec_chk': " %s hash preset"
@ -841,7 +878,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
return False
def _verify_seed_oldfmt(self,seed):
m = "Seed ID: %s. Is the seed ID correct?" % make_chksum_8(seed)
m = "Seed ID: %s. Is the Seed ID correct?" % make_chksum_8(seed)
if keypress_confirm(m, True):
return seed
else:
@ -878,6 +915,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
class IncogWalletHex (IncogWallet):
file_mode = "text"
desc = "hex incognito data"
fmt_codes = "mmincox","incox","incog_hex","xincog","ix","xi"
ext = "mmincox"

View file

@ -28,9 +28,9 @@ def print_help(opts_data):
print (" %-"+pn_len+"s %s") % (pn.upper()+":", opts_data['desc'].strip())
print (" %-"+pn_len+"s %s %s")%("USAGE:", pn, opts_data['usage'].strip())
sep = "\n "
print " OPTIONS:"+sep+"%s" % sep.join(opts_data['options'].strip().split("\n"))
print " OPTIONS:"+sep+"%s" % sep.join(opts_data['options'].strip().splitlines())
if "notes" in opts_data:
print " %s" % "\n ".join(opts_data['notes'][1:-1].split("\n"))
print " %s" % "\n ".join(opts_data['notes'][1:-1].splitlines())
def process_opts(argv,opts_data,short_opts,long_opts):
@ -86,7 +86,7 @@ def parse_opts(argv,opts_data,opt_filter=None):
pat = r"^-([a-zA-Z0-9]), --([a-zA-Z0-9-]{2,64})(=| )(.+)"
od,skip = [],True
for l in opts_data['options'].strip().split("\n"):
for l in opts_data['options'].strip().splitlines():
m = re.match(pat,l)
if m:
skip = True if (opt_filter and m.group(1) not in opt_filter) else False

View file

@ -22,7 +22,7 @@ test.py: Shared routines for the test suites
import sys,os
from binascii import hexlify
from mmgen.util import msg,write_to_file,red,green
from mmgen.util import msg,write_data_to_file,red,green
import mmgen.opt as opt
def cleandir(d):
@ -49,16 +49,20 @@ def mk_tmpdir(cfg):
def get_tmpfile_fn(cfg,fn):
return os.path.join(cfg['tmpdir'],fn)
def write_to_tmpfile(cfg,fn,data,mode='wb'):
write_to_file(os.path.join(cfg['tmpdir'],fn),data,silent=True,mode=mode)
def write_to_tmpfile(cfg,fn,data,binary=False):
write_data_to_file(
os.path.join(cfg['tmpdir'],fn),
data,
silent=True,
binary=binary
)
def read_from_tmpfile(cfg,fn):
def read_from_file(fn,binary=False):
from mmgen.util import get_data_from_file
return get_data_from_file(os.path.join(cfg['tmpdir'],fn),silent=True)
return get_data_from_file(fn,silent=True,binary=binary)
def read_from_file(fn):
from mmgen.util import get_data_from_file
return get_data_from_file(fn,silent=True)
def read_from_tmpfile(cfg,fn,binary=False):
return read_from_file(os.path.join(cfg['tmpdir'],fn),binary=binary)
def ok():
if opt.verbose or opt.exact_output:

View file

@ -252,8 +252,9 @@ def usage(cmd):
help = usage
def hexdump(infile, cols=8, line_nums=True):
Msg(pretty_hexdump(get_data_from_file(infile,dash=True,silent=True),
cols=cols, line_nums=line_nums))
Msg(pretty_hexdump(
get_data_from_file(infile,dash=True,silent=True,binary=True),
cols=cols,line_nums=line_nums))
def unhexdump(infile):
if sys.platform[:3] == "win":
@ -316,42 +317,54 @@ def wif2addr(wif,compressed=False):
addr = bitcoin.privnum2addr(int(s_enc,16),compressed)
Vmsg_r("Addr: "); Msg(addr)
from mmgen.mnemonic import *
wordlists = "electrum","tirosh"
dfl_wordlist = "electrum"
def mn_rand128(wordlist="electrum"): do_random_mn(16,wordlist)
def mn_rand192(wordlist="electrum"): do_random_mn(24,wordlist)
def mn_rand256(wordlist="electrum"): do_random_mn(32,wordlist)
from mmgen.seed import Mnemonic
def do_random_mn(nbytes,wordlist):
hexrand = ba.hexlify(get_random(nbytes))
Vmsg("Seed: %s" % hexrand)
for wlname in (wordlists if wordlist == "all" else [wordlist]):
if wordlist == "all":
Msg("%s mnemonic:" % (wlname.capitalize()))
mn = Mnemonic.hex2mn(hexrand,wordlist=wlname)
Msg(" ".join(mn))
def hex2mn(s,wordlist="electrum"):
import mmgen.mnemonic
wl = get_wordlist(wordlist)
Msg(" ".join(get_mnemonic_from_seed(ba.unhexlify(s), wl, wordlist)))
def mn_rand128(wordlist=dfl_wordlist): do_random_mn(16,wordlist)
def mn_rand192(wordlist=dfl_wordlist): do_random_mn(24,wordlist)
def mn_rand256(wordlist=dfl_wordlist): do_random_mn(32,wordlist)
def mn2hex(s,wordlist="electrum"):
import mmgen.mnemonic
wl = get_wordlist(wordlist)
Msg(ba.hexlify(get_seed_from_mnemonic(s.split(),wl,True)))
def hex2mn(s,wordlist=dfl_wordlist):
mn = Mnemonic.hex2mn(s,wordlist)
Msg(" ".join(mn))
def mn2hex(s,wordlist=dfl_wordlist):
hexnum = Mnemonic.mn2hex(s.split(),wordlist)
Msg(hexnum)
def b32tohex(s):
b32a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
import mmgen.mnemonic
Msg(baseNtohex(32,s,b32a))
Msg(Mnemonic.baseNtohex(32,s,b32a))
def hextob32(s):
b32a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
import mmgen.mnemonic
Msg("".join(hextobaseN(32,s,b32a)))
Msg("".join(Mnemonic.hextobaseN(32,s,b32a)))
def mn_stats(wordlist="electrum"):
l = get_wordlist(wordlist)
check_wordlist(l,wordlist)
def mn_stats(wordlist=dfl_wordlist):
Mnemonic.check_wordlist(wordlist)
def mn_printlist(wordlist="electrum"):
wl = get_wordlist(wordlist)
def mn_printlist(wordlist=dfl_wordlist):
wl = Mnemonic.get_wordlist(wordlist)
Msg("\n".join(wl))
def id8(infile): Msg(make_chksum_8(get_data_from_file(infile,dash=True,silent=True)))
def id6(infile): Msg(make_chksum_6(get_data_from_file(infile,dash=True,silent=True)))
def id8(infile):
Msg(make_chksum_8(
get_data_from_file(infile,dash=True,silent=True,binary=True)
))
def id6(infile):
Msg(make_chksum_6(
get_data_from_file(infile,dash=True,silent=True,binary=True)
))
def str2id6(s): Msg(make_chksum_6("".join(s.split())))
# List MMGen addresses and their balances:
@ -478,7 +491,7 @@ def hexlify(s):
def sha256x2(s, file_input=False, hex_input=False):
from hashlib import sha256
if file_input: b = get_data_from_file(s)
if file_input: b = get_data_from_file(s,binary=True)
elif hex_input: b = decode_pretty_hexdump(s)
else: b = s
Msg(sha256(sha256(b).digest()).hexdigest())
@ -506,32 +519,27 @@ def hex2wif(hexpriv,compressed=False):
def encrypt(infile,outfile="",hash_preset=""):
data = get_data_from_file(infile,"data for encryption")
data = get_data_from_file(infile,"data for encryption",binary=True)
enc_d = mmgen_encrypt(data,"user data",hash_preset)
if outfile == '-':
write_to_stdout(enc_d,"encrypted data")
else:
if not outfile:
outfile = os.path.basename(infile) + "." + g.mmenc_ext
write_to_file(outfile,enc_d,"encrypted data",True,True)
if not outfile:
outfile = "%s.%s" % (os.path.basename(infile),g.mmenc_ext)
write_data_to_file(outfile,enc_d,"encrypted data",binary=True)
def decrypt(infile,outfile="",hash_preset=""):
enc_d = get_data_from_file(infile,"encrypted data")
enc_d = get_data_from_file(infile,"encrypted data",binary=True)
while True:
dec_d = mmgen_decrypt(enc_d,"user data",hash_preset)
if dec_d: break
msg("Trying again...")
if outfile == '-':
write_to_stdout(dec_d,"decrypted data",ask_terminal=not opt.quiet)
else:
if not outfile:
outfile = os.path.basename(infile)
if outfile[-len(g.mmenc_ext)-1:] == "."+g.mmenc_ext:
outfile = outfile[:-len(g.mmenc_ext)-1]
else:
outfile = outfile + ".dec"
write_to_file(outfile, dec_d, "decrypted data",True,True)
if not outfile:
o = os.path.basename(infile)
outfile = remove_extension(o,g.mmenc_ext)
if outfile == o: outfile += ".dec"
write_data_to_file(outfile,dec_d,"decrypted data",binary=True)
def find_incog_data(filename,iv_id,keep_searching=False):
@ -618,4 +626,4 @@ def rand2file(outfile, nbytes, threads=4, silent=False):
q2.join()
f.close()
def bytespec(s): Msg(parse_nbytes(s))
def bytespec(s): Msg(str(parse_nbytes(s)))

View file

@ -29,11 +29,12 @@ import mmgen.globalvars as g
pnm = g.proj_name
_red,_grn,_yel,_cya,_reset = \
["\033[%sm" % c for c in "31;1","32;1","33;1","36;1","0"]
_red,_grn,_yel,_cya,_reset,_grnbg = \
["\033[%sm" % c for c in "31;1","32;1","33;1","36;1","0","30;102"]
def red(s): return _red+s+_reset
def green(s): return _grn+s+_reset
def grnbg(s): return _grnbg+s+_reset
def yellow(s): return _yel+s+_reset
def cyan(s): return _cya+s+_reset
def nocolor(s): return s
@ -43,13 +44,13 @@ def start_mscolor():
global red,green,yellow,cyan,nocolor
import os
if "MMGEN_NOMSCOLOR" in os.environ:
red = green = yellow = cyan = nocolor
red = green = yellow = cyan = grnbg = nocolor
else:
try:
import colorama
colorama.init(strip=True,convert=True)
except:
red = green = yellow = cyan = nocolor
red = green = yellow = cyan = grnbg = nocolor
def msg(s): sys.stderr.write(s+"\n")
def msg_r(s): sys.stderr.write(s)
@ -144,7 +145,12 @@ def suf(arg,suf_type):
return "" if n == 1 else "s"
def get_extension(f):
return os.path.splitext(f)[1][1:]
a,b = os.path.splitext(f)
return ('',b[1:])[int(len(b) > 1)]
def remove_extension(f,e):
a,b = os.path.splitext(f)
return (f,a)[int(len(b) > 1 and b[1:] == e)]
def make_chksum_N(s,nchars,sep=False):
if nchars%4 or not (4 <= nchars <= 64): return False
@ -208,6 +214,11 @@ def is_utf8(s):
except: return False
else: return True
def is_ascii(s):
try: s.decode("ascii")
except: return False
else: return True
def match_ext(addr,ext):
return addr.split(".")[-1] == ext
@ -235,7 +246,8 @@ def pretty_hexdump(data,gw=2,cols=8,line_nums=False):
def decode_pretty_hexdump(data):
from string import hexdigits
lines = [re.sub('^['+hexdigits+']+:\s+','',l) for l in data.split("\n")]
pat = r'^[%s]+:\s+' % hexdigits
lines = [re.sub(pat,'',l) for l in data.splitlines()]
try:
return unhexlify("".join(("".join(lines).split())))
except:
@ -270,20 +282,12 @@ def compare_or_die(val1, desc1, val2, desc2, e="Error"):
dmsg("%s OK (%s)" % (capfirst(desc2),val2))
return True
def get_default_wordlist():
wl_id = g.default_wordlist
if wl_id == "electrum": from mmgen.mn_electrum import words as wl
elif wl_id == "tirosh": from mmgen.mn_tirosh import words as wl
return wl.strip().split("\n")
def open_file_or_exit(filename,mode):
try:
f = open(filename, mode)
except:
op = "reading" if 'r' in mode else "writing"
msg("Unable to open file '%s' for %s" % (filename,op))
sys.exit(2)
op = ("writing","reading")[int('r' in mode)]
die(2,"Unable to open file '%s' for %s" % (filename,op))
return f
@ -408,19 +412,6 @@ def confirm_or_exit(message, question, expect="YES"):
die(2,"Exiting at user request")
def write_to_stdout(data, desc, ask_terminal=True):
if sys.stdout.isatty() and ask_terminal:
confirm_or_exit("",'output {} to screen'.format(desc))
elif not sys.stdout.isatty():
try:
of = os.readlink("/proc/%d/fd/1" % os.getpid())
of_maybe = os.path.relpath(of)
of = of if of_maybe.find(os.path.pardir) == 0 else of_maybe
msg("Redirecting output to file '%s'" % of)
except:
msg("Redirecting output to file")
sys.stdout.write(data)
# New function
def write_data_to_file(
outfile,
@ -428,19 +419,26 @@ def write_data_to_file(
desc="data",
ask_write=False,
ask_write_prompt="",
ask_write_default_yes=False,
ask_write_default_yes=True,
ask_overwrite=True,
ask_tty=True,
no_tty=False,
silent=False
silent=False,
binary=False
):
if opt.stdout or not sys.stdout.isatty():
if silent: ask_tty = ask_overwrite = False
if opt.quiet: ask_overwrite = False
if ask_write_default_yes == False or ask_write_prompt:
ask_write = True
if opt.stdout or not sys.stdout.isatty() or outfile in ('','-'):
qmsg("Output to STDOUT requested")
write_ok = False
if sys.stdout.isatty():
if no_tty:
die(2,"Printing %s to screen is not allowed" % desc)
if ask_tty:
if ask_tty and not opt.quiet:
confirm_or_exit("",'output %s to screen' % desc)
else:
try: of = os.readlink("/proc/%d/fd/1" % os.getpid()) # Linux
@ -450,7 +448,7 @@ def write_data_to_file(
if of[:5] == "pipe:":
if no_tty:
die(2,"Writing %s to pipe is not allowed" % desc)
if ask_tty:
if ask_tty and not opt.quiet:
confirm_or_exit("",'output %s to pipe' % desc)
msg("")
of2,pd = os.path.relpath(of),os.path.pardir
@ -459,138 +457,41 @@ def write_data_to_file(
else:
msg("Redirecting output to file")
if binary and sys.platform[:3] == "win":
import msvcrt
msvcrt.setmode(sys.stdout.fileno(),os.O_BINARY)
sys.stdout.write(data)
else:
if opt.outdir: outfile = make_full_path(opt.outdir,outfile)
if ask_write:
if not ask_write_prompt: ask_write_prompt = "Save %s?" % desc
if not keypress_confirm(ask_write_prompt,
default_yes=ask_write_default_yes):
die(1,"Exiting at user request")
die(1,"%s not saved" % capfirst(desc))
hush = False
if file_exists(outfile):
if ask_overwrite and not silent:
q = "File '%s' already exists\nOverwrite?" % outfile
confirm_or_exit("",q)
msg("Overwriting file '%s'" % outfile)
if file_exists(outfile) and ask_overwrite:
q = "File '%s' already exists\nOverwrite?" % outfile
confirm_or_exit("",q)
msg("Overwriting file '%s'" % outfile)
hush = True
f = open_file_or_exit(outfile,'wb')
f = open_file_or_exit(outfile,'w'+('','b')[int(binary)])
try:
f.write(data)
except:
if not silent: msg("Failed to write %s to file '%s'" % (desc,outfile))
sys.exit(2)
die(2,"Failed to write %s to file '%s'" % (desc,outfile))
f.close
if not hush:
if not (hush or silent):
msg("%s written to file '%s'" % (capfirst(desc),outfile))
return True
def write_to_file(
outfile,
data,
desc="data",
confirm_overwrite=False,
verbose=False,
silent=False,
mode='wb'
):
if opt.outdir: outfile = make_full_path(opt.outdir,outfile)
try: os.stat(outfile)
except: pass
else:
if confirm_overwrite:
q = "File '%s' already exists\nOverwrite?" % outfile
confirm_or_exit("",q)
else:
if not silent: msg("Overwriting file '%s'" % outfile)
f = open_file_or_exit(outfile,mode)
try:
f.write(data)
except:
if not silent: msg("Failed to write %s to file '%s'" % (desc,outfile))
sys.exit(2)
f.close
if verbose: msg("%s written to file '%s'" % (capfirst(desc),outfile))
return True
def write_to_file_or_stdout(outfile, data, desc="data"):
if opt.stdout or not sys.stdout.isatty():
write_to_stdout(data, desc)
else:
write_to_file(outfile,data,desc,not opt.quiet,True)
from mmgen.bitcoin import b58decode_pad,b58encode_pad
def display_control_data(label,metadata,hash_preset,salt,enc_seed):
Msg("WALLET DATA")
fs = " {:18} {}"
pw_empty = "yes" if metadata[3] == "E" else "no"
for i in (
("Label:", label),
("Seed ID:", metadata[0].upper()),
("Key ID:", metadata[1].upper()),
("Seed length:", "%s bits (%s bytes)" %
(metadata[2],int(metadata[2])/8)),
("Scrypt params:", "Preset '%s' (%s)" % (hash_preset,
" ".join([str(i) for i in get_hash_params(hash_preset)]))),
("Passphrase empty?", pw_empty.capitalize()),
("Timestamp:", "%s UTC" % metadata[4]),
): Msg(fs.format(*i))
fs = " {:6} {}"
for i in (
("Salt:", ""),
(" b58:", b58encode_pad(salt)),
(" hex:", hexlify(salt)),
("Encrypted seed:", ""),
(" b58:", b58encode_pad(enc_seed)),
(" hex:", hexlify(enc_seed))
): Msg(fs.format(*i))
def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed):
seed_id = make_chksum_8(seed)
seed_len = str(len(seed)*8)
pw_status = "NE" if len(passwd) else "E"
hash_preset = opt.hash_preset
label = opt.label or "No Label"
metadata = seed_id.lower(),key_id.lower(),seed_len,\
pw_status,make_timestamp()
sf = b58encode_pad(salt)
esf = b58encode_pad(enc_seed)
lines = (
label,
"{} {} {} {} {}".format(*metadata),
"{}: {} {} {}".format(hash_preset,*get_hash_params(hash_preset)),
"{} {}".format(make_chksum_6(sf), split_into_cols(4,sf)),
"{} {}".format(make_chksum_6(esf), split_into_cols(4,esf))
)
chk = make_chksum_6(" ".join(lines))
outfile="{}-{}[{},{}].{}".format(
seed_id,key_id,seed_len,hash_preset,g.wallet_ext)
d = "\n".join((chk,)+lines)+"\n"
write_to_file(outfile,d,"wallet",not opt.quiet,True)
if opt.debug:
display_control_data(label,metadata,hash_preset,salt,enc_seed)
def _check_mmseed_format(words):
valid = False
@ -638,50 +539,6 @@ def _check_chksum_6(chk,val,desc,infile):
dmsg("%s checksum passed: %s" % (capfirst(desc),chk))
def get_data_from_wallet(infile,silent=False):
# Don't make this a qmsg: User will be prompted for passphrase and must see
# the filename.
if not silent and not opt.quiet:
msg("Getting {pnm} wallet data from file '{f}'".format(pnm=pnm,f=infile))
f = open_file_or_exit(infile, 'r')
lines = [i.strip() for i in f.readlines()]
f.close()
_check_wallet_format(infile, lines)
label = lines[1]
metadata = lines[2].split()
for i in 0,1: metadata[i] = metadata[i].upper()
hd = lines[3].split()
hash_preset = hd[0][:-1]
hash_params = [int(i) for i in hd[1:]]
if hash_params != get_hash_params(hash_preset):
msg("Hash parameters '%s' don't match hash preset '%s'" %
(" ".join(hash_params), hash_preset))
sys.exit(9)
res = {}
for i,key in (4,"salt"),(5,"enc_seed"):
l = lines[i].split()
val = "".join(l[1:])
_check_chksum_6(l[0], val, key, infile)
res[key] = b58decode_pad(val)
if res[key] == False:
msg("Invalid b58 number: %s" % val)
sys.exit(9)
_check_chksum_6(lines[0], " ".join(lines[1:]), "Master", infile)
return label,metadata,hash_preset,res['salt'],res['enc_seed']
def get_words_from_user(prompt):
# split() also strips
words = my_raw_input(prompt, echo=opt.echo_passphrase).split()
@ -719,7 +576,7 @@ def get_lines_from_file(infile,desc="",trim_comments=False):
if desc != "":
qmsg("Getting %s from file '%s'" % (desc,infile))
f = open_file_or_exit(infile,'r')
lines = f.read().splitlines()
lines = f.read().splitlines() # DOS-safe
f.close()
return remove_comments(lines) if trim_comments else lines
@ -729,11 +586,11 @@ def get_data_from_user(desc="data",silent=False):
dmsg("User input: [%s]" % data)
return data
def get_data_from_file(infile,desc="data",dash=False,silent=False):
def get_data_from_file(infile,desc="data",dash=False,silent=False,binary=False):
if dash and infile == "-": return sys.stdin.read()
if not silent:
qmsg("Getting %s from file '%s'" % (desc,infile))
f = open_file_or_exit(infile,'rb')
f = open_file_or_exit(infile,'r'+('','b')[int(binary)])
data = f.read()
f.close()
return data
@ -757,7 +614,7 @@ def get_seed_from_seed_data(words):
msg("Invalid b58 number: %s" % val)
return False
msg("Valid seed data for seed ID %s" % make_chksum_8(seed))
msg("Valid seed data for Seed ID %s" % make_chksum_8(seed))
return seed
else:
msg("Invalid checksum for {pnm} seed".format(pnm=pnm))
@ -787,8 +644,7 @@ def get_mmgen_passphrase(desc,passchg=False):
def get_bitcoind_passphrase(prompt):
if opt.passwd_file:
pwfile_reuse_warning()
return get_data_from_file(opt.passwd_file,
"passphrase").strip("\r\n")
return get_data_from_file(opt.passwd_file,"passphrase").strip("\r\n")
else:
return my_raw_input(prompt, echo=opt.echo_passphrase)

View file

@ -37,7 +37,6 @@ setup(
'mmgen.filename',
'mmgen.license',
'mmgen.mn_electrum',
'mmgen.mnemonic',
'mmgen.mn_tirosh',
'mmgen.obj',
'mmgen.opts',

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@ os.chdir(os.path.join(pn,os.pardir))
sys.path.__setitem__(0,os.path.abspath(os.curdir))
import mmgen.opt as opt
from mmgen.util import msg,msg_r,vmsg,vmsg_r,Msg,mmsg,mdie,start_mscolor
from mmgen.util import *
from collections import OrderedDict
start_mscolor()
@ -108,9 +108,7 @@ if opt.list_cmds:
import binascii
from mmgen.test import *
from mmgen.util import get_data_from_file,write_to_file,get_lines_from_file
from mmgen.tx import is_wif,is_btc_addr,is_b58_str
from mmgen.mnemonic import get_seed_from_mnemonic
class MMGenToolTestSuite(object):
@ -192,12 +190,12 @@ class MMGenToolTestSuite(object):
return ret
def run_cmd_out(self,name,carg=None,Return=False,kwargs="",fn_idx="",extra_msg=""):
if carg: write_to_tmpfile(cfg,"%s%s.in" % (name,fn_idx),carg+"\n",mode='w')
if carg: write_to_tmpfile(cfg,"%s%s.in" % (name,fn_idx),carg+"\n")
ret = self.run_cmd(name,[carg] if carg else [],kwargs=kwargs,extra_msg=extra_msg)
if carg: vmsg("In: " + repr(carg))
vmsg("Out: " + repr(ret))
if ret:
write_to_tmpfile(cfg,"%s%s.out" % (name,fn_idx),ret+"\n",mode='w')
write_to_tmpfile(cfg,"%s%s.out" % (name,fn_idx),ret+"\n")
if Return: return ret
else: ok()
else:
@ -207,10 +205,10 @@ class MMGenToolTestSuite(object):
def run_cmd_randinput(self,name,strip=True):
s = os.urandom(128)
fn = name+".in"
write_to_tmpfile(cfg,fn,s)
write_to_tmpfile(cfg,fn,s,binary=True)
ret = self.run_cmd(name,[get_tmpfile_fn(cfg,fn)],strip=strip)
fn = name+".out"
write_to_tmpfile(cfg,fn,ret+"\n",mode='w')
write_to_tmpfile(cfg,fn,ret+"\n")
ok()
vmsg("Returned: %s" % ret)
@ -244,14 +242,14 @@ class MMGenToolTestSuite(object):
def unhexdump(self,name,fn1,fn2):
ret = self.run_cmd(name,[fn2],strip=False)
orig = read_from_file(fn1)
orig = read_from_file(fn1,binary=True)
cmp_or_die(orig,ret)
def rand2file(self,name):
of = name + ".out"
dlen = 1024
self.run_cmd(name,[of,str(1024),"threads=4","silent=1"],strip=False)
d = read_from_tmpfile(cfg,of)
d = read_from_tmpfile(cfg,of,binary=True)
cmp_or_die(dlen,len(d))
def strtob58(self,name): self.run_cmd_out(name,getrandstr(16))
@ -297,8 +295,8 @@ class MMGenToolTestSuite(object):
for n,fi,fo,m in (1,f1,f2,""),(2,f3,f4,"from compressed"):
self.run_cmd_chk(name,fi,fo,extra_msg=m)
def privhex2addr(self,name,f1,f2):
key1 = read_from_file(f1)
key2 = read_from_file(f2)
key1 = read_from_file(f1).rstrip()
key2 = read_from_file(f2).rstrip()
for n,args in enumerate([[key1],[key2,"compressed=1"]]):
ret = self.run_cmd(name,args).rstrip()
iaddr = read_from_tmpfile(cfg,"randpair%s.out" % (n+1)).split()[-1]