Add role listing to cic-eth tag cli tool

This commit is contained in:
nolash 2021-10-30 13:19:31 +02:00
parent cbd4aef004
commit 0b912b99b6
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
7 changed files with 150 additions and 20 deletions

View File

@ -123,7 +123,7 @@ class AdminApi:
return s_lock.apply_async() return s_lock.apply_async()
def tag_account(self, tag, address_hex, chain_spec): def tag_account(self, chain_spec, tag, address):
"""Persistently associate an address with a plaintext tag. """Persistently associate an address with a plaintext tag.
Some tags are known by the system and is used to resolve addresses to use for certain transactions. Some tags are known by the system and is used to resolve addresses to use for certain transactions.
@ -138,7 +138,7 @@ class AdminApi:
'cic_eth.eth.account.set_role', 'cic_eth.eth.account.set_role',
[ [
tag, tag,
address_hex, address,
chain_spec.asdict(), chain_spec.asdict(),
], ],
queue=self.queue, queue=self.queue,
@ -146,6 +146,30 @@ class AdminApi:
return s_tag.apply_async() return s_tag.apply_async()
def get_tag_account(self, chain_spec, tag=None, address=None):
if address != None:
s_tag = celery.signature(
'cic_eth.eth.account.role',
[
address,
chain_spec.asdict(),
],
queue=self.queue,
)
else:
s_tag = celery.signature(
'cic_eth.eth.account.role_account',
[
tag,
chain_spec.asdict(),
],
queue=self.queue,
)
return s_tag.apply_async()
def have_account(self, address_hex, chain_spec): def have_account(self, address_hex, chain_spec):
s_have = celery.signature( s_have = celery.signature(
'cic_eth.eth.account.have', 'cic_eth.eth.account.have',
@ -503,7 +527,7 @@ class AdminApi:
queue=self.queue, queue=self.queue,
) )
t = s.apply_async() t = s.apply_async()
role = t.get() role = t.get()[0][1]
if role != None: if role != None:
tx['sender_description'] = role tx['sender_description'] = role
@ -556,7 +580,7 @@ class AdminApi:
queue=self.queue, queue=self.queue,
) )
t = s.apply_async() t = s.apply_async()
role = t.get() role = t.get()[0][1]
if role != None: if role != None:
tx['recipient_description'] = role tx['recipient_description'] = role

View File

@ -24,8 +24,22 @@ class AccountRole(SessionBase):
tag = Column(Text) tag = Column(Text)
address_hex = Column(String(42)) address_hex = Column(String(42))
# TODO: @staticmethod
def all(session=None):
session = SessionBase.bind_session(session)
pairs = []
q = session.query(AccountRole.tag, AccountRole.address_hex)
for r in q.all():
pairs.append((r[1], r[0]),)
SessionBase.release_session(session)
return pairs
@staticmethod @staticmethod
def get_address(tag, session): def get_address(tag, session):
"""Get Ethereum address matching the given tag """Get Ethereum address matching the given tag

View File

@ -266,19 +266,46 @@ def set_role(self, tag, address, chain_spec_dict):
@celery_app.task(bind=True, base=BaseTask) @celery_app.task(bind=True, base=BaseTask)
def role(self, address, chain_spec_dict): def role(self, address, chain_spec_dict):
"""Return account role for address """Return account role for address and/or role
:param account: Account to check :param account: Account to check
:type account: str, 0x-hex :type account: str, 0x-hex
:param chain_str: Chain spec string representation :param chain_spec_dict: Chain spec dict representation
:type chain_str: str :type chain_spec_dict: dict
:returns: Account, or None if not exists :returns: Account, or None if not exists
:rtype: Varies :rtype: Varies
""" """
session = self.create_session() session = self.create_session()
role_tag = AccountRole.role_for(address, session=session) role_tag = AccountRole.role_for(address, session=session)
session.close() session.close()
return role_tag return [(address, role_tag,)]
@celery_app.task(bind=True, base=BaseTask)
def role_account(self, role_tag, chain_spec_dict):
"""Return address for role.
If the role parameter is None, will return addresses for all roles.
:param role_tag: Role to match
:type role_tag: str
:param chain_spec_dict: Chain spec dict representation
:type chain_spec_dict: dict
:returns: List with a single account/tag pair for a single tag, or a list of account and tag pairs for all tags
:rtype: list
"""
session = self.create_session()
pairs = None
if role_tag != None:
addr = AccountRole.get_address(role_tag, session=session)
pairs = [(addr, role_tag,)]
else:
pairs = AccountRole.all(session=session)
session.close()
return pairs
@celery_app.task(bind=True, base=CriticalSQLAlchemyTask) @celery_app.task(bind=True, base=CriticalSQLAlchemyTask)

View File

@ -8,6 +8,7 @@ import re
# external imports # external imports
import cic_eth.cli import cic_eth.cli
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainlib.eth.address import is_address
from xdg.BaseDirectory import xdg_config_home from xdg.BaseDirectory import xdg_config_home
# local imports # local imports
@ -21,12 +22,18 @@ logg = logging.getLogger()
arg_flags = cic_eth.cli.argflag_std_base | cic_eth.cli.Flag.UNSAFE | cic_eth.cli.Flag.CHAIN_SPEC arg_flags = cic_eth.cli.argflag_std_base | cic_eth.cli.Flag.UNSAFE | cic_eth.cli.Flag.CHAIN_SPEC
local_arg_flags = cic_eth.cli.argflag_local_taskcallback local_arg_flags = cic_eth.cli.argflag_local_taskcallback
argparser = cic_eth.cli.ArgumentParser(arg_flags) argparser = cic_eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('tag', type=str, help='address tag') argparser.add_argument('--set', action='store_true', help='sets the given tag')
argparser.add_positional('address', type=str, help='address') argparser.add_argument('--tag', type=str, help='operate on the given tag')
argparser.add_positional('address', required=False, type=str, help='address associated with tag')
argparser.process_local_flags(local_arg_flags) argparser.process_local_flags(local_arg_flags)
args = argparser.parse_args() args = argparser.parse_args()
config = cic_eth.cli.Config.from_args(args, arg_flags, local_arg_flags) extra_args = {
'set': None,
'tag': None,
'address': None,
}
config = cic_eth.cli.Config.from_args(args, arg_flags, local_arg_flags, extra_args=extra_args)
celery_app = cic_eth.cli.CeleryApp.from_config(config) celery_app = cic_eth.cli.CeleryApp.from_config(config)
@ -39,7 +46,17 @@ api = AdminApi(None)
def main(): def main():
admin_api.tag_account(args.tag, args.address, chain_spec) if config.get('_ADDRESS') != None and not is_address(config.get('_ADDRESS')):
sys.stderr.write('Invalid address {}'.format(config.get('_ADDRESS')))
sys.exit(1)
if config.get('_SET'):
admin_api.tag_account(chain_spec, config.get('_TAG'), config.get('_ADDRESS'))
else:
t = admin_api.get_tag_account(chain_spec, tag=config.get('_TAG'), address=config.get('_ADDRESS'))
r = t.get()
for v in r:
sys.stdout.write('{}\t{}\n'.format(v[1], v[0]))
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -103,11 +103,11 @@ def test_tag_account(
api = AdminApi(eth_rpc, queue=None) api = AdminApi(eth_rpc, queue=None)
t = api.tag_account('foo', agent_roles['ALICE'], default_chain_spec) t = api.tag_account(default_chain_spec, 'foo', agent_roles['ALICE'])
t.get() t.get()
t = api.tag_account('bar', agent_roles['BOB'], default_chain_spec) t = api.tag_account(default_chain_spec, 'bar', agent_roles['BOB'])
t.get() t.get()
t = api.tag_account('bar', agent_roles['CAROL'], default_chain_spec) t = api.tag_account(default_chain_spec, 'bar', agent_roles['CAROL'])
t.get() t.get()
assert AccountRole.get_address('foo', init_database) == tx_normalize.wallet_address(agent_roles['ALICE']) assert AccountRole.get_address('foo', init_database) == tx_normalize.wallet_address(agent_roles['ALICE'])

View File

@ -141,9 +141,57 @@ def test_role_task(
) )
t = s.apply_async() t = s.apply_async()
r = t.get() r = t.get()
assert r == 'foo' assert r[0][0] == address
assert r[0][1] == 'foo'
def test_get_role_task(
init_database,
celery_session_worker,
default_chain_spec,
):
address_foo = '0x' + os.urandom(20).hex()
role_foo = AccountRole.set('foo', address_foo)
init_database.add(role_foo)
address_bar = '0x' + os.urandom(20).hex()
role_bar = AccountRole.set('bar', address_bar)
init_database.add(role_bar)
init_database.commit()
s = celery.signature(
'cic_eth.eth.account.role_account',
[
'bar',
default_chain_spec.asdict(),
],
queue=None,
)
t = s.apply_async()
r = t.get()
assert r[0][0] == address_bar
assert r[0][1] == 'bar'
s = celery.signature(
'cic_eth.eth.account.role_account',
[
None,
default_chain_spec.asdict(),
],
queue=None,
)
t = s.apply_async()
r = t.get()
x_tags = ['foo', 'bar']
x_addrs = [address_foo, address_bar]
for v in r:
x_addrs.remove(v[0])
x_tags.remove(v[1])
assert len(x_tags) == 0
assert len(x_addrs) == 0
def test_gift( def test_gift(
init_database, init_database,

View File

@ -29,11 +29,11 @@ REDIS_HOST_CALLBACK=${REDIS_HOST_CALLBACK:-$REDIS_HOST}
REDIS_PORT_CALLBACK=${REDIS_PORT_CALLBACK:-$REDIS_PORT} REDIS_PORT_CALLBACK=${REDIS_PORT_CALLBACK:-$REDIS_PORT}
>&2 echo -e "\033[;96mcreate account for gas gifter\033[;39m" >&2 echo -e "\033[;96mcreate account for gas gifter\033[;39m"
gas_gifter=`cic-eth-create --redis-timeout 120 $DEV_DEBUG_FLAG --redis-host-callback $REDIS_HOST_CALLBACK --redis-port-callback $REDIS_PORT_CALLBACK --no-register` gas_gifter=`cic-eth-create --redis-timeout 120 $DEV_DEBUG_FLAG --redis-host-callback $REDIS_HOST_CALLBACK --redis-port-callback $REDIS_PORT_CALLBACK --no-register`
cic-eth-tag -i $CHAIN_SPEC GAS_GIFTER $gas_gifter cic-eth-tag -i $CHAIN_SPEC --set --tag GAS_GIFTER $gas_gifter
>&2 echo -e "\033[;96mcreate account for accounts index writer\033[;39m" >&2 echo -e "\033[;96mcreate account for accounts index writer\033[;39m"
accounts_index_writer=`cic-eth-create --redis-timeout 120 $DEV_DEBUG_FLAG --redis-host-callback $REDIS_HOST_CALLBACK --redis-port-callback $REDIS_PORT_CALLBACK --no-register` accounts_index_writer=`cic-eth-create --redis-timeout 120 $DEV_DEBUG_FLAG --redis-host-callback $REDIS_HOST_CALLBACK --redis-port-callback $REDIS_PORT_CALLBACK --no-register`
cic-eth-tag -i $CHAIN_SPEC ACCOUNT_REGISTRY_WRITER $accounts_index_writer cic-eth-tag -i $CHAIN_SPEC --set --tag ACCOUNT_REGISTRY_WRITER $accounts_index_writer
# Assign system writer for accounts index # Assign system writer for accounts index