accounts-index

Accounts index evm contract tooling with permissioned writes
Log | Files | Refs

commit 4060101b29866d38d6f99e7f20803c17e3110bb3
parent 308fcd727fff4697d8fe8ce092eeae38defc4255
Author: nolash <dev@holbrook.no>
Date:   Fri, 30 Jul 2021 07:27:36 +0200

Implement chainlib cli util

Diffstat:
Mpython/eth_accounts_index/runnable/add.py | 119+++++++++++++++++++++++++++----------------------------------------------------
Mpython/eth_accounts_index/runnable/deploy.py | 92++++++++++++++++++++-----------------------------------------------------------
Mpython/eth_accounts_index/runnable/list.py | 74++++++++++++++++++++++++++++++--------------------------------------------
Mpython/eth_accounts_index/runnable/writer.py | 132+++++++++++++++++++++++++++----------------------------------------------------
Mpython/requirements.txt | 4++--
Mpython/setup.cfg | 2+-
6 files changed, 141 insertions(+), 282 deletions(-)

diff --git a/python/eth_accounts_index/runnable/add.py b/python/eth_accounts_index/runnable/add.py @@ -12,20 +12,12 @@ import argparse import logging import sys -# third-party imports -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore.dict import DictKeystore +# external imports +import chainlib.eth.cli from chainlib.chain import ChainSpec -from chainlib.eth.nonce import ( - RPCNonceOracle, - OverrideNonceOracle, - ) -from chainlib.eth.gas import ( - RPCGasOracle, - OverrideGasOracle, - ) from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.tx import receipt +from chainlib.eth.address import to_checksum_address # local imports from eth_accounts_index.registry import AccountRegistry @@ -33,87 +25,56 @@ from eth_accounts_index.registry import AccountRegistry logging.basicConfig(level=logging.WARNING) logg = logging.getLogger() -script_dir = os.path.dirname(__file__) -data_dir = os.path.join(script_dir, '..', 'data') - -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed') -argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string') -argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') -argparser.add_argument('-a', '--contract-address', dest='a', required=True, type=str, help='Contract address to account index to edit') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -argparser.add_argument('-d', action='store_true', help='Dump RPC calls to terminal and do not send') -argparser.add_argument('--gas-price', type=int, dest='gas_price', help='Override gas price') -argparser.add_argument('--nonce', type=int, help='Override transaction nonce') -argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') -argparser.add_argument('address', type=str, help='Address to add') +arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) +argparser.add_positional('address', type=str, help='Address to add to registry') args = argparser.parse_args() -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) +extra_args = { + 'address': None, + } +config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=AccountRegistry.gas()) -block_last = args.w -block_all = args.ww +wallet = chainlib.eth.cli.Wallet() +wallet.from_config(config) -passphrase_env = 'ETH_PASSPHRASE' -if args.env_prefix != None: - passphrase_env = args.env_prefix + '_' + passphrase_env -passphrase = os.environ.get(passphrase_env) -if passphrase == None: - logg.warning('no passphrase given') - passphrase='' +rpc = chainlib.eth.cli.Rpc(wallet=wallet) +conn = rpc.connect_by_config(config) -signer_address = None -keystore = DictKeystore() -if args.y != None: - logg.debug('loading keystore file {}'.format(args.y)) - signer_address = keystore.import_keystore_file(args.y, password=passphrase) - logg.debug('now have key for signer address {}'.format(signer_address)) -signer = EIP155Signer(keystore) +chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) -chain_spec = ChainSpec.from_chain_str(args.i) -rpc = EthHTTPConnection(args.p) +def main(): + signer = rpc.get_signer() + signer_address = rpc.get_sender_address() -nonce_oracle = None -if args.nonce != None: - nonce_oracle = OverrideNonceOracle(signer_address, args.nonce) -else: - nonce_oracle = RPCNonceOracle(signer_address, rpc) + gas_oracle = rpc.get_gas_oracle() + nonce_oracle = rpc.get_nonce_oracle() -gas_oracle = None -if args.gas_price !=None: - gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=AccountRegistry.gas) -else: - gas_oracle = RPCGasOracle(rpc, code_callback=AccountRegistry.gas) + subject_address = to_checksum_address(config.get('_ADDRESS')) + if not config.true('_UNSAFE') and subject_address != add_0x(config.get('_ADDRESS')): + raise ValueError('invalid checksum address for subject_address') -dummy = args.d -contract_address = args.a -account = args.address + contract_address = to_checksum_address(config.get('_EXEC_ADDRESS')) + if not config.true('_UNSAFE') and contract_address != add_0x(config.get('_EXEC_ADDRESS')): + raise ValueError('invalid checksum address for contract') -def main(): - if __name__ == '__main__': - c = AccountRegistry(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) - (tx_hash_hex, o) = c.add(contract_address, signer_address, account) - if dummy: - print(tx_hash_hex) - print(o) - else: - rpc.do(o) - r = rpc.wait(tx_hash_hex) - if block_last: - if r['status'] == 0: - sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you') - sys.exit(1) - - print(tx_hash_hex) + c = AccountRegistry(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) + (tx_hash_hex, o) = c.add(contract_address, signer_address, subject_address) + + if config.get('_RPC_SEND'): + conn.do(o) + if config.get('_WAIT'): + r = conn.wait(tx_hash_hex) + if r['status'] == 0: + sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you') + sys.exit(1) + + print(tx_hash_hex) + else: + print(o) if __name__ == '__main__': diff --git a/python/eth_accounts_index/runnable/deploy.py b/python/eth_accounts_index/runnable/deploy.py @@ -12,18 +12,9 @@ import json import argparse import logging -# third-party imports -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore.dict import DictKeystore +# external imports +import chainlib.eth.cli from chainlib.chain import ChainSpec -from chainlib.eth.nonce import ( - RPCNonceOracle, - OverrideNonceOracle, - ) -from chainlib.eth.gas import ( - RPCGasOracle, - OverrideGasOracle, - ) from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.tx import receipt @@ -33,75 +24,36 @@ from eth_accounts_index.registry import AccountRegistry logging.basicConfig(level=logging.WARNING) logg = logging.getLogger() -script_dir = os.path.dirname(__file__) -data_dir = os.path.join(script_dir, '..', 'data') - -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed') -argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string') -argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -argparser.add_argument('-d', action='store_true', help='Dump RPC calls to terminal and do not send') -argparser.add_argument('--gas-price', type=int, dest='gas_price', help='Override gas price') -argparser.add_argument('--nonce', type=int, help='Override transaction nonce') -argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') +arg_flags = chainlib.eth.cli.argflag_std_write +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) args = argparser.parse_args() -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) +config = chainlib.eth.cli.Config.from_args(args, arg_flags, default_fee_limit=AccountRegistry.gas()) -block_all = args.ww -block_last = args.w or block_all +wallet = chainlib.eth.cli.Wallet() +wallet.from_config(config) -passphrase_env = 'ETH_PASSPHRASE' -if args.env_prefix != None: - passphrase_env = args.env_prefix + '_' + passphrase_env -passphrase = os.environ.get(passphrase_env) -if passphrase == None: - logg.warning('no passphrase given') - passphrase='' +rpc = chainlib.eth.cli.Rpc(wallet=wallet) +conn = rpc.connect_by_config(config) -signer_address = None -keystore = DictKeystore() -if args.y != None: - logg.debug('loading keystore file {}'.format(args.y)) - signer_address = keystore.import_keystore_file(args.y, password=passphrase) - logg.debug('now have key for signer address {}'.format(signer_address)) -signer = EIP155Signer(keystore) +chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) -chain_spec = ChainSpec.from_chain_str(args.i) -rpc = EthHTTPConnection(args.p) -nonce_oracle = None -if args.nonce != None: - nonce_oracle = OverrideNonceOracle(signer_address, args.nonce) -else: - nonce_oracle = RPCNonceOracle(signer_address, rpc) - -gas_oracle = None -if args.gas_price !=None: - gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=AccountRegistry.gas) -else: - gas_oracle = RPCGasOracle(rpc, code_callback=AccountRegistry.gas) - -dummy = args.d +def main(): + signer = rpc.get_signer() + signer_address = rpc.get_sender_address() + gas_oracle = rpc.get_gas_oracle() + nonce_oracle = rpc.get_nonce_oracle() -def main(): c = AccountRegistry(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) + (tx_hash_hex, o) = c.constructor(signer_address) - if dummy: - print(tx_hash_hex) - print(o) - else: - rpc.do(o) - if block_last: - r = rpc.wait(tx_hash_hex) + + if config.get('_RPC_SEND'): + conn.do(o) + if config.get('_WAIT'): + r = conn.wait(tx_hash_hex) if r['status'] == 0: sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you') sys.exit(1) @@ -111,6 +63,8 @@ def main(): print(address) else: print(tx_hash_hex) + else: + print(o) if __name__ == '__main__': diff --git a/python/eth_accounts_index/runnable/list.py b/python/eth_accounts_index/runnable/list.py @@ -12,12 +12,9 @@ import json import argparse import logging -# third-party imports -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore.dict import DictKeystore +# external imports +import chainlib.eth.cli from chainlib.chain import ChainSpec -from chainlib.eth.nonce import RPCNonceOracle -from chainlib.eth.gas import RPCGasOracle from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.tx import receipt from chainlib.eth.constant import ZERO_CONTENT @@ -25,73 +22,62 @@ from chainlib.error import JSONRPCException # local imports from eth_accounts_index import AccountsIndex +from eth_accounts_index.registry import AccountRegistry logging.basicConfig(level=logging.WARNING) logg = logging.getLogger() -script_dir = os.path.dirname(__file__) -data_dir = os.path.join(script_dir, '..', 'data') - -default_format = 'terminal' - -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='RPC provider url (http only)') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string') -argparser.add_argument('-a', '--contract-address', dest='a', required=True, type=str, help='Contract address') -argparser.add_argument('-f', '--format', dest='f', type=str, default=default_format, help='Output format [human, brief]') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') -argparser.add_argument('address', type=str, nargs='?', help='Address to check registration for') +arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) +argparser.add_positional('address', required=False, type=str, help='Check only whether given address is in registry') args = argparser.parse_args() -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) +extra_args = { + 'address': None, + } +config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=AccountRegistry.gas()) -chain_spec = ChainSpec.from_chain_str(args.i) +wallet = chainlib.eth.cli.Wallet() +wallet.from_config(config) -rpc = EthHTTPConnection(args.p) -account_registry_address = args.a -address = args.address -fmt = args.f +rpc = chainlib.eth.cli.Rpc(wallet=wallet) +conn = rpc.connect_by_config(config) +chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) -def out_element(e, fmt=default_format, w=sys.stdout): - logg.debug('format {}'.format(fmt)) - if fmt == 'brief': - w.write(str(e[1]) + '\n') - else: - w.write('{} {}\n'.format(e[0], e[1])) + +def out_element(e, w=sys.stdout): + w.write(str(e[1]) + '\n') -def element(ifc, address, fmt=default_format, w=sys.stdout): - o = ifc.have(account_registry_address, address) - r = rpc.do(o) +def element(ifc, conn, contract_address, address, w=sys.stdout): + o = ifc.have(contract_address, address) + r = conn.do(o) have = ifc.parse_have(r) - out_element((address, have), fmt, w) + out_element((0, address), w) -def ls(ifc, fmt=default_format, w=sys.stdout): +def ls(ifc, conn, contract_address, w=sys.stdout): i = 0 while True: - o = ifc.entry(account_registry_address, i) + o = ifc.entry(contract_address, i) try: - r = rpc.do(o) + r = conn.do(o) account = ifc.parse_account(r) - out_element((i, account), fmt, w) + out_element((i, account), w) i += 1 except JSONRPCException as e: break def main(): + address = config.get('_ADDRESS') + contract_address = config.get('_EXEC_ADDRESS') c = AccountsIndex(chain_spec) if address != None: - element(c, address, fmt=fmt, w=sys.stdout) + element(c, conn, contract_address, address, w=sys.stdout) else: - ls(c, fmt=fmt, w=sys.stdout) + ls(c, conn, contract_address, w=sys.stdout) if __name__ == '__main__': diff --git a/python/eth_accounts_index/runnable/writer.py b/python/eth_accounts_index/runnable/writer.py @@ -12,20 +12,12 @@ import argparse import logging import sys -# third-party imports -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore.dict import DictKeystore +# external imports +import chainlib.eth.cli from chainlib.chain import ChainSpec -from chainlib.eth.nonce import ( - RPCNonceOracle, - OverrideNonceOracle, - ) -from chainlib.eth.gas import ( - RPCGasOracle, - OverrideGasOracle, - ) from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.tx import receipt +from chainlib.eth.address import to_checksum_address # local imports from eth_accounts_index.registry import AccountRegistry @@ -33,94 +25,60 @@ from eth_accounts_index.registry import AccountRegistry logging.basicConfig(level=logging.WARNING) logg = logging.getLogger() -script_dir = os.path.dirname(__file__) -data_dir = os.path.join(script_dir, '..', 'data') - -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed') -argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string') -argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') -argparser.add_argument('-a', '--contract-address', dest='a', required=True, type=str, help='Contract address to account index to edit') -argparser.add_argument('--delete', action='store_true', help='Delete address') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -argparser.add_argument('-d', action='store_true', help='Dump RPC calls to terminal and do not send') -argparser.add_argument('--gas-price', type=int, dest='gas_price', help='Override gas price') -argparser.add_argument('--nonce', type=int, help='Override transaction nonce') -argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration') -argparser.add_argument('address', type=str, help='Subject address') +arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) +argparser.add_argument('--rm', action='store_true', help='Delete entry') +argparser.add_positional('address', type=str, help='Update writer array with this address') args = argparser.parse_args() -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) - -block_last = args.w -block_all = args.ww - -passphrase_env = 'ETH_PASSPHRASE' -if args.env_prefix != None: - passphrase_env = args.env_prefix + '_' + passphrase_env -passphrase = os.environ.get(passphrase_env) -if passphrase == None: - logg.warning('no passphrase given') - passphrase='' - -signer_address = None -keystore = DictKeystore() -if args.y != None: - logg.debug('loading keystore file {}'.format(args.y)) - signer_address = keystore.import_keystore_file(args.y, password=passphrase) - logg.debug('now have key for signer address {}'.format(signer_address)) -signer = EIP155Signer(keystore) - -chain_spec = ChainSpec.from_chain_str(args.i) - -rpc = EthHTTPConnection(args.p) -nonce_oracle = None -if args.nonce != None: - nonce_oracle = OverrideNonceOracle(signer_address, args.nonce) -else: - nonce_oracle = RPCNonceOracle(signer_address, rpc) - -gas_oracle = None -if args.gas_price !=None: - gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=AccountRegistry.gas) -else: - gas_oracle = RPCGasOracle(rpc, code_callback=AccountRegistry.gas) - -dummy = args.d - -contract_address = args.a -address = args.address -delete = False -if args.delete: - delete = True +extra_args = { + 'rm': None, + 'address': None, + } +config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=AccountRegistry.gas()) + +wallet = chainlib.eth.cli.Wallet() +wallet.from_config(config) + +rpc = chainlib.eth.cli.Rpc(wallet=wallet) +conn = rpc.connect_by_config(config) + +chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) def main(): + signer = rpc.get_signer() + signer_address = rpc.get_sender_address() + + gas_oracle = rpc.get_gas_oracle() + nonce_oracle = rpc.get_nonce_oracle() + c = AccountRegistry(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) - tx_hash_hex = None - o = None - if delete: - (tx_hash_hex, o) = c.delete_writer(contract_address, signer_address, address) - else: - (tx_hash_hex, o) = c.add_writer(contract_address, signer_address, address) - if dummy: - print(tx_hash_hex) - print(o) + + subject_address = to_checksum_address(config.get('_ADDRESS')) + if not config.true('_UNSAFE') and subject_address != add_0x(config.get('_ADDRESS')): + raise ValueError('invalid checksum address for subject_address') + + + contract_address = to_checksum_address(config.get('_EXEC_ADDRESS')) + if not config.true('_UNSAFE') and contract_address != add_0x(config.get('_EXEC_ADDRESS')): + raise ValueError('invalid checksum address for contract') + + if config.get('_RM'): + (tx_hash_hex, o) = c.delete_writer(contract_address, signer_address, subject_address) else: - rpc.do(o) - r = rpc.wait(tx_hash_hex) - if block_last: + (tx_hash_hex, o) = c.add_writer(contract_address, signer_address, subject_address) + if config.get('_RPC_SEND'): + conn.do(o) + if config.get('_WAIT'): + r = conn.wait(tx_hash_hex) if r['status'] == 0: sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you') sys.exit(1) print(tx_hash_hex) + else: + print(o) if __name__ == '__main__': diff --git a/python/requirements.txt b/python/requirements.txt @@ -1,3 +1,3 @@ confini>=0.3.6rc3,<0.5.0 -chainlib-eth~=0.0.5a2 -crypto-dev-signer~=0.4.14b7 +chainlib-eth>=0.0.7a4,<=0.1.0 +crypto-dev-signer>=0.4.14b7,<=0.4.14 diff --git a/python/setup.cfg b/python/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = eth-accounts-index -version = 0.0.12a2 +version = 0.1.1a1 description = Accounts index evm contract tooling with permissioned writes author = Louis Holbrook author_email = dev@holbrook.no