POC single token task chain for token proof lookups

This commit is contained in:
nolash 2021-10-09 13:22:14 +02:00
parent f648d3ee68
commit 6098374a4e
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
8 changed files with 202 additions and 140 deletions

View File

@ -17,7 +17,8 @@ from cic_eth.enum import LockEnum
app = celery.current_app app = celery.current_app
logg = logging.getLogger(__name__) #logg = logging.getLogger(__name__)
logg = logging.getLogger()
class Api(ApiBase): class Api(ApiBase):
@ -41,39 +42,51 @@ class Api(ApiBase):
def tokens(self, token_symbols, proof=None): def tokens(self, token_symbols, proof=None):
if isinstance(proof, str): if isinstance(proof, str):
proof = [[proof]] proof = [proof]
chain_spec_dict = self.chain_spec.asdict() chain_spec_dict = self.chain_spec.asdict()
i = 0
s_group = []
for token_symbol in token_symbols:
s_token_resolve = celery.signature( s_token_resolve = celery.signature(
'cic_eth.eth.erc20.resolve_tokens_by_symbol', 'cic_eth.eth.erc20.resolve_token_by_symbol',
[ [
token_symbols, token_symbol,
chain_spec_dict, chain_spec_dict,
], ],
queue=self.queue, queue=self.queue,
) )
s_token = celery.signature( s_token_info = celery.signature(
'cic_eth.eth.erc20.token_info', 'cic_eth.eth.erc20.token_info',
[ [
chain_spec_dict, chain_spec_dict,
proof, proof[i],
], ],
queue=self.queue, queue=self.queue,
) )
# s_token_verify = celery.signature( s_token_verify = celery.signature(
# 'cic_eth.eth.erc20.verify_token_info', 'cic_eth.eth.erc20.verify_token_info',
# [ [
# chain_spec_dict, chain_spec_dict,
# ], self.callback_success,
# queue=self.queue, self.callback_error,
# ) ],
#s_token.link(s_token_verify) queue=self.queue,
s_token_resolve.link(s_token) )
if self.callback_param != None: i += 1
s_token.link(self.callback_success)
return s_token_resolve.apply_async() s_token_info.link(s_token_verify)
s_token_resolve.link(s_token_info)
#if self.callback_param != None:
# s_token_verify.link(self.callback_success)
# s_token_verify.on_error(self.callback_error)
s_group.append(s_token_resolve)
# return s_token_resolve.apply_async()
return celery.group(s_group)()
# def convert_transfer(self, from_address, to_address, target_return, minimum_return, from_token_symbol, to_token_symbol): # def convert_transfer(self, from_address, to_address, target_return, minimum_return, from_token_symbol, to_token_symbol):

View File

@ -1,7 +1,10 @@
import logging
import celery import celery
celery_app = celery.current_app celery_app = celery.current_app
logg = celery_app.log.get_default_logger() #logg = celery_app.log.get_default_logger()
logg = logging.getLogger()
@celery_app.task(bind=True) @celery_app.task(bind=True)

View File

@ -328,6 +328,26 @@ def approve(self, tokens, holder_address, spender_address, value, chain_spec_dic
return tx_hash_hex return tx_hash_hex
@celery_app.task(bind=True, base=CriticalWeb3Task)
def resolve_token_by_symbol(self, token_symbol, chain_spec_dict):
chain_spec = ChainSpec.from_dict(chain_spec_dict)
rpc = RPCConnection.connect(chain_spec, 'default')
registry = CICRegistry(chain_spec, rpc)
session = self.create_session()
sender_address = AccountRole.get_address('DEFAULT', session)
session.close()
token_address = registry.by_name(token_symbol, sender_address=sender_address)
logg.debug('token {}'.format(token_address))
token = {
'address': token_address,
'symbol': token_symbol,
'converters': [],
}
return token
@celery_app.task(bind=True, base=CriticalWeb3Task) @celery_app.task(bind=True, base=CriticalWeb3Task)
def resolve_tokens_by_symbol(self, token_symbols, chain_spec_dict): def resolve_tokens_by_symbol(self, token_symbols, chain_spec_dict):
"""Returns contract addresses of an array of ERC20 token symbols """Returns contract addresses of an array of ERC20 token symbols
@ -478,49 +498,52 @@ def cache_approve_data(
@celery_app.task(bind=True, base=BaseTask) @celery_app.task(bind=True, base=BaseTask)
def token_info(self, tokens, chain_spec_dict, proofs=[]): def token_info(self, token, chain_spec_dict, proofs=[]):
chain_spec = ChainSpec.from_dict(chain_spec_dict) chain_spec = ChainSpec.from_dict(chain_spec_dict)
rpc = RPCConnection.connect(chain_spec, 'default') rpc = RPCConnection.connect(chain_spec, 'default')
result_data = [] result_data = []
queue = self.request.delivery_info.get('routing_key')
i = 0
s_group = []
for token in tokens:
token_chain_object = ERC20Token(chain_spec, rpc, add_0x(token['address'])) token_chain_object = ERC20Token(chain_spec, rpc, add_0x(token['address']))
token_chain_object.load(rpc) token_chain_object.load(rpc)
token_symbol_proof_hex = to_identifier(token_chain_object.symbol) token_symbol_proof_hex = to_identifier(token_chain_object.symbol)
token_proofs = [token_symbol_proof_hex] token_proofs = [token_symbol_proof_hex]
if len(proofs) > 0: token_proofs += proofs
token_proofs += proofs[i]
token_data = { token_data = {
'decimals': token_chain_object.decimals, 'decimals': token_chain_object.decimals,
'name': token_chain_object.name, 'name': token_chain_object.name,
'symbol': token_chain_object.symbol, 'symbol': token_chain_object.symbol,
'address': tx_normalize.executable_address(token_chain_object.address), 'address': tx_normalize.executable_address(token_chain_object.address),
'proofs': token_proofs,
} }
result_data.append(token_data)
return token_data
@celery_app.task(bind=True, base=BaseTask)
def verify_token_info(self, token, chain_spec_dict, success_callback, error_callback):
queue = self.request.delivery_info.get('routing_key')
s = celery.signature( s = celery.signature(
'cic_eth.eth.trust.verify_proofs', 'cic_eth.eth.trust.verify_proofs',
[ [
token, token,
token_chain_object.address, token['address'],
token_proofs, token['proofs'],
chain_spec_dict, chain_spec_dict,
success_callback,
error_callback,
], ],
queue=queue, queue=queue,
) )
s_group.append(s) s.link(success_callback)
i += 1 s.on_error(error_callback)
s.apply_async()
#s_group.append(s)
celery.group(s_group)() #celery.group(s_group)()
#return result_data return token
@celery_app.task(bind=True, base=BaseTask) @celery_app.task(bind=True, base=BaseTask)

View File

@ -17,15 +17,25 @@ from cic_eth.error import TrustError
celery_app = celery.current_app celery_app = celery.current_app
logg = logging.getLogger() logg = logging.getLogger()
@celery_app.task(bind=True, base=BaseTask)
def collect(self, collection):
logg.debug('collect {}'.format(collection))
return collection @celery_app.task(bind=True, base=BaseTask)
def verify_proof(self, chained_input, proof, subject, chain_spec_dict, success_callback, error_callback):
proof = strip_0x(proof)
proofs = []
logg.debug('proof count {}'.format(len(proofs)))
if len(proofs) == 0:
logg.debug('error {}'.format(len(proofs)))
raise TrustError('foo')
return (chained_input, (proof, proofs))
@celery_app.task(bind=True, base=BaseTask) @celery_app.task(bind=True, base=BaseTask)
def verify_proof(self, chained_input, proof, subject, chain_spec_dict): def verify_proofs(self, chained_input, subject, proofs, chain_spec_dict, success_callback, error_callback):
queue = self.request.delivery_info.get('routing_key')
chain_spec = ChainSpec.from_dict(chain_spec_dict) chain_spec = ChainSpec.from_dict(chain_spec_dict)
rpc = RPCConnection.connect(chain_spec, 'default') rpc = RPCConnection.connect(chain_spec, 'default')
@ -37,11 +47,14 @@ def verify_proof(self, chained_input, proof, subject, chain_spec_dict):
declarator = Declarator(chain_spec) declarator = Declarator(chain_spec)
logg.debug('foo {}'.format(proof)) have_proofs = {}
proof = strip_0x(proof)
logg.debug('proof is {}'.format(proof)) for proof in proofs:
proof = strip_0x(proof)
have_proofs[proof] = []
proof_count = 0
for trusted_address in self.trusted_addresses: for trusted_address in self.trusted_addresses:
o = declarator.declaration(declarator_address, trusted_address, subject, sender_address=sender_address) o = declarator.declaration(declarator_address, trusted_address, subject, sender_address=sender_address)
r = rpc.do(o) r = rpc.do(o)
@ -52,50 +65,13 @@ def verify_proof(self, chained_input, proof, subject, chain_spec_dict):
declaration = strip_0x(declaration) declaration = strip_0x(declaration)
if declaration == proof: if declaration == proof:
logg.debug('have token proof {} match for trusted address {}'.format(declaration, trusted_address)) logg.debug('have token proof {} match for trusted address {}'.format(declaration, trusted_address))
proof_count += 1 have_proofs[proof].append(trusted_address)
logg.debug('proof count {}'.format(proof_count)) out_proofs = {}
if proof_count == 0: for proof in have_proofs.keys():
logg.debug('error {}'.format(proof_count)) if len(have_proofs[proof]) == 0:
raise TrustError('no trusted records found for subject {} proof {}'.format(subject, proof)) logg.error('missing signer for proof {} subject {}'.format(proof, subject))
raise TrustError((subject, proof,))
out_proofs[proof] = have_proofs[proof]
return chained_input return (chained_input, out_proofs)
@celery_app.task(bind=True, base=BaseTask)
def verify_proofs(self, chained_input, subject, proofs, chain_spec_dict):
if isinstance(proofs, str):
proofs = [[proofs]]
elif not isinstance(proofs, list):
raise ValueError('proofs argument must be string or list')
i = 0
for proof in proofs:
if not isinstance(proof, list):
proofs[i] = [proof]
logg.debug('proof entry {} is not a list'.format(i))
i += 1
queue = self.request.delivery_info.get('routing_key')
s_group = []
for proof in proofs:
logg.debug('proof before {}'.format(proof))
if isinstance(proof, str):
proof = [proof]
for single_proof in proof:
logg.debug('proof after {}'.format(single_proof))
s = celery.signature(
'cic_eth.eth.trust.verify_proof',
[
chained_input,
single_proof,
subject,
chain_spec_dict,
],
queue=queue,
)
#s_group.append(s)
s.apply_async()
#return chained_input

View File

@ -4,13 +4,12 @@ import tempfile
import logging import logging
import shutil import shutil
# local impors # local imports
from cic_eth.task import BaseTask from cic_eth.task import BaseTask
#logg = logging.getLogger(__name__) #logg = logging.getLogger(__name__)
logg = logging.getLogger() logg = logging.getLogger()
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def init_celery_tasks( def init_celery_tasks(
contract_roles, contract_roles,
@ -42,6 +41,7 @@ def celery_includes():
'cic_eth.callbacks.noop', 'cic_eth.callbacks.noop',
'cic_eth.callbacks.http', 'cic_eth.callbacks.http',
'cic_eth.pytest.mock.filter', 'cic_eth.pytest.mock.filter',
'cic_eth.pytest.mock.callback',
] ]

View File

@ -1 +1,2 @@
from .filter import * from .filter import *
from .callback import *

View File

@ -0,0 +1,28 @@
# standard imports
import logging
# external imports
import celery
#logg = logging.getLogger(__name__)
logg = logging.getLogger()
celery_app = celery.current_app
class CallbackTask(celery.Task):
errs = {}
oks = {}
@celery_app.task(bind=True, base=CallbackTask)
def test_error_callback(self, a, b, c):
o = CallbackTask.oks
s = 'ok'
if c > 0:
o = CallbackTask.errs
s = 'err'
if o.get(b) == None:
o[b] = []
o[b].append(a)
logg.debug('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> test callback ({}): {} {} {}'.format(s, a, b, c))

View File

@ -1,8 +1,11 @@
# standard imports # standard imports
import logging import logging
import os import os
import uuid
import time
# external imports # external imports
import celery
import pytest import pytest
from hexathon import ( from hexathon import (
strip_0x, strip_0x,
@ -14,6 +17,7 @@ from cic_eth.api.api_task import Api
from cic_eth.task import BaseTask from cic_eth.task import BaseTask
from cic_eth.error import TrustError from cic_eth.error import TrustError
from cic_eth.encode import tx_normalize from cic_eth.encode import tx_normalize
from cic_eth.pytest.mock.callback import CallbackTask
logg = logging.getLogger() logg = logging.getLogger()
@ -48,15 +52,16 @@ def test_tokens(
custodial_roles, custodial_roles,
foo_token_declaration, foo_token_declaration,
bar_token_declaration, bar_token_declaration,
celery_session_worker, celery_worker,
): ):
api = Api(str(default_chain_spec), queue=None) api = Api(str(default_chain_spec), queue=None, callback_param='foo')
t = api.token('FOO', proof=foo_token_declaration) t = api.tokens(['FOO'], proof=[[foo_token_declaration]])
r = t.get() r = t.get()
logg.debug('r {}'.format(r)) logg.debug('rr {}'.format(r))
assert len(r) == 1 assert len(r) == 1
assert r[0]['address'] == strip_0x(foo_token)
t = api.tokens(['BAR', 'FOO'], proof=[[bar_token_declaration], [foo_token_declaration]]) t = api.tokens(['BAR', 'FOO'], proof=[[bar_token_declaration], [foo_token_declaration]])
r = t.get() r = t.get()
@ -65,8 +70,21 @@ def test_tokens(
assert r[1]['address'] == strip_0x(foo_token) assert r[1]['address'] == strip_0x(foo_token)
assert r[0]['address'] == strip_0x(bar_token) assert r[0]['address'] == strip_0x(bar_token)
celery_app = celery.current_app
api_param = str(uuid.uuid4())
api = Api(str(default_chain_spec), queue=None, callback_param=api_param, callback_task='cic_eth.pytest.mock.callback.test_error_callback')
bogus_proof = os.urandom(32).hex() bogus_proof = os.urandom(32).hex()
with pytest.raises(TrustError): t = api.tokens(['FOO'], proof=[[bogus_proof]])
t = api.token('FOO', proof=bogus_proof) r = t.get()
r = t.get_leaf() logg.debug('r {}'.format(r))
logg.debug('should raise {}'.format(r)) assert len(CallbackTask.errs[api_param]) == 1
assert CallbackTask.oks.get(api_param) == None
api_param = str(uuid.uuid4())
api = Api(str(default_chain_spec), queue=None, callback_param=api_param, callback_task='cic_eth.pytest.mock.callback.test_error_callback')
t = api.tokens(['BAR'], proof=[[bar_token_declaration]])
r = t.get()
logg.debug('rr {} {}'.format(r, t.children))
time.sleep(0.1)
assert len(CallbackTask.oks[api_param]) == 1