contract-registry

Ethereum Smart Contract key-value registry
Log | Files | Refs

commit c02ad2404db6124eb5f805e427785bb0bfc67d25
parent 3fd2f1d6b78bbb3f3f3d80da8502382ba352b2b6
Author: nolash <dev@holbrook.no>
Date:   Fri, 30 Jul 2021 08:13:47 +0200

Implement chainlib cli util

Diffstat:
Apython/MANIFEST.in | 1+
Mpython/eth_contract_registry/runnable/deploy.py | 108++++++++++++++++++++++---------------------------------------------------------
Mpython/eth_contract_registry/runnable/list.py | 77++++++++++++++++++++++++++++++++++++-----------------------------------------
Mpython/eth_contract_registry/runnable/set.py | 138++++++++++++++++++++++++++++++++-----------------------------------------------
Mpython/requirements.txt | 6+++---
Mpython/setup.cfg | 2+-
6 files changed, 126 insertions(+), 206 deletions(-)

diff --git a/python/MANIFEST.in b/python/MANIFEST.in @@ -0,0 +1 @@ +include *requirements.txt **/data/*.json **/data/*.bin diff --git a/python/eth_contract_registry/runnable/deploy.py b/python/eth_contract_registry/runnable/deploy.py @@ -13,17 +13,8 @@ import argparse import logging # external imports -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore.dict import DictKeystore +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,80 +24,39 @@ from eth_contract_registry.registry import ContractRegistry 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') +arg_flags = chainlib.eth.cli.argflag_std_write +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) argparser.add_argument('--identifier', type=str, action='append', default=[], help='Add contract identifier') -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') args = argparser.parse_args() -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) - -block_all = args.ww -block_last = args.w or block_all - -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=ContractRegistry.gas) -else: - gas_oracle = RPCGasOracle(rpc, code_callback=ContractRegistry.gas) - -dummy = args.d - -identifiers = args.identifier -if 'ContractRegistry' not in identifiers: - identifiers = ['ContractRegistry'] + identifiers -logg.debug('adding identifiers {}'.format(identifiers)) +extra_args = { + 'identifier': None, + } +config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=ContractRegistry.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 = ContractRegistry(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) - (tx_hash_hex, o) = c.constructor(signer_address, identifiers) - if dummy: - print(tx_hash_hex) - print(o) - else: - rpc.do(o) - if block_last: - r = rpc.wait(tx_hash_hex) + (tx_hash_hex, o) = c.constructor(signer_address, config.get('_IDENTIFIER')) + + 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) @@ -116,6 +66,8 @@ def main(): print(address) else: print(tx_hash_hex) + else: + print(o) if __name__ == '__main__': diff --git a/python/eth_contract_registry/runnable/list.py b/python/eth_contract_registry/runnable/list.py @@ -12,16 +12,18 @@ 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 from chainlib.error import JSONRPCException +from chainlib.eth.address import to_checksum_address +from hexathon import ( + add_0x, + strip_0x, + ) # local imports from eth_contract_registry.registry import ContractRegistry @@ -29,58 +31,44 @@ from eth_contract_registry.registry import ContractRegistry 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('-r', '--registry', dest='r', required=True, type=str, help='Contract registry 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') +arg_flags = chainlib.eth.cli.argflag_std_read | chainlib.eth.cli.Flag.EXEC +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) argparser.add_argument('identifier', type=str, nargs='?', help='Token symbol to return address for') args = argparser.parse_args() -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) +extra_args = { + 'identifier': None, + } +config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=ContractRegistry.gas()) -chain_spec = ChainSpec.from_chain_str(args.i) +wallet = chainlib.eth.cli.Wallet() +wallet.from_config(config) -rpc = EthHTTPConnection(args.p) -registry_address = args.r -identifier = args.identifier -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(e[1] + '\n') - else: - w.write('{} {}\n'.format(e[0], e[1])) + +def out_element(e, w=sys.stdout): + w.write(e[0] + '\t' + e[1] + '\n') -def element(ifc, identifier, fmt=default_format, w=sys.stdout): +def element(ifc, conn, registry_address, identifier, w=sys.stdout): o = ifc.address_of(registry_address, identifier) - r = rpc.do(o) + r = conn.do(o) address = ifc.parse_address_of(r) - out_element((identifier, address), fmt, w) + out_element((identifier, address), w) -def ls(ifc, fmt=default_format, w=sys.stdout): +def ls(ifc, conn, registry_address, w=sys.stdout): i = 0 while True: o = ifc.identifier(registry_address, i) try: - r = rpc.do(o) + r = conn.do(o) identifier = ifc.parse_identifier(r) - element(ifc, identifier, fmt, w) + element(ifc, conn, registry_address, identifier, w) i += 1 except JSONRPCException: break @@ -88,10 +76,17 @@ def ls(ifc, fmt=default_format, w=sys.stdout): def main(): c = ContractRegistry(chain_spec) + + identifier = config.get('_IDENTIFIER') + + registry_address = to_checksum_address(config.get('_EXEC_ADDRESS')) + if not config.true('_UNSAFE') and registry_address != add_0x(config.get('_EXEC_ADDRESS')): + raise ValueError('invalid checksum address for contract') + if identifier != None: - element(c, identifier, fmt=fmt, w=sys.stdout) + element(c, conn, identifier, registry_address, w=sys.stdout) else: - ls(c, fmt=fmt, w=sys.stdout) + ls(c, conn, registry_address, w=sys.stdout) if __name__ == '__main__': diff --git a/python/eth_contract_registry/runnable/set.py b/python/eth_contract_registry/runnable/set.py @@ -13,20 +13,16 @@ import argparse import logging # external imports -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore.dict import DictKeystore +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.constant import ZERO_CONTENT +from chainlib.eth.address import to_checksum_address +from hexathon import ( + add_0x, + strip_0x, + ) # local imports from eth_contract_registry.registry import ContractRegistry @@ -34,89 +30,65 @@ from eth_contract_registry.registry import ContractRegistry 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('-r', '--registry', dest='r', type=str, help='Contract registry 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('identifier', type=str, help='Contract registry identifier') -argparser.add_argument('address', type=str, help='Address to set for identifier') +arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) +argparser.add_argument('--chain-hash', type=str, dest='chain_hash', default=ZERO_CONTENT, help='Chain config hash to use for entry') +argparser.add_argument('--identifier', required=True, type=str, help='Contract identifier to set') +argparser.add_positional('address', type=str, help='Contract address to set for identifier') args = argparser.parse_args() -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) - -block_all = args.ww -block_last = args.w or block_all - -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=ContractRegistry.gas) -else: - gas_oracle = RPCGasOracle(rpc, code_callback=ContractRegistry.gas) - -dummy = args.d - -registry_address = args.r -if registry_address == None: - raise ValueError('Registry address must be set') -identifier = args.identifier -address = args.address - +extra_args = { + 'chain_hash': None, + 'identifier': None, + 'address': None, + } +config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=ContractRegistry.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 = ContractRegistry(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) - (tx_hash_hex, o) = c.set(registry_address, signer_address, identifier, address, chain_spec, ZERO_CONTENT) - if dummy: - print(tx_hash_hex) - print(o) - else: - rpc.do(o) - if block_last: - r = rpc.wait(tx_hash_hex) + + 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') + + registry_address = to_checksum_address(config.get('_EXEC_ADDRESS')) + if not config.true('_UNSAFE') and registry_address != add_0x(config.get('_EXEC_ADDRESS')): + raise ValueError('invalid checksum address for contract') + + chain_config_hash = config.get('_CHAIN_HASH') + chain_config_hash_bytes = bytes.fromhex(strip_0x(chain_config_hash)) + if len(chain_config_hash_bytes) != 32: + raise ValueError('chain config hash must be 32 bytes') + chain_config_hash = add_0x(chain_config_hash) + + (tx_hash_hex, o) = c.set(registry_address, signer_address, config.get('_IDENTIFIER'), subject_address, chain_spec, chain_config_hash) + + 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 -crypto-dev-signer~=0.4.14b6 -chainlib-eth~=0.0.5a1 +confini>=0.3.6rc3,<0.5.0 +crypto-dev-signer>=0.4.14b7,<0.4.14 +chainlib-eth>=0.0.7a4,<=0.1.0 diff --git a/python/setup.cfg b/python/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = eth-contract-registry -version = 0.5.6a1 +version = 0.6.1a1 description = Ethereum Smart Contract key-value registry author = Louis Holbrook author_email = dev@holbrook.no