From f648d3ee683f76136f3ca2d2d7b50fd237500e84 Mon Sep 17 00:00:00 2001 From: nolash Date: Sat, 9 Oct 2021 00:48:20 +0200 Subject: [PATCH] WIP token info proof verify --- apps/cic-eth/cic_eth/api/api_task.py | 18 ++-- apps/cic-eth/cic_eth/eth/erc20.py | 45 ++++----- apps/cic-eth/cic_eth/eth/trust.py | 96 ++++++++++++------- .../tests/task/api/test_app_noncritical.py | 31 ++++-- 4 files changed, 115 insertions(+), 75 deletions(-) diff --git a/apps/cic-eth/cic_eth/api/api_task.py b/apps/cic-eth/cic_eth/api/api_task.py index 433e0783..61bc9e39 100644 --- a/apps/cic-eth/cic_eth/api/api_task.py +++ b/apps/cic-eth/cic_eth/api/api_task.py @@ -61,17 +61,17 @@ class Api(ApiBase): queue=self.queue, ) - s_token_verify = celery.signature( - 'cic_eth.eth.erc20.verify_token_info', - [ - chain_spec_dict, - ], - queue=self.queue, - ) +# s_token_verify = celery.signature( +# 'cic_eth.eth.erc20.verify_token_info', +# [ +# chain_spec_dict, +# ], +# queue=self.queue, +# ) + #s_token.link(s_token_verify) s_token_resolve.link(s_token) - s_token.link(s_token_verify) if self.callback_param != None: - s_token_verify.link(self.callback_success) + s_token.link(self.callback_success) return s_token_resolve.apply_async() diff --git a/apps/cic-eth/cic_eth/eth/erc20.py b/apps/cic-eth/cic_eth/eth/erc20.py index 61240977..ff13d283 100644 --- a/apps/cic-eth/cic_eth/eth/erc20.py +++ b/apps/cic-eth/cic_eth/eth/erc20.py @@ -483,7 +483,11 @@ def token_info(self, tokens, chain_spec_dict, proofs=[]): rpc = RPCConnection.connect(chain_spec, 'default') 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.load(rpc) @@ -497,39 +501,26 @@ def token_info(self, tokens, chain_spec_dict, proofs=[]): 'decimals': token_chain_object.decimals, 'name': token_chain_object.name, 'symbol': token_chain_object.symbol, - 'address': token_chain_object.address, - 'proofs': token_proofs, + 'address': tx_normalize.executable_address(token_chain_object.address), } result_data.append(token_data) + s = celery.signature( + 'cic_eth.eth.trust.verify_proofs', + [ + token, + token_chain_object.address, + token_proofs, + chain_spec_dict, + ], + queue=queue, + ) + s_group.append(s) i += 1 - return result_data + celery.group(s_group)() - -@celery_app.task(bind=True, base=BaseTask) -def verify_token_info(self, tokens, chain_spec_dict): - subjects = [] - proofs = [] - for token in tokens: - subjects.append(token['address']) - proofs.append(token['proofs']) - - queue = self.request.delivery_info.get('routing_key') - - s = celery.signature( - 'cic_eth.eth.trust.verify_proofs', - [ - tokens, - chain_spec_dict, - subjects, - proofs, - ], - queue=queue, - ) - s.apply_async() - - return tokens + #return result_data @celery_app.task(bind=True, base=BaseTask) diff --git a/apps/cic-eth/cic_eth/eth/trust.py b/apps/cic-eth/cic_eth/eth/trust.py index ebe930bd..96759042 100644 --- a/apps/cic-eth/cic_eth/eth/trust.py +++ b/apps/cic-eth/cic_eth/eth/trust.py @@ -8,6 +8,7 @@ from chainlib.connection import RPCConnection from chainlib.chain import ChainSpec from cic_eth.db.models.role import AccountRole from cic_eth_registry import CICRegistry +from hexathon import strip_0x # local imports from cic_eth.task import BaseTask @@ -16,21 +17,17 @@ from cic_eth.error import TrustError celery_app = celery.current_app 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_proofs(self, chained_input, chain_spec_dict, subjects, proofs): - if not isinstance(subjects, list): - raise ValueError('subjects argument must be list') - if isinstance(proofs, str): - proofs = [[proofs]] - elif not isinstance(proofs, list): - raise ValueError('proofs argument must be string or list') - if len(proofs) != 1 and len(subjects) != len(proofs): - raise ValueError('proof argument must be single proof or one proof input per subject') - +def verify_proof(self, chained_input, proof, subject, chain_spec_dict): chain_spec = ChainSpec.from_dict(chain_spec_dict) rpc = RPCConnection.connect(chain_spec, 'default') - declarator = Declarator(chain_spec) session = self.create_session() sender_address = AccountRole.get_address('DEFAULT', session) @@ -38,32 +35,67 @@ def verify_proofs(self, chained_input, chain_spec_dict, subjects, proofs): registry = CICRegistry(chain_spec, rpc) declarator_address = registry.by_name('AddressDeclarator', sender_address=sender_address) + declarator = Declarator(chain_spec) + + logg.debug('foo {}'.format(proof)) + proof = strip_0x(proof) + logg.debug('proof is {}'.format(proof)) + + proof_count = 0 + for trusted_address in self.trusted_addresses: + o = declarator.declaration(declarator_address, trusted_address, subject, sender_address=sender_address) + r = rpc.do(o) + declarations = declarator.parse_declaration(r) + logg.debug('comparing proof {} with declarations for {} by {}: {}'.format(proof, subject, trusted_address, declarations)) + + for declaration in declarations: + declaration = strip_0x(declaration) + if declaration == proof: + logg.debug('have token proof {} match for trusted address {}'.format(declaration, trusted_address)) + proof_count += 1 + + logg.debug('proof count {}'.format(proof_count)) + if proof_count == 0: + logg.debug('error {}'.format(proof_count)) + raise TrustError('no trusted records found for subject {} proof {}'.format(subject, proof)) + + return chained_input + + +@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 - i = 0 - for subject in subjects: - for trusted_address in self.trusted_addresses: - proof_count = {} - for proof in proofs[i]: - o = declarator.declaration(declarator_address, trusted_address, subject, sender_address=sender_address) - r = rpc.do(o) - declarations = declarator.parse_declaration(r) - logg.debug('comparing proof {} with declarations for {} by {}: {}'.format(proofs, subject, trusted_address, declarations)) - for declaration in declarations: - if declaration == proof: - logg.debug('have token proof {} match for trusted address {}'.format(declaration, trusted_address)) - if proof_count.get(proof) == None: - proof_count[proof] = 0 - proof_count[proof] += 1 - - for k in proof_count.keys(): - if proof_count[k] == 0: - raise TrustError('no proof found for token {}'.format(subject)) + queue = self.request.delivery_info.get('routing_key') - i += 1 + 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 + #return chained_input diff --git a/apps/cic-eth/tests/task/api/test_app_noncritical.py b/apps/cic-eth/tests/task/api/test_app_noncritical.py index e4031f0e..bd8e8a1f 100644 --- a/apps/cic-eth/tests/task/api/test_app_noncritical.py +++ b/apps/cic-eth/tests/task/api/test_app_noncritical.py @@ -1,9 +1,19 @@ # standard imports import logging +import os + +# external imports +import pytest +from hexathon import ( + strip_0x, + uniform as hex_uniform, + ) # local imports from cic_eth.api.api_task import Api from cic_eth.task import BaseTask +from cic_eth.error import TrustError +from cic_eth.encode import tx_normalize logg = logging.getLogger() @@ -38,18 +48,25 @@ def test_tokens( custodial_roles, foo_token_declaration, bar_token_declaration, - celery_worker, + celery_session_worker, ): api = Api(str(default_chain_spec), queue=None) t = api.token('FOO', proof=foo_token_declaration) - r = t.get_leaf() + r = t.get() + logg.debug('r {}'.format(r)) assert len(r) == 1 - assert r[0]['address'] == foo_token - t = api.tokens(['BAR', 'FOO'], proof=[[foo_token_declaration], [bar_token_declaration]]) - r = t.get_leaf() + t = api.tokens(['BAR', 'FOO'], proof=[[bar_token_declaration], [foo_token_declaration]]) + r = t.get() + logg.debug('results {}'.format(r)) assert len(r) == 2 - assert r[1]['address'] == foo_token - assert r[0]['address'] == bar_token + assert r[1]['address'] == strip_0x(foo_token) + assert r[0]['address'] == strip_0x(bar_token) + + bogus_proof = os.urandom(32).hex() + with pytest.raises(TrustError): + t = api.token('FOO', proof=bogus_proof) + r = t.get_leaf() + logg.debug('should raise {}'.format(r))