various minor fixes and cleanups
This commit is contained in:
parent
11b04d4d9d
commit
3a09017804
16 changed files with 67 additions and 28 deletions
|
|
@ -1,5 +1,6 @@
|
|||
include README.md SIGNING_KEYS.pub LICENSE INSTALL
|
||||
include doc/wiki/using-mmgen/*
|
||||
|
||||
include test/*.py
|
||||
include test/test_py_d/*.py
|
||||
include test/ref/*
|
||||
|
|
@ -10,6 +11,9 @@ include test/ref/dash/*
|
|||
include test/ref/zcash/*
|
||||
include test/ref/monero/*
|
||||
|
||||
include mmgen/altcoins/eth/rlp/LICENSE
|
||||
include mmgen/altcoins/eth/pyethereum/LICENSE
|
||||
|
||||
include scripts/compute-file-chksum.py
|
||||
include scripts/create-token.py
|
||||
include scripts/test-release.sh
|
||||
|
|
|
|||
|
|
@ -375,7 +375,6 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
|
|||
gen_keys = False
|
||||
has_keys = False
|
||||
ext = 'addrs'
|
||||
scramble_hash_rounds = 10 # not too many rounds, so hand decoding can still be feasible
|
||||
chksum_rec_f = lambda foo,e: (str(e.idx), e.addr)
|
||||
|
||||
def __init__(self,addrfile='',al_id='',adata=[],seed='',addr_idxs='',src='',
|
||||
|
|
@ -497,7 +496,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
|
|||
if g.proto.is_testnet():
|
||||
scramble_key += ':testnet'
|
||||
dmsg_sc('str',scramble_key)
|
||||
return scramble_seed(seed,scramble_key.encode(),self.scramble_hash_rounds)
|
||||
return scramble_seed(seed,scramble_key.encode(),g.scramble_hash_rounds)
|
||||
|
||||
def encrypt(self,desc='new key list'):
|
||||
from mmgen.crypto import mmgen_encrypt
|
||||
|
|
@ -886,7 +885,7 @@ Record this checksum: it will be used to verify the password file in the future
|
|||
# NB: In original implementation, pw_id_str was 'baseN', not 'bN'
|
||||
scramble_key = '{}:{}:{}'.format(self.pw_fmt,self.pw_len,self.pw_id_str)
|
||||
from mmgen.crypto import scramble_seed
|
||||
return scramble_seed(seed,scramble_key.encode(),self.scramble_hash_rounds)
|
||||
return scramble_seed(seed,scramble_key.encode(),g.scramble_hash_rounds)
|
||||
|
||||
class AddrData(MMGenObject):
|
||||
msgs = {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ def help_notes(k):
|
|||
'rel_fee_desc': MMGenTX().rel_fee_desc,
|
||||
'fee_spec_letters': fee_spec_letters(),
|
||||
'passwd': """
|
||||
PASSPHRASE NOTE:
|
||||
|
||||
For passphrases all combinations of whitespace are equal, and leading and
|
||||
trailing space are ignored. This permits reading passphrase or brainwallet
|
||||
data from a multi-line file with free spacing and indentation.
|
||||
|
|
|
|||
|
|
@ -45,8 +45,9 @@ def sha256_rounds(s,n):
|
|||
def scramble_seed(seed,scramble_key,hash_rounds):
|
||||
import hmac
|
||||
scr_seed = hmac.new(seed,scramble_key,sha256).digest()
|
||||
fs = 'Seed: {}\nScramble key: {}\nScrambled seed: {}'
|
||||
dmsg(fs.format(seed.hex(),scramble_key.decode(),scr_seed.hex()))
|
||||
if g.debug:
|
||||
fs = 'Seed: {!r}\nScramble key: {}\nScrambled seed: {}\n'
|
||||
msg(fs.format(seed.hex(),scramble_key,scr_seed.hex()))
|
||||
return sha256_rounds(scr_seed,hash_rounds)
|
||||
|
||||
def encrypt_seed(seed,key):
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ class g(object):
|
|||
min_urandchars = 10
|
||||
|
||||
seed_lens = 128,192,256
|
||||
scramble_hash_rounds = 10
|
||||
|
||||
mmenc_ext = 'mmenc'
|
||||
salt_len = 16
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@
|
|||
main.py - Script launcher for the MMGen suite
|
||||
"""
|
||||
|
||||
def launch(what):
|
||||
def launch(mod):
|
||||
|
||||
if what in ('walletgen','walletchk','walletconv','passchg'):
|
||||
what = 'wallet'
|
||||
if what == 'keygen': what = 'addrgen'
|
||||
if mod in ('walletgen','walletchk','walletconv','passchg'):
|
||||
mod = 'wallet'
|
||||
if mod == 'keygen': mod = 'addrgen'
|
||||
|
||||
import sys,os
|
||||
from mmgen.globalvars import g
|
||||
|
|
@ -36,7 +36,7 @@ def launch(what):
|
|||
atexit.register(lambda: termios.tcsetattr(fd,termios.TCSADRAIN,old))
|
||||
|
||||
try:
|
||||
__import__('mmgen.main_' + what)
|
||||
__import__('mmgen.main_' + mod)
|
||||
except KeyboardInterrupt:
|
||||
sys.stderr.write('\nUser interrupt\n')
|
||||
except EOFError:
|
||||
|
|
|
|||
|
|
@ -30,8 +30,14 @@ usage = '[opts] [infile]'
|
|||
nargs = 1
|
||||
iaction = 'convert'
|
||||
oaction = 'convert'
|
||||
invoked_as = 'passchg' if g.prog_name == 'mmgen-passchg' else g.prog_name.partition('-wallet')[2]
|
||||
bw_note = True
|
||||
do_bw_note = True
|
||||
|
||||
invoked_as = {
|
||||
'mmgen-walletgen': 'gen',
|
||||
'mmgen-walletconv': 'conv',
|
||||
'mmgen-walletchk': 'chk',
|
||||
'mmgen-passchg': 'passchg',
|
||||
}[g.prog_name]
|
||||
|
||||
# full: defhHiJkKlLmoOpPqrSvz-
|
||||
if invoked_as == 'gen':
|
||||
|
|
@ -51,9 +57,7 @@ elif invoked_as == 'passchg':
|
|||
desc = 'Change the passphrase, hash preset or label of an {pnm} wallet'
|
||||
opt_filter = 'efhdiHkKOlLmpPqrSvz-'
|
||||
iaction = 'input'
|
||||
bw_note = False
|
||||
else:
|
||||
die(1,"'{}': unrecognized invocation".format(g.prog_name))
|
||||
do_bw_note = False
|
||||
|
||||
opts_data = {
|
||||
'text': {
|
||||
|
|
@ -108,7 +112,7 @@ FMT CODES:
|
|||
'notes': lambda s: s.format(
|
||||
f='\n '.join(SeedSource.format_fmt_codes().splitlines()),
|
||||
n_pw=help_notes('passwd'),
|
||||
n_bw=('','\n\n' + help_notes('brainwallet'))[bw_note]
|
||||
n_bw=('','\n\n'+help_notes('brainwallet'))[do_bw_note]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -128,6 +132,7 @@ if invoked_as in ('conv','passchg'):
|
|||
msg(m1+m2)
|
||||
|
||||
ss_in = None if invoked_as == 'gen' else SeedSource(sf,passchg=(invoked_as=='passchg'))
|
||||
|
||||
if invoked_as == 'chk':
|
||||
lbl = ss_in.ssdata.label.hl() if hasattr(ss_in.ssdata,'label') else 'NONE'
|
||||
vmsg('Wallet label: {}'.format(lbl))
|
||||
|
|
|
|||
|
|
@ -118,7 +118,8 @@ class InitErrors(object):
|
|||
|
||||
@staticmethod
|
||||
def arg_chk(cls,on_fail):
|
||||
assert on_fail in ('die','return','silent','raise'),'arg_chk in class {}'.format(cls.__name__)
|
||||
assert on_fail in ('die','return','silent','raise'),(
|
||||
"'{}': invalid value for 'on_fail' in class {}".format(on_fail,cls.__name__) )
|
||||
|
||||
@staticmethod
|
||||
def init_fail(m,on_fail):
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ def init(opts_data,add_opts=[],opt_filter=None,parse_only=False):
|
|||
|
||||
if hasattr(g,'cfg_options_changed'):
|
||||
ymsg("Warning: config file options have changed! See '{}' for details".format(g.cfg_file+'.sample'))
|
||||
from mmgen.util import my_raw_input
|
||||
my_raw_input('Hit ENTER to continue: ')
|
||||
|
||||
if g.debug and g.prog_name != 'test.py':
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ def _usage(cmd=None,exit_val=1):
|
|||
Msg('')
|
||||
Msg(m2)
|
||||
elif cmd in MMGenToolCmd._user_commands():
|
||||
docstr = getattr(MMGenToolCmd,cmd).__doc__.strip()
|
||||
msg('{}\n'.format(capfirst(docstr)))
|
||||
msg('USAGE: {} {} {}'.format(g.prog_name,cmd,_create_call_sig(cmd)))
|
||||
else:
|
||||
die(1,"'{}': no such tool command".format(cmd))
|
||||
|
|
@ -678,8 +680,8 @@ class MMGenToolCmdWallet(MMGenToolCmdBase):
|
|||
def gen_addr(self,mmgen_addr:str,wallet='',target='addr'):
|
||||
"generate a single MMGen address from default or specified wallet"
|
||||
addr = MMGenID(mmgen_addr)
|
||||
sf = get_seed_file([wallet] if wallet else [],1)
|
||||
opt.quiet = True
|
||||
sf = get_seed_file([wallet] if wallet else [],1)
|
||||
from mmgen.seed import SeedSource
|
||||
ss = SeedSource(sf)
|
||||
if ss.seed.sid != addr.sid:
|
||||
|
|
@ -885,8 +887,9 @@ class MMGenToolCmdMonero(MMGenToolCmdBase):
|
|||
while True:
|
||||
ret = p.expect([r' / .*',r'\[wallet.*:.*'])
|
||||
if ret == 0: # TODO: coverage
|
||||
height = p.after
|
||||
msg_r('\r Block {}{}'.format(p.before.split()[-1],height))
|
||||
cur_block = p.before.decode().split()[-1]
|
||||
height = p.after.decode()
|
||||
msg_r('\r Block {}{}'.format(cur_block,height))
|
||||
elif ret == 1:
|
||||
if height:
|
||||
height = height.split()[-1]
|
||||
|
|
|
|||
|
|
@ -41,8 +41,12 @@ if g.platform == 'win':
|
|||
def msg(s): msg_r(s + '\n')
|
||||
def Msg(s): Msg_r(s + '\n')
|
||||
else:
|
||||
def msg_r(s): g.stderr.write(s)
|
||||
def Msg_r(s): g.stdout.write(s)
|
||||
def msg_r(s):
|
||||
g.stderr.write(s)
|
||||
g.stderr.flush()
|
||||
def Msg_r(s):
|
||||
g.stdout.write(s)
|
||||
g.stdout.flush()
|
||||
def msg(s): g.stderr.write(s + '\n')
|
||||
def Msg(s): g.stdout.write(s + '\n')
|
||||
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -117,12 +117,10 @@ setup(
|
|||
'mmgen.altcoins.eth.tx',
|
||||
'mmgen.altcoins.eth.tw',
|
||||
|
||||
'mmgen/altcoins/eth/pyethereum/LICENSE',
|
||||
'mmgen.altcoins.eth.pyethereum.__init__',
|
||||
'mmgen.altcoins.eth.pyethereum.transactions',
|
||||
'mmgen.altcoins.eth.pyethereum.utils',
|
||||
|
||||
'mmgen/altcoins/eth/rlp/LICENSE',
|
||||
'mmgen/altcoins/eth/rlp/__init__',
|
||||
'mmgen/altcoins/eth/rlp/atomic',
|
||||
'mmgen/altcoins/eth/rlp/codec',
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ def run_test(test,arg,input_data):
|
|||
del arg['ret']
|
||||
del arg_copy['ret']
|
||||
kwargs.update(arg)
|
||||
elif type(arg) == tuple:
|
||||
args = arg
|
||||
else:
|
||||
args = [arg]
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -199,7 +199,6 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
|
|||
t.expect('move it to the data directory? (Y/n): ','y')
|
||||
self.have_dfl_wallet = True
|
||||
t.written_to_file('MMGen wallet')
|
||||
t.req_exit_val = 0
|
||||
return t
|
||||
|
||||
def passchg(self,wf,pf,label_action='cmdline'):
|
||||
|
|
|
|||
|
|
@ -40,6 +40,15 @@ from mmgen.seed import is_mnemonic
|
|||
|
||||
def is_str(s): return type(s) == str
|
||||
|
||||
def md5_hash(s):
|
||||
from hashlib import md5
|
||||
return md5(s.encode()).hexdigest()
|
||||
|
||||
def md5_hash_strip(s):
|
||||
import re
|
||||
s = re.sub('\x1b\[[;0-9]+?m','',s) # strip ANSI color sequences
|
||||
return md5_hash(s.strip())
|
||||
|
||||
opts_data = {
|
||||
'text': {
|
||||
'desc': "Simple test suite for the 'mmgen-tool' utility",
|
||||
|
|
@ -592,7 +601,12 @@ def run_test(gid,cmd_name):
|
|||
cmd_err = p.stderr.read()
|
||||
if cmd_err: vmsg(cmd_err.strip().decode())
|
||||
if p.wait() != 0:
|
||||
die(1,'Spawned program exited with error')
|
||||
import re
|
||||
m = re.match(b"tool command returned '(None|False)'\n",cmd_err)
|
||||
if m:
|
||||
return { b'None': None, b'False': False }[m.group(1)]
|
||||
else:
|
||||
ydie(1,'Spawned program exited with error: {}'.format(cmd_err))
|
||||
|
||||
return cmd_out
|
||||
|
||||
|
|
@ -655,7 +669,11 @@ def run_test(gid,cmd_name):
|
|||
elif out is not None:
|
||||
assert cmd_out == out,"Output ({!r}) doesn't match expected output ({!r})".format(cmd_out,out)
|
||||
|
||||
if type(out) in (list,tuple):
|
||||
if type(out) == tuple and type(out[0]).__name__ == 'function':
|
||||
func_out = out[0](cmd_out)
|
||||
assert func_out == out[1],(
|
||||
"{}({}) == {} failed!\nOutput: {}".format(out[0].__name__,cmd_out,out[1],func_out))
|
||||
elif type(out) in (list,tuple):
|
||||
for co,o in zip(cmd_out.split('\n') if opt.fork else cmd_out,out):
|
||||
check_output(co,o)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ class UnitTests(object):
|
|||
extra_desc,
|
||||
'' if opt.quiet else '\n'))
|
||||
else:
|
||||
Msg('Testing transactions from {!r}'.format(fn))
|
||||
Msg_r('Testing transactions from {!r}'.format(fn))
|
||||
if not opt.quiet: Msg('')
|
||||
|
||||
def test_core_vectors():
|
||||
self._get_core_repo_root()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue