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')
This commit is contained in:
The MMGen Project 2020-02-15 14:32:14 +00:00
commit f805663041
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
2 changed files with 140 additions and 1 deletions

View file

@ -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

View file

@ -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: