Improved options handling, some files moved and renamed.
Users who are upgrading must delete the 'opt' directory in their previous installation before installing. On a Linux system, this is typically located at: /usr/local/lib/python2.7/dist-packages/mmgen/opt
This commit is contained in:
parent
01fbc328b8
commit
c7056a7ba2
28 changed files with 542 additions and 481 deletions
|
|
@ -30,6 +30,7 @@ from mmgen.bitcoin import numtowif
|
|||
from mmgen.util import *
|
||||
from mmgen.tx import is_mmgen_idx,is_mmgen_seed_id,is_btc_addr,is_wif,get_wif2addr_f
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
|
||||
addrmsgs = {
|
||||
'addrfile_header': """
|
||||
|
|
@ -60,13 +61,13 @@ def test_for_keyconv():
|
|||
return True
|
||||
|
||||
|
||||
def generate_addrs(seed, addrnums, opts):
|
||||
def generate_addrs(seed, addrnums):
|
||||
|
||||
from util import make_chksum_8
|
||||
seed_id = make_chksum_8(seed) # Must do this before seed gets clobbered
|
||||
|
||||
if 'a' in opts['gen_what']:
|
||||
if g.no_keyconv or test_for_keyconv() == False:
|
||||
if 'a' in opt.gen_what:
|
||||
if opt.no_keyconv or test_for_keyconv() == False:
|
||||
msg("Using (slow) internal ECDSA library for address generation")
|
||||
from mmgen.bitcoin import privnum2addr
|
||||
keyconv = False
|
||||
|
|
@ -81,7 +82,7 @@ def generate_addrs(seed, addrnums, opts):
|
|||
'ka': ('key/address pair','s'),
|
||||
'k': ('key','s'),
|
||||
'a': ('address','es')
|
||||
}[opts['gen_what']]
|
||||
}[opt.gen_what]
|
||||
|
||||
from mmgen.addr import AddrInfoEntry,AddrInfo
|
||||
|
||||
|
|
@ -89,7 +90,7 @@ def generate_addrs(seed, addrnums, opts):
|
|||
seed = sha512(seed).digest()
|
||||
num += 1 # round
|
||||
|
||||
if g.debug: print "Seed round %s: %s" % (num, hexlify(seed))
|
||||
if opt.debug: print "Seed round %s: %s" % (num, hexlify(seed))
|
||||
if num != addrnums[pos]: continue
|
||||
|
||||
pos += 1
|
||||
|
|
@ -103,20 +104,20 @@ def generate_addrs(seed, addrnums, opts):
|
|||
sec = sha256(sha256(seed).digest()).hexdigest()
|
||||
wif = numtowif(int(sec,16))
|
||||
|
||||
if 'a' in opts['gen_what']:
|
||||
if 'a' in opt.gen_what:
|
||||
if keyconv:
|
||||
e.addr = check_output([keyconv, wif]).split()[1]
|
||||
else:
|
||||
e.addr = privnum2addr(int(sec,16))
|
||||
|
||||
if 'k' in opts['gen_what']: e.wif = wif
|
||||
if 'b16' in opts: e.sec = sec
|
||||
if 'k' in opt.gen_what: e.wif = wif
|
||||
if opt.b16: e.sec = sec
|
||||
|
||||
out.append(e)
|
||||
|
||||
m = w[0] if t_addrs == 1 else w[0]+w[1]
|
||||
qmsg("\r%s: %s %s generated%s" % (seed_id,t_addrs,m," "*15))
|
||||
a = AddrInfo(has_keys='k' in opts['gen_what'])
|
||||
a = AddrInfo(has_keys='k' in opt.gen_what)
|
||||
a.initialize(seed_id,out)
|
||||
return a
|
||||
|
||||
|
|
|
|||
|
|
@ -21,23 +21,38 @@ config.py: Constants and configuration options for the MMGen suite
|
|||
"""
|
||||
|
||||
import sys, os
|
||||
prog_name = os.path.basename(sys.argv[0])
|
||||
|
||||
author = "Philemon"
|
||||
email = "<mmgen-py@yandex.com>"
|
||||
Cdates = '2013-2015'
|
||||
version = '0.7.9'
|
||||
# Variables - these might be altered at runtime:
|
||||
|
||||
quiet,verbose,no_keyconv = False,False,False
|
||||
user_entropy = ""
|
||||
hash_preset = '3'
|
||||
usr_randchars = 30
|
||||
use_urandchars = False
|
||||
|
||||
min_screen_width = 80
|
||||
max_tx_comment_len = 72
|
||||
# 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")
|
||||
|
||||
from decimal import Decimal
|
||||
tx_fee = Decimal("0.00005")
|
||||
max_tx_fee = Decimal("0.01")
|
||||
|
||||
proj_name = "MMGen"
|
||||
seed_len = 256
|
||||
http_timeout = 30
|
||||
|
||||
# Constants - these don't change at runtime
|
||||
|
||||
proj_name = "MMGen"
|
||||
prog_name = os.path.basename(sys.argv[0])
|
||||
author = "Philemon"
|
||||
email = "<mmgen-py@yandex.com>"
|
||||
Cdates = '2013-2015'
|
||||
version = '0.7.9'
|
||||
|
||||
min_screen_width = 80
|
||||
max_tx_comment_len = 72
|
||||
|
||||
wallet_ext = "mmdat"
|
||||
seed_ext = "mmseed"
|
||||
|
|
@ -48,49 +63,37 @@ incog_hex_ext = "mmincox"
|
|||
|
||||
seedfile_exts = wallet_ext, seed_ext, mn_ext, brain_ext, incog_ext
|
||||
|
||||
rawtx_ext = "raw"
|
||||
sigtx_ext = "sig"
|
||||
addrfile_ext = "addrs"
|
||||
rawtx_ext = "raw"
|
||||
sigtx_ext = "sig"
|
||||
addrfile_ext = "addrs"
|
||||
addrfile_chksum_ext = "chk"
|
||||
keyfile_ext = "keys"
|
||||
keyaddrfile_ext = "akeys"
|
||||
mmenc_ext = "mmenc"
|
||||
keyfile_ext = "keys"
|
||||
keyaddrfile_ext = "akeys"
|
||||
mmenc_ext = "mmenc"
|
||||
|
||||
default_wl = "electrum"
|
||||
#default_wl = "tirosh"
|
||||
|
||||
# Global value sets user opt
|
||||
dfl_vars = "seed_len","hash_preset"
|
||||
# If user opt is set, different global opt is set to 'True'
|
||||
usr_set_vars = { "usr_randchars": "use_urandchars" }
|
||||
|
||||
# User opt sets global value
|
||||
usr_set_vars = "no_keyconv","verbose","quiet","usr_randchars"
|
||||
# Global value sets user opt
|
||||
dfl_vars = "seed_len","hash_preset","usr_randchars","debug"
|
||||
|
||||
seed_lens = 128,192,256
|
||||
seed_len = 256
|
||||
|
||||
mn_lens = [i / 32 * 3 for i in seed_lens]
|
||||
|
||||
http_timeout = 30
|
||||
|
||||
keyconv_exec = "keyconv"
|
||||
|
||||
# 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")
|
||||
|
||||
mins_per_block = 8.5
|
||||
mins_per_block = 8.5
|
||||
passwd_max_tries = 5
|
||||
|
||||
usr_randchars = 30
|
||||
max_urandchars,min_urandchars = 80,10
|
||||
use_urandchars = False
|
||||
|
||||
salt_len = 16
|
||||
aesctr_iv_len = 16
|
||||
salt_len = 16
|
||||
aesctr_iv_len = 16
|
||||
|
||||
hash_preset = '3'
|
||||
hash_presets = {
|
||||
# Scrypt params:
|
||||
# ID N p r
|
||||
|
|
@ -114,7 +117,6 @@ max_addr_label_len = 32
|
|||
wallet_label_symbols = addr_label_symbols
|
||||
max_wallet_label_len = 32
|
||||
|
||||
user_entropy = ""
|
||||
#addr_label_punc = ".","_",",","-"," ","(",")"
|
||||
#addr_label_symbols = tuple(ascii_letters + digits) + addr_label_punc
|
||||
#wallet_label_punc = addr_label_punc
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ from binascii import hexlify
|
|||
from hashlib import sha256
|
||||
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
from mmgen.util import *
|
||||
from mmgen.term import get_char
|
||||
|
||||
|
|
@ -77,7 +78,7 @@ def decrypt_seed(enc_seed, key, seed_id, key_id):
|
|||
if compare_checksums(chk2,"of decrypted seed",seed_id,"in header"):
|
||||
qmsg("Passphrase is OK")
|
||||
else:
|
||||
if not g.debug:
|
||||
if not opt.debug:
|
||||
msg_r("Checking key ID...")
|
||||
if compare_checksums(chk1, "of key", key_id, "in header"):
|
||||
msg("Key ID is correct but decryption of seed failed")
|
||||
|
|
@ -89,7 +90,7 @@ def decrypt_seed(enc_seed, key, seed_id, key_id):
|
|||
# else:
|
||||
# qmsg("Generated IDs (Seed/Key): %s/%s" % (chk2,chk1))
|
||||
|
||||
if g.debug: print "Decrypted seed: %s" % hexlify(dec_seed)
|
||||
if opt.debug: print "Decrypted seed: %s" % hexlify(dec_seed)
|
||||
|
||||
vmsg("OK")
|
||||
return dec_seed
|
||||
|
|
@ -153,18 +154,18 @@ def make_key(passwd,salt,hash_preset,
|
|||
what="encryption key",from_what="passphrase",verbose=False):
|
||||
|
||||
if from_what: what += " from "
|
||||
if g.verbose or verbose:
|
||||
if opt.verbose or verbose:
|
||||
msg_r("Generating %s%s.\nPlease wait..." % (what,from_what))
|
||||
key = scrypt_hash_passphrase(passwd, salt, hash_preset)
|
||||
if g.verbose or verbose:
|
||||
if opt.verbose or verbose:
|
||||
msg("done")
|
||||
if g.debug: print "Key: %s" % hexlify(key)
|
||||
if opt.debug: print "Key: %s" % hexlify(key)
|
||||
return key
|
||||
|
||||
|
||||
def get_random_data_from_user(uchars):
|
||||
|
||||
if g.quiet: msg("Enter %s random symbols" % uchars)
|
||||
if opt.quiet: msg("Enter %s random symbols" % uchars)
|
||||
else: msg(crmsg['usr_rand_notice'] % uchars)
|
||||
|
||||
prompt = "You may begin typing. %s symbols left: "
|
||||
|
|
@ -184,12 +185,12 @@ def get_random_data_from_user(uchars):
|
|||
time_data.append(now - saved_time)
|
||||
saved_time = now
|
||||
|
||||
if g.quiet: msg_r("\r")
|
||||
if opt.quiet: msg_r("\r")
|
||||
else: msg_r("\rThank you. That's enough.%s\n\n" % (" "*18))
|
||||
|
||||
fmt_time_data = ["{:.22f}".format(i) for i in time_data]
|
||||
|
||||
if g.debug:
|
||||
if opt.debug:
|
||||
msg("\nUser input:\n%s\nKeystroke time intervals:\n%s\n" %
|
||||
(key_data,"\n".join(fmt_time_data)))
|
||||
|
||||
|
|
@ -206,7 +207,7 @@ def get_random(length):
|
|||
from_what = "OS random data"
|
||||
if not g.user_entropy:
|
||||
g.user_entropy = \
|
||||
sha256(get_random_data_from_user(g.usr_randchars)).digest()
|
||||
sha256(get_random_data_from_user(opt.usr_randchars)).digest()
|
||||
from_what += " plus user-supplied entropy"
|
||||
else:
|
||||
from_what += " plus saved user-supplied entropy"
|
||||
|
|
@ -218,7 +219,6 @@ def get_random(length):
|
|||
|
||||
def get_seed_from_wallet(
|
||||
infile,
|
||||
opts,
|
||||
prompt_info="{} wallet".format(g.proj_name),
|
||||
silent=False
|
||||
):
|
||||
|
|
@ -226,22 +226,22 @@ def get_seed_from_wallet(
|
|||
wdata = get_data_from_wallet(infile,silent=silent)
|
||||
label,metadata,hash_preset,salt,enc_seed = wdata
|
||||
|
||||
if g.debug: display_control_data(*wdata)
|
||||
if opt.debug: display_control_data(*wdata)
|
||||
|
||||
padd = " "+infile if g.quiet else ""
|
||||
passwd = get_mmgen_passphrase(prompt_info+padd,opts)
|
||||
padd = " "+infile if opt.quiet else ""
|
||||
passwd = get_mmgen_passphrase(prompt_info+padd)
|
||||
|
||||
key = make_key(passwd, salt, hash_preset)
|
||||
|
||||
return decrypt_seed(enc_seed, key, metadata[0], metadata[1])
|
||||
|
||||
|
||||
def get_hidden_incog_data(opts):
|
||||
def get_hidden_incog_data():
|
||||
# Already sanity-checked:
|
||||
fname,offset,seed_len = opts['from_incog_hidden'].split(",")
|
||||
fname,offset,seed_len = opt.from_incog_hidden.split(",")
|
||||
qmsg("Getting hidden incog data from file '%s'" % fname)
|
||||
|
||||
z = 0 if 'old_incog_fmt' in opts else 8
|
||||
z = 0 if opt.old_incog_fmt else 8
|
||||
dlen = g.aesctr_iv_len + g.salt_len + (int(seed_len)/8) + z
|
||||
|
||||
fsize = check_data_fits_file_at_offset(fname,int(offset),dlen,"read")
|
||||
|
|
@ -265,13 +265,12 @@ def confirm_old_format():
|
|||
elif reply in 'nN': msg("\nExiting at user request"); sys.exit(1)
|
||||
elif reply in 'mM': msg(""); return True
|
||||
else:
|
||||
if g.verbose: msg("\nInvalid reply")
|
||||
if opt.verbose: msg("\nInvalid reply")
|
||||
else: msg_r("\r")
|
||||
|
||||
|
||||
def get_seed_from_incog_wallet(
|
||||
infile,
|
||||
opts,
|
||||
prompt_info="{} incognito wallet".format(g.proj_name),
|
||||
silent=False,
|
||||
hex_input=False
|
||||
|
|
@ -279,8 +278,8 @@ def get_seed_from_incog_wallet(
|
|||
|
||||
what = "incognito wallet data"
|
||||
|
||||
if "from_incog_hidden" in opts:
|
||||
d = get_hidden_incog_data(opts)
|
||||
if opt.from_incog_hidden:
|
||||
d = get_hidden_incog_data()
|
||||
else:
|
||||
d = get_data_from_file(infile,what)
|
||||
if hex_input:
|
||||
|
|
@ -290,7 +289,7 @@ def get_seed_from_incog_wallet(
|
|||
msg("Data in file '%s' is not in hexadecimal format" % infile)
|
||||
sys.exit(2)
|
||||
# File could be of invalid length, so check:
|
||||
z = 0 if 'old_incog_fmt' in opts else 8
|
||||
z = 0 if opt.old_incog_fmt else 8
|
||||
valid_dlens = [i/8 + g.aesctr_iv_len + g.salt_len + z for i in g.seed_lens]
|
||||
# New fmt: [56, 64, 72]. Old fmt: [48, 56, 64].
|
||||
if len(d) not in valid_dlens:
|
||||
|
|
@ -308,11 +307,11 @@ def get_seed_from_incog_wallet(
|
|||
incog_id = make_iv_chksum(iv)
|
||||
msg("Incog ID: %s (IV ID: %s)" % (incog_id,make_chksum_8(iv)))
|
||||
qmsg("Check the applicable value against your records.")
|
||||
vmsg(crmsg['incog_iv_id_hidden' if "from_incog_hidden" in opts
|
||||
vmsg(crmsg['incog_iv_id_hidden' if opt.from_incog_hidden
|
||||
else 'incog_iv_id'])
|
||||
|
||||
while True:
|
||||
passwd = get_mmgen_passphrase(prompt_info+" "+incog_id,opts)
|
||||
passwd = get_mmgen_passphrase(prompt_info+" "+incog_id)
|
||||
|
||||
qmsg("Configured hash presets: %s" % " ".join(sorted(g.hash_presets)))
|
||||
hp = get_hash_preset_from_user(what="incog wallet")
|
||||
|
|
@ -333,7 +332,7 @@ def get_seed_from_incog_wallet(
|
|||
m = "Seed ID: %s. Is the Seed ID correct?" % sid
|
||||
return keypress_confirm(m, True)
|
||||
|
||||
if 'old_incog_fmt' in opts:
|
||||
if opt.old_incog_fmt:
|
||||
if confirm_correct_seed_id(old_fmt_sid):
|
||||
break
|
||||
else:
|
||||
|
|
@ -349,7 +348,7 @@ def get_seed_from_incog_wallet(
|
|||
return seed
|
||||
|
||||
|
||||
def _get_seed(infile,opts,silent=False,seed_id=""):
|
||||
def _get_seed(infile,silent=False,seed_id=""):
|
||||
|
||||
ext = get_extension(infile)
|
||||
|
||||
|
|
@ -359,10 +358,10 @@ def _get_seed(infile,opts,silent=False,seed_id=""):
|
|||
elif ext == g.wallet_ext: source = "wallet"
|
||||
elif ext == g.incog_ext: source = "incognito wallet"
|
||||
elif ext == g.incog_hex_ext: source = "incognito wallet"
|
||||
elif 'from_mnemonic' in opts: source = "mnemonic"
|
||||
elif 'from_brain' in opts: source = "brainwallet"
|
||||
elif 'from_seed' in opts: source = "seed"
|
||||
elif 'from_incog' in opts: source = "incognito wallet"
|
||||
elif opt.from_mnemonic : source = "mnemonic"
|
||||
elif opt.from_brain : source = "brainwallet"
|
||||
elif opt.from_seed : source = "seed"
|
||||
elif opt.from_incog : source = "incognito wallet"
|
||||
else:
|
||||
if infile: msg(
|
||||
"Invalid file extension for file: %s\nValid extensions: '.%s'" %
|
||||
|
|
@ -373,26 +372,26 @@ def _get_seed(infile,opts,silent=False,seed_id=""):
|
|||
seed_id_str = " for seed ID "+seed_id if seed_id else ""
|
||||
if source == "mnemonic":
|
||||
prompt = "Enter mnemonic%s: " % seed_id_str
|
||||
words = get_words(infile,"mnemonic data",prompt,opts)
|
||||
words = get_words(infile,"mnemonic data",prompt)
|
||||
wl = get_default_wordlist()
|
||||
from mmgen.mnemonic import get_seed_from_mnemonic
|
||||
seed = get_seed_from_mnemonic(words,wl)
|
||||
elif source == "brainwallet":
|
||||
if 'from_brain' not in opts:
|
||||
if not opt.from_brain:
|
||||
msg("'--from-brain' parameters must be specified for brainwallet file")
|
||||
sys.exit(2)
|
||||
prompt = "Enter brainwallet passphrase%s: " % seed_id_str
|
||||
words = get_words(infile,"brainwallet data",prompt,opts)
|
||||
seed = _get_seed_from_brain_passphrase(words,opts)
|
||||
words = get_words(infile,"brainwallet data",prompt)
|
||||
seed = _get_seed_from_brain_passphrase(words)
|
||||
elif source == "seed":
|
||||
prompt = "Enter seed%s in %s format: " % (seed_id_str,g.seed_ext)
|
||||
words = get_words(infile,"seed data",prompt,opts)
|
||||
words = get_words(infile,"seed data",prompt)
|
||||
seed = get_seed_from_seed_data(words)
|
||||
elif source == "wallet":
|
||||
seed = get_seed_from_wallet(infile, opts, silent=silent)
|
||||
seed = get_seed_from_wallet(infile, silent=silent)
|
||||
elif source == "incognito wallet":
|
||||
h = ext == g.incog_hex_ext or 'from_incog_hex' in opts
|
||||
seed = get_seed_from_incog_wallet(infile, opts, silent=silent, hex_input=h)
|
||||
h = (ext == g.incog_hex_ext) or opt.from_incog_hex
|
||||
seed = get_seed_from_incog_wallet(infile, silent=silent, hex_input=h)
|
||||
|
||||
|
||||
if infile and not seed and (
|
||||
|
|
@ -400,25 +399,25 @@ def _get_seed(infile,opts,silent=False,seed_id=""):
|
|||
msg("Invalid %s file '%s'" % (source,infile))
|
||||
sys.exit(2)
|
||||
|
||||
if g.debug: print "Seed: %s" % hexlify(seed)
|
||||
if opt.debug: print "Seed: %s" % hexlify(seed)
|
||||
|
||||
return seed
|
||||
|
||||
|
||||
# Repeat if entered data is invalid
|
||||
def get_seed_retry(infile,opts,seed_id=""):
|
||||
def get_seed_retry(infile,seed_id=""):
|
||||
silent = False
|
||||
while True:
|
||||
seed = _get_seed(infile,opts,silent=silent,seed_id=seed_id)
|
||||
seed = _get_seed(infile,silent=silent,seed_id=seed_id)
|
||||
silent = True
|
||||
if seed: return seed
|
||||
|
||||
|
||||
def _get_seed_from_brain_passphrase(words,opts):
|
||||
def _get_seed_from_brain_passphrase(words):
|
||||
bp = " ".join(words)
|
||||
if g.debug: print "Sanitized brain passphrase: %s" % bp
|
||||
seed_len,hash_preset = get_from_brain_opt_params(opts)
|
||||
if g.debug: print "Brainwallet l = %s, p = %s" % (seed_len,hash_preset)
|
||||
if opt.debug: print "Sanitized brain passphrase: %s" % bp
|
||||
seed_len,hash_preset = get_from_brain_opt_params()
|
||||
if opt.debug: print "Brainwallet l = %s, p = %s" % (seed_len,hash_preset)
|
||||
vmsg_r("Hashing brainwallet data. Please wait...")
|
||||
# Use buflen arg of scrypt.hash() to get seed of desired length
|
||||
seed = scrypt_hash_passphrase(bp, "", hash_preset, buflen=seed_len/8)
|
||||
|
|
@ -429,7 +428,7 @@ def _get_seed_from_brain_passphrase(words,opts):
|
|||
# Vars for mmgen_*crypt functions only
|
||||
salt_len,sha256_len,nonce_len = 32,32,32
|
||||
|
||||
def mmgen_encrypt(data,what="data",hash_preset='',opts={}):
|
||||
def mmgen_encrypt(data,what="data",hash_preset=''):
|
||||
salt,iv,nonce = get_random(salt_len),\
|
||||
get_random(g.aesctr_iv_len), \
|
||||
get_random(nonce_len)
|
||||
|
|
@ -451,7 +450,7 @@ def mmgen_decrypt(data,what="data",hash_preset=""):
|
|||
hp = hash_preset or get_hash_preset_from_user('3',what)
|
||||
m = "default" if hp == '3' else "user-requested"
|
||||
qmsg("Using %s hash preset of '%s'" % (m,hp))
|
||||
passwd = get_mmgen_passphrase(what,{})
|
||||
passwd = get_mmgen_passphrase(what)
|
||||
key = make_key(passwd, salt, hp)
|
||||
dec_d = decrypt_data(enc_d, key, int(hexlify(iv),16), what)
|
||||
if dec_d[:sha256_len] == sha256(dec_d[sha256_len:]).digest():
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import sys
|
|||
from mmgen.util import msg, msg_r
|
||||
from mmgen.term import get_char
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
|
||||
gpl = {
|
||||
'warning': """
|
||||
|
|
@ -589,7 +590,7 @@ copy of the Program in return for a fee.
|
|||
|
||||
def do_license_msg(immed=False):
|
||||
|
||||
if g.quiet or g.no_license: return
|
||||
if opt.quiet or g.no_license: return
|
||||
|
||||
msg(gpl['warning'])
|
||||
prompt = "%s " % gpl['prompt'].strip()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ mmgen-addrgen: Generate a series or range of addresses from an MMGen
|
|||
import sys
|
||||
|
||||
import mmgen.config as g
|
||||
from mmgen.Opts import *
|
||||
import mmgen.opt as opt
|
||||
from mmgen.license import *
|
||||
from mmgen.util import *
|
||||
from mmgen.crypto import *
|
||||
|
|
@ -32,8 +32,7 @@ from mmgen.addr import *
|
|||
|
||||
what = "keys" if sys.argv[0].split("-")[-1] == "keygen" else "addresses"
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': """Generate a range or list of {} from an {g.proj_name} wallet,
|
||||
mnemonic, seed or password""".format(what,g=g),
|
||||
'usage':"[opts] [infile] <address range or list>",
|
||||
|
|
@ -114,25 +113,24 @@ UNENCRYPTED form. Generate only the key(s) you need and guard them carefully.
|
|||
""".format(g.proj_name),
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data,add_opts=["b16"])
|
||||
|
||||
if 'show_hash_presets' in opts: show_hash_presets()
|
||||
if 'from_incog_hex' in opts or 'from_incog_hidden' in opts:
|
||||
opts['from_incog'] = True
|
||||
if opt.show_hash_presets: show_hash_presets()
|
||||
if opt.from_incog_hex or opt.from_incog_hidden: opt.from_incog = True
|
||||
|
||||
if g.debug: show_opts_and_cmd_args(opts,cmd_args)
|
||||
if opt.debug: opt.opts.show_opts_and_cmd_args(cmd_args)
|
||||
|
||||
if len(cmd_args) == 1 and (
|
||||
'from_mnemonic' in opts
|
||||
or 'from_brain' in opts
|
||||
or 'from_seed' in opts
|
||||
or 'from_incog_hidden' in opts
|
||||
opt.from_mnemonic
|
||||
or opt.from_brain
|
||||
or opt.from_seed
|
||||
or opt.from_incog_hidden
|
||||
):
|
||||
infile,addr_idx_arg = "",cmd_args[0]
|
||||
elif len(cmd_args) == 2:
|
||||
infile,addr_idx_arg = cmd_args
|
||||
check_infile(infile)
|
||||
else: usage(help_data)
|
||||
else: opt.opts.usage(opts_data)
|
||||
|
||||
addr_idxs = parse_addr_idxs(addr_idx_arg)
|
||||
|
||||
|
|
@ -141,46 +139,46 @@ if not addr_idxs: sys.exit(2)
|
|||
do_license_msg()
|
||||
|
||||
# Interact with user:
|
||||
if what == "keys" and not g.quiet:
|
||||
if what == "keys" and not opt.quiet:
|
||||
confirm_or_exit(wmsg['unencrypted_secret_keys'], 'continue')
|
||||
|
||||
# Generate data:
|
||||
|
||||
seed = get_seed_retry(infile,opts)
|
||||
seed = get_seed_retry(infile)
|
||||
|
||||
opts['gen_what'] = "a" if what == "addresses" else (
|
||||
"k" if 'no_addresses' in opts else "ka")
|
||||
opt.gen_what = "a" if what == "addresses" else (
|
||||
"k" if opt.no_addresses else "ka")
|
||||
|
||||
ainfo = generate_addrs(seed, addr_idxs, opts)
|
||||
ainfo = generate_addrs(seed, addr_idxs)
|
||||
|
||||
addrdata_str = ainfo.fmt_data()
|
||||
outfile_base = "{}[{}]".format(make_chksum_8(seed), ainfo.idxs_fmt)
|
||||
|
||||
if 'a' in opts['gen_what']:
|
||||
w = "key-address" if 'k' in opts['gen_what'] else "address"
|
||||
if 'a' in opt.gen_what:
|
||||
w = "key-address" if 'k' in opt.gen_what else "address"
|
||||
qmsg("Checksum for %s data %s: %s" % (w,outfile_base,ainfo.checksum))
|
||||
if 'save_checksum' in opts:
|
||||
if opt.save_checksum:
|
||||
write_to_file(outfile_base+"."+g.addrfile_chksum_ext,
|
||||
ainfo.checksum+"\n",opts,"%s data checksum" % w,True,True,False)
|
||||
ainfo.checksum+"\n","%s data checksum" % w,True,True,False)
|
||||
else:
|
||||
qmsg("This checksum will be used to verify the %s file in the future."%w)
|
||||
qmsg("Record it to a safe location.")
|
||||
|
||||
if 'k' in opts['gen_what'] and keypress_confirm("Encrypt key list?"):
|
||||
addrdata_str = mmgen_encrypt(addrdata_str,"new key list","",opts)
|
||||
if 'k' in opt.gen_what and keypress_confirm("Encrypt key list?"):
|
||||
addrdata_str = mmgen_encrypt(addrdata_str,"new key list","")
|
||||
enc_ext = "." + g.mmenc_ext
|
||||
else: enc_ext = ""
|
||||
|
||||
# Output data:
|
||||
if 'stdout' in opts or not sys.stdout.isatty():
|
||||
if opt.stdout or not sys.stdout.isatty():
|
||||
if enc_ext and sys.stdout.isatty():
|
||||
msg("Cannot write encrypted data to screen. Exiting")
|
||||
sys.exit(2)
|
||||
write_to_stdout(addrdata_str,what,
|
||||
(what=="keys"and not g.quiet and sys.stdout.isatty()))
|
||||
(what=="keys"and not opt.quiet and sys.stdout.isatty()))
|
||||
else:
|
||||
outfile = "%s.%s%s" % (outfile_base, (
|
||||
g.keyaddrfile_ext if "ka" in opts['gen_what'] else (
|
||||
g.keyfile_ext if "k" in opts['gen_what'] else
|
||||
g.keyaddrfile_ext if "ka" in opt.gen_what else (
|
||||
g.keyfile_ext if "k" in opt.gen_what else
|
||||
g.addrfile_ext)), enc_ext)
|
||||
write_to_file(outfile,addrdata_str,opts,what,not g.quiet,True)
|
||||
write_to_file(outfile,addrdata_str,what,not opt.quiet,True)
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ mmgen-addrimport: Import addresses into a MMGen bitcoind tracking wallet
|
|||
"""
|
||||
|
||||
import sys, time
|
||||
from mmgen.Opts import *
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
from mmgen.license import *
|
||||
from mmgen.util import *
|
||||
from mmgen.tx import connect_to_bitcoind
|
||||
from mmgen.addr import AddrInfo,AddrInfoEntry
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': """Import addresses (both {pnm} and non-{pnm}) into a bitcoind
|
||||
tracking wallet""".format(pnm=g.proj_name),
|
||||
'usage':"[opts] [mmgen address file]",
|
||||
|
|
@ -47,12 +47,12 @@ in the tracking wallet.
|
|||
"""
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if len(cmd_args) == 1:
|
||||
infile = cmd_args[0]
|
||||
check_infile(infile)
|
||||
if 'addrlist' in opts:
|
||||
if opt.addrlist:
|
||||
lines = get_lines_from_file(
|
||||
infile,"non-{} addresses".format(g.proj_name),trim_comments=True)
|
||||
ai,adata = AddrInfo(),[]
|
||||
|
|
@ -62,7 +62,7 @@ if len(cmd_args) == 1:
|
|||
adata.append(a)
|
||||
ai.initialize(None,adata)
|
||||
else:
|
||||
ai = AddrInfo(infile,has_keys='keyaddr_file' in opts)
|
||||
ai = AddrInfo(infile,has_keys=opt.keyaddr_file)
|
||||
else:
|
||||
msg("""
|
||||
"You must specify an mmgen address file (or a list of non-%s addresses
|
||||
|
|
@ -80,10 +80,9 @@ for e in ai.addrdata:
|
|||
m = (" from seed ID %s" % ai.seed_id) if ai.seed_id else ""
|
||||
qmsg("OK. %s addresses%s" % (ai.num_addrs,m))
|
||||
|
||||
import mmgen.config as g
|
||||
g.http_timeout = 3600
|
||||
|
||||
if not 'test' in opts:
|
||||
if not opt.test:
|
||||
c = connect_to_bitcoind()
|
||||
|
||||
m = """
|
||||
|
|
@ -92,30 +91,30 @@ necessary only if an address you're importing is already on the blockchain,
|
|||
has a balance and is not already in your tracking wallet. Note that the
|
||||
rescanning process is very slow (>30 min. for each imported address on a
|
||||
low-powered computer).
|
||||
""".strip() if "rescan" in opts else """
|
||||
""".strip() if opt.rescan else """
|
||||
WARNING: If any of the addresses you're importing is already on the blockchain,
|
||||
has a balance and is not already in your tracking wallet, you must exit the
|
||||
program now and rerun it using the '--rescan' option. Otherwise you may ignore
|
||||
this message and continue.
|
||||
""".strip()
|
||||
|
||||
if g.quiet: m = ""
|
||||
if opt.quiet: m = ""
|
||||
confirm_or_exit(m, "continue", expect="YES")
|
||||
|
||||
err_flag = False
|
||||
|
||||
def import_address(addr,label,rescan):
|
||||
try:
|
||||
if not 'test' in opts:
|
||||
if not opt.test:
|
||||
c.importaddress(addr,label,rescan)
|
||||
except:
|
||||
global err_flag
|
||||
err_flag = True
|
||||
|
||||
w_n_of_m = len(str(ai.num_addrs)) * 2 + 2
|
||||
w_mmid = "" if 'addrlist' in opts else len(str(max(ai.idxs()))) + 12
|
||||
w_mmid = "" if opt.addrlist else len(str(max(ai.idxs()))) + 12
|
||||
|
||||
if "rescan" in opts:
|
||||
if opt.rescan:
|
||||
import threading
|
||||
msg_fmt = "\r%s %-{}s %-34s %s".format(w_n_of_m)
|
||||
else:
|
||||
|
|
@ -128,7 +127,7 @@ for n,e in enumerate(ai.addrdata):
|
|||
if e.comment: label += " " + e.comment
|
||||
else: label = "non-%s" % g.proj_name
|
||||
|
||||
if "rescan" in opts:
|
||||
if opt.rescan:
|
||||
t = threading.Thread(target=import_address, args=(e.addr,label,True))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
|
|
|||
|
|
@ -22,13 +22,12 @@ mmgen-passchg: Change an MMGen deterministic wallet's passphrase, label or
|
|||
"""
|
||||
|
||||
import sys
|
||||
from mmgen.Opts import *
|
||||
from mmgen.util import *
|
||||
from mmgen.crypto import *
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': """Change the passphrase, hash preset or label of an {}
|
||||
deterministic wallet""".format(g.proj_name),
|
||||
'usage': "[opts] [filename]",
|
||||
|
|
@ -55,9 +54,9 @@ NOTE: The key ID will change if either the passphrase or hash preset are
|
|||
"""
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if 'show_hash_presets' in opts: show_hash_presets()
|
||||
if opt.show_hash_presets: show_hash_presets()
|
||||
|
||||
if len(cmd_args) != 1:
|
||||
msg("One input file must be specified")
|
||||
|
|
@ -71,36 +70,36 @@ seed_id,key_id = metadata[:2]
|
|||
# Repeat on incorrect pw entry
|
||||
while True:
|
||||
p = "{} wallet".format(g.proj_name)
|
||||
passwd = get_mmgen_passphrase(p,{},not 'keep_old_passphrase' in opts)
|
||||
passwd = get_mmgen_passphrase(p,not opt.keep_old_passphrase)
|
||||
key = make_key(passwd, salt, hash_preset)
|
||||
seed = decrypt_seed(enc_seed, key, seed_id, key_id)
|
||||
if seed: break
|
||||
|
||||
changed = {}
|
||||
|
||||
if 'label' in opts:
|
||||
if opts['label'] != label:
|
||||
msg("Label changed: '%s' -> '%s'" % (label, opts['label']))
|
||||
if opt.label:
|
||||
if opt.label != label:
|
||||
msg("Label changed: '%s' -> '%s'" % (label, opt.label))
|
||||
changed['label'] = True
|
||||
else:
|
||||
msg("Label is unchanged: '%s'" % (label))
|
||||
else: opts['label'] = label # Copy the old label
|
||||
else: opt.label = label # Copy the old label
|
||||
|
||||
if 'hash_preset' in opts:
|
||||
if hash_preset != opts['hash_preset']:
|
||||
if opt.hash_preset:
|
||||
if hash_preset != opt.hash_preset:
|
||||
qmsg("Hash preset has changed (%s -> %s)" %
|
||||
(hash_preset, opts['hash_preset']))
|
||||
(hash_preset, opt.hash_preset))
|
||||
changed['preset'] = True
|
||||
else:
|
||||
msg("Hash preset is unchanged")
|
||||
else:
|
||||
opts['hash_preset'] = hash_preset
|
||||
opt.hash_preset = hash_preset
|
||||
|
||||
if 'keep_old_passphrase' in opts:
|
||||
if opt.keep_old_passphrase:
|
||||
msg("Keeping old passphrase by user request")
|
||||
else:
|
||||
new_passwd = get_new_passphrase(
|
||||
"{} wallet".format(g.proj_name), opts, True)
|
||||
"{} wallet".format(g.proj_name), True)
|
||||
|
||||
if new_passwd == passwd:
|
||||
qmsg("Passphrase is unchanged")
|
||||
|
|
@ -115,7 +114,7 @@ if 'preset' in changed or 'passwd' in changed: # Update key ID, salt
|
|||
from hashlib import sha256
|
||||
|
||||
salt = sha256(salt + get_random(128)).digest()[:g.salt_len]
|
||||
key = make_key(passwd, salt, opts['hash_preset'])
|
||||
key = make_key(passwd, salt, opt.hash_preset)
|
||||
new_key_id = make_chksum_8(key)
|
||||
qmsg("Key ID changed: %s -> %s" % (key_id,new_key_id))
|
||||
key_id = new_key_id
|
||||
|
|
@ -124,4 +123,4 @@ elif not 'label' in changed:
|
|||
msg("Data unchanged. No file will be written")
|
||||
sys.exit(2)
|
||||
|
||||
write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts)
|
||||
write_wallet_to_file(seed, passwd, key_id, salt, enc_seed)
|
||||
|
|
|
|||
|
|
@ -23,11 +23,10 @@ mmgen-tool: Perform various MMGen- and Bitcoin-related operations.
|
|||
|
||||
import sys
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
import mmgen.tool as tool
|
||||
from mmgen.Opts import *
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': "Perform various MMGen- and Bitcoin-related operations",
|
||||
'usage': "[opts] <command> <command args>",
|
||||
'options': """
|
||||
|
|
@ -46,10 +45,10 @@ command
|
|||
""".format(tool.cmd_help,g.prog_name)
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if len(cmd_args) < 1:
|
||||
usage(help_data)
|
||||
opt.opts.usage(opts_data)
|
||||
sys.exit(1)
|
||||
|
||||
command = cmd_args.pop(0)
|
||||
|
|
@ -64,6 +63,4 @@ if cmd_args and cmd_args[0] == '--help':
|
|||
|
||||
args,kwargs = tool.process_args(g.prog_name, command, cmd_args)
|
||||
|
||||
tool.opts = opts
|
||||
|
||||
tool.__dict__[command](*args,**kwargs)
|
||||
|
|
|
|||
|
|
@ -25,12 +25,11 @@ import sys
|
|||
from decimal import Decimal
|
||||
|
||||
import mmgen.config as g
|
||||
from mmgen.Opts import *
|
||||
import mmgen.opt as opt
|
||||
from mmgen.license import *
|
||||
from mmgen.tx import *
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': "Create a BTC transaction with outputs to specified addresses",
|
||||
'usage': "[opts] <addr,amt> ... [change addr] [addr file] ...",
|
||||
'options': """
|
||||
|
|
@ -124,7 +123,7 @@ def format_unspent_outputs_for_printing(out,sort_info,total):
|
|||
)
|
||||
|
||||
|
||||
def sort_and_view(unspent,opts):
|
||||
def sort_and_view(unspent):
|
||||
|
||||
def s_amt(i): return i.amount
|
||||
def s_txid(i): return "%s %03s" % (i.txid,i.vout)
|
||||
|
|
@ -239,7 +238,7 @@ 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, opts,"",False,False)
|
||||
write_to_file(of, d, "",False,False)
|
||||
write_to_file_msg = "Data written to '%s'\n\n" % of
|
||||
elif reply == 'v':
|
||||
do_pager("\n".join(out))
|
||||
|
|
@ -333,16 +332,16 @@ def mmaddr2btcaddr(c,mmaddr,acct_data,ail):
|
|||
return btcaddr
|
||||
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if g.debug: show_opts_and_cmd_args(opts,cmd_args)
|
||||
if opt.debug: show_opts_and_cmd_args(cmd_args)
|
||||
|
||||
if 'comment_file' in opts:
|
||||
comment = get_tx_comment_from_file(opts['comment_file'])
|
||||
if opt.comment_file:
|
||||
comment = get_tx_comment_from_file(opt.comment_file)
|
||||
|
||||
c = connect_to_bitcoind()
|
||||
|
||||
if not 'info' in opts:
|
||||
if not opt.info:
|
||||
do_license_msg(immed=True)
|
||||
|
||||
tx_out,acct_data,change_addr = {},{},""
|
||||
|
|
@ -389,30 +388,31 @@ if not 'info' in opts:
|
|||
msg("At least one output must be specified on the command line")
|
||||
sys.exit(2)
|
||||
|
||||
tx_fee = opts['tx_fee'] if 'tx_fee' in opts else g.tx_fee
|
||||
tx_fee = opt.tx_fee if opt.tx_fee else g.tx_fee
|
||||
tx_fee = normalize_btc_amt(tx_fee)
|
||||
if tx_fee > g.max_tx_fee:
|
||||
msg("Transaction fee too large: %s > %s" % (tx_fee,g.max_tx_fee))
|
||||
sys.exit(2)
|
||||
|
||||
if g.debug: show_opts_and_cmd_args(opts,cmd_args)
|
||||
if opt.debug: show_opts_and_cmd_args(cmd_args)
|
||||
|
||||
if g.bogus_wallet_data: # for debugging purposes only
|
||||
import mmgen.rpc.data
|
||||
us = eval(get_data_from_file(g.bogus_wallet_data))
|
||||
else:
|
||||
us = c.listunspent()
|
||||
# write_to_file("bogus_unspent.json", repr(us), opts); sys.exit()
|
||||
# write_to_file("bogus_unspent.json", repr(us)); sys.exit()
|
||||
|
||||
if not us: msg(wmsg['no_spendable_outputs']); sys.exit(2)
|
||||
for o in us:
|
||||
o.mmid,o.comment = parse_mmgen_label(o.account)
|
||||
del o.account
|
||||
unspent = sort_and_view(us,opts)
|
||||
unspent = sort_and_view(us)
|
||||
|
||||
total = trim_exponent(sum([i.amount for i in unspent]))
|
||||
|
||||
msg("Total unspent: %s BTC (%s outputs)" % (total, len(unspent)))
|
||||
if 'info' in opts: sys.exit(0)
|
||||
if opt.info: sys.exit(0)
|
||||
|
||||
send_amt = sum([tx_out[i] for i in tx_out.keys()])
|
||||
msg("Total amount to spend: %s%s" % (
|
||||
|
|
@ -458,11 +458,11 @@ if change > 0: tx_out[change_addr] = float(change)
|
|||
|
||||
tx_in = [{"txid":i.txid, "vout":i.vout} for i in sel_unspent]
|
||||
|
||||
if g.debug:
|
||||
if opt.debug:
|
||||
print "tx_in:", repr(tx_in)
|
||||
print "tx_out:", repr(tx_out)
|
||||
|
||||
if 'comment_file' in opts:
|
||||
if opt.comment_file:
|
||||
if keypress_confirm("Edit comment?",False):
|
||||
comment = get_tx_comment_from_user(comment)
|
||||
else:
|
||||
|
|
@ -493,6 +493,6 @@ 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,opts,"transaction",False,True)
|
||||
write_to_file(outfile,data,"transaction",False,True)
|
||||
else:
|
||||
msg("Transaction not saved")
|
||||
|
|
|
|||
|
|
@ -23,13 +23,12 @@ mmgen-txsend: Broadcast a transaction signed by 'mmgen-txsign' to the network
|
|||
import sys
|
||||
|
||||
import mmgen.config as g
|
||||
from mmgen.Opts import *
|
||||
import mmgen.opt as opt
|
||||
from mmgen.license import *
|
||||
from mmgen.tx import *
|
||||
from mmgen.util import msg,check_infile,get_lines_from_file,confirm_or_exit
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': "Send a Bitcoin transaction signed by {}-txsign".format(g.proj_name.lower()),
|
||||
'usage': "[opts] <signed transaction file>",
|
||||
'options': """
|
||||
|
|
@ -39,11 +38,11 @@ help_data = {
|
|||
"""
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if len(cmd_args) == 1:
|
||||
infile = cmd_args[0]; check_infile(infile)
|
||||
else: usage(help_data)
|
||||
else: opt.opts.usage(opts_data)
|
||||
|
||||
# Begin execution
|
||||
|
||||
|
|
@ -66,13 +65,13 @@ if keypress_confirm("Edit transaction comment?"):
|
|||
inputs_data, b2m_map, comment)
|
||||
w = "signed transaction with edited comment"
|
||||
outfile = infile
|
||||
write_to_file(outfile,data,opts,w,False,True,True)
|
||||
write_to_file(outfile,data,w,False,True,True)
|
||||
|
||||
warn = "Once this transaction is sent, there's no taking it back!"
|
||||
what = "broadcast this transaction to the network"
|
||||
expect = "YES, I REALLY WANT TO DO THIS"
|
||||
|
||||
if g.quiet: warn,expect = "","YES"
|
||||
if opt.quiet: warn,expect = "","YES"
|
||||
|
||||
confirm_or_exit(warn, what, expect)
|
||||
|
||||
|
|
@ -87,4 +86,4 @@ except:
|
|||
msg("Transaction sent: %s" % tx_id)
|
||||
|
||||
of = "tx_{}[{}].txid".format(*metadata[:2])
|
||||
write_to_file(of, tx_id+"\n",opts,"transaction ID",True,True)
|
||||
write_to_file(of, tx_id+"\n","transaction ID",True,True)
|
||||
|
|
|
|||
|
|
@ -23,12 +23,11 @@ mmgen-txsign: Sign a transaction generated by 'mmgen-txcreate'
|
|||
import sys
|
||||
|
||||
import mmgen.config as g
|
||||
from mmgen.Opts import *
|
||||
import mmgen.opt as opt
|
||||
from mmgen.license import *
|
||||
from mmgen.tx import *
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': "Sign Bitcoin transactions generated by {}-txcreate".format(g.proj_name.lower()),
|
||||
'usage': "[opts] <transaction file> .. [mmgen wallet/seed/words/brainwallet file] ..",
|
||||
'options': """
|
||||
|
|
@ -103,7 +102,7 @@ Removed %s duplicate wif key%s from keylist (also in {MMG} key-address file
|
|||
""".strip().format(MMG=g.proj_name),
|
||||
}
|
||||
|
||||
def get_seed_for_seed_id(seed_id,infiles,saved_seeds,opts):
|
||||
def get_seed_for_seed_id(seed_id,infiles,saved_seeds):
|
||||
|
||||
if seed_id in saved_seeds.keys():
|
||||
return saved_seeds[seed_id]
|
||||
|
|
@ -112,11 +111,10 @@ def get_seed_for_seed_id(seed_id,infiles,saved_seeds,opts):
|
|||
|
||||
while True:
|
||||
if infiles:
|
||||
seed = get_seed_retry(infiles.pop(0),opts)
|
||||
elif "from_brain" in opts or "from_mnemonic" in opts \
|
||||
or "from_seed" in opts or "from_incog" in opts:
|
||||
seed = get_seed_retry(infiles.pop(0))
|
||||
elif opt.from_brain or opt.from_mnemonic or opt.from_seed or opt.from_incog:
|
||||
qmsg("Need seed data for seed ID %s" % seed_id)
|
||||
seed = get_seed_retry("",opts,seed_id)
|
||||
seed = get_seed_retry("",seed_id)
|
||||
msg("User input produced seed ID %s" % make_chksum_8(seed))
|
||||
else:
|
||||
msg("ERROR: No seed source found for seed ID: %s" % seed_id)
|
||||
|
|
@ -128,7 +126,7 @@ def get_seed_for_seed_id(seed_id,infiles,saved_seeds,opts):
|
|||
if sid == seed_id: return seed
|
||||
|
||||
|
||||
def get_keys_for_mmgen_addrs(mmgen_addrs,infiles,saved_seeds,opts):
|
||||
def get_keys_for_mmgen_addrs(mmgen_addrs,infiles,saved_seeds):
|
||||
|
||||
seed_ids = set([i[:8] for i in mmgen_addrs])
|
||||
vmsg("Need seed%s: %s" % (suf(seed_ids,"k")," ".join(seed_ids)))
|
||||
|
|
@ -137,9 +135,10 @@ def get_keys_for_mmgen_addrs(mmgen_addrs,infiles,saved_seeds,opts):
|
|||
from mmgen.addr import generate_addrs
|
||||
for seed_id in seed_ids:
|
||||
# Returns only if seed is found
|
||||
seed = get_seed_for_seed_id(seed_id,infiles,saved_seeds,opts)
|
||||
seed = get_seed_for_seed_id(seed_id,infiles,saved_seeds)
|
||||
addr_nums = [int(i[9:]) for i in mmgen_addrs if i[:8] == seed_id]
|
||||
ai = generate_addrs(seed,addr_nums,{'gen_what':"ka"})
|
||||
opt.gen_what = "ka"
|
||||
ai = generate_addrs(seed,addr_nums)
|
||||
d += [("{}:{}".format(seed_id,e.idx),e.addr,e.wif) for e in ai.addrdata]
|
||||
return d
|
||||
|
||||
|
|
@ -148,7 +147,7 @@ def sign_transaction(c,tx_hex,tx_num_str,sig_data,keys=None):
|
|||
|
||||
if keys:
|
||||
qmsg("Passing %s key%s to bitcoind" % (len(keys),suf(keys,"k")))
|
||||
if g.debug: print "Keys:\n %s" % "\n ".join(keys)
|
||||
if opt.debug: print "Keys:\n %s" % "\n ".join(keys)
|
||||
|
||||
msg_r("Signing transaction{}...".format(tx_num_str))
|
||||
from mmgen.rpc import exceptions
|
||||
|
|
@ -161,7 +160,7 @@ def sign_transaction(c,tx_hex,tx_num_str,sig_data,keys=None):
|
|||
return sig_tx
|
||||
|
||||
|
||||
def sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys,opts):
|
||||
def sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys):
|
||||
|
||||
try:
|
||||
sig_tx = sign_transaction(c,tx_hex,tx_num_str,sig_data,keys)
|
||||
|
|
@ -170,7 +169,7 @@ def sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys,opts):
|
|||
msg("Using keys in wallet.dat as per user request")
|
||||
prompt = "Enter passphrase for bitcoind wallet: "
|
||||
while True:
|
||||
passwd = get_bitcoind_passphrase(prompt,opts)
|
||||
passwd = get_bitcoind_passphrase(prompt)
|
||||
|
||||
try:
|
||||
c.walletpassphrase(passwd, 9999)
|
||||
|
|
@ -190,11 +189,11 @@ def sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys,opts):
|
|||
return sig_tx
|
||||
|
||||
|
||||
def check_maps_from_seeds(maplist,label,infiles,saved_seeds,opts,return_keys=False):
|
||||
def check_maps_from_seeds(maplist,label,infiles,saved_seeds,return_keys=False):
|
||||
|
||||
if not maplist: return []
|
||||
qmsg("Checking MMGen -> BTC address mappings for %ss (from seeds)" % label)
|
||||
d = get_keys_for_mmgen_addrs(maplist.keys(),infiles,saved_seeds,opts)
|
||||
d = get_keys_for_mmgen_addrs(maplist.keys(),infiles,saved_seeds)
|
||||
# 0=mmaddr 1=addr 2=wif
|
||||
m = dict([(e[0],e[1]) for e in d])
|
||||
for a,b in zip(sorted(m),sorted(maplist)):
|
||||
|
|
@ -214,9 +213,9 @@ for the following non-{} address{}:\n {}""".format(
|
|||
g.proj_name,suf(addrs,"a"),"\n ".join(addrs)).strip()
|
||||
|
||||
|
||||
def parse_mmgen_keyaddr_file(opts):
|
||||
def parse_mmgen_keyaddr_file():
|
||||
from mmgen.addr import AddrInfo
|
||||
ai = AddrInfo(opts['mmgen_keys_from_file'],has_keys=True)
|
||||
ai = AddrInfo(opt.mmgen_keys_from_file,has_keys=True)
|
||||
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)
|
||||
|
|
@ -224,8 +223,8 @@ def parse_mmgen_keyaddr_file(opts):
|
|||
[("%s:%s"%(ai.seed_id,e.idx), (e.addr,e.wif)) for e in ai.addrdata])
|
||||
|
||||
|
||||
def parse_keylist(opts,from_file):
|
||||
fn = opts['keys_from_file']
|
||||
def parse_keylist(from_file):
|
||||
fn = opt.keys_from_file
|
||||
d = get_data_from_file(fn,"non-%s keylist" % g.proj_name)
|
||||
enc_ext = get_extension(fn) == g.mmenc_ext
|
||||
if enc_ext or not is_utf8(d):
|
||||
|
|
@ -279,17 +278,16 @@ def get_keys_from_keylist(kldata,other_addrs):
|
|||
return ret
|
||||
|
||||
|
||||
opts,infiles = parse_opts(sys.argv,help_data)
|
||||
infiles = opt.opts.init(opts_data,add_opts=["b16"])
|
||||
|
||||
for l in (
|
||||
('tx_id', 'info'),
|
||||
('tx_id', 'terse_info'),
|
||||
): warn_incompatible_opts(opts,l)
|
||||
): opt.opts.warn_incompatible_opts(l)
|
||||
|
||||
if 'from_incog_hex' in opts or 'from_incog_hidden' in opts:
|
||||
opts['from_incog'] = True
|
||||
if opt.from_incog_hex or opt.from_incog_hidden: opt.from_incog = True
|
||||
|
||||
if not infiles: usage(help_data)
|
||||
if not infiles: opt.opts.usage(opts_data)
|
||||
for i in infiles: check_infile(i)
|
||||
|
||||
c = connect_to_bitcoind()
|
||||
|
|
@ -298,14 +296,14 @@ saved_seeds = {}
|
|||
tx_files = [i for i in infiles if get_extension(i) == g.rawtx_ext]
|
||||
seed_files = [i for i in infiles if get_extension(i) != g.rawtx_ext]
|
||||
|
||||
if not "info" in opts and not "terse_info" in opts:
|
||||
if not opt.info and not opt.terse_info:
|
||||
do_license_msg(immed=True)
|
||||
|
||||
from_file = { 'mmdata':{}, 'kldata':{} }
|
||||
if 'mmgen_keys_from_file' in opts:
|
||||
from_file['mmdata'] = parse_mmgen_keyaddr_file(opts) or {}
|
||||
if 'keys_from_file' in opts:
|
||||
from_file['kldata'] = parse_keylist(opts,from_file) or {}
|
||||
if opt.mmgen_keys_from_file:
|
||||
from_file['mmdata'] = parse_mmgen_keyaddr_file() or {}
|
||||
if opt.keys_from_file:
|
||||
from_file['kldata'] = parse_keylist(from_file) or {}
|
||||
|
||||
tx_num_str = ""
|
||||
for tx_num,tx_file in enumerate(tx_files,1):
|
||||
|
|
@ -313,19 +311,19 @@ for tx_num,tx_file in enumerate(tx_files,1):
|
|||
msg("\nTransaction #%s of %s:" % (tx_num,len(tx_files)))
|
||||
tx_num_str = " #%s" % tx_num
|
||||
|
||||
m = "" if 'tx_id' in opts else "transaction data"
|
||||
m = "" if opt.tx_id else "transaction data"
|
||||
tx_data = get_lines_from_file(tx_file,m)
|
||||
|
||||
metadata,tx_hex,inputs_data,b2m_map,comment = parse_tx_file(tx_data,tx_file)
|
||||
vmsg("Successfully opened transaction file '%s'" % tx_file)
|
||||
|
||||
if 'tx_id' in opts:
|
||||
if opt.tx_id:
|
||||
msg(metadata[0])
|
||||
sys.exit(0)
|
||||
|
||||
if 'info' in opts or 'terse_info' in opts:
|
||||
if opt.info or opt.terse_info:
|
||||
view_tx_data(c,inputs_data,tx_hex,b2m_map,comment,metadata,pause=False,
|
||||
terse='terse_info' in opts)
|
||||
terse=opt.terse_info)
|
||||
sys.exit(0)
|
||||
|
||||
prompt_and_view_tx_data(c,"View data for transaction{}?".format(tx_num_str),
|
||||
|
|
@ -336,7 +334,7 @@ for tx_num,tx_file in enumerate(tx_files,1):
|
|||
|
||||
keys = get_keys_from_keylist(from_file['kldata'],other_addrs)
|
||||
|
||||
if other_addrs and not 'use_wallet_dat' in opts:
|
||||
if other_addrs and not opt.use_wallet_dat:
|
||||
missing_keys_errormsg(other_addrs)
|
||||
sys.exit(2)
|
||||
|
||||
|
|
@ -347,8 +345,8 @@ for tx_num,tx_file in enumerate(tx_files,1):
|
|||
keys += check_maps_from_kafile(imap,"input",from_file['mmdata'],True)
|
||||
check_maps_from_kafile(omap,"output",from_file['mmdata'])
|
||||
|
||||
keys += check_maps_from_seeds(imap,"input",seed_files,saved_seeds,opts,True)
|
||||
check_maps_from_seeds(omap,"output",seed_files,saved_seeds,opts)
|
||||
keys += check_maps_from_seeds(imap,"input",seed_files,saved_seeds,True)
|
||||
check_maps_from_seeds(omap,"output",seed_files,saved_seeds)
|
||||
|
||||
extra_sids = set(saved_seeds.keys()) - sids
|
||||
if extra_sids:
|
||||
|
|
@ -360,9 +358,9 @@ for tx_num,tx_file in enumerate(tx_files,1):
|
|||
{"txid":i['txid'],"vout":i['vout'],"scriptPubKey":i['scriptPubKey']}
|
||||
for i in inputs_data]
|
||||
|
||||
if 'use_wallet_dat' in opts:
|
||||
if opt.use_wallet_dat:
|
||||
sig_tx = sign_tx_with_bitcoind_wallet(
|
||||
c,tx_hex,tx_num_str,sig_data,keys,opts)
|
||||
c,tx_hex,tx_num_str,sig_data,keys)
|
||||
else:
|
||||
sig_tx = sign_transaction(c,tx_hex,tx_num_str,sig_data,keys)
|
||||
|
||||
|
|
@ -374,7 +372,7 @@ for tx_num,tx_file in enumerate(tx_files,1):
|
|||
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)
|
||||
write_to_file(outfile,data,opts,w,(not g.quiet),True,False)
|
||||
write_to_file(outfile,data,w,(not opt.quiet),True,False)
|
||||
else:
|
||||
msg_r("failed\nSome keys were missing. ")
|
||||
msg("Transaction %scould not be signed." % tx_num_str)
|
||||
|
|
|
|||
|
|
@ -23,12 +23,11 @@ mmgen-walletchk: Check integrity of an MMGen deterministic wallet, display
|
|||
|
||||
import sys
|
||||
import mmgen.config as g
|
||||
from mmgen.Opts import *
|
||||
import mmgen.opt as opt
|
||||
from mmgen.util import *
|
||||
from mmgen.crypto import *
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': """Check integrity of an {} deterministic wallet, display
|
||||
its information, and export seed and mnemonic data.
|
||||
""".format(g.proj_name),
|
||||
|
|
@ -61,14 +60,14 @@ to disable this option, then specify '-r0' on the command line.
|
|||
"""
|
||||
}
|
||||
|
||||
def wallet_to_incog_data(infile,opts):
|
||||
def wallet_to_incog_data(infile):
|
||||
|
||||
d = get_data_from_wallet(infile,silent=True)
|
||||
seed_id,key_id,preset,salt,enc_seed = \
|
||||
d[1][0], d[1][1], d[2].split(":")[0], d[3], d[4]
|
||||
|
||||
while True:
|
||||
passwd = get_mmgen_passphrase("{} wallet".format(g.proj_name),opts)
|
||||
passwd = get_mmgen_passphrase("{} wallet".format(g.proj_name))
|
||||
key = make_key(passwd, salt, preset, "main key")
|
||||
seed = decrypt_seed(enc_seed, key, seed_id, key_id)
|
||||
if seed: break
|
||||
|
|
@ -77,7 +76,7 @@ def wallet_to_incog_data(infile,opts):
|
|||
iv_id = make_iv_chksum(iv)
|
||||
msg("Incog ID: %s" % iv_id)
|
||||
|
||||
if not 'old_incog_fmt' in opts:
|
||||
if not opt.old_incog_fmt:
|
||||
salt = get_random(g.salt_len)
|
||||
key = make_key(passwd, salt, preset, "incog wallet key")
|
||||
key_id = make_chksum_8(key)
|
||||
|
|
@ -92,13 +91,13 @@ def wallet_to_incog_data(infile,opts):
|
|||
return iv+wrap_enc,seed_id,key_id,iv_id,preset
|
||||
|
||||
|
||||
def export_to_hidden_incog(incog_enc,opts):
|
||||
outfile,offset = opts['export_incog_hidden'].split(",") #Already sanity-checked
|
||||
if 'outdir' in opts: outfile = make_full_path(opts['outdir'],outfile)
|
||||
def export_to_hidden_incog(incog_enc):
|
||||
outfile,offset = opt.export_incog_hidden.split(",") #Already sanity-checked
|
||||
if opt.outdir: outfile = make_full_path(opt.outdir,outfile)
|
||||
|
||||
check_data_fits_file_at_offset(outfile,int(offset),len(incog_enc),"write")
|
||||
|
||||
if not g.quiet: confirm_or_exit("","alter file '%s'" % outfile)
|
||||
if not opt.quiet: confirm_or_exit("","alter file '%s'" % outfile)
|
||||
import os
|
||||
f = os.open(outfile,os.O_RDWR)
|
||||
os.lseek(f, int(offset), os.SEEK_SET)
|
||||
|
|
@ -108,60 +107,60 @@ def export_to_hidden_incog(incog_enc,opts):
|
|||
(os.path.relpath(outfile),offset))
|
||||
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if 'export_incog_hidden' in opts or 'export_incog_hex' in opts:
|
||||
opts['export_incog'] = True
|
||||
if opt.export_incog_hidden or opt.export_incog_hex:
|
||||
opt.export_incog = True
|
||||
|
||||
if len(cmd_args) != 1: usage(help_data)
|
||||
if len(cmd_args) != 1: opt.opts.usage(opts_data)
|
||||
|
||||
check_infile(cmd_args[0])
|
||||
|
||||
if set(['outdir','export_incog_hidden']) <= set(opts.keys()):
|
||||
if opt.outdir and opt.export_incog_hidden:
|
||||
msg("Warning: '--outdir' option is ignored when exporting hidden incog data")
|
||||
|
||||
g.use_urandchars = True
|
||||
|
||||
if 'export_mnemonic' in opts:
|
||||
if opt.export_mnemonic:
|
||||
qmsg("Exporting mnemonic data to file by user request")
|
||||
elif 'export_seed' in opts:
|
||||
elif opt.export_seed:
|
||||
qmsg("Exporting seed data to file by user request")
|
||||
elif 'export_incog' in opts:
|
||||
elif opt.export_incog:
|
||||
qmsg("Exporting wallet to incognito format by user request")
|
||||
incog_enc,seed_id,key_id,iv_id,preset = \
|
||||
wallet_to_incog_data(cmd_args[0],opts)
|
||||
wallet_to_incog_data(cmd_args[0])
|
||||
|
||||
if "export_incog_hidden" in opts:
|
||||
export_to_hidden_incog(incog_enc,opts)
|
||||
if opt.export_incog_hidden:
|
||||
export_to_hidden_incog(incog_enc)
|
||||
else:
|
||||
z = 0 if 'old_incog_fmt' in opts else 8
|
||||
z = 0 if opt.old_incog_fmt else 8
|
||||
seed_len = (len(incog_enc)-g.salt_len-g.aesctr_iv_len-z)*8
|
||||
fn = "%s-%s-%s[%s,%s].%s" % (
|
||||
seed_id, key_id, iv_id, seed_len, preset,
|
||||
g.incog_hex_ext if "export_incog_hex" in opts else g.incog_ext
|
||||
g.incog_hex_ext if opt.export_incog_hex else g.incog_ext
|
||||
)
|
||||
data = pretty_hexdump(incog_enc,2,8,line_nums=False) \
|
||||
if "export_incog_hex" in opts else incog_enc
|
||||
write_to_file_or_stdout(fn, data, opts, "incognito wallet data")
|
||||
if opt.export_incog_hex else incog_enc
|
||||
write_to_file_or_stdout(fn, data, "incognito wallet data")
|
||||
|
||||
sys.exit()
|
||||
|
||||
seed = get_seed_retry(cmd_args[0], opts)
|
||||
seed = get_seed_retry(cmd_args[0])
|
||||
if seed: msg("Wallet is OK")
|
||||
else:
|
||||
msg("Error opening wallet")
|
||||
sys.exit(2)
|
||||
|
||||
if 'export_mnemonic' in opts:
|
||||
if opt.export_mnemonic:
|
||||
wl = get_default_wordlist()
|
||||
from mmgen.mnemonic import get_mnemonic_from_seed
|
||||
mn = get_mnemonic_from_seed(seed, wl, g.default_wl, g.debug)
|
||||
mn = get_mnemonic_from_seed(seed, wl, g.default_wl, opt.debug)
|
||||
fn = "%s.%s" % (make_chksum_8(seed).upper(), g.mn_ext)
|
||||
write_to_file_or_stdout(fn, " ".join(mn)+"\n", opts, "mnemonic data")
|
||||
write_to_file_or_stdout(fn, " ".join(mn)+"\n", "mnemonic data")
|
||||
|
||||
elif 'export_seed' in opts:
|
||||
elif opt.export_seed:
|
||||
from mmgen.bitcoin import b58encode_pad
|
||||
data = col4(b58encode_pad(seed))
|
||||
chk = make_chksum_6(b58encode_pad(seed))
|
||||
fn = "%s.%s" % (make_chksum_8(seed).upper(), g.seed_ext)
|
||||
write_to_file_or_stdout(fn, "%s %s\n" % (chk,data), opts, "seed data")
|
||||
write_to_file_or_stdout(fn, "%s %s\n" % (chk,data), "seed data")
|
||||
|
|
|
|||
|
|
@ -24,13 +24,12 @@ import sys, os
|
|||
from hashlib import sha256
|
||||
|
||||
import mmgen.config as g
|
||||
from mmgen.Opts import *
|
||||
import mmgen.opt as opt
|
||||
from mmgen.license import *
|
||||
from mmgen.util import *
|
||||
from mmgen.crypto import *
|
||||
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': "Generate an {} deterministic wallet".format(g.proj_name),
|
||||
'usage': "[opts] [infile]",
|
||||
'options': """
|
||||
|
|
@ -121,11 +120,12 @@ future, you must continue using these same parameters
|
|||
""",
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
import mmgen.opt as opt
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if 'show_hash_presets' in opts: show_hash_presets()
|
||||
if opt.show_hash_presets: show_hash_presets()
|
||||
|
||||
if g.debug: show_opts_and_cmd_args(opts,cmd_args)
|
||||
if opt.debug: opt.opts.show_opts_and_cmd_args(cmd_args)
|
||||
|
||||
if len(cmd_args) == 1:
|
||||
infile = cmd_args[0]
|
||||
|
|
@ -140,7 +140,7 @@ if len(cmd_args) == 1:
|
|||
sys.exit(1)
|
||||
elif len(cmd_args) == 0:
|
||||
infile = ""
|
||||
else: usage(help_data)
|
||||
else: opt.opts.usage(opts_data)
|
||||
|
||||
g.use_urandchars = True
|
||||
|
||||
|
|
@ -148,31 +148,27 @@ g.use_urandchars = True
|
|||
|
||||
do_license_msg()
|
||||
|
||||
if 'from_brain' in opts and not g.quiet:
|
||||
if opt.from_brain and not opt.quiet:
|
||||
confirm_or_exit(wmsg['brain_warning'].format(
|
||||
g.proj_name, *get_from_brain_opt_params(opts)),
|
||||
g.proj_name, *get_from_brain_opt_params()),
|
||||
"continue")
|
||||
|
||||
for i in 'from_mnemonic','from_brain','from_seed','from_incog':
|
||||
if infile or (i in opts):
|
||||
seed = get_seed_retry(infile,opts)
|
||||
# if "from_incog" in opts or get_extension(infile) == g.incog_ext:
|
||||
# qmsg(cmessages['incog'] % make_chksum_8(seed))
|
||||
# else: qmsg("")
|
||||
qmsg("")
|
||||
break
|
||||
if infile or (opt.from_mnemonic or opt.from_brain
|
||||
or opt.from_seed or opt.from_incog):
|
||||
seed = get_seed_retry(infile)
|
||||
qmsg("")
|
||||
else:
|
||||
# Truncate random data for smaller seed lengths
|
||||
seed = sha256(get_random(128)).digest()[:opts['seed_len']/8]
|
||||
seed = sha256(get_random(128)).digest()[:opt.seed_len/8]
|
||||
|
||||
salt = sha256(get_random(128)).digest()[:g.salt_len]
|
||||
|
||||
qmsg(wmsg['choose_wallet_passphrase'] % opts['hash_preset'])
|
||||
qmsg(wmsg['choose_wallet_passphrase'] % opt.hash_preset)
|
||||
|
||||
passwd = get_new_passphrase("new {} wallet".format(g.proj_name), opts)
|
||||
passwd = get_new_passphrase("new {} wallet".format(g.proj_name))
|
||||
|
||||
key = make_key(passwd, salt, opts['hash_preset'])
|
||||
key = make_key(passwd, salt, opt.hash_preset)
|
||||
|
||||
enc_seed = encrypt_seed(seed, key)
|
||||
|
||||
write_wallet_to_file(seed,passwd,make_chksum_8(key),salt,enc_seed,opts)
|
||||
write_wallet_to_file(seed,passwd,make_chksum_8(key),salt,enc_seed)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ from binascii import hexlify
|
|||
from mmgen.util import msg,msg_r,make_chksum_8,Vmsg
|
||||
from mmgen.crypto import get_random
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
|
||||
wl_checksums = {
|
||||
"electrum": '5ca31424',
|
||||
|
|
|
|||
22
mmgen/opt.py
Executable file
22
mmgen/opt.py
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#!/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/>.
|
||||
|
||||
"""
|
||||
opt.py: an empty namespace for the global opt variables
|
||||
"""
|
||||
import opts
|
||||
|
|
@ -17,15 +17,18 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Opts.py: Option handling routines for the MMGen suite
|
||||
opts.py: Further options processing after mmgen.share.Opts
|
||||
"""
|
||||
|
||||
import sys
|
||||
import mmgen.config as g
|
||||
import mmgen.opt.Opts
|
||||
from mmgen.util import msg,check_infile,check_outfile,check_outdir,msgrepr_exit,msgrepr
|
||||
|
||||
def usage(hd): mmgen.opt.Opts.usage(hd)
|
||||
import mmgen.config as g
|
||||
import mmgen.share.Opts
|
||||
import opt
|
||||
from mmgen.util import msg,msgrepr_exit,msgrepr
|
||||
|
||||
def usage(opts_data):
|
||||
print "USAGE: %s %s" % (opts_data['prog_name'], opts_data['usage'])
|
||||
sys.exit(2)
|
||||
|
||||
def print_version_info():
|
||||
print """
|
||||
|
|
@ -33,19 +36,38 @@ def print_version_info():
|
|||
Copyright (C) {g.Cdates} by {g.author} {g.email}.
|
||||
""".format(g=g).strip()
|
||||
|
||||
def warn_incompatible_opts(opts,incompat_list):
|
||||
bad = [k for k in opts.keys() if k in incompat_list]
|
||||
def warn_incompatible_opts(incompat_list):
|
||||
bad = [k for k in opt.__dict__ if opt.__dict__[k] and k in incompat_list]
|
||||
if len(bad) > 1:
|
||||
msg("Mutually exclusive options: %s" % " ".join(
|
||||
["--"+b.replace("_","-") for b in bad]))
|
||||
sys.exit(1)
|
||||
|
||||
def parse_opts(argv,help_data):
|
||||
def typeconvert_from_dfl(opts,opt):
|
||||
|
||||
if len(argv) == 2 and argv[1] == '--version':
|
||||
vtype = type(g.__dict__[opt])
|
||||
if g.debug: print "Override opt: %-15s [%s]" % (opt,vtype)
|
||||
|
||||
try:
|
||||
opts[opt] = vtype(opts[opt])
|
||||
except:
|
||||
d = {
|
||||
'int': 'an integer',
|
||||
'str': 'a string',
|
||||
'float': 'a float',
|
||||
'bool': 'a boolean value',
|
||||
}
|
||||
m = [d[k] for k in d if __builtins__[k] == vtype][0]
|
||||
msg("'%s': invalid parameter for '--%s' option (not %s)" %
|
||||
(opts[opt],opt.replace("_","-"),m))
|
||||
sys.exit(1)
|
||||
|
||||
def init(opts_data,add_opts=[]):
|
||||
|
||||
if len(sys.argv) == 2 and sys.argv[1] == '--version':
|
||||
print_version_info(); sys.exit()
|
||||
|
||||
opts,args,short_opts,long_opts = mmgen.opt.Opts.parse_opts(argv,help_data)
|
||||
opts,args,short_opts,long_opts = mmgen.share.Opts.parse_opts(sys.argv,opts_data)
|
||||
|
||||
if g.debug:
|
||||
print "short opts: %s" % repr(short_opts)
|
||||
|
|
@ -53,46 +75,58 @@ def parse_opts(argv,help_data):
|
|||
print "user-selected opts: %s" % repr(opts)
|
||||
print "cmd args: %s" % repr(args)
|
||||
|
||||
# check opts without modifying them
|
||||
if not check_opts(opts,long_opts): sys.exit(1)
|
||||
|
||||
# If user opt is set, an opt in mmgen.config is set to 'True'
|
||||
for v in g.usr_set_vars:
|
||||
if v in opts:
|
||||
g.__dict__[g.usr_set_vars[v]] = True
|
||||
|
||||
# If user opt is unset, set it to default value in mmgen.config (g):
|
||||
# If set, convert its type based on value in mmgen.config
|
||||
for v in g.dfl_vars:
|
||||
if v in opts: typeconvert_from_dfl(opts,v)
|
||||
else: opts[v] = g.__dict__[v]
|
||||
|
||||
if g.debug: print "opts after typeconvert: %s" % opts
|
||||
|
||||
# A hack, but harmless
|
||||
extra_opts = [
|
||||
"quiet","verbose","debug",
|
||||
"outdir","echo_passphrase","passwd_file"
|
||||
] + add_opts
|
||||
|
||||
# Transfer opts into our custom namespace
|
||||
for o in [s.rstrip("=") for s in long_opts] + extra_opts:
|
||||
opt.__dict__[o] = opts[o] if o in opts else None
|
||||
|
||||
for l in (
|
||||
('from_incog_hidden','from_incog','from_seed','from_mnemonic','from_brain'),
|
||||
('export_incog','export_incog_hex','export_incog_hidden','export_mnemonic',
|
||||
'export_seed'),
|
||||
('quiet','verbose')
|
||||
): warn_incompatible_opts(opts,l)
|
||||
): warn_incompatible_opts(l)
|
||||
|
||||
if 'usr_randchars' in opts: g.use_urandchars = True
|
||||
del mmgen.share.Opts
|
||||
return args
|
||||
|
||||
# check opts[] dictionary without modifying it
|
||||
if not check_opts(opts,long_opts): sys.exit(1)
|
||||
def show_opts_and_cmd_args(cmd_args):
|
||||
print "Processed options:"
|
||||
d = opt.__dict__
|
||||
for k in d:
|
||||
if k[:2] != "__" and k != "opts" and d[k] != None:
|
||||
msg("%-20s: %s" % (k, d[k]))
|
||||
print "Cmd args: %s" % repr(cmd_args)
|
||||
|
||||
# If user opt is unset, set it to default value in mmgen.config (g):
|
||||
for v in g.dfl_vars:
|
||||
if v in opts: typeconvert_override_var(opts,v)
|
||||
else: opts[v] = g.__dict__[v]
|
||||
def show_all_opts():
|
||||
msg("Processed options:")
|
||||
d = opt.__dict__
|
||||
for k in d:
|
||||
if k[:2] != "__" and k != "opts":
|
||||
msg("%-20s: %s" % (k, d[k]))
|
||||
|
||||
# Opposite of above: set the value in mmgen.config (g) from user opt:
|
||||
for k in g.usr_set_vars:
|
||||
if k in opts:
|
||||
v = opts[k]
|
||||
try: v = type(g.__dict__[k])(v)
|
||||
except:
|
||||
msg(
|
||||
"Argument '%s' for option '--%s' cannot be converted to target type %s" %
|
||||
(v,k.replace("_","-"),type(g.__dict__[k]))
|
||||
)
|
||||
sys.exit(1)
|
||||
g.__dict__[k] = v
|
||||
|
||||
if g.debug: print "opts after typeconvert: %s" % opts
|
||||
|
||||
return opts,args
|
||||
|
||||
|
||||
def show_opts_and_cmd_args(opts,cmd_args):
|
||||
print "Processed options: %s" % repr(opts)
|
||||
print "Cmd args: %s" % repr(cmd_args)
|
||||
|
||||
def check_opts(opts,long_opts):
|
||||
def check_opts(opts,long_opts): # Returns false if any check fails
|
||||
|
||||
def opt_splits(val,sep,n,what):
|
||||
sepword = "comma" if sep == "," else (
|
||||
|
|
@ -136,10 +170,12 @@ def check_opts(opts,long_opts):
|
|||
# Check for file existence and readability
|
||||
if opt in ('keys_from_file','mmgen_keys_from_file',
|
||||
'passwd_file','keysforaddrs','comment_file'):
|
||||
from mmgen.util import check_infile
|
||||
check_infile(val) # exits on error
|
||||
continue
|
||||
|
||||
if opt == 'outdir':
|
||||
from mmgen.util import check_outdir
|
||||
check_outdir(val) # exits on error
|
||||
elif opt == 'label':
|
||||
if not opt_compares(len(val),"<=",g.max_wallet_label_len,"label length"):
|
||||
|
|
@ -155,11 +191,13 @@ def check_opts(opts,long_opts):
|
|||
if opt == 'from_incog_hidden':
|
||||
if not opt_splits(val,",",3,what): return False
|
||||
infile,offset,seed_len = val.split(",")
|
||||
from mmgen.util import check_infile
|
||||
check_infile(infile)
|
||||
w = "seed length " + what
|
||||
if not opt_is_int(seed_len,w): return False
|
||||
if not opt_is_in_list(int(seed_len),g.seed_lens,w): return False
|
||||
else:
|
||||
from mmgen.util import check_outfile
|
||||
if not opt_splits(val,",",2,what): return False
|
||||
outfile,offset = val.split(",")
|
||||
check_outfile(outfile)
|
||||
|
|
@ -184,24 +222,6 @@ def check_opts(opts,long_opts):
|
|||
if not opt_compares(val,">=",g.min_urandchars,what): return False
|
||||
if not opt_compares(val,"<=",g.max_urandchars,what): return False
|
||||
else:
|
||||
if g.debug: print "check_opts(): No test for opt '%s'" % opt
|
||||
if 'debug' in opts: print "check_opts(): No test for opt '%s'" % opt
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def typeconvert_override_var(opts,opt):
|
||||
|
||||
vtype = type(eval("g."+opt))
|
||||
if g.debug: print "Override opt: %-15s [%s]" % (opt,vtype)
|
||||
|
||||
if vtype == int: f,t = int,"an integer"
|
||||
elif vtype == str: f,t = str,"a string"
|
||||
elif vtype == float: f,t = float,"a float"
|
||||
elif vtype == bool: f,t = bool,"a boolean value"
|
||||
|
||||
try:
|
||||
opts[opt] = f(opts[opt])
|
||||
except:
|
||||
msg("'%s': invalid parameter for '--%s' option (not %s)" %
|
||||
(opts[opt],opt.replace("_","-"),t))
|
||||
sys.exit(1)
|
||||
|
|
@ -18,23 +18,25 @@
|
|||
|
||||
import sys, getopt
|
||||
|
||||
def usage(hd):
|
||||
print "USAGE: %s %s" % (hd['prog_name'], hd['usage'])
|
||||
def usage(opts_data):
|
||||
print "USAGE: %s %s" % (opts_data['prog_name'], opts_data['usage'])
|
||||
sys.exit(2)
|
||||
|
||||
def print_help(help_data):
|
||||
pn = help_data['prog_name']
|
||||
def print_help(opts_data):
|
||||
pn = opts_data['prog_name']
|
||||
pn_len = str(len(pn)+2)
|
||||
print (" %-"+pn_len+"s %s") % (pn.upper()+":", help_data['desc'].strip())
|
||||
print (" %-"+pn_len+"s %s %s")%("USAGE:", pn, help_data['usage'].strip())
|
||||
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(help_data['options'].strip().split("\n"))
|
||||
if "notes" in help_data:
|
||||
print " %s" % "\n ".join(help_data['notes'][1:-1].split("\n"))
|
||||
print " OPTIONS:"+sep+"%s" % sep.join(opts_data['options'].strip().split("\n"))
|
||||
if "notes" in opts_data:
|
||||
print " %s" % "\n ".join(opts_data['notes'][1:-1].split("\n"))
|
||||
|
||||
|
||||
def process_opts(argv,help_data,short_opts,long_opts):
|
||||
def process_opts(argv,opts_data,short_opts,long_opts):
|
||||
|
||||
import os
|
||||
opts_data['prog_name'] = os.path.split(sys.argv[0])[1]
|
||||
long_opts = [i.replace("_","-") for i in long_opts]
|
||||
|
||||
try: cl_opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
|
||||
|
|
@ -48,7 +50,7 @@ def process_opts(argv,help_data,short_opts,long_opts):
|
|||
else: short_opts_l += i
|
||||
|
||||
for opt, arg in cl_opts:
|
||||
if opt in ("-h","--help"): print_help(help_data); sys.exit()
|
||||
if opt in ("-h","--help"): print_help(opts_data); sys.exit()
|
||||
elif opt[:2] == "--" and opt[2:] in long_opts:
|
||||
opts[opt[2:].replace("-","_")] = True
|
||||
elif opt[:2] == "--" and opt[2:]+"=" in long_opts:
|
||||
|
|
@ -63,9 +65,9 @@ def process_opts(argv,help_data,short_opts,long_opts):
|
|||
return opts,args
|
||||
|
||||
|
||||
def parse_opts(argv,help_data):
|
||||
def parse_opts(argv,opts_data):
|
||||
|
||||
lines = help_data['options'].strip().split("\n")
|
||||
lines = opts_data['options'].strip().split("\n")
|
||||
import re
|
||||
pat = r"^-([a-zA-Z0-9]), --([a-zA-Z0-9-]{1,64})(=| )(.+)"
|
||||
rep = r"-{0}, --{1}{w}{3}"
|
||||
|
|
@ -75,10 +77,10 @@ def parse_opts(argv,help_data):
|
|||
if d[2] == " ": d[2] = ""
|
||||
short_opts = "".join([d[0]+d[2].replace("=",":") for d in opt_data])
|
||||
long_opts = [d[1].replace("-","_")+d[2] for d in opt_data]
|
||||
help_data['options'] = "\n".join(
|
||||
opts_data['options'] = "\n".join(
|
||||
[rep.format(w=" ", *m.groups())
|
||||
if m else k for m,k in [(re.match(pat,l),l) for l in lines]]
|
||||
)
|
||||
opts,args = process_opts(argv,help_data,short_opts,long_opts)
|
||||
opts,args = process_opts(argv,opts_data,short_opts,long_opts)
|
||||
|
||||
return opts,args,short_opts,long_opts
|
||||
BIN
mmgen/share/Opts.pyc
Normal file
BIN
mmgen/share/Opts.pyc
Normal file
Binary file not shown.
BIN
mmgen/share/__init__.pyc
Normal file
BIN
mmgen/share/__init__.pyc
Normal file
Binary file not shown.
|
|
@ -22,6 +22,7 @@ term.py: Terminal-handling routines for the MMGen suite
|
|||
|
||||
import sys, os, struct
|
||||
import mmgen.config as g
|
||||
import opt
|
||||
from mmgen.util import msg, msg_r
|
||||
|
||||
def _kb_hold_protect_unix():
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ addr.py: Shared routines for the test suites
|
|||
import sys,os
|
||||
from binascii import hexlify
|
||||
from mmgen.util import msg,write_to_file
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
|
||||
_red,_grn,_yel,_cya,_reset = (
|
||||
["\033[%sm" % c for c in "31;1","32;1","33;1","36;1","0"]
|
||||
|
|
@ -58,7 +58,7 @@ def get_tmpfile_fn(cfg,fn):
|
|||
return os.path.join(cfg['tmpdir'],fn)
|
||||
|
||||
def write_to_tmpfile(cfg,fn,data):
|
||||
write_to_file(os.path.join(cfg['tmpdir'],fn),data,{},silent=True)
|
||||
write_to_file(os.path.join(cfg['tmpdir'],fn),data,silent=True)
|
||||
|
||||
def read_from_tmpfile(cfg,fn):
|
||||
from mmgen.util import get_data_from_file
|
||||
|
|
@ -69,7 +69,7 @@ def read_from_file(fn):
|
|||
return get_data_from_file(fn,silent=True)
|
||||
|
||||
def ok():
|
||||
if g.verbose or g.exact_output:
|
||||
if opt.verbose or opt.exact_output:
|
||||
sys.stderr.write(green("OK\n"))
|
||||
else: msg(" OK")
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@ import mmgen.bitcoin as bitcoin
|
|||
import binascii as ba
|
||||
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
from mmgen.crypto import *
|
||||
from mmgen.util import *
|
||||
from mmgen.tx import *
|
||||
|
||||
opts = {}
|
||||
from collections import OrderedDict
|
||||
cmd_data = OrderedDict([
|
||||
("help", []),
|
||||
|
|
@ -230,7 +230,7 @@ def print_convert_results(indata,enc,dec,dtype):
|
|||
|
||||
error = False if are_equal(indata,dec,dtype) else True
|
||||
|
||||
if error or g.verbose:
|
||||
if error or opt.verbose:
|
||||
Msg("Input: %s" % repr(indata))
|
||||
Msg("Encoded data: %s" % repr(enc))
|
||||
Msg("Recoded data: %s" % repr(dec))
|
||||
|
|
@ -470,13 +470,13 @@ def hex2wif(hexpriv,compressed=False):
|
|||
|
||||
def encrypt(infile,outfile="",hash_preset=""):
|
||||
data = get_data_from_file(infile,"data for encryption")
|
||||
enc_d = mmgen_encrypt(data,"user data",hash_preset,opts)
|
||||
enc_d = mmgen_encrypt(data,"user data",hash_preset)
|
||||
if outfile == '-':
|
||||
write_to_stdout(enc_d,"encrypted data",confirm=True)
|
||||
else:
|
||||
if not outfile:
|
||||
outfile = os.path.basename(infile) + "." + g.mmenc_ext
|
||||
write_to_file(outfile, enc_d, opts,"encrypted data",True,True)
|
||||
write_to_file(outfile,enc_d,"encrypted data",True,True)
|
||||
|
||||
|
||||
def decrypt(infile,outfile="",hash_preset=""):
|
||||
|
|
@ -494,7 +494,7 @@ def decrypt(infile,outfile="",hash_preset=""):
|
|||
outfile = outfile[:-len(g.mmenc_ext)-1]
|
||||
else:
|
||||
outfile = outfile + ".dec"
|
||||
write_to_file(outfile, dec_d, opts,"decrypted data",True,True)
|
||||
write_to_file(outfile, dec_d, "decrypted data",True,True)
|
||||
|
||||
|
||||
def find_incog_data(filename,iv_id,keep_searching=False):
|
||||
|
|
@ -553,7 +553,7 @@ def rand2file(outfile, nbytes, threads=4, silent=False):
|
|||
from threading import Thread
|
||||
bsize = 2**20
|
||||
roll = bsize * 4
|
||||
if 'outdir' in opts: outfile = make_full_path(opts['outdir'],outfile)
|
||||
if opt.outdir: outfile = make_full_path(opt.outdir,outfile)
|
||||
f = open(outfile,"w")
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from decimal import Decimal
|
|||
from collections import OrderedDict
|
||||
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
from mmgen.util import *
|
||||
from mmgen.term import do_pager
|
||||
|
||||
|
|
@ -45,7 +46,7 @@ def normalize_btc_amt(amt):
|
|||
msg("%s: Invalid amount" % amt)
|
||||
return False
|
||||
|
||||
if g.debug:
|
||||
if opt.debug:
|
||||
print "Decimal(amt): %s\nAs tuple: %s" % (amt,repr(ret.as_tuple()))
|
||||
|
||||
if ret.as_tuple()[-1] < -8:
|
||||
|
|
@ -260,7 +261,7 @@ def wiftoaddr_keyconv(wif):
|
|||
return wiftoaddr(wif)
|
||||
|
||||
def get_wif2addr_f():
|
||||
if g.no_keyconv: return wiftoaddr
|
||||
if opt.no_keyconv: return wiftoaddr
|
||||
from mmgen.addr import test_for_keyconv
|
||||
return wiftoaddr_keyconv if test_for_keyconv() else wiftoaddr
|
||||
|
||||
|
|
|
|||
114
mmgen/util.py
114
mmgen/util.py
|
|
@ -26,27 +26,37 @@ from binascii import hexlify,unhexlify
|
|||
|
||||
import mmgen.config as g
|
||||
|
||||
def msg(s): sys.stderr.write(s + "\n")
|
||||
_red,_grn,_yel,_cya,_reset = (
|
||||
["\033[%sm" % c for c in "31;1","32;1","33;1","36;1","0"]
|
||||
)
|
||||
def red(s): return _red+s+_reset
|
||||
def green(s): return _grn+s+_reset
|
||||
def yellow(s): return _yel+s+_reset
|
||||
def cyan(s): return _cya+s+_reset
|
||||
|
||||
def msgred(s): sys.stderr.write(red(s+"\n"))
|
||||
|
||||
def msg(s): sys.stderr.write(s+"\n")
|
||||
def msg_r(s): sys.stderr.write(s)
|
||||
def qmsg(s,alt=False):
|
||||
if g.quiet:
|
||||
if opt.quiet:
|
||||
if alt != False: sys.stderr.write(alt + "\n")
|
||||
else: sys.stderr.write(s + "\n")
|
||||
def qmsg_r(s,alt=False):
|
||||
if g.quiet:
|
||||
if opt.quiet:
|
||||
if alt != False: sys.stderr.write(alt)
|
||||
else: sys.stderr.write(s)
|
||||
def vmsg(s):
|
||||
if g.verbose: sys.stderr.write(s + "\n")
|
||||
if opt.verbose: sys.stderr.write(s + "\n")
|
||||
def vmsg_r(s):
|
||||
if g.verbose: sys.stderr.write(s)
|
||||
if opt.verbose: sys.stderr.write(s)
|
||||
|
||||
def Msg(s): sys.stdout.write(s + "\n")
|
||||
def Msg_r(s): sys.stdout.write(s)
|
||||
def Vmsg(s):
|
||||
if g.verbose: sys.stdout.write(s + "\n")
|
||||
if opt.verbose: sys.stdout.write(s + "\n")
|
||||
def Vmsg_r(s):
|
||||
if g.verbose: sys.stdout.write(s)
|
||||
if opt.verbose: sys.stdout.write(s)
|
||||
|
||||
|
||||
def msgrepr(*args):
|
||||
|
|
@ -122,8 +132,10 @@ def is_utf8(s):
|
|||
def match_ext(addr,ext):
|
||||
return addr.split(".")[-1] == ext
|
||||
|
||||
def get_from_brain_opt_params(opts):
|
||||
l,p = opts['from_brain'].split(",")
|
||||
import opt as opt
|
||||
|
||||
def get_from_brain_opt_params():
|
||||
l,p = opt.from_brain.split(",")
|
||||
return(int(l),p)
|
||||
|
||||
def pretty_hexdump(data,gw=2,cols=8,line_nums=False):
|
||||
|
|
@ -165,7 +177,7 @@ def compare_checksums(chksum1, desc1, chksum2, desc2):
|
|||
vmsg("OK (%s)" % chksum1.upper())
|
||||
return True
|
||||
else:
|
||||
if g.debug:
|
||||
if opt.debug:
|
||||
print \
|
||||
"ERROR!\nComputed checksum %s (%s) doesn't match checksum %s (%s)" \
|
||||
% (desc1,chksum1,desc2,chksum2)
|
||||
|
|
@ -266,18 +278,18 @@ def parse_addr_idxs(arg,sep=","):
|
|||
return sorted(set(ret))
|
||||
|
||||
|
||||
def get_new_passphrase(what, opts, passchg=False):
|
||||
def get_new_passphrase(what, passchg=False):
|
||||
|
||||
w = "{}passphrase for {}".format("new " if passchg else "", what)
|
||||
if 'passwd_file' in opts:
|
||||
pw = " ".join(_get_words_from_file(opts['passwd_file'],w))
|
||||
elif 'echo_passphrase' in opts:
|
||||
pw = " ".join(_get_words_from_user("Enter {}: ".format(w), opts))
|
||||
if opt.passwd_file:
|
||||
pw = " ".join(_get_words_from_file(opt.passwd_file,w))
|
||||
elif opt.echo_passphrase:
|
||||
pw = " ".join(_get_words_from_user("Enter {}: ".format(w)))
|
||||
else:
|
||||
for i in range(g.passwd_max_tries):
|
||||
pw = " ".join(_get_words_from_user("Enter {}: ".format(w),opts))
|
||||
pw2 = " ".join(_get_words_from_user("Repeat passphrase: ",opts))
|
||||
if g.debug: print "Passphrases: [%s] [%s]" % (pw,pw2)
|
||||
pw = " ".join(_get_words_from_user("Enter {}: ".format(w)))
|
||||
pw2 = " ".join(_get_words_from_user("Repeat passphrase: "))
|
||||
if opt.debug: print "Passphrases: [%s] [%s]" % (pw,pw2)
|
||||
if pw == pw2:
|
||||
vmsg("Passphrases match"); break
|
||||
else: msg("Passphrases do not match. Try again.")
|
||||
|
|
@ -324,9 +336,9 @@ def write_to_stdout(data, what, confirm=True):
|
|||
sys.stdout.write(data)
|
||||
|
||||
|
||||
def write_to_file(outfile,data,opts,what="data",confirm_overwrite=False,verbose=False,exit_on_error=True,silent=False):
|
||||
def write_to_file(outfile,data,what="data",confirm_overwrite=False,verbose=False,exit_on_error=True,silent=False):
|
||||
|
||||
if 'outdir' in opts: outfile = make_full_path(opts['outdir'],outfile)
|
||||
if opt.outdir: outfile = make_full_path(opt.outdir,outfile)
|
||||
|
||||
from os import stat
|
||||
try: stat(outfile)
|
||||
|
|
@ -355,18 +367,18 @@ def write_to_file(outfile,data,opts,what="data",confirm_overwrite=False,verbose=
|
|||
return True
|
||||
|
||||
|
||||
def write_to_file_or_stdout(outfile, data, opts, what="data"):
|
||||
def write_to_file_or_stdout(outfile, data, what="data"):
|
||||
|
||||
if 'stdout' in opts or not sys.stdout.isatty():
|
||||
if opt.stdout or not sys.stdout.isatty():
|
||||
write_to_stdout(data, what, confirm=True)
|
||||
else:
|
||||
write_to_file(outfile,data,opts,what,not g.quiet,True)
|
||||
write_to_file(outfile,data,what,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")
|
||||
print "WALLET DATA"
|
||||
fs = " {:18} {}"
|
||||
pw_empty = "yes" if metadata[3] == "E" else "no"
|
||||
for i in (
|
||||
|
|
@ -379,7 +391,7 @@ def display_control_data(label,metadata,hash_preset,salt,enc_seed):
|
|||
" ".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))
|
||||
): print fs.format(*i)
|
||||
|
||||
fs = " {:6} {}"
|
||||
for i in (
|
||||
|
|
@ -389,16 +401,16 @@ def display_control_data(label,metadata,hash_preset,salt,enc_seed):
|
|||
("Encrypted seed:", ""),
|
||||
(" b58:", b58encode_pad(enc_seed)),
|
||||
(" hex:", hexlify(enc_seed))
|
||||
): msg(fs.format(*i))
|
||||
): print fs.format(*i)
|
||||
|
||||
|
||||
def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
|
||||
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 = opts['hash_preset']
|
||||
label = opts['label'] if 'label' in opts else "No Label"
|
||||
hash_preset = opt.hash_preset
|
||||
label = opt.label if opt.label else "No Label"
|
||||
metadata = seed_id.lower(),key_id.lower(),seed_len,\
|
||||
pw_status,make_timestamp()
|
||||
sf = b58encode_pad(salt)
|
||||
|
|
@ -417,9 +429,9 @@ def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
|
|||
seed_id,key_id,seed_len,hash_preset,g.wallet_ext)
|
||||
|
||||
d = "\n".join((chk,)+lines)+"\n"
|
||||
write_to_file(outfile,d,opts,"wallet",not g.quiet,True)
|
||||
write_to_file(outfile,d,"wallet",not opt.quiet,True)
|
||||
|
||||
if g.debug:
|
||||
if opt.debug:
|
||||
display_control_data(label,metadata,hash_preset,salt,enc_seed)
|
||||
|
||||
|
||||
|
|
@ -467,7 +479,7 @@ def _check_chksum_6(chk,val,desc,infile):
|
|||
msg("%s checksum incorrect in file '%s'!" % (desc,infile))
|
||||
msg("Checksum: %s. Computed value: %s" % (chk,comp_chk))
|
||||
sys.exit(2)
|
||||
elif g.debug:
|
||||
elif opt.debug:
|
||||
print "%s checksum passed: %s" % (desc.capitalize(),chk)
|
||||
|
||||
|
||||
|
|
@ -475,7 +487,7 @@ 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 g.quiet:
|
||||
if not silent and not opt.quiet:
|
||||
msg("Getting {} wallet data from file '{}'".format(g.proj_name,infile))
|
||||
|
||||
f = open_file_or_exit(infile, 'r')
|
||||
|
|
@ -515,10 +527,10 @@ def get_data_from_wallet(infile,silent=False):
|
|||
return label,metadata,hash_preset,res['salt'],res['enc_seed']
|
||||
|
||||
|
||||
def _get_words_from_user(prompt, opts):
|
||||
def _get_words_from_user(prompt):
|
||||
# split() also strips
|
||||
words = my_raw_input(prompt, echo='echo_passphrase' in opts).split()
|
||||
if g.debug: print "Sanitized input: [%s]" % " ".join(words)
|
||||
words = my_raw_input(prompt, echo=opt.echo_passphrase).split()
|
||||
if opt.debug: print "Sanitized input: [%s]" % " ".join(words)
|
||||
return words
|
||||
|
||||
|
||||
|
|
@ -528,15 +540,15 @@ def _get_words_from_file(infile,what):
|
|||
# split() also strips
|
||||
words = f.read().split()
|
||||
f.close()
|
||||
if g.debug: print "Sanitized input: [%s]" % " ".join(words)
|
||||
if opt.debug: print "Sanitized input: [%s]" % " ".join(words)
|
||||
return words
|
||||
|
||||
|
||||
def get_words(infile,what,prompt,opts):
|
||||
def get_words(infile,what,prompt):
|
||||
if infile:
|
||||
return _get_words_from_file(infile,what)
|
||||
else:
|
||||
return _get_words_from_user(prompt,opts)
|
||||
return _get_words_from_user(prompt)
|
||||
|
||||
def remove_comments(lines):
|
||||
import re
|
||||
|
|
@ -594,31 +606,31 @@ def get_seed_from_seed_data(words):
|
|||
|
||||
passwd_file_used = False
|
||||
|
||||
def mark_passwd_file_as_used(opts):
|
||||
def mark_passwd_file_as_used():
|
||||
global passwd_file_used
|
||||
if passwd_file_used:
|
||||
msg_r("WARNING: Reusing passphrase from file '%s'." % opts['passwd_file'])
|
||||
msg_r("WARNING: Reusing passphrase from file '%s'." % opt.passwd_file)
|
||||
msg(" This may not be what you want!")
|
||||
passwd_file_used = True
|
||||
|
||||
|
||||
def get_mmgen_passphrase(prompt_info,opts,passchg=False):
|
||||
def get_mmgen_passphrase(prompt_info,passchg=False):
|
||||
prompt = "Enter {}passphrase for {}: ".format(
|
||||
"old " if passchg else "",prompt_info)
|
||||
if 'passwd_file' in opts:
|
||||
mark_passwd_file_as_used(opts)
|
||||
return " ".join(_get_words_from_file(opts['passwd_file'],"passphrase"))
|
||||
if opt.passwd_file:
|
||||
mark_passwd_file_as_used()
|
||||
return " ".join(_get_words_from_file(opt.passwd_file,"passphrase"))
|
||||
else:
|
||||
return " ".join(_get_words_from_user(prompt,opts))
|
||||
return " ".join(_get_words_from_user(prompt))
|
||||
|
||||
|
||||
def get_bitcoind_passphrase(prompt,opts):
|
||||
if 'passwd_file' in opts:
|
||||
mark_passwd_file_as_used(opts)
|
||||
return get_data_from_file(opts['passwd_file'],
|
||||
def get_bitcoind_passphrase(prompt):
|
||||
if opt.passwd_file:
|
||||
mark_passwd_file_as_used()
|
||||
return get_data_from_file(opt.passwd_file,
|
||||
"passphrase").strip("\r\n")
|
||||
else:
|
||||
return my_raw_input(prompt, echo='echo_passphrase' in opts)
|
||||
return my_raw_input(prompt, echo=opt.echo_passphrase)
|
||||
|
||||
|
||||
def check_data_fits_file_at_offset(fname,offset,dlen,action):
|
||||
|
|
|
|||
28
setup.py
28
setup.py
|
|
@ -1,12 +1,33 @@
|
|||
#!/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/>.
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name = 'mmgen',
|
||||
decription = 'A complete Bitcoin cold-storage solution for the command line',
|
||||
version = '0.7.9',
|
||||
author = 'Philemon',
|
||||
author_email = 'mmgen-py@yandex.com',
|
||||
url = 'https://github.com/mmgen/mmgen',
|
||||
license = 'GNU GPL v3',
|
||||
platforms = 'Linux, MS Windows',
|
||||
keywords = 'Bitcoin, wallet, cold storage, offline storage, open-source, command-line, Python, Bitcoin Core, bitcoind',
|
||||
py_modules = [
|
||||
'mmgen.__init__',
|
||||
'mmgen.addr',
|
||||
|
|
@ -17,7 +38,8 @@ setup(
|
|||
'mmgen.mn_electrum',
|
||||
'mmgen.mnemonic',
|
||||
'mmgen.mn_tirosh',
|
||||
'mmgen.Opts',
|
||||
'mmgen.opts',
|
||||
'mmgen.opt',
|
||||
'mmgen.term',
|
||||
'mmgen.test',
|
||||
'mmgen.tool',
|
||||
|
|
@ -36,8 +58,8 @@ setup(
|
|||
'mmgen.main_walletchk',
|
||||
'mmgen.main_walletgen',
|
||||
|
||||
'mmgen.opt.__init__',
|
||||
'mmgen.opt.Opts',
|
||||
'mmgen.share.__init__',
|
||||
'mmgen.share.Opts',
|
||||
|
||||
'mmgen.rpc.__init__',
|
||||
'mmgen.rpc.config',
|
||||
|
|
|
|||
100
test/test.py
100
test/test.py
|
|
@ -9,6 +9,7 @@ os.chdir(os.path.join(pn,os.pardir))
|
|||
sys.path.__setitem__(0,os.path.abspath(os.curdir))
|
||||
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
from mmgen.util import msgrepr,msgrepr_exit,Msg
|
||||
from mmgen.test import *
|
||||
|
||||
|
|
@ -202,15 +203,14 @@ meta_cmds = OrderedDict([
|
|||
['tool', (9,("tool_encrypt","tool_decrypt","tool_encrypt_ref","tool_decrypt_ref"))],
|
||||
])
|
||||
|
||||
from mmgen.Opts import *
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': "Test suite for the MMGen suite",
|
||||
'usage':"[options] [command or metacommand]",
|
||||
'options': """
|
||||
-h, --help Print this help message
|
||||
-b, --buf-keypress Use buffered keypresses as with real human input
|
||||
-d, --debug Produce debugging output
|
||||
-D, --direct-exec Bypass pexpect and execute a command directly (for debugging only)
|
||||
-e, --exact-output Show the exact output of the MMGen script(s) being run
|
||||
-l, --list-cmds List and describe the tests and commands in the test suite
|
||||
-p, --pause Pause between tests, resuming on keypress
|
||||
|
|
@ -224,47 +224,43 @@ If no command is given, the whole suite of tests is run.
|
|||
"""
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
|
||||
if 'system' in opts: sys.path.pop(0)
|
||||
if opt.system: sys.path.pop(0)
|
||||
|
||||
env = os.environ
|
||||
if 'buf_keypress' in opts:
|
||||
if opt.buf_keypress:
|
||||
send_delay = 0.3
|
||||
else:
|
||||
send_delay = 0
|
||||
env["MMGEN_DISABLE_HOLD_PROTECT"] = "1"
|
||||
os.environ["MMGEN_DISABLE_HOLD_PROTECT"] = "1"
|
||||
|
||||
for k in 'debug','verbose','exact_output','pause','quiet':
|
||||
g.__dict__[k] = True if k in opts else False
|
||||
if opt.debug: opt.verbose = True
|
||||
|
||||
if g.debug: g.verbose = True
|
||||
|
||||
if g.exact_output:
|
||||
if opt.exact_output:
|
||||
def msg(s): pass
|
||||
vmsg = vmsg_r = msg_r = msg
|
||||
else:
|
||||
def msg(s): sys.stderr.write(s+"\n")
|
||||
def vmsg(s):
|
||||
if g.verbose: sys.stderr.write(s+"\n")
|
||||
if opt.verbose: sys.stderr.write(s+"\n")
|
||||
def msg_r(s): sys.stderr.write(s)
|
||||
def vmsg_r(s):
|
||||
if g.verbose: sys.stderr.write(s)
|
||||
if opt.verbose: sys.stderr.write(s)
|
||||
|
||||
stderr_save = sys.stderr
|
||||
|
||||
def silence():
|
||||
if not (g.verbose or g.exact_output):
|
||||
if not (opt.verbose or opt.exact_output):
|
||||
sys.stderr = open("/dev/null","a")
|
||||
|
||||
def end_silence():
|
||||
if not (g.verbose or g.exact_output):
|
||||
if not (opt.verbose or opt.exact_output):
|
||||
sys.stderr = stderr_save
|
||||
|
||||
def errmsg(s): stderr_save.write(s+"\n")
|
||||
def errmsg_r(s): stderr_save.write(s)
|
||||
|
||||
if "list_cmds" in opts:
|
||||
if opt.list_cmds:
|
||||
fs = " {:<{w}} - {}"
|
||||
Msg("Available commands:")
|
||||
w = max([len(i) for i in cmd_data])
|
||||
|
|
@ -281,15 +277,14 @@ if "list_cmds" in opts:
|
|||
sys.exit()
|
||||
|
||||
import pexpect,time,re
|
||||
import mmgen.config as g
|
||||
from mmgen.util import get_data_from_file,write_to_file,get_lines_from_file
|
||||
|
||||
def my_send(p,t,delay=send_delay,s=False):
|
||||
if delay: time.sleep(delay)
|
||||
ret = p.send(t) # returns num bytes written
|
||||
if delay: time.sleep(delay)
|
||||
if g.verbose:
|
||||
ls = "" if g.debug or not s else " "
|
||||
if opt.verbose:
|
||||
ls = "" if opt.debug or not s else " "
|
||||
es = "" if s else " "
|
||||
msg("%sSEND %s%s" % (ls,es,yellow("'%s'"%t.replace('\n',r'\n'))))
|
||||
return ret
|
||||
|
|
@ -297,7 +292,7 @@ def my_send(p,t,delay=send_delay,s=False):
|
|||
def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False):
|
||||
quo = "'" if type(s) == str else ""
|
||||
|
||||
if g.verbose: msg_r("EXPECT %s" % yellow(quo+str(s)+quo))
|
||||
if opt.verbose: msg_r("EXPECT %s" % yellow(quo+str(s)+quo))
|
||||
else: msg_r("+")
|
||||
|
||||
try:
|
||||
|
|
@ -309,7 +304,7 @@ def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False):
|
|||
errmsg(red("\nERROR. Expect %s%s%s timed out. Exiting" % (quo,s,quo)))
|
||||
sys.exit(1)
|
||||
|
||||
if g.debug or (g.verbose and type(s) != str): msg_r(" ==> %s " % ret)
|
||||
if opt.debug or (opt.verbose and type(s) != str): msg_r(" ==> %s " % ret)
|
||||
|
||||
if ret == -1:
|
||||
errmsg("Error. Expect returned %s" % ret)
|
||||
|
|
@ -329,7 +324,7 @@ def get_file_with_ext(ext,mydir,delete=True):
|
|||
|
||||
if len(flist) > 1:
|
||||
if delete:
|
||||
if not g.quiet:
|
||||
if not opt.quiet:
|
||||
msg("Multiple *.%s files in '%s' - deleting" % (ext,mydir))
|
||||
for f in flist: os.unlink(f)
|
||||
return False
|
||||
|
|
@ -341,7 +336,7 @@ def get_addrfile_checksum(display=False):
|
|||
silence()
|
||||
from mmgen.addr import AddrInfo
|
||||
chk = AddrInfo(addrfile).checksum
|
||||
if g.verbose and display: msg("Checksum: %s" % cyan(chk))
|
||||
if opt.verbose and display: msg("Checksum: %s" % cyan(chk))
|
||||
end_silence()
|
||||
return chk
|
||||
|
||||
|
|
@ -354,21 +349,24 @@ def verify_checksum_or_exit(checksum,chk):
|
|||
|
||||
class MMGenExpect(object):
|
||||
|
||||
def __init__(self,name,mmgen_cmd,cmd_args=[],env=env):
|
||||
if not 'system' in opts:
|
||||
def __init__(self,name,mmgen_cmd,cmd_args=[]):
|
||||
if not opt.system:
|
||||
mmgen_cmd = os.path.join(os.curdir,mmgen_cmd)
|
||||
desc = cmd_data[name][1]
|
||||
if g.verbose or g.exact_output:
|
||||
if opt.verbose or opt.exact_output:
|
||||
sys.stderr.write(
|
||||
green("Testing %s\nExecuting " % desc) +
|
||||
cyan("'%s %s'\n" % (mmgen_cmd," ".join(cmd_args)))
|
||||
)
|
||||
else:
|
||||
msg_r("Testing %s " % (desc+":"))
|
||||
# msgrepr(mmgen_cmd,cmd_args); msg("")
|
||||
if env: self.p = pexpect.spawn(mmgen_cmd,cmd_args,env=env)
|
||||
else: self.p = pexpect.spawn(mmgen_cmd,cmd_args)
|
||||
if g.exact_output: self.p.logfile = sys.stdout
|
||||
|
||||
if opt.direct_exec:
|
||||
os.system(" ".join([mmgen_cmd] + cmd_args))
|
||||
sys.exit()
|
||||
else:
|
||||
self.p = pexpect.spawn(mmgen_cmd,cmd_args)
|
||||
if opt.exact_output: self.p.logfile = sys.stdout
|
||||
|
||||
def license(self):
|
||||
p = "'w' for conditions and warranty info, or 'c' to continue: "
|
||||
|
|
@ -381,7 +379,7 @@ class MMGenExpect(object):
|
|||
vmsg_r("SEND ")
|
||||
while self.p.expect('left: ',0.1) == 0:
|
||||
ch = rand_chars.pop(0)
|
||||
msg_r(yellow(ch)+" " if g.verbose else "+")
|
||||
msg_r(yellow(ch)+" " if opt.verbose else "+")
|
||||
self.p.send(ch)
|
||||
except:
|
||||
vmsg("EOT")
|
||||
|
|
@ -476,12 +474,12 @@ def create_fake_unspent_data(adata,unspent_data_file,tx_data,non_mmgen_input='')
|
|||
btcaddr = privnum2addr(privnum,compressed=True)
|
||||
of = os.path.join(cfgs[non_mmgen_input]['tmpdir'],non_mmgen_fn)
|
||||
write_to_file(of, hextowif("{:064x}".format(privnum),
|
||||
compressed=True)+"\n",{},"compressed bitcoin key")
|
||||
compressed=True)+"\n","compressed bitcoin key")
|
||||
|
||||
add_fake_unspent_entry(out,btcaddr,"Non-MMGen address")
|
||||
|
||||
# msg("\n".join([repr(o) for o in out])); sys.exit()
|
||||
write_to_file(unspent_data_file,repr(out),{},"Unspent outputs",verbose=True)
|
||||
write_to_file(unspent_data_file,repr(out),"Unspent outputs",verbose=True)
|
||||
|
||||
|
||||
def add_comments_to_addr_file(addrfile,tfile):
|
||||
|
|
@ -503,18 +501,18 @@ def make_brainwallet_file(fn):
|
|||
return "".join([ws_list[getrandnum(1)%len(ws_list)] for i in range(nchars)])
|
||||
rand_pairs = [wl[getrandnum(4) % len(wl)] + rand_ws_seq() for i in range(nwords)]
|
||||
d = "".join(rand_pairs).rstrip() + "\n"
|
||||
if g.verbose: msg_r("Brainwallet password:\n%s" % cyan(d))
|
||||
write_to_file(fn,d,{},"brainwallet password")
|
||||
if opt.verbose: msg_r("Brainwallet password:\n%s" % cyan(d))
|
||||
write_to_file(fn,d,"brainwallet password")
|
||||
|
||||
def do_between():
|
||||
if g.pause:
|
||||
if opt.pause:
|
||||
from mmgen.util import keypress_confirm
|
||||
if keypress_confirm(green("Continue?"),default_yes=True):
|
||||
if g.verbose or g.exact_output: sys.stderr.write("\n")
|
||||
if opt.verbose or opt.exact_output: sys.stderr.write("\n")
|
||||
else:
|
||||
errmsg("Exiting at user request")
|
||||
sys.exit()
|
||||
elif g.verbose or g.exact_output:
|
||||
elif opt.verbose or opt.exact_output:
|
||||
sys.stderr.write("\n")
|
||||
|
||||
|
||||
|
|
@ -569,7 +567,7 @@ def refcheck(what,chk,refchk):
|
|||
if chk == refchk:
|
||||
ok()
|
||||
else:
|
||||
if not g.verbose: errmsg("")
|
||||
if not opt.verbose: errmsg("")
|
||||
errmsg(red("""
|
||||
Fatal error - %s '%s' does not match reference value '%s'. Aborting test
|
||||
""".strip() % (what,chk,refchk)))
|
||||
|
|
@ -586,7 +584,7 @@ def check_deps(ts,name,cmds):
|
|||
msg("'%s': unrecognized command" % cmd)
|
||||
sys.exit(1)
|
||||
|
||||
if not g.quiet:
|
||||
if not opt.quiet:
|
||||
msg("Checking dependencies for '%s'" % (cmd))
|
||||
|
||||
check_needs_rerun(ts,cmd,build=False)
|
||||
|
|
@ -603,8 +601,8 @@ def clean(dirs=[]):
|
|||
ts = MMGenTestSuite()
|
||||
dirlist = ts.list_tmp_dirs()
|
||||
if not dirs: dirs = dirlist.keys()
|
||||
for d in dirs:
|
||||
if d in sorted(dirlist):
|
||||
for d in sorted(dirs):
|
||||
if d in dirlist:
|
||||
cleandir(dirlist[d])
|
||||
else:
|
||||
msg("%s: invalid directory number" % d)
|
||||
|
|
@ -741,7 +739,7 @@ class MMGenTestSuite(object):
|
|||
self.txcreate_common(name,sources=['1'])
|
||||
|
||||
def txcreate_common(self,name,sources=['1'],non_mmgen_input=''):
|
||||
if g.verbose or g.exact_output:
|
||||
if opt.verbose or opt.exact_output:
|
||||
sys.stderr.write(green("Generating fake transaction info\n"))
|
||||
silence()
|
||||
from mmgen.addr import AddrInfo,AddrInfoList
|
||||
|
|
@ -784,11 +782,11 @@ class MMGenTestSuite(object):
|
|||
|
||||
for num in tx_data: cmd_args += [tx_data[num]['addrfile']]
|
||||
|
||||
env["MMGEN_BOGUS_WALLET_DATA"] = unspent_data_file
|
||||
os.environ["MMGEN_BOGUS_WALLET_DATA"] = unspent_data_file
|
||||
end_silence()
|
||||
if g.verbose or g.exact_output: sys.stderr.write("\n")
|
||||
if opt.verbose or opt.exact_output: sys.stderr.write("\n")
|
||||
|
||||
t = MMGenExpect(name,"mmgen-txcreate",cmd_args,env)
|
||||
t = MMGenExpect(name,"mmgen-txcreate",cmd_args)
|
||||
t.license()
|
||||
for num in tx_data.keys():
|
||||
t.expect_getend("Getting address data from file ")
|
||||
|
|
@ -871,7 +869,7 @@ class MMGenTestSuite(object):
|
|||
def export_incog_hidden(self,name,walletfile):
|
||||
rf,rd = os.path.join(cfg['tmpdir'],hincog_fn),os.urandom(hincog_bytes)
|
||||
vmsg(green("Writing %s bytes of data to file '%s'" % (hincog_bytes,rf)))
|
||||
write_to_file(rf,rd,{},verbose=g.verbose)
|
||||
write_to_file(rf,rd,verbose=opt.verbose)
|
||||
t = self.export_incog(name,walletfile,args=["-G","%s,%s"%(rf,hincog_offset)])
|
||||
t.written_to_file("Data",query="")
|
||||
ok()
|
||||
|
|
@ -1033,7 +1031,7 @@ class MMGenTestSuite(object):
|
|||
|
||||
def tool_encrypt_ref(self,name):
|
||||
infn = get_tmpfile_fn(cfg,cfg['tool_enc_ref_infn'])
|
||||
write_to_file(infn,cfg['tool_enc_reftext'],{},silent=True)
|
||||
write_to_file(infn,cfg['tool_enc_reftext'],silent=True)
|
||||
self.tool_encrypt(name,infn)
|
||||
|
||||
# Two deps produced by one prog is broken - TODO
|
||||
|
|
@ -1051,7 +1049,7 @@ class MMGenTestSuite(object):
|
|||
self.tool_decrypt(name,f1,f2)
|
||||
|
||||
# main()
|
||||
if g.pause:
|
||||
if opt.pause:
|
||||
import termios,atexit
|
||||
fd = sys.stdin.fileno()
|
||||
old = termios.tcgetattr(fd)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ pn = os.path.dirname(sys.argv[0])
|
|||
os.chdir(os.path.join(pn,os.pardir))
|
||||
sys.path.__setitem__(0,os.path.abspath(os.curdir))
|
||||
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
from mmgen.util import msg,msg_r,vmsg,vmsg_r,Msg,msgrepr, msgrepr_exit
|
||||
from collections import OrderedDict
|
||||
|
||||
|
|
@ -74,9 +74,7 @@ cfg = {
|
|||
'tmpdir_num': 10,
|
||||
}
|
||||
|
||||
from mmgen.Opts import *
|
||||
help_data = {
|
||||
'prog_name': g.prog_name,
|
||||
opts_data = {
|
||||
'desc': "Test suite for the 'mmgen-tool' utility",
|
||||
'usage':"[options] [command]",
|
||||
'options': """
|
||||
|
|
@ -92,18 +90,15 @@ If no command is given, the whole suite of tests is run.
|
|||
"""
|
||||
}
|
||||
|
||||
opts,cmd_args = parse_opts(sys.argv,help_data)
|
||||
cmd_args = opt.opts.init(opts_data,add_opts=["exact_output"])
|
||||
|
||||
if 'system' in opts: sys.path.pop(0)
|
||||
if opt.system: sys.path.pop(0)
|
||||
|
||||
env = os.environ
|
||||
|
||||
for k in 'debug','verbose','quiet','exact_output':
|
||||
g.__dict__[k] = True if k in opts else False
|
||||
if opt.debug: opt.verbose = True
|
||||
|
||||
if g.debug: g.verbose = True
|
||||
|
||||
if "list_cmds" in opts:
|
||||
if opt.list_cmds:
|
||||
fs = " {:<{w}} - {}"
|
||||
Msg("Available commands:")
|
||||
w = max([len(i) for i in cmd_data])
|
||||
|
|
@ -114,7 +109,6 @@ if "list_cmds" in opts:
|
|||
sys.exit()
|
||||
|
||||
import binascii
|
||||
import mmgen.config as g
|
||||
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
|
||||
|
|
@ -162,14 +156,14 @@ class MMGenToolTestSuite(object):
|
|||
|
||||
def run_cmd(self,name,tool_args,kwargs="",extra_msg="",silent=False):
|
||||
mmgen_tool = "mmgen-tool"
|
||||
if not 'system' in opts:
|
||||
if not opt.system:
|
||||
mmgen_tool = os.path.join(os.curdir,mmgen_tool)
|
||||
|
||||
sys_cmd = [mmgen_tool, "-d",cfg['tmpdir'], name] + tool_args + kwargs.split()
|
||||
if extra_msg: extra_msg = "(%s)" % extra_msg
|
||||
full_name = " ".join([name]+kwargs.split()+extra_msg.split())
|
||||
if not silent:
|
||||
if g.verbose:
|
||||
if opt.verbose:
|
||||
sys.stderr.write(green("Testing %s\nExecuting " % full_name))
|
||||
sys.stderr.write("%s\n" % cyan(repr(sys_cmd)))
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue