Browse Source

Version 0.8.7a

  --testnet option added to all relevant scripts
  utility scripts under scripts/ updated
philemon 8 years ago
parent
commit
3897ec3297

+ 6 - 0
MANIFEST.in

@@ -2,4 +2,10 @@ include README.md SIGNING_KEY.pub LICENSE INSTALL
 include doc/wiki/using-mmgen/*
 include test/*.py
 include test/ref/*
+
+include scripts/bitcoind-walletunlock.py
+include scripts/compute-file-chksum.py
+include scripts/deinstall.sh
+include scripts/tx-old2new.py
+
 prune test/ref/__db*

+ 11 - 5
mmgen/globalvars.py

@@ -20,6 +20,9 @@
 globalvars.py:  Constants and configuration options for the MMGen suite
 """
 
+version      = '0.8.7a'
+release_date = 'November 2016'
+
 import sys,os
 
 # Variables - these might be altered at runtime:
@@ -53,12 +56,11 @@ prog_name = os.path.basename(sys.argv[0])
 author    = 'Philemon'
 email     = '<mmgen-py@yandex.com>'
 Cdates    = '2013-2016'
-version   = '0.8.7'
 
 required_opts = [
-	'quiet','verbose','debug','outdir','echo_passphrase','passwd_file',
-	'usr_randchars','stdout','show_hash_presets','label',
-	'keep_passphrase','keep_hash_preset','brain_params','b16'
+	'quiet','verbose','debug','outdir','echo_passphrase','passwd_file','stdout',
+	'show_hash_presets','label','keep_passphrase','keep_hash_preset',
+	'brain_params','b16','usr_randchars'
 ]
 incompatible_opts = (
 	('quiet','verbose'),
@@ -71,9 +73,13 @@ incompatible_opts = (
 min_screen_width = 80
 minconf = 1
 
-# Global value sets user opt
+# Global var sets user opt:
 dfl_vars = 'minconf','seed_len','hash_preset','usr_randchars','debug','tx_confs','tx_fee_adj','tx_fee','key_generator'
 
+# User opt sets global var:
+usr_sets_global = ['testnet']
+required_opts += usr_sets_global
+
 keyconv_exec = 'keyconv'
 
 mins_per_block   = 9

+ 2 - 1
mmgen/main_addrgen.py

@@ -34,7 +34,7 @@ By default, both addresses and secret keys are generated.
 """.strip()
 else:
 	gen_what = 'addresses'
-	opt_filter = 'hbcdeiHOKlpzPqSv'
+	opt_filter = 'hbcdeiHOKlpzPqSv-'
 	note1 = """
 If available, the external 'keyconv' program will be used for address
 generation.
@@ -66,6 +66,7 @@ opts_data = {
 -P, --passwd-file= f  Get wallet passphrase from file 'f'.
 -q, --quiet           Produce quieter output; suppress some warnings.
 -S, --stdout          Print {what} to stdout.
+--, --testnet         Generate testnet keys/addresses instead of mainnet ones
 -v, --verbose         Produce more verbose output.
 -x, --b16             Print secret keys in hexadecimal too.
 """.format(

+ 1 - 0
mmgen/main_addrimport.py

@@ -41,6 +41,7 @@ opts_data = {
 -r, --rescan       Rescan the blockchain.  Required if address to import is
                    on the blockchain and has a balance.  Rescanning is slow.
 -t, --test         Simulate operation; don't actually import addresses
+--, --testnet      Use Bitcoin testnet instead of mainnet
 """,
 	'notes': """\n
 This command can also be used to update the comment fields of addresses already

+ 1 - 0
mmgen/main_tool.py

@@ -34,6 +34,7 @@ opts_data = {
 -q, --quiet           Produce quieter output
 -r, --usr-randchars=n Get 'n' characters of additional randomness from
                       user (min={g.min_urandchars}, max={g.max_urandchars})
+--, --testnet         Use Bitcoin testnet instead of mainnet
 -v, --verbose         Produce more verbose output
 """.format(g=g),
 	'notes': """

+ 2 - 1
mmgen/main_txcreate.py

@@ -33,14 +33,15 @@ opts_data = {
 	'options': """
 -h, --help            Print this help message
 -a, --tx-fee-adj=   f Adjust transaction fee by factor 'f' (see below)
+-B, --no-blank        Don't blank screen before displaying unspent outputs
 -c, --comment-file= f Source the transaction's comment from file 'f'
 -C, --tx-confs=     c Desired number of confirmations (default: {g.tx_confs})
 -d, --outdir=       d Specify an alternate directory 'd' for output
--e, --clear-screen    Clear screen before displaying unspent outputs
 -f, --tx-fee=       f Transaction fee (default: {g.tx_fee} BTC (but see below))
 -m, --minconf=      n Minimum number of confirmations required to spend outputs (default: 1)
 -i, --info            Display unspent outputs and exit
 -q, --quiet           Suppress warnings; overwrite files without prompting
+--, --testnet         Create transaction for Bitcoin testnet instead of mainnet
 -v, --verbose         Produce more verbose output
 """.format(g=g),
 	'notes': """

+ 1 - 0
mmgen/main_txsend.py

@@ -31,6 +31,7 @@ opts_data = {
 -h, --help      Print this help message
 -d, --outdir= d Specify an alternate directory 'd' for output
 -q, --quiet     Suppress warnings; overwrite files without prompting
+--, --testnet   Use Bitcoin testnet instead of mainnet
 """
 }
 

+ 1 - 0
mmgen/main_txsign.py

@@ -63,6 +63,7 @@ opts_data = {
                       prompting
 -I, --info            Display information about the transaction and exit.
 -t, --terse-info      Like '--info', but produce more concise output.
+--, --testnet         Transaction is for Bitcoin testnet rather than mainnet
 -v, --verbose         Produce more verbose output
 """.format(
 		g=g,pnm=pnm,pnl=pnm.lower(),

+ 3 - 1
mmgen/opts.py

@@ -130,8 +130,10 @@ def init(opts_data,add_opts=[],opt_filter=None):
 			g.required_opts + add_opts + skipped_opts:
 		setattr(opt,o,uopts[o] if o in uopts else None)
 
-	# A special case - do this here, before opt gets set from g.dfl_vars
+	# User opt sets global var - do these here, before opt gets set from g.dfl_vars
 	if opt.usr_randchars: g.use_urandchars = True
+	for k in g.usr_sets_global:
+		if getattr(opt,k): setattr(g,k,True)
 
 	# If user opt is set, convert its type based on value in mmgen.globalvars (g)
 	# If unset, set it to default value in mmgen.globalvars (g)

+ 1 - 0
mmgen/rpc.py

@@ -152,6 +152,7 @@ class BitcoinRPCConnection(object):
 		'sendrawtransaction',
 		'signrawtransaction',
 		'getrawmempool',
+		'walletpassphrase',
 	)
 
 	for name in rpcmethods:

+ 20 - 12
mmgen/share/Opts.py

@@ -21,6 +21,7 @@ Opts.py:  Generic options handling
 """
 
 import sys, getopt
+from mmgen.util import pp_die,pp_msg # DEBUG
 
 def usage(opts_data):
 	print 'USAGE: %s %s' % (opts_data['prog_name'], opts_data['usage'])
@@ -43,26 +44,27 @@ def process_opts(argv,opts_data,short_opts,long_opts):
 	opts_data['prog_name'] = os.path.basename(sys.argv[0])
 	long_opts  = [i.replace('_','-') for i in long_opts]
 
-	try: cl_opts,args = getopt.getopt(argv[1:], short_opts, long_opts)
+#	pp_msg(long_opts) # DEBUG
+	try: cl_opts,args = getopt.getopt(argv[1:], short_opts.replace('-',''), long_opts)
 	except getopt.GetoptError as err:
 		print str(err); sys.exit(2)
 
-	opts,short_opts_l = {},[]
-
-	for i in short_opts:
-		if i == ':': short_opts_l[-1] += i
-		else:        short_opts_l     += i
+	sopts_list = ':_'.join(['_'.join(list(i)) for i in short_opts.split(':')]).split('_')
+	opts = {}
 
+#	pp_msg(cl_opts) # DEBUG
+#	pp_msg(sopts_list) # DEBUG
+#	pp_die(args)
 	for opt, arg in cl_opts:
 		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:
 			opts[opt[2:].replace('-','_')] = arg
-		elif opt[0] == '-' and opt[1]     in short_opts_l:
-			opts[long_opts[short_opts_l.index(opt[1:])].replace('-','_')] = True
-		elif opt[0] == '-' and opt[1:]+':' in short_opts_l:
-			opts[long_opts[short_opts_l.index(
+		elif opt[1] != '-' and opt[1] in sopts_list:
+			opts[long_opts[sopts_list.index(opt[1:])].replace('-','_')] = True
+		elif opt[1] != '-' and opt[1:]+':' in sopts_list:
+			opts[long_opts[sopts_list.index(
 					opt[1:]+':')][:-1].replace('-','_')] = arg
 		else: assert False, 'Invalid option'
 
@@ -87,7 +89,7 @@ def process_opts(argv,opts_data,short_opts,long_opts):
 def parse_opts(argv,opts_data,opt_filter=None):
 
 	import re
-	pat = r'^-([a-zA-Z0-9]), --([a-zA-Z0-9-]{2,64})(=| )(.+)'
+	pat = r'^-([a-zA-Z0-9-]), --([a-zA-Z0-9-]{2,64})(=| )(.+)'
 	od,skip = [],True
 
 	for l in opts_data['options'].strip().splitlines():
@@ -100,12 +102,18 @@ def parse_opts(argv,opts_data,opt_filter=None):
 			if not skip: od[-1][3] += '\n' + l
 
 	opts_data['options'] = '\n'.join(
-		['-{}, --{} {}'.format(d[0],d[1],d[3]) for d in od if d[6] == False]
+		['{:<3} --{} {}'.format(
+			('-'+d[0]+',','')[d[0]=='-'],d[1],d[3]) for d in od if d[6] == False]
 	)
+#	print opts_data['options']; sys.exit() # DEBUG
+# 	pp_die(od) # DEBUG
 	short_opts    = ''.join([d[0]+d[4] for d in od if d[6] == False])
 	long_opts     = [d[1].replace('-','_')+d[5] for d in od if d[6] == False]
 	skipped_opts  = [d[1].replace('-','_') for d in od if d[6] == True]
+#	pp_die(short_opts) # DEBUG
+#	pp_msg(long_opts) # DEBUG
 
 	opts,args = process_opts(argv,opts_data,short_opts,long_opts)
+#	pp_die(opts) # DEBUG
 
 	return opts,args,short_opts,long_opts,skipped_opts

+ 1 - 1
mmgen/tw.py

@@ -123,7 +123,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 			my_raw_input(m1+'\n'+m2.format(g.min_screen_width))
 
 	def display(self):
-		if opt.clear_screen: msg(CUR_HOME+ERASE_ALL)
+		if not opt.no_blank: msg(CUR_HOME+ERASE_ALL)
 		msg(self.format_for_display())
 
 	def format_for_display(self):

+ 10 - 31
scripts/bitcoind-walletunlock.py

@@ -19,43 +19,22 @@
 bitcoind-walletunlock.py: Unlock a Bitcoin wallet securely
 """
 
-import sys
-from mmgen.Opts import *
-from mmgen.tx import *
-from mmgen.util import msg, my_getpass, my_raw_input
+import sys,getpass
+from mmgen.common import *
 
-prog_name = sys.argv[0].split("/")[-1]
-
-help_data = {
-	'prog_name': prog_name,
+opts_data = {
+	'prog_name': sys.argv[0].split('/')[-1],
 	'desc':    "Unlock a Bitcoin wallet securely",
 	'usage':   "[opts]",
 	'options': """
--h, --help                 Print this help message
--e, --echo-passphrase      Print passphrase to screen when typing it
+-h, --help              Print this help message
+-e, --echo-passphrase   Print passphrase to screen when typing it
+--, --testnet           Use testnet instead of mainnet
 """
 }
 
-short_opts = "he"
-long_opts  = "help","echo_passphrase"
-
-opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
-
-c = connect_to_bitcoind()
-
-prompt = "Enter passphrase: "
-if 'echo_passphrase' in opts:
-	password = my_raw_input(prompt)
-else:
-	password = my_getpass(prompt)
+cmd_args = opts.init(opts_data)
 
-from bitcoinrpc import exceptions
+password = (getpass.getpass,raw_input)[bool(opt.echo_passphrase)]('Enter passphrase: ')
 
-try:
-	c.walletpassphrase(password, 9999)
-except exceptions.WalletWrongEncState:
-	msg("Wallet is unencrypted")
-except exceptions.WalletPassphraseIncorrect:
-	msg("Passphrase incorrect")
-except exceptions.WalletAlreadyUnlocked:
-	msg("WARNING: Wallet already unlocked!")
+bitcoin_connection().walletpassphrase(password, 9999); msg('OK')

+ 2 - 2
scripts/compute-file-chksum.py

@@ -1,7 +1,6 @@
 #!/usr/bin/env python
 
 from mmgen.common import *
-from mmgen.util import *
 
 opts_data = {
 	'desc': 'Compute checksum for a MMGen data file',
@@ -19,5 +18,6 @@ start = (1,0)[bool(opt.include_first_line)]
 a = make_chksum_6(' '.join(lines[start:]))
 if start == 1:
 	b = lines[0]
-	msg(("Checksum in file (%s) doesn't match computed value!" % b,"Checksum in file OK")[a==b])
+	m = ("Checksum in file (%s) doesn't match computed value!" % b,'Checksum in file OK')[a==b]
+	msg(m)
 Msg(a)

+ 6 - 4
scripts/deinstall.sh

@@ -1,7 +1,9 @@
 #!/bin/bash
 
-CMD='rm -r /usr/local/bin/mmgen-* /usr/local/lib/python2.7/dist-packages/mmgen*'
+CMD='rm -rf /usr/local/bin/mmgen-* /usr/local/lib/python2.7/dist-packages/mmgen*'
 
-set -x
-
-if [ "$EUID" = 0 ]; then $CMD; else sudo $CMD; fi
+if [ "$EUID" = 0 ]; then
+	set -x; $CMD
+else
+	set -x; sudo $CMD
+fi

+ 3 - 2
setup.py

@@ -42,10 +42,11 @@ module1 = Extension(
 	include_dirs = ['/usr/local/include'],
 	)
 
+from mmgen.globalvars import version
 setup(
 		name         = 'mmgen',
 		description  = 'A complete Bitcoin offline/online wallet solution for the command line',
-		version      = '0.8.7',
+		version      = version,
 		author       = 'Philemon',
 		author_email = 'mmgen-py@yandex.com',
 		url          = 'https://github.com/mmgen/mmgen',
@@ -100,6 +101,6 @@ setup(
 			'mmgen-txcreate',
 			'mmgen-txsign',
 			'mmgen-txsend',
-			'mmgen-tool',
+			'mmgen-tool'
 		]
 	)

+ 2 - 1
test/gentest.py

@@ -39,8 +39,9 @@ opts_data = {
 	'usage':'[options] [spec] [rounds | dump file]',
 	'options': """
 -h, --help         Print this help message
--v, --verbose      Produce more verbose output
 -q, --quiet        Produce quieter output
+--, --testnet      Run for testnet rather than mainnet
+-v, --verbose      Produce more verbose output
 """,
 	'notes': """
     Tests:

+ 40 - 35
test/test.py

@@ -45,6 +45,45 @@ sys.path.__setitem__(0,os.path.abspath(os.curdir))
 # Import these _after_ local path's been added to sys.path
 from mmgen.common import *
 from mmgen.test import *
+
+tb_cmd = 'scripts/traceback.py'
+log_file = 'test.py_log'
+
+opts_data = {
+#	'sets': [('non_interactive',bool,'verbose',None)],
+	'desc': 'Test suite for the MMGen suite',
+	'usage':'[options] [command(s) or metacommand(s)]',
+	'options': """
+-h, --help          Print this help message.
+-b, --buf-keypress  Use buffered keypresses as with real human input.
+-d, --debug-scripts Turn on debugging output in executed scripts.
+-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 commands in the test suite.
+-L, --log           Log commands to file {lf}
+-n, --names         Display command names instead of descriptions.
+-I, --non-interactive Non-interactive operation (MS Windows mode)
+-p, --pause         Pause between tests, resuming on keypress.
+-P, --profile       Record the execution time of each script.
+-q, --quiet         Produce minimal output.  Suppress dependency info.
+-r, --resume=c      Resume at command 'c' after interrupted run
+-s, --system        Test scripts and modules installed on system rather
+                    than those in the repo root.
+-S, --skip-deps     Skip dependency checking for command
+-u, --usr-random    Get random data interactively from user
+--, --testnet       Run on testnet rather than mainnet
+-t, --traceback     Run the command inside the '{tb_cmd}' script.
+-v, --verbose       Produce more verbose output.
+""".format(tb_cmd=tb_cmd,lf=log_file),
+	'notes': """
+
+If no command is given, the whole suite of tests is run.
+"""
+}
+
+cmd_args = opts.init(opts_data)
+
 tn_desc = ('','.testnet')[g.testnet]
 
 start_mscolor()
@@ -56,7 +95,6 @@ scripts = (
 	'walletchk', 'walletconv', 'walletgen'
 )
 
-tb_cmd         = 'scripts/traceback.py'
 hincog_fn      = 'rand_data'
 hincog_bytes   = 1024*1024
 hincog_offset  = 98765
@@ -466,41 +504,8 @@ meta_cmds = OrderedDict([
 ])
 
 del cmd_group
-log_file = 'test.py_log'
 
-opts_data = {
-#	'sets': [('non_interactive',bool,'verbose',None)],
-	'desc': 'Test suite for the MMGen suite',
-	'usage':'[options] [command(s) or metacommand(s)]',
-	'options': """
--h, --help          Print this help message.
--b, --buf-keypress  Use buffered keypresses as with real human input.
--d, --debug-scripts Turn on debugging output in executed scripts.
--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 commands in the test suite.
--L, --log           Log commands to file {lf}
--n, --names         Display command names instead of descriptions.
--I, --non-interactive Non-interactive operation (MS Windows mode)
--p, --pause         Pause between tests, resuming on keypress.
--P, --profile       Record the execution time of each script.
--q, --quiet         Produce minimal output.  Suppress dependency info.
--r, --resume=c      Resume at command 'c' after interrupted run
--s, --system        Test scripts and modules installed on system rather
-                    than those in the repo root.
--S, --skip-deps     Skip dependency checking for command
--u, --usr-random    Get random data interactively from user
--t, --traceback     Run the command inside the '{tb_cmd}' script.
--v, --verbose       Produce more verbose output.
-""".format(tb_cmd=tb_cmd,lf=log_file),
-	'notes': """
-
-If no command is given, the whole suite of tests is run.
-"""
-}
-
-cmd_args = opts.init(opts_data)
+if opt.testnet: os.environ['MMGEN_TESTNET'] = '1'
 
 if opt.profile: opt.names = True
 if opt.resume: opt.skip_deps = True

+ 2 - 0
test/tooltest.py

@@ -116,6 +116,7 @@ opts_data = {
 -l, --list-cmds     List and describe the tests and commands in the test suite
 -s, --system        Test scripts and modules installed on system rather than
                     those in the repo root
+--, --testnet       Run on testnet rather than mainnet
 -v, --verbose       Produce more verbose output
 """,
 	'notes': """
@@ -125,6 +126,7 @@ If no command is given, the whole suite of tests is run.
 }
 
 cmd_args = opts.init(opts_data,add_opts=['exact_output','profile'])
+if opt.testnet: os.environ['MMGEN_TESTNET'] = '1'
 
 if opt.system: sys.path.pop(0)