diff --git a/apps/cic-cache/requirements.txt b/apps/cic-cache/requirements.txt index 00030b74..92e95994 100644 --- a/apps/cic-cache/requirements.txt +++ b/apps/cic-cache/requirements.txt @@ -1,13 +1,13 @@ -cic-base==0.1.3a3+build.984b5cff +cic-base~=0.2.0a2 alembic==1.4.2 -confini~=0.3.6rc3 +confini>=0.3.6rc3,<0.5.0 uwsgi==2.0.19.1 moolb~=0.1.0 -cic-eth-registry~=0.5.6a1 +cic-eth-registry~=0.5.6a2 SQLAlchemy==1.3.20 semver==2.13.0 psycopg2==2.8.6 celery==4.4.7 redis==3.5.3 -chainsyncer[sql]~=0.0.3a3 -erc20-faucet~=0.2.2a1 +chainsyncer[sql]~=0.0.3a4 +erc20-faucet~=0.2.2a2 diff --git a/apps/cic-eth/admin_requirements.txt b/apps/cic-eth/admin_requirements.txt index 2a55cc29..cc620677 100644 --- a/apps/cic-eth/admin_requirements.txt +++ b/apps/cic-eth/admin_requirements.txt @@ -1,5 +1,5 @@ SQLAlchemy==1.3.20 -cic-eth-registry~=0.5.6a1 +cic-eth-registry~=0.5.6a2 hexathon~=0.0.1a7 -chainqueue~=0.0.2b5 -eth-erc20==0.0.10a2 +chainqueue~=0.0.2b6 +eth-erc20~=0.0.10a3 diff --git a/apps/cic-eth/cic_eth/ext/tx.py b/apps/cic-eth/cic_eth/ext/tx.py index 007b4136..77083874 100644 --- a/apps/cic-eth/cic_eth/ext/tx.py +++ b/apps/cic-eth/cic_eth/ext/tx.py @@ -14,9 +14,11 @@ from chainlib.eth.tx import ( ) from chainlib.eth.block import block_by_number from chainlib.eth.contract import abi_decode_single +from chainlib.eth.constant import ZERO_ADDRESS from hexathon import strip_0x from cic_eth_registry import CICRegistry from cic_eth_registry.erc20 import ERC20Token +from cic_eth_registry.error import UnknownContractError from chainqueue.db.models.otx import Otx from chainqueue.db.enum import StatusEnum from chainqueue.sql.query import get_tx_cache @@ -114,9 +116,6 @@ def list_tx_by_bloom(self, bloomspec, address, chain_spec_dict): # TODO: pass through registry to validate declarator entry of token #token = registry.by_address(tx['to'], sender_address=self.call_address) - token = ERC20Token(chain_spec, rpc, tx['to']) - token_symbol = token.symbol - token_decimals = token.decimals times = tx_times(tx['hash'], chain_spec) tx_r = { 'hash': tx['hash'], @@ -126,12 +125,6 @@ def list_tx_by_bloom(self, bloomspec, address, chain_spec_dict): 'destination_value': tx_token_value, 'source_token': tx['to'], 'destination_token': tx['to'], - 'source_token_symbol': token_symbol, - 'destination_token_symbol': token_symbol, - 'source_token_decimals': token_decimals, - 'destination_token_decimals': token_decimals, - 'source_token_chain': chain_str, - 'destination_token_chain': chain_str, 'nonce': tx['nonce'], } if times['queue'] != None: @@ -146,8 +139,8 @@ def list_tx_by_bloom(self, bloomspec, address, chain_spec_dict): # TODO: Surely it must be possible to optimize this # TODO: DRY this with callback filter in cic_eth/runnable/manager # TODO: Remove redundant fields from end representation (timestamp, tx_hash) -@celery_app.task() -def tx_collate(tx_batches, chain_spec_dict, offset, limit, newest_first=True): +@celery_app.task(bind=True, base=BaseTask) +def tx_collate(self, tx_batches, chain_spec_dict, offset, limit, newest_first=True, verify_contracts=True): """Merges transaction data from multiple sources and sorts them in chronological order. :param tx_batches: Transaction data inputs @@ -196,6 +189,32 @@ def tx_collate(tx_batches, chain_spec_dict, offset, limit, newest_first=True): if newest_first: ks.reverse() for k in ks: - txs.append(txs_by_block[k]) + tx = txs_by_block[k] + if verify_contracts: + try: + tx = verify_and_expand(tx, chain_spec, sender_address=BaseTask.call_address) + except UnknownContractError: + logg.error('verify failed on tx {}, skipping'.format(tx['hash'])) + continue + txs.append(tx) return txs + + +def verify_and_expand(tx, chain_spec, sender_address=ZERO_ADDRESS): + rpc = RPCConnection.connect(chain_spec, 'default') + registry = CICRegistry(chain_spec, rpc) + + if tx.get('source_token_symbol') == None and tx['source_token'] != ZERO_ADDRESS: + r = registry.by_address(tx['source_token'], sender_address=sender_address) + token = ERC20Token(chain_spec, rpc, tx['source_token']) + tx['source_token_symbol'] = token.symbol + tx['source_token_decimals'] = token.decimals + + if tx.get('destination_token_symbol') == None and tx['destination_token'] != ZERO_ADDRESS: + r = registry.by_address(tx['destination_token'], sender_address=sender_address) + token = ERC20Token(chain_spec, rpc, tx['destination_token']) + tx['destination_token_symbol'] = token.symbol + tx['destination_token_decimals'] = token.decimals + + return tx diff --git a/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py b/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py index 23953229..54b8ad58 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/filters/register.py @@ -12,20 +12,24 @@ from hexathon import ( # local imports from .base import SyncFilter -logg = logging.getLogger().getChild(__name__) +logg = logging.getLogger(__name__) account_registry_add_log_hash = '0x9cc987676e7d63379f176ea50df0ae8d2d9d1141d1231d4ce15b5965f73c9430' class RegistrationFilter(SyncFilter): - def __init__(self, chain_spec, queue): + def __init__(self, chain_spec, contract_address, queue=None): self.chain_spec = chain_spec self.queue = queue + self.contract_address = contract_address def filter(self, conn, block, tx, db_session=None): - registered_address = None + if self.contract_address != tx.inputs[0]: + logg.debug('not an account registry tx; {} != {}'.format(self.contract_address, tx.inputs[0])) + return None + for l in tx.logs: event_topic_hex = l['topics'][0] if event_topic_hex == account_registry_add_log_hash: diff --git a/apps/cic-eth/cic_eth/runnable/daemons/tracker.py b/apps/cic-eth/cic_eth/runnable/daemons/tracker.py index 0a977825..94b29883 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/tracker.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/tracker.py @@ -78,6 +78,14 @@ chain_spec = ChainSpec.from_chain_str(config.get('CIC_CHAIN_SPEC')) cic_base.rpc.setup(chain_spec, config.get('ETH_PROVIDER')) +rpc = RPCConnection.connect(chain_spec, 'default') +registry = None +try: + registry = connect_registry(rpc, chain_spec, config.get('CIC_REGISTRY_ADDRESS')) +except UnknownContractError as e: + logg.exception('Registry contract connection failed for {}: {}'.format(config.get('CIC_REGISTRY_ADDRESS'), e)) + sys.exit(1) +logg.info('connected contract registry {}'.format(config.get('CIC_REGISTRY_ADDRESS'))) def main(): @@ -85,7 +93,6 @@ def main(): celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) # Connect to blockchain with chainlib - rpc = RPCConnection.connect(chain_spec, 'default') o = block_latest() r = rpc.do(o) @@ -151,7 +158,8 @@ def main(): tx_filter = TxFilter(chain_spec, config.get('_CELERY_QUEUE')) - registration_filter = RegistrationFilter(chain_spec, config.get('_CELERY_QUEUE')) + account_registry_address = registry.by_name('AccountRegistry') + registration_filter = RegistrationFilter(chain_spec, account_registry_address, queue=config.get('_CELERY_QUEUE')) gas_filter = GasFilter(chain_spec, config.get('_CELERY_QUEUE')) diff --git a/apps/cic-eth/cic_eth/version.py b/apps/cic-eth/cic_eth/version.py index 8f85db25..036c79b2 100644 --- a/apps/cic-eth/cic_eth/version.py +++ b/apps/cic-eth/cic_eth/version.py @@ -9,7 +9,7 @@ import semver version = ( 0, 12, - 0, + 1, 'alpha.2', ) diff --git a/apps/cic-eth/requirements.txt b/apps/cic-eth/requirements.txt index 95ce95bc..35486723 100644 --- a/apps/cic-eth/requirements.txt +++ b/apps/cic-eth/requirements.txt @@ -1,3 +1,3 @@ celery==4.4.7 -chainlib~=0.0.5a1 +chainlib~=0.0.5a2 semver==2.13.0 diff --git a/apps/cic-eth/services_requirements.txt b/apps/cic-eth/services_requirements.txt index cab48e40..16713117 100644 --- a/apps/cic-eth/services_requirements.txt +++ b/apps/cic-eth/services_requirements.txt @@ -1,15 +1,15 @@ -chainsyncer[sql]~=0.0.3a3 -chainqueue~=0.0.2b5 +chainsyncer[sql]~=0.0.3a4 +chainqueue~=0.0.2b6 alembic==1.4.2 -confini~=0.3.6rc4 +confini>=0.3.6rc4,<0.5.0 redis==3.5.3 hexathon~=0.0.1a7 pycryptodome==3.10.1 liveness~=0.0.1a7 -eth-address-index~=0.1.2a1 -eth-accounts-index~=0.0.12a1 -cic-eth-registry~=0.5.6a1 -erc20-faucet~=0.2.2a1 -erc20-transfer-authorization~=0.3.2a1 -sarafu-faucet~=0.0.4a1 +eth-address-index~=0.1.2a2 +eth-accounts-index~=0.0.12a2 +cic-eth-registry~=0.5.6a2 +erc20-faucet~=0.2.2a2 +erc20-transfer-authorization~=0.3.2a2 +sarafu-faucet~=0.0.4a3 moolb~=0.1.1b2 diff --git a/apps/cic-eth/test_requirements.txt b/apps/cic-eth/test_requirements.txt index 600a7df3..088324c5 100644 --- a/apps/cic-eth/test_requirements.txt +++ b/apps/cic-eth/test_requirements.txt @@ -6,4 +6,4 @@ pytest-redis==2.0.0 redis==3.5.3 eth-tester==0.5.0b3 py-evm==0.3.0a20 -eth-erc20~=0.0.10a2 +eth-erc20~=0.0.10a3 diff --git a/apps/cic-eth/tests/filters/test_filter_bogus.py b/apps/cic-eth/tests/filters/test_filter_bogus.py index 30edbc70..01539a5b 100644 --- a/apps/cic-eth/tests/filters/test_filter_bogus.py +++ b/apps/cic-eth/tests/filters/test_filter_bogus.py @@ -18,6 +18,7 @@ def test_filter_bogus( cic_registry, contract_roles, register_lookups, + account_registry, ): fltrs = [ @@ -26,7 +27,7 @@ def test_filter_bogus( TxFilter(default_chain_spec, None), CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER']), StragglerFilter(default_chain_spec, None), - RegistrationFilter(default_chain_spec, queue=None), + RegistrationFilter(default_chain_spec, account_registry, queue=None), ] for fltr in fltrs: diff --git a/apps/cic-eth/tests/filters/test_register_filter.py b/apps/cic-eth/tests/filters/test_register_filter.py index ce4543bb..431da1fb 100644 --- a/apps/cic-eth/tests/filters/test_register_filter.py +++ b/apps/cic-eth/tests/filters/test_register_filter.py @@ -1,3 +1,7 @@ +# standard imports +import logging +import os + # external imports from eth_accounts_index.registry import AccountRegistry from chainlib.connection import RPCConnection @@ -14,12 +18,17 @@ from chainlib.eth.block import ( Block, ) from erc20_faucet import Faucet -from hexathon import strip_0x +from hexathon import ( + strip_0x, + add_0x, + ) from chainqueue.sql.query import get_account_tx # local imports from cic_eth.runnable.daemons.filters.register import RegistrationFilter +logg = logging.getLogger() + def test_register_filter( default_chain_spec, @@ -60,7 +69,11 @@ def test_register_filter( tx = Tx(tx_src, block=block, rcpt=rcpt) tx.apply_receipt(rcpt) - fltr = RegistrationFilter(default_chain_spec, queue=None) + fltr = RegistrationFilter(default_chain_spec, add_0x(os.urandom(20).hex()), queue=None) + t = fltr.filter(eth_rpc, block, tx, db_session=init_database) + assert t == None + + fltr = RegistrationFilter(default_chain_spec, account_registry, queue=None) t = fltr.filter(eth_rpc, block, tx, db_session=init_database) t.get_leaf() diff --git a/apps/cic-eth/tests/task/test_task_list.py b/apps/cic-eth/tests/task/test_task_list.py new file mode 100644 index 00000000..93983476 --- /dev/null +++ b/apps/cic-eth/tests/task/test_task_list.py @@ -0,0 +1,92 @@ +# external imports +import celery +import pytest +from chainlib.connection import RPCConnection +from chainlib.eth.constant import ZERO_ADDRESS +from chainlib.eth.gas import ( + RPCGasOracle, + ) +from chainlib.eth.tx import ( + TxFormat, + unpack, + ) +from chainlib.eth.nonce import RPCNonceOracle +from eth_erc20 import ERC20 +from hexathon import ( + add_0x, + strip_0x, + ) +from chainqueue.db.models.tx import TxCache +from chainqueue.db.models.otx import Otx + + +def test_ext_tx_collate( + default_chain_spec, + init_database, + eth_rpc, + eth_signer, + custodial_roles, + agent_roles, + foo_token, + bar_token, + register_tokens, + cic_registry, + register_lookups, + init_celery_tasks, + celery_session_worker, + ): + + rpc = RPCConnection.connect(default_chain_spec, 'default') + nonce_oracle = RPCNonceOracle(custodial_roles['FOO_TOKEN_GIFTER'], eth_rpc) + gas_oracle = RPCGasOracle(eth_rpc) + + c = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + transfer_value_foo = 1000 + transfer_value_bar = 1024 + (tx_hash_hex, tx_signed_raw_hex) = c.transfer(foo_token, custodial_roles['FOO_TOKEN_GIFTER'], agent_roles['ALICE'], transfer_value_foo, tx_format=TxFormat.RLP_SIGNED) + tx = unpack(bytes.fromhex(strip_0x(tx_signed_raw_hex)), default_chain_spec) + + otx = Otx( + tx['nonce'], + tx_hash_hex, + tx_signed_raw_hex, + ) + init_database.add(otx) + init_database.commit() + + txc = TxCache( + tx_hash_hex, + tx['from'], + tx['to'], + foo_token, + bar_token, + transfer_value_foo, + transfer_value_bar, + 666, + 13, + session=init_database, + ) + init_database.add(txc) + init_database.commit() + + s = celery.signature( + 'cic_eth.ext.tx.tx_collate', + [ + {tx_hash_hex: tx_signed_raw_hex}, + default_chain_spec.asdict(), + 0, + 100, + ], + queue=None, + ) + t = s.apply_async() + r = t.get_leaf() + assert t.successful() + + assert len(r) == 1 + + tx = r[0] + assert tx['source_token_symbol'] == 'FOO' + assert tx['source_token_decimals'] == 6 + assert tx['destination_token_symbol'] == 'BAR' + assert tx['destination_token_decimals'] == 9 diff --git a/apps/cic-eth/tools_requirements.txt b/apps/cic-eth/tools_requirements.txt index 67ab3257..0920b4b2 100644 --- a/apps/cic-eth/tools_requirements.txt +++ b/apps/cic-eth/tools_requirements.txt @@ -1,7 +1,7 @@ -crypto-dev-signer~=0.4.14b6 +crypto-dev-signer~=0.4.14b7 chainqueue~=0.0.2b5 -confini~=0.3.6rc4 -cic-eth-registry~=0.5.6a1 +confini>=0.3.6rc4,<0.5.0 +cic-eth-registry~=0.5.6a2 redis==3.5.3 hexathon~=0.0.1a7 pycryptodome==3.10.1 diff --git a/apps/cic-notify/cic_notify/version.py b/apps/cic-notify/cic_notify/version.py index e8f70c71..475867be 100644 --- a/apps/cic-notify/cic_notify/version.py +++ b/apps/cic-notify/cic_notify/version.py @@ -9,7 +9,7 @@ import semver logg = logging.getLogger() -version = (0, 4, 0, 'alpha.7') +version = (0, 4, 0, 'alpha.8') version_object = semver.VersionInfo( major=version[0], diff --git a/apps/cic-notify/requirements.txt b/apps/cic-notify/requirements.txt index 17b36f50..5b677093 100644 --- a/apps/cic-notify/requirements.txt +++ b/apps/cic-notify/requirements.txt @@ -1 +1 @@ -cic_base[full_graph]==0.1.3a3+build.984b5cff +cic_base[full_graph]~=0.2.0a3 diff --git a/apps/cic-ussd/.config/app.ini b/apps/cic-ussd/.config/app.ini index 1a0b5e4f..7fdb8c44 100644 --- a/apps/cic-ussd/.config/app.ini +++ b/apps/cic-ussd/.config/app.ini @@ -1,7 +1,7 @@ [app] ALLOWED_IP=0.0.0.0/0 LOCALE_FALLBACK=en -LOCALE_PATH=/usr/src/cic-ussd/var/lib/locale/ +LOCALE_PATH=var/lib/locale/ MAX_BODY_LENGTH=1024 PASSWORD_PEPPER=QYbzKff6NhiQzY3ygl2BkiKOpER8RE/Upqs/5aZWW+I= SERVICE_CODE=*483*46#,*483*061#,*384*96# @@ -11,13 +11,13 @@ SUPPORT_PHONE_NUMBER=0757628885 REGION=KE [ussd] -MENU_FILE=/usr/src/data/ussd_menu.json +MENU_FILE=data/ussd_menu.json user = pass = [statemachine] -STATES=/usr/src/cic-ussd/states/ -TRANSITIONS=/usr/src/cic-ussd/transitions/ +STATES=states/ +TRANSITIONS=transitions/ [client] host = diff --git a/apps/cic-ussd/.config/pgp.ini b/apps/cic-ussd/.config/pgp.ini index c06f2838..7d0dc63b 100644 --- a/apps/cic-ussd/.config/pgp.ini +++ b/apps/cic-ussd/.config/pgp.ini @@ -1,5 +1,5 @@ [pgp] -export_dir = /usr/src/pgp/keys/ +export_dir = pgp/keys/ keys_path = /usr/src/secrets/ private_keys = privatekeys_meta.asc passphrase = diff --git a/apps/cic-ussd/docker/start_cic_user_server.sh b/apps/cic-ussd/docker/start_cic_user_server.sh index 08742684..5d6ecb00 100644 --- a/apps/cic-ussd/docker/start_cic_user_server.sh +++ b/apps/cic-ussd/docker/start_cic_user_server.sh @@ -4,4 +4,4 @@ user_server_port=${SERVER_PORT:-9500} -/usr/local/bin/uwsgi --wsgi-file /usr/local/lib/python3.8/site-packages/cic_ussd/runnable/daemons/cic_user_server.py --http :"$user_server_port" --pyargv "$@" +/usr/local/bin/uwsgi --wsgi-file cic_ussd/runnable/daemons/cic_user_server.py --http :"$user_server_port" --pyargv "$@" diff --git a/apps/cic-ussd/docker/start_cic_user_ussd_server.sh b/apps/cic-ussd/docker/start_cic_user_ussd_server.sh index 9bb6b9b5..35b18207 100644 --- a/apps/cic-ussd/docker/start_cic_user_ussd_server.sh +++ b/apps/cic-ussd/docker/start_cic_user_ussd_server.sh @@ -4,4 +4,4 @@ user_ussd_server_port=${SERVER_PORT:-9000} -/usr/local/bin/uwsgi --wsgi-file /usr/local/lib/python3.8/site-packages/cic_ussd/runnable/daemons/cic_user_ussd_server.py --http :"$user_ussd_server_port" --pyargv "$@" +/usr/local/bin/uwsgi --wsgi-file cic_ussd/runnable/daemons/cic_user_ussd_server.py --http :"$user_ussd_server_port" --pyargv "$@" diff --git a/apps/cic-ussd/requirements.txt b/apps/cic-ussd/requirements.txt index a9c0cbf8..2b96a9d8 100644 --- a/apps/cic-ussd/requirements.txt +++ b/apps/cic-ussd/requirements.txt @@ -1,4 +1,4 @@ -cic_base[full_graph]==0.1.3a3+build.984b5cff +cic_base[full_graph]==0.2.0a3 cic-eth~=0.12.0a1 -cic-notify~=0.4.0a7 +cic-notify~=0.4.0a8 cic-types~=0.1.0a11 diff --git a/apps/contract-migration/reset.sh b/apps/contract-migration/reset.sh index 8c5f5b3b..3b99a3d0 100755 --- a/apps/contract-migration/reset.sh +++ b/apps/contract-migration/reset.sh @@ -3,14 +3,9 @@ set -a default_token=giftable_erc20_token -CIC_DEFAULT_TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL:-GFT} TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL} -TOKEN_NAME=${TOKEN_NAME:-$TOKEN_SYMBOL} +TOKEN_NAME=${TOKEN_NAME} TOKEN_TYPE=${TOKEN_TYPE:-$default_token} -if [ $TOKEN_TYPE == 'default' ]; then - >&2 echo resolving "default" token to $default_token - TOKEN_TYPE=$default_token -fi cat <&2 echo token symbol not set, setting defaults for type $TOKEN_TYPE + TOKEN_SYMBOL="GFT" + TOKEN_NAME="Giftable Token" + elif [ -z "$TOKEN_NAME" ]; then + >&2 echo token name not set, setting same as symbol for type $TOKEN_TYPE + TOKEN_NAME=$TOKEN_SYMBOL + fi >&2 echo deploying default token $TOKEN_TYPE - DEV_RESERVE_ADDRESS=`giftable-token-deploy $gas_price_arg -p $ETH_PROVIDER -y $DEV_ETH_KEYSTORE_FILE -i $CIC_CHAIN_SPEC -vv -ww --name $TOKEN_NAME --symbol $TOKEN_SYMBOL --decimals 6 -vv` - elif [ $TOKEN_TYPE == 'erc20_demurrage_token' ]; then + echo giftable-token-deploy $gas_price_arg -p $ETH_PROVIDER -y $DEV_ETH_KEYSTORE_FILE -i $CIC_CHAIN_SPEC -vv -ww --name "$TOKEN_NAME" --symbol $TOKEN_SYMBOL --decimals 6 -vv + DEV_RESERVE_ADDRESS=`giftable-token-deploy $gas_price_arg -p $ETH_PROVIDER -y $DEV_ETH_KEYSTORE_FILE -i $CIC_CHAIN_SPEC -vv -ww --name "$TOKEN_NAME" --symbol $TOKEN_SYMBOL --decimals 6 -vv` + elif [ "$TOKEN_TYPE" == "erc20_demurrage_token" ]; then + if [ -z "$TOKEN_SYMBOL" ]; then + >&2 echo token symbol not set, setting defaults for type $TOKEN_TYPE + TOKEN_SYMBOL="SARAFU" + TOKEN_NAME="Sarafu Token" + elif [ -z "$TOKEN_NAME" ]; then + >&2 echo token name not set, setting same as symbol for type $TOKEN_TYPE + TOKEN_NAME=$TOKEN_SYMBOL + fi >&2 echo deploying token $TOKEN_TYPE if [ -z $TOKEN_SINK_ADDRESS ]; then if [ ! -z $TOKEN_REDISTRIBUTION_PERIOD ]; then >&2 echo -e "\033[;93mtoken sink address not set, so redistribution will be BURNED\033[;39m" fi fi - DEV_RESERVE_ADDRESS=`erc20-demurrage-token-deploy $gas_price_arg -p $ETH_PROVIDER -y $DEV_ETH_KEYSTORE_FILE -i $CIC_CHAIN_SPEC -vv -ww` + DEV_RESERVE_ADDRESS=`erc20-demurrage-token-deploy $gas_price_arg -p $ETH_PROVIDER -y $DEV_ETH_KEYSTORE_FILE -i $CIC_CHAIN_SPEC --name "$TOKEN_NAME" --symbol $TOKEN_SYMBOL -vv -ww` else >&2 echo unknown token type $TOKEN_TYPE exit 1 diff --git a/apps/data-seeding/cic_eth/import_balance.py b/apps/data-seeding/cic_eth/import_balance.py index 99e8eef4..7f7c840c 100644 --- a/apps/data-seeding/cic_eth/import_balance.py +++ b/apps/data-seeding/cic_eth/import_balance.py @@ -11,7 +11,6 @@ import csv import json # external imports -import eth_abi import confini from hexathon import ( strip_0x, @@ -29,7 +28,10 @@ from chainlib.eth.gas import OverrideGasOracle from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.tx import TxFactory from chainlib.jsonrpc import JSONRPCRequest -from chainlib.eth.error import EthException +from chainlib.eth.error import ( + EthException, + RequestMismatchException, + ) from chainlib.chain import ChainSpec from chainlib.eth.constant import ZERO_ADDRESS from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer @@ -37,6 +39,9 @@ from crypto_dev_signer.keystore.dict import DictKeystore from cic_types.models.person import Person from eth_erc20 import ERC20 from cic_base.eth.syncer import chain_interface +from eth_accounts_index import AccountsIndex +from eth_contract_registry import Registry +from eth_token_index import TokenUniqueSymbolIndex logging.basicConfig(level=logging.WARNING) @@ -131,58 +136,52 @@ class Handler: logg.debug('no payload, skipping {}'.format(tx)) return - if tx.payload[:8] == self.account_index_add_signature: - recipient = eth_abi.decode_single('address', bytes.fromhex(tx.payload[-64:])) - #original_address = to_checksum_address(self.addresses[to_checksum_address(recipient)]) - user_file = 'new/{}/{}/{}.json'.format( - recipient[2:4].upper(), - recipient[4:6].upper(), - recipient[2:].upper(), - ) - filepath = os.path.join(self.user_dir, user_file) - o = None - try: - f = open(filepath, 'r') - o = json.load(f) - f.close() - except FileNotFoundError: - logg.error('no import record of address {}'.format(recipient)) - return - u = Person.deserialize(o) - original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0] - try: - balance = self.balances[original_address] - except KeyError as e: - logg.error('balance get fail orig {} new {}'.format(original_address, recipient)) - return - - # TODO: store token object in handler ,get decimals from there - multiplier = 10**6 - balance_full = balance * multiplier - logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full)) - - (tx_hash_hex, o) = self.tx_factory.transfer(self.token_address, signer_address, recipient, balance_full) - logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient)) - r = conn.do(o) - - tx_path = os.path.join( - user_dir, - 'txs', - strip_0x(tx_hash_hex), - ) - f = open(tx_path, 'w') - f.write(strip_0x(o['params'][0])) + recipient = None + try: + r = AccountsIndex.parse_add_request(tx.payload) + except RequestMismatchException: + return + recipient = r[0] + + user_file = 'new/{}/{}/{}.json'.format( + recipient[2:4].upper(), + recipient[4:6].upper(), + recipient[2:].upper(), + ) + filepath = os.path.join(self.user_dir, user_file) + o = None + try: + f = open(filepath, 'r') + o = json.load(f) f.close() -# except TypeError as e: -# logg.warning('typerror {}'.format(e)) -# pass -# except IndexError as e: -# logg.warning('indexerror {}'.format(e)) -# pass -# except EthException as e: -# logg.error('send error {}'.format(e).ljust(200)) - #except KeyError as e: - # logg.error('key record not found in imports: {}'.format(e).ljust(200)) + except FileNotFoundError: + logg.error('no import record of address {}'.format(recipient)) + return + u = Person.deserialize(o) + original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0] + try: + balance = self.balances[original_address] + except KeyError as e: + logg.error('balance get fail orig {} new {}'.format(original_address, recipient)) + return + + # TODO: store token object in handler ,get decimals from there + multiplier = 10**6 + balance_full = balance * multiplier + logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full)) + + (tx_hash_hex, o) = self.tx_factory.transfer(self.token_address, signer_address, recipient, balance_full) + logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient)) + r = conn.do(o) + + tx_path = os.path.join( + user_dir, + 'txs', + strip_0x(tx_hash_hex), + ) + f = open(tx_path, 'w') + f.write(strip_0x(o['params'][0])) + f.close() def progress_callback(block_number, tx_index): @@ -198,49 +197,26 @@ def main(): nonce_oracle = RPCNonceOracle(signer_address, conn) # Get Token registry address - txf = TxFactory(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=None) - tx = txf.template(signer_address, config.get('CIC_REGISTRY_ADDRESS')) - - registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8] - data = add_0x(registry_addressof_method) - data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex() - txf.set_code(tx, data) - - j = JSONRPCRequest() - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) + registry = Registry(chain_spec) + o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry') r = conn.do(o) - token_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + token_index_address = registry.parse_address_of(r) + token_index_address = to_checksum_address(token_index_address) logg.info('found token index address {}'.format(token_index_address)) - - + # Get Sarafu token address - tx = txf.template(signer_address, token_index_address) - data = add_0x(registry_addressof_method) - h = hashlib.new('sha256') - h.update(token_symbol.encode('utf-8')) - z = h.digest() - data += eth_abi.encode_single('bytes32', z).hex() - txf.set_code(tx, data) - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) + token_index = TokenUniqueSymbolIndex(chain_spec) + o = token_index.address_of(token_index_address, token_symbol) r = conn.do(o) + token_address = token_index.parse_address_of(r) try: - sarafu_token_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + token_address = to_checksum_address(token_address) except ValueError as e: logg.critical('lookup failed for token {}: {}'.format(token_symbol, e)) sys.exit(1) - - if sarafu_token_address == ZERO_ADDRESS: - raise KeyError('token address for symbol {} is zero'.format(token_symbol)) - - logg.info('found token address {}'.format(sarafu_token_address)) + logg.info('found token address {}'.format(token_address)) + + sys.exit(0) syncer_backend = MemBackend(chain_str, 0) @@ -248,22 +224,6 @@ def main(): o = block_latest() r = conn.do(o) block_offset = int(strip_0x(r), 16) + 1 -# -# addresses = {} -# f = open('{}/addresses.csv'.format(user_dir, 'r')) -# while True: -# l = f.readline() -# if l == None: -# break -# r = l.split(',') -# try: -# k = r[0] -# v = r[1].rstrip() -# addresses[k] = v -# sys.stdout.write('loading address mapping {} -> {}'.format(k, v).ljust(200) + "\r") -# except IndexError as e: -# break -# f.close() # TODO get decimals from token balances = {} diff --git a/apps/data-seeding/cic_ussd/import_ussd_data.py b/apps/data-seeding/cic_ussd/import_ussd_data.py index fddd8bb6..44f06be9 100644 --- a/apps/data-seeding/cic_ussd/import_ussd_data.py +++ b/apps/data-seeding/cic_ussd/import_ussd_data.py @@ -17,7 +17,7 @@ default_config_dir = '/usr/local/etc/cic' arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-c', type=str, default=default_config_dir, help='config file') -arg_parser.add_argument('-q', type=str, default='cic-eth', help='Task queue') +arg_parser.add_argument('-q', type=str, default='cic-import-ussd', help='Task queue') arg_parser.add_argument('-v', action='store_true', help='Be verbose') arg_parser.add_argument('-vv', action='store_true', help='Be more verbose') arg_parser.add_argument('user_dir', type=str, help='path to users export dir tree') diff --git a/apps/data-seeding/create_import_users.py b/apps/data-seeding/create_import_users.py index dc252fce..aa8e4e59 100644 --- a/apps/data-seeding/create_import_users.py +++ b/apps/data-seeding/create_import_users.py @@ -206,7 +206,7 @@ def gen(): # fake.local_latitude() p.location['latitude'] = (random.random() * 180) - 90 # fake.local_latitude() - p.location['longitude'] = (random.random() * 360) - 179 + p.location['longitude'] = (random.random() * 360) - 180 return (old_blockchain_checksum_address, phone, p) diff --git a/apps/data-seeding/eth/import_balance.py b/apps/data-seeding/eth/import_balance.py index 2d436a66..e70bce49 100644 --- a/apps/data-seeding/eth/import_balance.py +++ b/apps/data-seeding/eth/import_balance.py @@ -11,7 +11,6 @@ import csv import json # external imports -import eth_abi import confini from hexathon import ( strip_0x, @@ -29,13 +28,20 @@ from chainlib.eth.gas import OverrideGasOracle from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.tx import TxFactory from chainlib.jsonrpc import JSONRPCRequest -from chainlib.eth.error import EthException +from chainlib.eth.error import ( + EthException, + RequestMismatchException, + ) from chainlib.chain import ChainSpec from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer from crypto_dev_signer.keystore.dict import DictKeystore from cic_types.models.person import Person from eth_erc20 import ERC20 from cic_base.eth.syncer import chain_interface +from eth_accounts_index import AccountsIndex +from eth_contract_registry import Registry +from eth_token_index import TokenUniqueSymbolIndex +from erc20_faucet import Faucet logging.basicConfig(level=logging.WARNING) @@ -50,7 +56,7 @@ argparser.add_argument('-c', type=str, default=config_dir, help='config root to argparser.add_argument('--old-chain-spec', type=str, dest='old_chain_spec', default='evm:oldchain:1', help='chain spec') argparser.add_argument('-i', '--chain-spec', type=str, dest='i', help='chain spec') argparser.add_argument('-r', '--registry-address', type=str, dest='r', help='CIC Registry address') -argparser.add_argument('--token-symbol', default='SRF', type=str, dest='token_symbol', help='Token symbol to use for trnsactions') +argparser.add_argument('--token-symbol', default='GFT', type=str, dest='token_symbol', help='Token symbol to use for trnsactions') argparser.add_argument('--head', action='store_true', help='start at current block height (overrides --offset)') 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('-q', type=str, default='cic-eth', help='celery queue to submit transaction tasks to') @@ -112,12 +118,16 @@ class Handler: account_index_add_signature = keccak256_string_to_hex('add(address)')[:8] - def __init__(self, conn, chain_spec, user_dir, balances, token_address, signer, gas_oracle, nonce_oracle): + def __init__(self, conn, chain_spec, user_dir, balances, token_address, faucet_address, signer_address, signer, gas_oracle, nonce_oracle): self.token_address = token_address + self.faucet_address = faucet_address self.user_dir = user_dir self.balances = balances self.chain_spec = chain_spec - self.tx_factory = ERC20(chain_spec, signer, gas_oracle, nonce_oracle) + self.nonce_oracle = nonce_oracle + self.gas_oracle = gas_oracle + self.signer_address = signer_address + self.signer = signer def name(self): @@ -129,58 +139,59 @@ class Handler: logg.debug('no payload, skipping {}'.format(tx)) return - if tx.payload[:8] == self.account_index_add_signature: - recipient = eth_abi.decode_single('address', bytes.fromhex(tx.payload[-64:])) - #original_address = to_checksum_address(self.addresses[to_checksum_address(recipient)]) - user_file = 'new/{}/{}/{}.json'.format( - recipient[2:4].upper(), - recipient[4:6].upper(), - recipient[2:].upper(), - ) - filepath = os.path.join(self.user_dir, user_file) - o = None - try: - f = open(filepath, 'r') - o = json.load(f) - f.close() - except FileNotFoundError: - logg.error('no import record of address {}'.format(recipient)) - return - u = Person.deserialize(o) - original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0] - try: - balance = self.balances[original_address] - except KeyError as e: - logg.error('balance get fail orig {} new {}'.format(original_address, recipient)) - return - - # TODO: store token object in handler ,get decimals from there - multiplier = 10**6 - balance_full = balance * multiplier - logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full)) - - (tx_hash_hex, o) = self.tx_factory.transfer(self.token_address, signer_address, recipient, balance_full) - logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient)) - r = conn.do(o) - - tx_path = os.path.join( - user_dir, - 'txs', - strip_0x(tx_hash_hex), - ) - f = open(tx_path, 'w') - f.write(strip_0x(o['params'][0])) + recipient = None + try: + r = AccountsIndex.parse_add_request(tx.payload) + except RequestMismatchException: + return + recipient = r[0] + + user_file = 'new/{}/{}/{}.json'.format( + recipient[2:4].upper(), + recipient[4:6].upper(), + recipient[2:].upper(), + ) + filepath = os.path.join(self.user_dir, user_file) + o = None + try: + f = open(filepath, 'r') + o = json.load(f) f.close() -# except TypeError as e: -# logg.warning('typerror {}'.format(e)) -# pass -# except IndexError as e: -# logg.warning('indexerror {}'.format(e)) -# pass -# except EthException as e: -# logg.error('send error {}'.format(e).ljust(200)) - #except KeyError as e: - # logg.error('key record not found in imports: {}'.format(e).ljust(200)) + except FileNotFoundError: + logg.error('no import record of address {}'.format(recipient)) + return + u = Person.deserialize(o) + original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0] + try: + balance = self.balances[original_address] + except KeyError as e: + logg.error('balance get fail orig {} new {}'.format(original_address, recipient)) + return + + # TODO: store token object in handler ,get decimals from there + erc20 = ERC20(self.chain_spec, signer=self.signer, gas_oracle=self.gas_oracle, nonce_oracle=self.nonce_oracle) + o = erc20.decimals(self.token_address) + r = conn.do(o) + decimals = erc20.parse_decimals(r) + multiplier = 10 ** decimals + balance_full = balance * multiplier + logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full)) + (tx_hash_hex, o) = erc20.transfer(self.token_address, self.signer_address, recipient, balance_full) + logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient)) + r = conn.do(o) + + tx_path = os.path.join( + user_dir, + 'txs', + strip_0x(tx_hash_hex), + ) + f = open(tx_path, 'w') + f.write(strip_0x(o['params'][0])) + f.close() + + faucet = Faucet(self.chain_spec, signer=self.signer, gas_oracle=self.gas_oracle, nonce_oracle=self.nonce_oracle) + (tx_hash, o) = faucet.give_to(self.faucet_address, self.signer_address, recipient) + r = conn.do(o) def progress_callback(block_number, tx_index): @@ -196,45 +207,31 @@ def main(): nonce_oracle = RPCNonceOracle(signer_address, conn) # Get Token registry address - txf = TxFactory(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=None) - tx = txf.template(signer_address, config.get('CIC_REGISTRY_ADDRESS')) - - registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8] - data = add_0x(registry_addressof_method) - data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex() - txf.set_code(tx, data) - - j = JSONRPCRequest() - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) + registry = Registry(chain_spec) + o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry') r = conn.do(o) - token_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + token_index_address = registry.parse_address_of(r) + token_index_address = to_checksum_address(token_index_address) logg.info('found token index address {}'.format(token_index_address)) - + + # Get Faucet address + o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'Faucet') + r = conn.do(o) + faucet_address = registry.parse_address_of(r) + faucet_address = to_checksum_address(faucet_address) + logg.info('found faucet {}'.format(faucet_address)) # Get Sarafu token address - tx = txf.template(signer_address, token_index_address) - data = add_0x(registry_addressof_method) - h = hashlib.new('sha256') - h.update(token_symbol.encode('utf-8')) - z = h.digest() - data += eth_abi.encode_single('bytes32', z).hex() - txf.set_code(tx, data) - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) + token_index = TokenUniqueSymbolIndex(chain_spec) + o = token_index.address_of(token_index_address, token_symbol) r = conn.do(o) + token_address = token_index.parse_address_of(r) try: - sarafu_token_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + token_address = to_checksum_address(token_address) except ValueError as e: logg.critical('lookup failed for token {}: {}'.format(token_symbol, e)) sys.exit(1) - logg.info('found token address {}'.format(sarafu_token_address)) + logg.info('found token address {}'.format(token_address)) syncer_backend = MemBackend(chain_str, 0) @@ -242,22 +239,6 @@ def main(): o = block_latest() r = conn.do(o) block_offset = int(strip_0x(r), 16) + 1 -# -# addresses = {} -# f = open('{}/addresses.csv'.format(user_dir, 'r')) -# while True: -# l = f.readline() -# if l == None: -# break -# r = l.split(',') -# try: -# k = r[0] -# v = r[1].rstrip() -# addresses[k] = v -# sys.stdout.write('loading address mapping {} -> {}'.format(k, v).ljust(200) + "\r") -# except IndexError as e: -# break -# f.close() # TODO get decimals from token balances = {} @@ -282,7 +263,7 @@ def main(): syncer_backend.set(block_offset, 0) syncer = HeadSyncer(syncer_backend, chain_interface, block_callback=progress_callback) - handler = Handler(conn, chain_spec, user_dir, balances, sarafu_token_address, signer, gas_oracle, nonce_oracle) + handler = Handler(conn, chain_spec, user_dir, balances, token_address, faucet_address, signer_address, signer, gas_oracle, nonce_oracle) syncer.add_filter(handler) syncer.loop(1, conn) diff --git a/apps/data-seeding/requirements.txt b/apps/data-seeding/requirements.txt index ab043327..0919fb95 100644 --- a/apps/data-seeding/requirements.txt +++ b/apps/data-seeding/requirements.txt @@ -1,4 +1,12 @@ -sarafu-faucet==0.0.4a1 -cic-eth[tools]==0.12.0a1 +sarafu-faucet==0.0.4a3 +cic-eth[tools]==0.12.1a1 cic-types==0.1.0a13 -crypto-dev-signer==0.4.14b6 +crypto-dev-signer==0.4.14b7 +faker==4.17.1 +chainsyncer~=0.0.3a3 +chainlib-eth~=0.0.5a1 +eth-address-index~=0.1.2a1 +eth-contract-registry~=0.5.6a1 +eth-accounts-index~=0.0.12a1 +eth-erc20~=0.0.10a3 +erc20-faucet~=0.2.2a1 diff --git a/apps/data-seeding/verify.py b/apps/data-seeding/verify.py index 09813d9b..911f0750 100644 --- a/apps/data-seeding/verify.py +++ b/apps/data-seeding/verify.py @@ -14,7 +14,6 @@ import urllib.parse # external imports import celery import confini -import eth_abi from chainlib.chain import ChainSpec from chainlib.eth.address import to_checksum_address from chainlib.eth.connection import EthHTTPConnection @@ -33,6 +32,9 @@ from cic_types.models.person import ( from erc20_faucet import Faucet from eth_erc20 import ERC20 from hexathon.parse import strip_0x, add_0x +from eth_contract_registry import Registry +from eth_accounts_index import AccountsIndex +from eth_token_index import TokenUniqueSymbolIndex logging.basicConfig(level=logging.WARNING) logg = logging.getLogger() @@ -43,7 +45,8 @@ custodial_tests = [ 'local_key', 'gas', 'faucet', - 'ussd' + 'ussd', + 'ussd_pins', ] metadata_tests = [ @@ -71,6 +74,7 @@ argparser.add_argument('-i', '--chain-spec', type=str, dest='i', help='chain spe argparser.add_argument('--meta-provider', type=str, dest='meta_provider', default='http://localhost:63380', help='cic-meta url') argparser.add_argument('--ussd-provider', type=str, dest='ussd_provider', default='http://localhost:63315', help='cic-ussd url') argparser.add_argument('--skip-custodial', dest='skip_custodial', action='store_true', help='skip all custodial verifications') +argparser.add_argument('--skip-metadata', dest='skip_metadata', action='store_true', help='skip all metadata verifications') argparser.add_argument('--exclude', action='append', type=str, default=[], help='skip specified verification') argparser.add_argument('--include', action='append', type=str, help='include specified verification') argparser.add_argument('--token-symbol', default='GFT', type=str, dest='token_symbol', help='Token symbol to use for trnsactions') @@ -130,6 +134,11 @@ if args.skip_custodial: for t in custodial_tests: if t not in exclude: exclude.append(t) +if args.skip_metadata: + logg.info('will skip all metadata verifications ({})'.format(','.join(metadata_tests))) + for t in metadata_tests: + if t not in exclude: + exclude.append(t) for t in include: if t not in all_tests: raise ValueError('Cannot include unknown verification "{}"'.format(t)) @@ -140,7 +149,7 @@ for t in include: api = None for t in custodial_tests: if t in active_tests: - from cic_eth.api.api_admin import AdminApi + from cic_eth.api.admin import AdminApi api = AdminApi(None) logg.info('activating custodial module'.format(t)) break @@ -263,19 +272,11 @@ class Verifier: def verify_accounts_index(self, address, balance=None): - tx = self.tx_factory.template(ZERO_ADDRESS, self.index_address) - data = keccak256_string_to_hex('have(address)')[:8] - data += eth_abi.encode_single('address', address).hex() - tx = self.tx_factory.set_code(tx, data) - tx = self.tx_factory.normalize(tx) - j = JSONRPCRequest() - o = j.template() - o['method'] = 'eth_call' - o['params'].append(tx) - o = j.finalize(o) + accounts_index = AccountsIndex(self.chain_spec) + o = accounts_index.have(self.index_address, address) r = self.conn.do(o) - logg.debug('index check for {}: {}'.format(address, r)) - n = eth_abi.decode_single('uint256', bytes.fromhex(strip_0x(r))) + n = accounts_index.parse_have(r) + logg.debug('index check for {}: {}'.format(address, n)) if n != 1: raise VerifierError(n, 'accounts index') @@ -427,70 +428,39 @@ def main(): gas_oracle = OverrideGasOracle(conn=conn, limit=8000000) # Get Token registry address - txf = TxFactory(chain_spec, signer=None, gas_oracle=gas_oracle, nonce_oracle=None) - tx = txf.template(ZERO_ADDRESS, config.get('CIC_REGISTRY_ADDRESS')) - - # TODO: replace with cic-eth-registry - registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8] - data = add_0x(registry_addressof_method) - data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex() - txf.set_code(tx, data) - - j = JSONRPCRequest() - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) + registry = Registry(chain_spec) + o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry') r = conn.do(o) - token_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + token_index_address = registry.parse_address_of(r) + token_index_address = to_checksum_address(token_index_address) logg.info('found token index address {}'.format(token_index_address)) - data = add_0x(registry_addressof_method) - data += eth_abi.encode_single('bytes32', b'AccountRegistry').hex() - txf.set_code(tx, data) - - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) + # Get Account registry address + o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'AccountRegistry') r = conn.do(o) - account_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + account_index_address = registry.parse_address_of(r) + account_index_address = to_checksum_address(account_index_address) logg.info('found account index address {}'.format(account_index_address)) - data = add_0x(registry_addressof_method) - data += eth_abi.encode_single('bytes32', b'Faucet').hex() - txf.set_code(tx, data) - - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) + # Get Faucet address + o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'Faucet') r = conn.do(o) - faucet_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) + faucet_address = registry.parse_address_of(r) + faucet_index_address = to_checksum_address(token_index_address) logg.info('found faucet {}'.format(faucet_address)) - - - # Get Sarafu token address - tx = txf.template(ZERO_ADDRESS, token_index_address) - data = add_0x(registry_addressof_method) - h = hashlib.new('sha256') - h.update(token_symbol.encode('utf-8')) - z = h.digest() - data += eth_abi.encode_single('bytes32', z).hex() - txf.set_code(tx, data) - o = j.template() - o['method'] = 'eth_call' - o['params'].append(txf.normalize(tx)) - o['params'].append('latest') - o = j.finalize(o) +# Get Sarafu token address + token_index = TokenUniqueSymbolIndex(chain_spec) + o = token_index.address_of(token_index_address, token_symbol) r = conn.do(o) - sarafu_token_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) - logg.info('found token address {}'.format(sarafu_token_address)) - + token_address = token_index.parse_address_of(r) + try: + token_address = to_checksum_address(token_address) + except ValueError as e: + logg.critical('lookup failed for token {}: {}'.format(token_symbol, e)) + sys.exit(1) + logg.info('found token address {}'.format(token_address)) + balances = {} f = open('{}/balances.csv'.format(user_dir, 'r')) i = 0 @@ -511,7 +481,7 @@ def main(): f.close() - verifier = Verifier(conn, api, gas_oracle, chain_spec, account_index_address, sarafu_token_address, faucet_address, user_dir, exit_on_error) + verifier = Verifier(conn, api, gas_oracle, chain_spec, account_index_address, token_address, faucet_address, user_dir, exit_on_error) user_new_dir = os.path.join(user_dir, 'new') i = 0 diff --git a/docker-compose.yml b/docker-compose.yml index ead24b40..6a42825f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -103,14 +103,14 @@ services: DEV_FAUCET_AMOUNT: ${DEV_FAUCET_AMOUNT:-0} #DEV_SARAFU_DEMURRAGE_LEVEL: ${DEV_SARAFU_DEMURRAGE_LEVEL:-196454828847045000000000000000000} DEV_ETH_GAS_PRICE: ${DEV_ETH_GAS_PRICE:-1} - CIC_DEFAULT_TOKEN_SYMBOL: ${CIC_DEFAULT_TOKEN_SYMBOL:-GFT} + CIC_DEFAULT_TOKEN_SYMBOL: $CIC_DEFAULT_TOKEN_SYMBOL TOKEN_NAME: $TOKEN_NAME TOKEN_DECIMALS: $TOKEN_DECIMALS TOKEN_REDISTRIBUTION_PERIOD: $TOKEN_REDISTRIBUTION_PERIOD TOKEN_SUPPLY_LIMIT: $TOKEN_SUPPLY_LIMIT TOKEN_DEMURRAGE_LEVEL: ${TOKEN_DEMURRAGE_LEVEL:-196454828847045000000000000000000} TOKEN_SINK_ADDRESS: $TOKEN_SINK_ADDRESS - TOKEN_TYPE: ${TOKEN_TYPE:-default} + TOKEN_TYPE: $TOKEN_TYPE #CONFINI_DIR: ${CONFINI_DIR:-/tmp/cic/config} command: ["./run_job.sh"] #command: ["./reset.sh"]