Browse Source

new Tool API interface

- provides a convenient interface to selected methods in the mmgen.tool module
- Type `pydoc3 mmgen.tool.tool_api` for available methods and call signatures

## Examples:

### Initialize:

    from mmgen.tool import tool_api
    tool = tool_api()

### Utility methods:

    # Skip user entropy gathering (not recommended)
    tool.usr_randchars = 0

    # Generate a random hex secret:
    hexsec = tool.randhex()

    # Reverse the hex string:
    hexsec_rev = tool.hexreverse(hexsec)

    # Get the HASH160 of the value:
    sec_hash160 = tool.hash160(hexsec)

    # Convert the value to base58 format:
    sec_b58 = tool.hextob58(hexsec)

    # Convert the value to base58 check format:
    sec_b58chk = tool.hextob58chk(hexsec)

    # Convert the byte specification '4G' to an integer:
    four_g = tool.bytespec('4G')

    # Convert the byte specification '4GB' to an integer:
    four_gb = tool.bytespec('4GB')

### Key/address generation:

    # List available coins:
    print(' '.join(tool.coins))

    # Initialize a coin/network pair:
    proto = tool.init_coin('btc','mainnet')

    # Print the available address types for current coin/network, along with a
    # description.  If tool.addrtype is unset, the first-listed will be used:
    tool.print_addrtypes()

    # Set the address type to P2PKH with compressed public key:
    tool.addrtype = 'compressed'

    # Generate the key and address:
    wif = tool.hex2wif(hexsec)
    addr = tool.wif2addr(wif)

    # Generate an LTC regtest Segwit key and address:
    proto = tool.init_coin('ltc','regtest')
    tool.addrtype = 'segwit'
    wif = tool.hex2wif(hexsec)
    addr = tool.wif2addr(wif)

    # Generate a random LTC regtest Bech32 key/address pair:
    tool.addrtype = 'bech32'
    wif,addr = tool.randpair()

### Mnemonic seed phrase generation:

    # Generate an MMGen native mnemonic seed phrase:
    mmgen_seed = tool.hex2mn(hexsec)

    # Generate a BIP39 mnemonic seed phrase:
    bip39_seed = tool.hex2mn(hexsec,fmt='bip39')
The MMGen Project 5 years ago
parent
commit
f805663041
2 changed files with 140 additions and 1 deletions
  1. 113 0
      mmgen/tool.py
  2. 27 1
      test/tooltest2.py

+ 113 - 0
mmgen/tool.py

@@ -1087,3 +1087,116 @@ class MMGenToolCmd(
 		MMGenToolCmdRPC,
 		MMGenToolCmdMonero,
 	): pass
+
+class tool_api(
+		MMGenToolCmdUtil,
+		MMGenToolCmdCoin,
+		MMGenToolCmdMnemonic,
+	):
+	"""
+	API providing access to a subset of methods from the mmgen.tool module
+
+	Example:
+		from mmgen.tool import tool_api
+		tool = tool_api()
+
+		# Set the coin and network:
+		tool.init_coin('btc','mainnet')
+
+		# Print available address types:
+		tool.print_addrtypes()
+
+		# Set the address type:
+		tool.addrtype = 'segwit'
+
+		# Disable user entropy gathering (optional, reduces security):
+		tool.usr_randchars = 0
+
+		# Generate a random BTC segwit keypair:
+		wif,addr = tool.randpair()
+
+		# Set coin, network and address type:
+		tool.init_coin('ltc','testnet')
+		tool.addrtype = 'bech32'
+
+		# Generate a random LTC testnet Bech32 keypair:
+		wif,addr = tool.randpair()
+	"""
+
+	def __init__(self):
+		"""
+		Initializer - takes no arguments
+		"""
+		if not hasattr(opt,'version'):
+			opts.init({'text': { 'desc': '', 'usage':'', 'options':'' }})
+		opt.use_old_ed25519 = None
+		opt.type = None
+
+	def init_coin(self,coinsym,network):
+		"""
+		Initialize a coin/network pair
+		Valid choices for coins: one of the symbols returned by the 'coins' attribute
+		Valid choices for network: 'mainnet','testnet','regtest'
+		"""
+		from mmgen.protocol import init_coin,init_genonly_altcoins
+		init_genonly_altcoins(coinsym)
+		if network == 'regtest':
+			g.regtest = True
+		return init_coin(coinsym,{'mainnet':False,'testnet':True,'regtest':True}[network])
+
+	@property
+	def coins(self):
+		"""The available coins"""
+		from mmgen.protocol import CoinProtocol
+		from mmgen.altcoin import CoinInfo
+		return sorted(set(CoinProtocol.list_coins() + [c.symbol for c in CoinInfo.get_supported_coins(g.network)]))
+
+	@property
+	def coin(self):
+		"""The currently configured coin"""
+		return g.coin
+
+	@property
+	def network(self):
+		"""The currently configured network"""
+		if g.network == 'testnet':
+			return ('testnet','regtest')[g.regtest]
+		else:
+			return g.network
+
+	@property
+	def addrtypes(self):
+		"""
+		The available address types for current coin/network pair.  The
+		first-listed is the default
+		"""
+		return [MMGenAddrType(t).name for t in g.proto.mmtypes]
+
+	def print_addrtypes(self):
+		"""
+		Print the available address types for current coin/network pair along with
+		a description.  The first-listed is the default
+		"""
+		for t in [MMGenAddrType(s) for s in g.proto.mmtypes]:
+			print('{:<12} - {}'.format(t.name,t.desc))
+
+	@property
+	def addrtype(self):
+		"""The currently configured address type (is assignable)"""
+		return opt.type
+
+	@addrtype.setter
+	def addrtype(self,val):
+		opt.type = val
+
+	@property
+	def usr_randchars(self):
+		"""
+		The number of keystrokes of entropy to be gathered from the user.
+		Setting to zero disables user entropy gathering.
+		"""
+		return opt.usr_randchars
+
+	@usr_randchars.setter
+	def usr_randchars(self,val):
+		opt.usr_randchars = val

+ 27 - 1
test/tooltest2.py

@@ -55,6 +55,7 @@ opts_data = {
 		'usage':'[options] [command]...',
 		'options': """
 -h, --help           Print this help message
+-A, --tool-api       Test the tool_api subsystem
 -C, --coverage       Produce code coverage info using trace module
 -d, --die-on-missing Abort if no test data found for given command
 --, --longhelp       Print help message for long options (common options)
@@ -834,13 +835,34 @@ def run_test(gid,cmd_name):
 			opt.quiet = oq_save
 			return ret
 
+	def tool_api(cmd_name,args,out,opts,exec_code):
+		from mmgen.tool import tool_api
+		tool = tool_api()
+		if opts:
+			for o in opts:
+				if o.startswith('--type='):
+					tool.addrtype = o.split('=')[1]
+		pargs,kwargs = [],{}
+		for a in args:
+			if '=' in a:
+				a1,a2 = a.split('=')
+				kwargs[a1] = int(a2) if is_int(a2) else a2
+			else:
+				pargs.append(a)
+		return getattr(tool,cmd_name)(*pargs,**kwargs)
+
 	for d in data:
 		args,out,opts,exec_code = d + tuple([None] * (4-len(d)))
 		stdin_input = None
 		if args and type(args[0]) == bytes:
 			stdin_input = args[0]
 			args[0] = '-'
-		if opt.fork:
+
+		if opt.tool_api:
+			if args and args[0 ]== '-':
+				continue
+			cmd_out = tool_api(cmd_name,args,out,opts,exec_code)
+		elif opt.fork:
 			cmd_out = fork_cmd(cmd_name,args,out,opts,exec_code)
 		else:
 			if stdin_input and g.platform == 'win':
@@ -923,6 +945,10 @@ sys.argv = [sys.argv[0]] + ['--skip-cfg-file'] + sys.argv[1:]
 
 cmd_args = opts.init(opts_data,add_opts=['use_old_ed25519'])
 
+if opt.tool_api:
+	del tests['Wallet']
+	del tests['File']
+
 import mmgen.tool as tool
 
 if opt.list_tests: