Version 0.8.5rc1
This commit is contained in:
parent
9280428da3
commit
7affd8ebea
11 changed files with 65 additions and 82 deletions
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -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':
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -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',
|
||||
|
|
|
|||
62
test/test.py
62
test/test.py
|
|
@ -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-'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue