Version 0.8.5rc1

This commit is contained in:
philemon 2016-07-27 22:55:47 +03:00
commit 7affd8ebea
11 changed files with 65 additions and 82 deletions

View file

@ -89,7 +89,7 @@ class AddrList(MMGenObject): # Address info for a single seed ID
# A text label of {n} characters or less may be added to the right of each
# address, and it will be appended to the bitcoind wallet label upon import.
# The label may contain any printable ASCII symbol.
""".strip().format(n=g.max_addr_label_len,pnm=pnm),
""".strip().format(n=MMGenAddrLabel.max_len,pnm=pnm),
'record_chksum': """
Record this checksum: it will be used to verify the address file in the future
""".strip(),

View file

@ -51,7 +51,7 @@ class Filename(MMGenObject):
import stat
if stat.S_ISBLK(os.stat(fn).st_mode):
mode = (os.O_RDONLY,os.O_RDWR)[bool(write)]
if sys.platform[:3] == 'win': mode |= os.O_BINARY
if g.platform == 'win': mode |= os.O_BINARY
try:
fd = os.open(fn, mode)
except OSError as e:

View file

@ -20,7 +20,7 @@
globalvars.py: Constants and configuration options for the MMGen suite
"""
import sys, os
import sys,os
# Variables - these might be altered at runtime:
@ -29,13 +29,6 @@ hash_preset = '3'
usr_randchars = 30
use_urandchars = False
# returns None if env var unset
debug = os.getenv('MMGEN_DEBUG')
no_license = os.getenv('MMGEN_NOLICENSE')
bogus_wallet_data = os.getenv('MMGEN_BOGUS_WALLET_DATA')
disable_hold_protect = os.getenv('MMGEN_DISABLE_HOLD_PROTECT')
color = (False,True)[sys.stdout.isatty() and not os.getenv('MMGEN_DISABLE_COLOR')]
from mmgen.obj import BTCAmt
tx_fee = BTCAmt('0.0003')
tx_fee_adj = 1.0
@ -46,12 +39,19 @@ http_timeout = 60
# Constants - these don't change at runtime
# os.getenv() returns None if environmental var is unset
debug = os.getenv('MMGEN_DEBUG')
no_license = os.getenv('MMGEN_NOLICENSE')
bogus_wallet_data = os.getenv('MMGEN_BOGUS_WALLET_DATA')
disable_hold_protect = os.getenv('MMGEN_DISABLE_HOLD_PROTECT')
color = (False,True)[sys.stdout.isatty() and not os.getenv('MMGEN_DISABLE_COLOR')]
proj_name = 'MMGen'
prog_name = os.path.basename(sys.argv[0])
author = 'Philemon'
email = '<mmgen-py@yandex.com>'
Cdates = '2013-2016'
version = '0.8.4'
version = '0.8.5rc1'
required_opts = [
'quiet','verbose','debug','outdir','echo_passphrase','passwd_file',
@ -100,12 +100,8 @@ hash_presets = {
'7': [18, 8, 24],
}
mmgen_idx_max_digits = 7
printable_nonl = [chr(i+32) for i in range(95)]
printable = printable_nonl + ['\n','\t']
addr_label_symbols = wallet_label_symbols = printable_nonl
max_addr_label_len = 32
max_wallet_label_len = 48
max_tx_comment_len = 72 # Comment is b58 encoded, so can permit UTF-8
for k in ('win','linux'):
if sys.platform[:len(k)] == k: platform = k; break
else:
sys.stderr.write("'%s': platform not supported by %s\n" % (sys.platform,proj_name))
sys.exit(1)

View file

@ -39,8 +39,8 @@ class MMGenObject(object):
def conv(v,col_w):
vret = ''
if type(v) in (str,unicode):
import mmgen.globalvars as g
if not (set(list(v)) <= set(list(g.printable))):
from string import printable
if not (set(list(v)) <= set(list(printable))):
vret = repr(v)
else:
vret = fix_linebreaks(v,fixed_indent=0)

View file

@ -955,7 +955,7 @@ harder to find, you're advised to choose a much larger file size than this.
d.target_data_len = self._get_incog_data_len(opt.seed_len)
self._check_valid_offset(self.infile,'read')
flgs = os.O_RDONLY|os.O_BINARY if sys.platform[:3] == 'win' else os.O_RDONLY
flgs = os.O_RDONLY|os.O_BINARY if g.platform == 'win' else os.O_RDONLY
fh = os.open(self.infile.name,flgs)
os.lseek(fh,int(d.hincog_offset),os.SEEK_SET)
self.fmt_data = os.read(fh,d.target_data_len)
@ -1005,7 +1005,7 @@ harder to find, you're advised to choose a much larger file size than this.
self._check_valid_offset(f,'write')
if not opt.quiet: confirm_or_exit('',"alter file '%s'" % f.name)
flgs = os.O_RDWR|os.O_BINARY if sys.platform[:3] == 'win' else os.O_RDWR
flgs = os.O_RDWR|os.O_BINARY if g.platform == 'win' else os.O_RDWR
fh = os.open(f.name,flgs)
os.lseek(fh, int(d.hincog_offset), os.SEEK_SET)
os.write(fh, self.fmt_data)

View file

@ -21,7 +21,6 @@ term.py: Terminal-handling routines for the MMGen suite
"""
import os,struct
from mmgen.common import *
def _kb_hold_protect_unix():
@ -201,15 +200,9 @@ except:
get_terminal_size = _get_terminal_size_mswin
myflush = mswin_dummy_flush
except:
if not sys.platform.startswith('linux') \
and not sys.platform.startswith('win'):
msg('Unsupported platform: %s' % sys.platform)
msg('This program currently runs only on Linux and Windows')
else:
msg('Unable to set terminal mode')
msg('Unable to set terminal mode')
sys.exit(2)
def do_pager(text):
pagers = ['less','more']
@ -224,7 +217,7 @@ def do_pager(text):
# 'print' instead of the pager.
# We risk assuming that 'more' will always be available on a stock
# Windows installation.
if sys.platform.startswith('win'):
if g.platform == 'win':
if 'HOME' not in environ: # native Windows terminal
shell = True
pagers = ['more']

View file

@ -252,7 +252,7 @@ def hexdump(infile, cols=8, line_nums=True):
cols=cols,line_nums=line_nums))
def unhexdump(infile):
if sys.platform[:3] == 'win':
if g.platform == 'win':
import msvcrt
msvcrt.setmode(sys.stdout.fileno(),os.O_BINARY)
sys.stdout.write(decode_pretty_hexdump(
@ -425,7 +425,7 @@ def listaddresses(addrs='',minconf=1,showempty=False,pager=False,showbtcaddrs=Fa
)
def s_mmgen(key): # TODO
return '{}:{:>0{w}}'.format(w=g.mmgen_idx_max_digits, *key.split('_'))
return '{}:{:>0{w}}'.format(w=AddrIdx.max_digits, *key.split('_'))
out = []
for k in sorted(addrs,key=s_mmgen):
@ -572,7 +572,7 @@ def decrypt(infile,outfile='',hash_preset=''):
def find_incog_data(filename,iv_id,keep_searching=False):
ivsize,bsize,mod = g.aesctr_iv_len,4096,4096*8
n,carry = 0,' '*ivsize
flgs = os.O_RDONLY|os.O_BINARY if sys.platform[:3] == 'win' else os.O_RDONLY
flgs = os.O_RDONLY|os.O_BINARY if g.platform == 'win' else os.O_RDONLY
f = os.open(filename,flgs)
for ch in iv_id:
if ch not in '0123456789ABCDEF':

View file

@ -84,7 +84,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
def s_mmid(self,i):
if i.mmid:
return '{}:{:>0{w}}'.format(
*i.mmid.split(':'), w=g.mmgen_idx_max_digits)
*i.mmid.split(':'), w=AddrIdx.max_digits)
else: return 'G' + (i.label or '')
def do_sort(self,key,reverse=None):
@ -97,7 +97,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
def sort_info(self,include_group=True):
ret = ([],['Reverse'])[self.reverse]
ret.append(self.sort.capitalize().replace('Mmid','MMGenId'))
ret.append(self.sort.capitalize().replace('Mmid','MMGenID'))
if include_group and self.group and (self.sort in ('addr','txid','mmid')):
ret.append('Grouped')
return ret

View file

@ -57,7 +57,7 @@ def magenta(s): return _mag+s+_reset
def nocolor(s): return s
def start_mscolor():
if sys.platform[:3] == 'win':
if g.platform == 'win':
global red,green,yellow,cyan,nocolor
import os
if 'MMGEN_NOMSCOLOR' in os.environ:
@ -101,20 +101,6 @@ def pp_msg(d):
import pprint
msg(pprint.PrettyPrinter(indent=4).pformat(d))
def is_mmgen_wallet_label(s):
if len(s) > g.max_wallet_label_len:
msg('ERROR: wallet label length (%s chars) > maximum allowed (%s chars)' % (len(s),g.max_wallet_label_len))
return False
try: s = s.decode('utf8')
except: pass
for ch in s:
if ch not in g.wallet_label_symbols:
msg('ERROR: wallet label contains illegal symbol (%s)' % ch)
return False
return True
# From 'man dd':
# c=1, w=2, b=512, kB=1000, K=1024, MB=1000*1000, M=1024*1024,
# GB=1000*1000*1000, G=1024*1024*1024, and so on for T, P, E, Z, Y.
@ -503,7 +489,7 @@ def write_data_to_file(
else:
msg('Redirecting output to file')
if binary and sys.platform[:3] == 'win':
if binary and g.platform == 'win':
import msvcrt
msvcrt.setmode(sys.stdout.fileno(),os.O_BINARY)

View file

@ -21,7 +21,7 @@ from distutils.core import setup
setup(
name = 'mmgen',
description = 'A complete Bitcoin cold-storage solution for the command line',
version = '0.8.4',
version = '0.8.5rc1',
author = 'Philemon',
author_email = 'mmgen-py@yandex.com',
url = 'https://github.com/mmgen/mmgen',

View file

@ -482,6 +482,7 @@ opts_data = {
-s, --system Test scripts and modules installed on system rather
than those in the repo root.
-S, --skip-deps Skip dependency checking for command
-u, --usr-random Get random data interactively from user
-t, --traceback Run the command inside the '{tb_cmd}' script.
-v, --verbose Produce more verbose output.
""".format(tb_cmd=tb_cmd,lf=log_file),
@ -498,6 +499,9 @@ if opt.log:
log_fd = open(log_file,'a')
log_fd.write('\nLog started: %s\n' % make_timestr())
usr_rand_chars = (5,30)[bool(opt.usr_random)]
usr_rand_arg = '-r%s' % usr_rand_chars
if opt.system: sys.path.pop(0)
ni = bool(opt.non_interactive)
@ -530,7 +534,7 @@ stderr_save = sys.stderr
def silence():
if not (opt.verbose or opt.exact_output):
f = ('/dev/null','stderr.out')[sys.platform[:3]=='win']
f = ('/dev/null','stderr.out')[g.platform=='win']
sys.stderr = open(f,'a')
def end_silence():
@ -708,17 +712,21 @@ class MMGenExpect(object):
my_expect(self.p,'Generating encryption key from OS random data plus ' + m)
def usr_rand(self,num_chars):
rand_chars = list(getrandstr(num_chars,no_space=True))
my_expect(self.p,'symbols left: ','x')
try:
vmsg_r('SEND ')
while self.p.expect('left: ',0.1) == 0:
ch = rand_chars.pop(0)
msg_r(yellow(ch)+' ' if opt.verbose else '+')
self.p.send(ch)
except:
vmsg('EOT')
my_expect(self.p,'ENTER to continue: ','\n')
if opt.usr_random:
self.interactive()
my_send(self.p,'\n')
else:
rand_chars = list(getrandstr(num_chars,no_space=True))
my_expect(self.p,'symbols left: ','x')
try:
vmsg_r('SEND ')
while self.p.expect('left: ',0.1) == 0:
ch = rand_chars.pop(0)
msg_r(yellow(ch)+' ' if opt.verbose else '+')
self.p.send(ch)
except:
vmsg('EOT')
my_expect(self.p,'ENTER to continue: ','\n')
def passphrase_new(self,desc,passphrase):
my_expect(self.p,('Enter passphrase for %s: ' % desc), passphrase+'\n')
@ -807,7 +815,7 @@ labels = [
"Healthcare",
"Freelancing 1",
"Freelancing 2",
"Alice's assets",
"Alice's allowance",
"Bob's bequest",
"House purchase",
"Real estate fund",
@ -1043,14 +1051,14 @@ class MMGenTestSuite(object):
def walletgen(self,name,seed_len=None):
write_to_tmpfile(cfg,pwfile,cfg['wpasswd']+'\n')
add_args = (['-r5'],
add_args = ([usr_rand_arg],
['-q','-r0','-L','NI Wallet','-P',get_tmpfile_fn(cfg,pwfile)])[bool(ni)]
args = ['-d',cfg['tmpdir'],'-p1']
if seed_len: args += ['-l',str(seed_len)]
t = MMGenExpect(name,'mmgen-walletgen', args + add_args)
if ni: return
t.license()
t.usr_rand(10)
t.usr_rand(usr_rand_chars)
t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
t.label()
t.written_to_file('MMGen wallet')
@ -1069,13 +1077,13 @@ class MMGenTestSuite(object):
add_args = ['-r0', '-q', '-P%s' % get_tmpfile_fn(cfg,pwfile),
get_tmpfile_fn(cfg,bf)]
else:
add_args = ['-r5']
add_args = [usr_rand_arg]
t = MMGenExpect(name,'mmgen-walletconv', args + add_args)
if ni: return
t.license()
t.expect('Enter brainwallet: ', ref_wallet_brainpass+'\n')
t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
t.usr_rand(10)
t.usr_rand(usr_rand_chars)
sid = t.written_to_file('MMGen wallet').split('-')[0].split('/')[-1]
refcheck('Seed ID',sid,cfg['seed_id'])
@ -1086,7 +1094,7 @@ class MMGenTestSuite(object):
silence()
write_to_tmpfile(cfg,pwfile,get_data_from_file(pf))
end_silence()
add_args = (['-r16'],['-q','-r0','-P',pf])[bool(ni)]
add_args = ([usr_rand_arg],['-q','-r0','-P',pf])[bool(ni)]
t = MMGenExpect(name,'mmgen-passchg', add_args +
['-d',cfg['tmpdir'],'-p','2','-L','New Label',wf])
if ni: return
@ -1095,7 +1103,7 @@ class MMGenTestSuite(object):
t.expect_getend('Hash preset changed to ')
t.passphrase('MMGen wallet',cfg['wpasswd'],pwtype='new')
t.expect('Repeat passphrase: ',cfg['wpasswd']+'\n')
t.usr_rand(16)
t.usr_rand(usr_rand_chars)
t.expect_getend('Label changed to ')
# t.expect_getend('Key ID changed: ')
t.written_to_file('MMGen wallet')
@ -1295,7 +1303,7 @@ class MMGenTestSuite(object):
t.passphrase('MMGen wallet',cfg['wpasswd'])
if pw:
t.passphrase_new('new '+desc,cfg['wpasswd'])
t.usr_rand(10)
t.usr_rand(usr_rand_chars)
if ' '.join(desc.split()[-2:]) == 'incognito data':
t.expect('Generating encryption key from OS random data ')
t.expect('Generating encryption key from OS random data ')
@ -1323,7 +1331,7 @@ class MMGenTestSuite(object):
self.export_seed(name,wf,desc='mnemonic data',out_fmt='words')
def export_incog(self,name,wf,desc='incognito data',out_fmt='i',add_args=[]):
uargs = ['-p1','-r5'] + add_args
uargs = ['-p1',usr_rand_arg] + add_args
self.walletconv_export(name,wf,desc=desc,out_fmt=out_fmt,uargs=uargs,pw=True)
ok()
@ -1453,11 +1461,11 @@ class MMGenTestSuite(object):
bwf = os.path.join(cfg['tmpdir'],cfg['bw_filename'])
make_brainwallet_file(bwf)
seed_len = str(cfg['seed_len'])
args = ['-d',cfg['tmpdir'],'-p1','-r5','-l'+seed_len,'-ib']
args = ['-d',cfg['tmpdir'],'-p1',usr_rand_arg,'-l'+seed_len,'-ib']
t = MMGenExpect(name,'mmgen-walletconv', args + [bwf])
t.license()
t.passphrase_new('new MMGen wallet',cfg['wpasswd'])
t.usr_rand(10)
t.usr_rand(usr_rand_chars)
t.label()
t.written_to_file('MMGen wallet')
ok()
@ -1734,7 +1742,7 @@ class MMGenTestSuite(object):
# wallet conversion tests
def walletconv_in(self,name,infile,desc,uopts=[],pw=False,oo=False):
opts = ['-d',cfg['tmpdir'],'-o','words','-r5']
opts = ['-d',cfg['tmpdir'],'-o','words',usr_rand_arg]
if_arg = [infile] if infile else []
d = '(convert)'
if ni:
@ -1788,7 +1796,7 @@ class MMGenTestSuite(object):
rd = os.urandom(ref_wallet_incog_offset+128)
write_to_tmpfile(cfg,hincog_fn,rd)
else:
aa = ['-r5']
aa = [usr_rand_arg]
infile = os.path.join(ref_dir,cfg['seed_id']+'.mmwords')
t = MMGenExpect(name,'mmgen-walletconv',aa+opts+[infile],extra_desc='(convert)')
@ -1807,7 +1815,7 @@ class MMGenTestSuite(object):
t.license()
if pw:
t.passphrase_new('new '+desc,cfg['wpasswd'])
t.usr_rand(10)
t.usr_rand(usr_rand_chars)
if ' '.join(desc.split()[-2:]) == 'incognito data':
for i in (1,2,3):
t.expect('Generating encryption key from OS random data ')
@ -1876,7 +1884,7 @@ ts = MMGenTestSuite()
# Laggy flash media cause pexpect to crash, so read and write all temporary
# files to volatile memory in '/dev/shm'
if not opt.skip_deps:
if sys.platform[:3] == 'win':
if g.platform == 'win':
for cfg in sorted(cfgs): mk_tmpdir(cfgs[cfg])
else:
d,pfx = '/dev/shm','mmgen-test-'