Compare commits

...

17 Commits

Author SHA1 Message Date
nolash
5185e4dc08 Implement chaintool, chainsyncer alembic single source 2021-07-16 18:46:04 +02:00
Louis Holbrook
ed2521b582 Merge branch 'lash/migration-fix' into 'master'
Apply config changes to contract migration

See merge request grassrootseconomics/cic-internal-integration!229
2021-07-16 13:21:08 +00:00
Louis Holbrook
395930106a Apply config changes to contract migration 2021-07-16 13:21:07 +00:00
Louis Holbrook
ee1452e530 Merge branch 'lash/fix-ussd-impotrs' into 'master'
Make verify pass in ussd imports

See merge request grassrootseconomics/cic-internal-integration!228
2021-07-16 09:30:23 +00:00
nolash
8cdaf9f28a Fix confini instantiation in ussd 2021-07-15 00:54:48 +02:00
Louis Holbrook
402b968b6d Merge branch 'lash/dispatcher-leak' into 'master'
Fix dispatcher memory leak

See merge request grassrootseconomics/cic-internal-integration!220
2021-07-14 22:02:59 +00:00
Louis Holbrook
aa13517534 Fix dispatcher memory leak 2021-07-14 22:02:59 +00:00
Louis Holbrook
884b18f2f1 Merge branch 'lash/expand-tokens-in-list' into 'master'
Expand token symbol and decimals in tx listings

See merge request grassrootseconomics/cic-internal-integration!226
2021-07-14 15:06:20 +00:00
Louis Holbrook
494a8f3e88 Expand token symbol and decimals in tx listings 2021-07-14 15:06:20 +00:00
Geoff Turk
1214f605a7 Merge branch 'geoffturk/fix-geo-range' into 'master'
Fix out of range error for geolocation in import users script

See merge request grassrootseconomics/cic-internal-integration!225
2021-07-14 14:52:40 +00:00
Louis Holbrook
0783a6001c Merge branch 'lash/eth-abi-exorcism' into 'master'
Remove eth-abi dep in data seeding

See merge request grassrootseconomics/cic-internal-integration!224
2021-07-14 14:43:33 +00:00
Louis Holbrook
f9594b766a Remove eth-abi dep in data seeding 2021-07-14 14:43:32 +00:00
geoffturk
561ae62d5e Fix out of range error for geolocation in import users script 2021-07-13 09:42:53 +00:00
Louis Holbrook
d6782abbcc Merge branch 'lash/default-token-context' into 'master'
Add contextual token symbol and name defaults

Closes #85

See merge request grassrootseconomics/cic-internal-integration!219
2021-07-12 19:50:48 +00:00
Louis Holbrook
8f173fa30b Add contextual token symbol and name defaults 2021-07-12 19:50:48 +00:00
Louis Holbrook
3741cb3283 Merge branch 'lash/account-registry-filter-match' into 'master'
Only match account registry on correct contract address

Closes cic-eth#127

See merge request grassrootseconomics/cic-internal-integration!218
2021-07-12 19:50:32 +00:00
Louis Holbrook
54dd5acb62 Only match account registry on correct contract address 2021-07-12 19:50:32 +00:00
56 changed files with 610 additions and 454 deletions

View File

@@ -100,3 +100,4 @@ class SessionBase(Model):
logg.debug('destroying session {}'.format(session_key)) logg.debug('destroying session {}'.format(session_key))
session.commit() session.commit()
session.close() session.close()
del SessionBase.localsessions[session_key]

View File

@@ -1,13 +1,13 @@
cic-base==0.1.3a3+build.984b5cff cic-base~=0.2.0a4
alembic==1.4.2 alembic==1.4.2
confini~=0.3.6rc3 confini>=0.3.6rc3,<0.5.0
uwsgi==2.0.19.1 uwsgi==2.0.19.1
moolb~=0.1.0 moolb~=0.1.0
cic-eth-registry~=0.5.6a1 cic-eth-registry~=0.5.6a2
SQLAlchemy==1.3.20 SQLAlchemy==1.3.20
semver==2.13.0 semver==2.13.0
psycopg2==2.8.6 psycopg2==2.8.6
celery==4.4.7 celery==4.4.7
redis==3.5.3 redis==3.5.3
chainsyncer[sql]~=0.0.3a3 chainsyncer[sql]~=0.0.3a5
erc20-faucet~=0.2.2a1 erc20-faucet~=0.2.2a2

View File

@@ -1,5 +1,5 @@
SQLAlchemy==1.3.20 SQLAlchemy==1.3.20
cic-eth-registry~=0.5.6a1 cic-eth-registry~=0.5.6a2
hexathon~=0.0.1a7 hexathon~=0.0.1a7
chainqueue~=0.0.2b5 chainqueue~=0.0.2b6
eth-erc20==0.0.10a2 eth-erc20~=0.0.10a3

View File

@@ -8,7 +8,8 @@ Create Date: 2021-04-02 18:30:55.398388
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from chainqueue.db.migrations.sqlalchemy import ( #from chainqueue.db.migrations.sqlalchemy import (
from chainqueue.db.migrations.default.export import (
chainqueue_upgrade, chainqueue_upgrade,
chainqueue_downgrade, chainqueue_downgrade,
) )

View File

@@ -8,7 +8,7 @@ Create Date: 2021-04-02 18:36:44.459603
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from chainsyncer.db.migrations.sqlalchemy import ( from chainsyncer.db.migrations.default.export import (
chainsyncer_upgrade, chainsyncer_upgrade,
chainsyncer_downgrade, chainsyncer_downgrade,
) )

View File

@@ -126,3 +126,4 @@ class SessionBase(Model):
logg.debug('commit and destroy session {}'.format(session_key)) logg.debug('commit and destroy session {}'.format(session_key))
session.commit() session.commit()
session.close() session.close()
del SessionBase.localsessions[session_key]

View File

@@ -14,9 +14,11 @@ from chainlib.eth.tx import (
) )
from chainlib.eth.block import block_by_number from chainlib.eth.block import block_by_number
from chainlib.eth.contract import abi_decode_single from chainlib.eth.contract import abi_decode_single
from chainlib.eth.constant import ZERO_ADDRESS
from hexathon import strip_0x from hexathon import strip_0x
from cic_eth_registry import CICRegistry from cic_eth_registry import CICRegistry
from cic_eth_registry.erc20 import ERC20Token from cic_eth_registry.erc20 import ERC20Token
from cic_eth_registry.error import UnknownContractError
from chainqueue.db.models.otx import Otx from chainqueue.db.models.otx import Otx
from chainqueue.db.enum import StatusEnum from chainqueue.db.enum import StatusEnum
from chainqueue.sql.query import get_tx_cache 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 # TODO: pass through registry to validate declarator entry of token
#token = registry.by_address(tx['to'], sender_address=self.call_address) #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) times = tx_times(tx['hash'], chain_spec)
tx_r = { tx_r = {
'hash': tx['hash'], 'hash': tx['hash'],
@@ -126,12 +125,6 @@ def list_tx_by_bloom(self, bloomspec, address, chain_spec_dict):
'destination_value': tx_token_value, 'destination_value': tx_token_value,
'source_token': tx['to'], 'source_token': tx['to'],
'destination_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'], 'nonce': tx['nonce'],
} }
if times['queue'] != None: 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: Surely it must be possible to optimize this
# TODO: DRY this with callback filter in cic_eth/runnable/manager # TODO: DRY this with callback filter in cic_eth/runnable/manager
# TODO: Remove redundant fields from end representation (timestamp, tx_hash) # TODO: Remove redundant fields from end representation (timestamp, tx_hash)
@celery_app.task() @celery_app.task(bind=True, base=BaseTask)
def tx_collate(tx_batches, chain_spec_dict, offset, limit, newest_first=True): 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. """Merges transaction data from multiple sources and sorts them in chronological order.
:param tx_batches: Transaction data inputs :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: if newest_first:
ks.reverse() ks.reverse()
for k in ks: 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 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

View File

@@ -27,7 +27,7 @@ def database_engine(
SessionBase.poolable = False SessionBase.poolable = False
dsn = dsn_from_config(load_config) dsn = dsn_from_config(load_config)
#SessionBase.connect(dsn, True) #SessionBase.connect(dsn, True)
SessionBase.connect(dsn, debug=load_config.get('DATABASE_DEBUG') != None) SessionBase.connect(dsn, debug=load_config.true('DATABASE_DEBUG'))
return dsn return dsn

View File

@@ -100,6 +100,7 @@ def get_upcoming_tx(chain_spec, status=StatusEnum.READYSEND, not_status=None, re
q_outer = q_outer.join(Lock, isouter=True) q_outer = q_outer.join(Lock, isouter=True)
q_outer = q_outer.filter(or_(Lock.flags==None, Lock.flags.op('&')(LockEnum.SEND.value)==0)) q_outer = q_outer.filter(or_(Lock.flags==None, Lock.flags.op('&')(LockEnum.SEND.value)==0))
if not is_alive(status): if not is_alive(status):
SessionBase.release_session(session) SessionBase.release_session(session)
raise ValueError('not a valid non-final tx value: {}'.format(status)) raise ValueError('not a valid non-final tx value: {}'.format(status))

View File

@@ -80,7 +80,12 @@ def main():
t = api.create_account(register=register) t = api.create_account(register=register)
ps.get_message() ps.get_message()
o = ps.get_message(timeout=args.timeout) try:
o = ps.get_message(timeout=args.timeout)
except TimeoutError as e:
sys.stderr.write('got no new address from cic-eth before timeout: {}\n'.format(e))
sys.exit(1)
ps.unsubscribe()
m = json.loads(o['data']) m = json.loads(o['data'])
print(m['result']) print(m['result'])

View File

@@ -90,6 +90,7 @@ class DispatchSyncer:
def __init__(self, chain_spec): def __init__(self, chain_spec):
self.chain_spec = chain_spec self.chain_spec = chain_spec
self.session = None
def chain(self): def chain(self):
@@ -100,16 +101,18 @@ class DispatchSyncer:
c = len(txs.keys()) c = len(txs.keys())
logg.debug('processing {} txs {}'.format(c, list(txs.keys()))) logg.debug('processing {} txs {}'.format(c, list(txs.keys())))
chain_str = str(self.chain_spec) chain_str = str(self.chain_spec)
session = SessionBase.create_session() self.session = SessionBase.create_session()
for k in txs.keys(): for k in txs.keys():
tx_raw = txs[k] tx_raw = txs[k]
tx_raw_bytes = bytes.fromhex(strip_0x(tx_raw)) tx_raw_bytes = bytes.fromhex(strip_0x(tx_raw))
tx = unpack(tx_raw_bytes, self.chain_spec) tx = unpack(tx_raw_bytes, self.chain_spec)
try: try:
set_reserved(self.chain_spec, tx['hash'], session=session) set_reserved(self.chain_spec, tx['hash'], session=self.session)
self.session.commit()
except NotLocalTxError as e: except NotLocalTxError as e:
logg.warning('dispatcher was triggered with non-local tx {}'.format(tx['hash'])) logg.warning('dispatcher was triggered with non-local tx {}'.format(tx['hash']))
self.session.rollback()
continue continue
s_check = celery.signature( s_check = celery.signature(
@@ -132,16 +135,25 @@ class DispatchSyncer:
s_check.link(s_send) s_check.link(s_send)
t = s_check.apply_async() t = s_check.apply_async()
logg.info('processed {}'.format(k)) logg.info('processed {}'.format(k))
self.session.close()
self.session = None
def loop(self, w3, interval): def loop(self, interval):
while run: while run:
txs = {} txs = {}
typ = StatusBits.QUEUED typ = StatusBits.QUEUED
utxs = get_upcoming_tx(self.chain_spec, typ) utxs = get_upcoming_tx(self.chain_spec, typ)
for k in utxs.keys(): for k in utxs.keys():
txs[k] = utxs[k] txs[k] = utxs[k]
self.process(w3, txs) try:
conn = RPCConnection.connect(self.chain_spec, 'default')
self.process(conn, txs)
except ConnectionError as e:
if self.session != None:
self.session.close()
self.session = None
logg.error('connection to node failed: {}'.format(e))
if len(utxs) > 0: if len(utxs) > 0:
time.sleep(self.yield_delay) time.sleep(self.yield_delay)
@@ -151,8 +163,7 @@ class DispatchSyncer:
def main(): def main():
syncer = DispatchSyncer(chain_spec) syncer = DispatchSyncer(chain_spec)
conn = RPCConnection.connect(chain_spec, 'default') syncer.loop(float(config.get('DISPATCHER_LOOP_INTERVAL')))
syncer.loop(conn, float(config.get('DISPATCHER_LOOP_INTERVAL')))
sys.exit(0) sys.exit(0)

View File

@@ -12,20 +12,24 @@ from hexathon import (
# local imports # local imports
from .base import SyncFilter from .base import SyncFilter
logg = logging.getLogger().getChild(__name__) logg = logging.getLogger(__name__)
account_registry_add_log_hash = '0x9cc987676e7d63379f176ea50df0ae8d2d9d1141d1231d4ce15b5965f73c9430' account_registry_add_log_hash = '0x9cc987676e7d63379f176ea50df0ae8d2d9d1141d1231d4ce15b5965f73c9430'
class RegistrationFilter(SyncFilter): class RegistrationFilter(SyncFilter):
def __init__(self, chain_spec, queue): def __init__(self, chain_spec, contract_address, queue=None):
self.chain_spec = chain_spec self.chain_spec = chain_spec
self.queue = queue self.queue = queue
self.contract_address = contract_address
def filter(self, conn, block, tx, db_session=None): 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: for l in tx.logs:
event_topic_hex = l['topics'][0] event_topic_hex = l['topics'][0]
if event_topic_hex == account_registry_add_log_hash: if event_topic_hex == account_registry_add_log_hash:

View File

@@ -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')) 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(): def main():
@@ -85,7 +93,6 @@ def main():
celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL'))
# Connect to blockchain with chainlib # Connect to blockchain with chainlib
rpc = RPCConnection.connect(chain_spec, 'default')
o = block_latest() o = block_latest()
r = rpc.do(o) r = rpc.do(o)
@@ -151,7 +158,8 @@ def main():
tx_filter = TxFilter(chain_spec, config.get('_CELERY_QUEUE')) 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')) gas_filter = GasFilter(chain_spec, config.get('_CELERY_QUEUE'))

View File

@@ -9,7 +9,7 @@ import semver
version = ( version = (
0, 0,
12, 12,
0, 1,
'alpha.2', 'alpha.2',
) )

View File

@@ -6,4 +6,4 @@ HOST=localhost
PORT=5432 PORT=5432
ENGINE=sqlite ENGINE=sqlite
DRIVER=pysqlite DRIVER=pysqlite
DEBUG= DEBUG=0

View File

@@ -1,3 +1,3 @@
celery==4.4.7 celery==4.4.7
chainlib~=0.0.5a1 chainlib~=0.0.5a2
semver==2.13.0 semver==2.13.0

View File

@@ -1,15 +1,15 @@
chainsyncer[sql]~=0.0.3a3 chainsyncer[sql]~=0.0.4a1
chainqueue~=0.0.2b5 chainqueue~=0.0.3a1
alembic==1.4.2 alembic==1.4.2
confini~=0.3.6rc4 confini>=0.3.6rc4,<0.5.0
redis==3.5.3 redis==3.5.3
hexathon~=0.0.1a7 hexathon~=0.0.1a7
pycryptodome==3.10.1 pycryptodome==3.10.1
liveness~=0.0.1a7 liveness~=0.0.1a7
eth-address-index~=0.1.2a1 eth-address-index~=0.1.2a2
eth-accounts-index~=0.0.12a1 eth-accounts-index~=0.0.12a2
cic-eth-registry~=0.5.6a1 cic-eth-registry~=0.5.6a2
erc20-faucet~=0.2.2a1 erc20-faucet~=0.2.2a2
erc20-transfer-authorization~=0.3.2a1 erc20-transfer-authorization~=0.3.2a2
sarafu-faucet~=0.0.4a1 sarafu-faucet~=0.0.4a3
moolb~=0.1.1b2 moolb~=0.1.1b2

View File

@@ -6,4 +6,4 @@ pytest-redis==2.0.0
redis==3.5.3 redis==3.5.3
eth-tester==0.5.0b3 eth-tester==0.5.0b3
py-evm==0.3.0a20 py-evm==0.3.0a20
eth-erc20~=0.0.10a2 eth-erc20~=0.0.10a3

View File

@@ -18,6 +18,7 @@ def test_filter_bogus(
cic_registry, cic_registry,
contract_roles, contract_roles,
register_lookups, register_lookups,
account_registry,
): ):
fltrs = [ fltrs = [
@@ -26,7 +27,7 @@ def test_filter_bogus(
TxFilter(default_chain_spec, None), TxFilter(default_chain_spec, None),
CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER']), CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER']),
StragglerFilter(default_chain_spec, None), StragglerFilter(default_chain_spec, None),
RegistrationFilter(default_chain_spec, queue=None), RegistrationFilter(default_chain_spec, account_registry, queue=None),
] ]
for fltr in fltrs: for fltr in fltrs:

View File

@@ -1,3 +1,7 @@
# standard imports
import logging
import os
# external imports # external imports
from eth_accounts_index.registry import AccountRegistry from eth_accounts_index.registry import AccountRegistry
from chainlib.connection import RPCConnection from chainlib.connection import RPCConnection
@@ -14,12 +18,17 @@ from chainlib.eth.block import (
Block, Block,
) )
from erc20_faucet import Faucet 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 from chainqueue.sql.query import get_account_tx
# local imports # local imports
from cic_eth.runnable.daemons.filters.register import RegistrationFilter from cic_eth.runnable.daemons.filters.register import RegistrationFilter
logg = logging.getLogger()
def test_register_filter( def test_register_filter(
default_chain_spec, default_chain_spec,
@@ -60,7 +69,11 @@ def test_register_filter(
tx = Tx(tx_src, block=block, rcpt=rcpt) tx = Tx(tx_src, block=block, rcpt=rcpt)
tx.apply_receipt(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 = fltr.filter(eth_rpc, block, tx, db_session=init_database)
t.get_leaf() t.get_leaf()

View File

@@ -1,4 +1,5 @@
# external imports # external imports
import celery
from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.tx import ( from chainlib.eth.tx import (
receipt, receipt,
@@ -20,6 +21,7 @@ def test_translate(
cic_registry, cic_registry,
init_celery_tasks, init_celery_tasks,
register_lookups, register_lookups,
celery_session_worker,
): ):
nonce_oracle = RPCNonceOracle(contract_roles['CONTRACT_DEPLOYER'], eth_rpc) nonce_oracle = RPCNonceOracle(contract_roles['CONTRACT_DEPLOYER'], eth_rpc)
@@ -46,6 +48,20 @@ def test_translate(
'recipient': agent_roles['BOB'], 'recipient': agent_roles['BOB'],
'recipient_label': None, 'recipient_label': None,
} }
tx = translate_tx_addresses(tx, [contract_roles['CONTRACT_DEPLOYER']], default_chain_spec.asdict())
assert tx['sender_label'] == 'alice' #tx = translate_tx_addresses(tx, [contract_roles['CONTRACT_DEPLOYER']], default_chain_spec.asdict())
assert tx['recipient_label'] == 'bob' s = celery.signature(
'cic_eth.ext.address.translate_tx_addresses',
[
tx,
[contract_roles['CONTRACT_DEPLOYER']],
default_chain_spec.asdict(),
],
queue=None,
)
t = s.apply_async()
r = t.get_leaf()
assert t.successful()
assert r['sender_label'] == 'alice'
assert r['recipient_label'] == 'bob'

View File

@@ -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

View File

@@ -1,6 +1,7 @@
# third-party imports # extended imports
import pytest import pytest
import uuid import uuid
import unittest
# local imports # local imports
from cic_eth.db.models.nonce import ( from cic_eth.db.models.nonce import (
@@ -55,7 +56,7 @@ def test_nonce_reserve(
o = q.first() o = q.first()
assert o.nonce == 43 assert o.nonce == 43
nonce = NonceReservation.release(eth_empty_accounts[0], str(uu)) nonce = NonceReservation.release(eth_empty_accounts[0], str(uu), session=init_database)
init_database.commit() init_database.commit()
assert nonce == (str(uu), 42) assert nonce == (str(uu), 42)

View File

@@ -1,7 +1,7 @@
crypto-dev-signer~=0.4.14b6 crypto-dev-signer~=0.4.14b7
chainqueue~=0.0.2b5 chainqueue~=0.0.2b6
confini~=0.3.6rc4 confini>=0.3.6rc4,<0.5.0
cic-eth-registry~=0.5.6a1 cic-eth-registry~=0.5.6a2
redis==3.5.3 redis==3.5.3
hexathon~=0.0.1a7 hexathon~=0.0.1a7
pycryptodome==3.10.1 pycryptodome==3.10.1

View File

@@ -9,7 +9,7 @@ import semver
logg = logging.getLogger() logg = logging.getLogger()
version = (0, 4, 0, 'alpha.7') version = (0, 4, 0, 'alpha.8')
version_object = semver.VersionInfo( version_object = semver.VersionInfo(
major=version[0], major=version[0],

View File

@@ -1 +1 @@
cic_base[full_graph]==0.1.3a3+build.984b5cff cic_base[full_graph]~=0.2.0a3

View File

@@ -1,7 +1,7 @@
[app] [app]
ALLOWED_IP=0.0.0.0/0 ALLOWED_IP=0.0.0.0/0
LOCALE_FALLBACK=en LOCALE_FALLBACK=en
LOCALE_PATH=/usr/src/cic-ussd/var/lib/locale/ LOCALE_PATH=var/lib/locale/
MAX_BODY_LENGTH=1024 MAX_BODY_LENGTH=1024
PASSWORD_PEPPER=QYbzKff6NhiQzY3ygl2BkiKOpER8RE/Upqs/5aZWW+I= PASSWORD_PEPPER=QYbzKff6NhiQzY3ygl2BkiKOpER8RE/Upqs/5aZWW+I=
SERVICE_CODE=*483*46#,*483*061#,*384*96# SERVICE_CODE=*483*46#,*483*061#,*384*96#
@@ -11,13 +11,13 @@ SUPPORT_PHONE_NUMBER=0757628885
REGION=KE REGION=KE
[ussd] [ussd]
MENU_FILE=/usr/src/data/ussd_menu.json MENU_FILE=data/ussd_menu.json
user = user =
pass = pass =
[statemachine] [statemachine]
STATES=/usr/src/cic-ussd/states/ STATES=states/
TRANSITIONS=/usr/src/cic-ussd/transitions/ TRANSITIONS=transitions/
[client] [client]
host = host =

View File

@@ -1,5 +1,5 @@
[pgp] [pgp]
export_dir = /usr/src/pgp/keys/ export_dir = pgp/keys/
keys_path = /usr/src/secrets/ keys_path = /usr/src/secrets/
private_keys = privatekeys_meta.asc private_keys = privatekeys_meta.asc
passphrase = passphrase =

View File

@@ -127,3 +127,4 @@ class SessionBase(Model):
logg.debug('commit and destroy session {}'.format(session_key)) logg.debug('commit and destroy session {}'.format(session_key))
session.commit() session.commit()
session.close() session.close()
del SessionBase.localsessions[session_key]

View File

@@ -28,7 +28,7 @@ elif args.v:
logging.getLogger().setLevel(logging.INFO) logging.getLogger().setLevel(logging.INFO)
# parse config # parse config
config = Config(config_dir=args.c, env_prefix=args.env_prefix) config = Config(args.c, env_prefix=args.env_prefix)
config.process() config.process()
config.censor('PASSWORD', 'DATABASE') config.censor('PASSWORD', 'DATABASE')
logg.debug('config loaded from {}:\n{}'.format(args.c, config)) logg.debug('config loaded from {}:\n{}'.format(args.c, config))

View File

@@ -45,7 +45,7 @@ elif args.v:
logging.getLogger().setLevel(logging.INFO) logging.getLogger().setLevel(logging.INFO)
# parse config # parse config
config = Config(config_dir=args.c, env_prefix=args.env_prefix) config = Config(args.c, env_prefix=args.env_prefix)
config.process() config.process()
config.censor('PASSWORD', 'DATABASE') config.censor('PASSWORD', 'DATABASE')
logg.debug('config loaded from {}:\n{}'.format(args.c, config)) logg.debug('config loaded from {}:\n{}'.format(args.c, config))

View File

@@ -4,4 +4,4 @@
user_server_port=${SERVER_PORT:-9500} 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 "$@"

View File

@@ -4,4 +4,4 @@
user_ussd_server_port=${SERVER_PORT:-9000} 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 "$@"

View File

@@ -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-eth~=0.12.0a1
cic-notify~=0.4.0a7 cic-notify~=0.4.0a8
cic-types~=0.1.0a11 cic-types~=0.1.0a11

View File

@@ -30,7 +30,7 @@ arg_parser.add_argument('-vv', action='store_true', help='be more verbose')
args = arg_parser.parse_args() args = arg_parser.parse_args()
config = Config(config_dir=args.c, env_prefix=args.env_prefix) config = Config(args.c, env_prefix=args.env_prefix)
config.process() config.process()
config.censor('PASSWORD', 'DATABASE') config.censor('PASSWORD', 'DATABASE')
logg.debug(f'config:\n{config}') logg.debug(f'config:\n{config}')

View File

@@ -1,2 +0,0 @@
[bancor]
dir = /usr/local/share/cic/bancor

View File

@@ -0,0 +1,2 @@
[chain]
spec = evm:ethereum:1

View File

@@ -0,0 +1,4 @@
[redis]
host = localhost
port = 63379
db = 0

View File

@@ -0,0 +1,5 @@
[rpc]
http_provider = http://localhost:8545
http_authentication =
http_username =
http_password =

View File

@@ -0,0 +1,8 @@
[token]
name =
symbol =
decimals =
demurrage_level =
redistribution_period =
sink_address =
supply_limit = 0

View File

@@ -0,0 +1,3 @@
[wallet]
key_file =
passphrase =

View File

@@ -14,17 +14,18 @@ RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 2A518C819BE37D2C20
RUN mkdir -vp /usr/local/etc/cic RUN mkdir -vp /usr/local/etc/cic
ENV CONFINI_DIR /usr/local/etc/cic/ ENV CONFINI_DIR /usr/local/etc/cic/
RUN mkdir -vp $CONFINI_DIR #RUN mkdir -vp $CONFINI_DIR
ARG cic_config_commit=0abe0867f18077907c7023bf0ef5e466a3984dd8 #ARG cic_config_commit=24287fb253196820f23ff8a7177b122f2cd99a11
ARG cic_config_url=https://gitlab.com/grassrootseconomics/cic-config.git/ #ARG cic_config_url=https://gitlab.com/grassrootseconomics/cic-config.git/
RUN echo Install confini schema files && \ #RUN echo Install confini schema files && \
git clone --depth 1 $cic_config_url cic-config && \ # git clone --depth 1 $cic_config_url cic-config && \
cd cic-config && \ # cd cic-config && \
git fetch --depth 1 origin $cic_config_commit && \ # git fetch --depth 1 origin $cic_config_commit && \
git checkout $cic_config_commit && \ # git checkout $cic_config_commit && \
cp -v *.ini $CONFINI_DIR # cp -v *.ini $CONFINI_DIR
COPY config_template/ /usr/local/etc/cic/
COPY requirements.txt . COPY requirements.txt .
ARG pip_index_url=https://pypi.org/simple ARG pip_index_url=https://pypi.org/simple

View File

@@ -1,5 +1,11 @@
cic_base[full]==0.1.3a4+build.ce68c833 sarafu-faucet~=0.0.4a4
sarafu-faucet~=0.0.4a1 cic-eth[tools]==0.12.1a2
cic-eth[tools]==0.12.0a2
eth-erc20~=0.0.10a3 eth-erc20~=0.0.10a3
erc20-demurrage-token==0.0.2a3 erc20-demurrage-token==0.0.2a4
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
chainlib-eth~=0.0.5a4

View File

@@ -3,14 +3,9 @@
set -a set -a
default_token=giftable_erc20_token default_token=giftable_erc20_token
CIC_DEFAULT_TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL:-GFT}
TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL} TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL}
TOKEN_NAME=${TOKEN_NAME:-$TOKEN_SYMBOL} TOKEN_NAME=${TOKEN_NAME}
TOKEN_TYPE=${TOKEN_TYPE:-$default_token} 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 <<EOF cat <<EOF
external token settings: external token settings:
token_type: $TOKEN_TYPE token_type: $TOKEN_TYPE
@@ -23,7 +18,6 @@ token_supply_limit: $TOKEN_SUPPLY_LIMIT
EOF EOF
CIC_CHAIN_SPEC=${CIC_CHAIN_SPEC:-evm:bloxberg:8995} CIC_CHAIN_SPEC=${CIC_CHAIN_SPEC:-evm:bloxberg:8995}
TOKEN_SYMBOL=${TOKEN_SYMBOL:-GFT}
DEV_ETH_ACCOUNT_RESERVE_MINTER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER} DEV_ETH_ACCOUNT_RESERVE_MINTER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER}
DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER} DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER}
DEV_RESERVE_AMOUNT=${DEV_ETH_RESERVE_AMOUNT:-""10000000000000000000000000000000000} DEV_RESERVE_AMOUNT=${DEV_ETH_RESERVE_AMOUNT:-""10000000000000000000000000000000000}
@@ -75,17 +69,34 @@ if [[ -n "${ETH_PROVIDER}" ]]; then
./wait-for-it.sh "${ETH_PROVIDER_HOST}:${ETH_PROVIDER_PORT}" ./wait-for-it.sh "${ETH_PROVIDER_HOST}:${ETH_PROVIDER_PORT}"
fi fi
if [ $TOKEN_TYPE == $default_token ]; then if [ "$TOKEN_TYPE" == "$default_token" ]; then
if [ -z "$TOKEN_SYMBOL" ]; then
>&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 >&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` 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
elif [ $TOKEN_TYPE == 'erc20_demurrage_token' ]; then 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 >&2 echo deploying token $TOKEN_TYPE
if [ -z $TOKEN_SINK_ADDRESS ]; then if [ -z $TOKEN_SINK_ADDRESS ]; then
if [ ! -z $TOKEN_REDISTRIBUTION_PERIOD ]; then if [ ! -z $TOKEN_REDISTRIBUTION_PERIOD ]; then
>&2 echo -e "\033[;93mtoken sink address not set, so redistribution will be BURNED\033[;39m" >&2 echo -e "\033[;93mtoken sink address not set, so redistribution will be BURNED\033[;39m"
fi fi
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 else
>&2 echo unknown token type $TOKEN_TYPE >&2 echo unknown token type $TOKEN_TYPE
exit 1 exit 1
@@ -137,6 +148,7 @@ else
fi fi
mkdir -p $CIC_DATA_DIR mkdir -p $CIC_DATA_DIR
>&2 echo using data dir $CIC_DATA_DIR for environment variable dump
# this is consumed in downstream services to set environment variables # this is consumed in downstream services to set environment variables
cat << EOF > $CIC_DATA_DIR/.env cat << EOF > $CIC_DATA_DIR/.env

View File

@@ -15,10 +15,6 @@ CIC_DATA_DIR=${CIC_DATA_DIR:-/tmp/cic}
ETH_PASSPHRASE='' ETH_PASSPHRASE=''
CIC_DEFAULT_TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL:-GFT} CIC_DEFAULT_TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL:-GFT}
TOKEN_SYMBOL=$CIC_DEFAULT_TOKEN_SYMBOL TOKEN_SYMBOL=$CIC_DEFAULT_TOKEN_SYMBOL
if [[ $CIC_DEFAULT_TOKEN_SYMBOL != 'GFT' && $CIC_DEFAULT_TOKEN_SYMBOL != 'SRF' ]]; then
>&2 echo CIC_DEFAULT_TOKEN_SYMBOL must be one of [GFT,SRF], but was $CIC_DEFAULT_TOKEN_SYMBOL
exit 1
fi
# Debug flag # Debug flag
DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER=0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER=0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C
@@ -77,13 +73,13 @@ eth-accounts-index-writer -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER
# Transfer gas to custodial gas provider adddress # Transfer gas to custodial gas provider adddress
>&2 echo gift gas to gas gifter >&2 echo gift gas to gas gifter
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_GAS_GIFTER $gas_amount >&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug -a $DEV_ETH_ACCOUNT_GAS_GIFTER $gas_amount
>&2 echo gift gas to sarafu token owner >&2 echo gift gas to sarafu token owner
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_SARAFU_GIFTER $gas_amount >&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug -a $DEV_ETH_ACCOUNT_SARAFU_GIFTER $gas_amount
>&2 echo gift gas to account index owner >&2 echo gift gas to account index owner
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_ACCOUNT_REGISTRY_WRITER $gas_amount >&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug -a $DEV_ETH_ACCOUNT_ACCOUNT_REGISTRY_WRITER $gas_amount
# Send token to token creator # Send token to token creator

View File

@@ -167,7 +167,7 @@ If you have previously run the `cic_ussd` import incompletely, it could be a goo
Then, in sequence, run in first terminal: Then, in sequence, run in first terminal:
`python cic_eth/import_balance.py -v -c config -p <eth_provider> -r <cic_registry_address> --token-symbol <token_symbol> -y ../keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c out` `python cic_ussd/import_balance.py -v -c config -p <eth_provider> -r <cic_registry_address> --token-symbol <token_symbol> -y ../contract-migration/keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c out`
In second terminal: In second terminal:

View File

@@ -11,7 +11,6 @@ import csv
import json import json
# external imports # external imports
import eth_abi
import confini import confini
from hexathon import ( from hexathon import (
strip_0x, strip_0x,
@@ -29,7 +28,10 @@ from chainlib.eth.gas import OverrideGasOracle
from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.tx import TxFactory from chainlib.eth.tx import TxFactory
from chainlib.jsonrpc import JSONRPCRequest 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.chain import ChainSpec
from chainlib.eth.constant import ZERO_ADDRESS from chainlib.eth.constant import ZERO_ADDRESS
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer 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 cic_types.models.person import Person
from eth_erc20 import ERC20 from eth_erc20 import ERC20
from cic_base.eth.syncer import chain_interface 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) logging.basicConfig(level=logging.WARNING)
@@ -131,58 +136,52 @@ class Handler:
logg.debug('no payload, skipping {}'.format(tx)) logg.debug('no payload, skipping {}'.format(tx))
return return
if tx.payload[:8] == self.account_index_add_signature: recipient = None
recipient = eth_abi.decode_single('address', bytes.fromhex(tx.payload[-64:])) try:
#original_address = to_checksum_address(self.addresses[to_checksum_address(recipient)]) r = AccountsIndex.parse_add_request(tx.payload)
user_file = 'new/{}/{}/{}.json'.format( except RequestMismatchException:
recipient[2:4].upper(), return
recipient[4:6].upper(), recipient = r[0]
recipient[2:].upper(),
) user_file = 'new/{}/{}/{}.json'.format(
filepath = os.path.join(self.user_dir, user_file) recipient[2:4].upper(),
o = None recipient[4:6].upper(),
try: recipient[2:].upper(),
f = open(filepath, 'r') )
o = json.load(f) filepath = os.path.join(self.user_dir, user_file)
f.close() o = None
except FileNotFoundError: try:
logg.error('no import record of address {}'.format(recipient)) f = open(filepath, 'r')
return o = json.load(f)
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() f.close()
# except TypeError as e: except FileNotFoundError:
# logg.warning('typerror {}'.format(e)) logg.error('no import record of address {}'.format(recipient))
# pass return
# except IndexError as e: u = Person.deserialize(o)
# logg.warning('indexerror {}'.format(e)) original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0]
# pass try:
# except EthException as e: balance = self.balances[original_address]
# logg.error('send error {}'.format(e).ljust(200)) except KeyError as e:
#except KeyError as e: logg.error('balance get fail orig {} new {}'.format(original_address, recipient))
# logg.error('key record not found in imports: {}'.format(e).ljust(200)) 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): def progress_callback(block_number, tx_index):
@@ -198,49 +197,26 @@ def main():
nonce_oracle = RPCNonceOracle(signer_address, conn) nonce_oracle = RPCNonceOracle(signer_address, conn)
# Get Token registry address # Get Token registry address
txf = TxFactory(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=None) registry = Registry(chain_spec)
tx = txf.template(signer_address, config.get('CIC_REGISTRY_ADDRESS')) o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry')
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)
r = conn.do(o) 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)) logg.info('found token index address {}'.format(token_index_address))
# Get Sarafu token address # Get Sarafu token address
tx = txf.template(signer_address, token_index_address) token_index = TokenUniqueSymbolIndex(chain_spec)
data = add_0x(registry_addressof_method) o = token_index.address_of(token_index_address, token_symbol)
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)
r = conn.do(o) r = conn.do(o)
token_address = token_index.parse_address_of(r)
try: 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: except ValueError as e:
logg.critical('lookup failed for token {}: {}'.format(token_symbol, e)) logg.critical('lookup failed for token {}: {}'.format(token_symbol, e))
sys.exit(1) sys.exit(1)
logg.info('found token address {}'.format(token_address))
if sarafu_token_address == ZERO_ADDRESS:
raise KeyError('token address for symbol {} is zero'.format(token_symbol)) sys.exit(0)
logg.info('found token address {}'.format(sarafu_token_address))
syncer_backend = MemBackend(chain_str, 0) syncer_backend = MemBackend(chain_str, 0)
@@ -248,22 +224,6 @@ def main():
o = block_latest() o = block_latest()
r = conn.do(o) r = conn.do(o)
block_offset = int(strip_0x(r), 16) + 1 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 # TODO get decimals from token
balances = {} balances = {}

View File

@@ -11,7 +11,6 @@ const config = new crdt.Config('./config');
config.process(); config.process();
console.log(config); console.log(config);
function sendit(uid, envelope) { function sendit(uid, envelope) {
const d = envelope.toJSON(); const d = envelope.toJSON();

View File

@@ -17,7 +17,7 @@ default_config_dir = '/usr/local/etc/cic'
arg_parser = argparse.ArgumentParser() arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('-c', type=str, default=default_config_dir, help='config file') 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('-v', action='store_true', help='Be verbose')
arg_parser.add_argument('-vv', action='store_true', help='Be more 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') arg_parser.add_argument('user_dir', type=str, help='path to users export dir tree')

View File

@@ -206,7 +206,7 @@ def gen():
# fake.local_latitude() # fake.local_latitude()
p.location['latitude'] = (random.random() * 180) - 90 p.location['latitude'] = (random.random() * 180) - 90
# fake.local_latitude() # fake.local_latitude()
p.location['longitude'] = (random.random() * 360) - 179 p.location['longitude'] = (random.random() * 360) - 180
return (old_blockchain_checksum_address, phone, p) return (old_blockchain_checksum_address, phone, p)

View File

@@ -11,7 +11,6 @@ import csv
import json import json
# external imports # external imports
import eth_abi
import confini import confini
from hexathon import ( from hexathon import (
strip_0x, strip_0x,
@@ -29,13 +28,20 @@ from chainlib.eth.gas import OverrideGasOracle
from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.tx import TxFactory from chainlib.eth.tx import TxFactory
from chainlib.jsonrpc import JSONRPCRequest 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.chain import ChainSpec
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
from crypto_dev_signer.keystore.dict import DictKeystore from crypto_dev_signer.keystore.dict import DictKeystore
from cic_types.models.person import Person from cic_types.models.person import Person
from eth_erc20 import ERC20 from eth_erc20 import ERC20
from cic_base.eth.syncer import chain_interface 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) 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('--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('-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('-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('--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('--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') 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] 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.token_address = token_address
self.faucet_address = faucet_address
self.user_dir = user_dir self.user_dir = user_dir
self.balances = balances self.balances = balances
self.chain_spec = chain_spec 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): def name(self):
@@ -129,58 +139,59 @@ class Handler:
logg.debug('no payload, skipping {}'.format(tx)) logg.debug('no payload, skipping {}'.format(tx))
return return
if tx.payload[:8] == self.account_index_add_signature: recipient = None
recipient = eth_abi.decode_single('address', bytes.fromhex(tx.payload[-64:])) try:
#original_address = to_checksum_address(self.addresses[to_checksum_address(recipient)]) r = AccountsIndex.parse_add_request(tx.payload)
user_file = 'new/{}/{}/{}.json'.format( except RequestMismatchException:
recipient[2:4].upper(), return
recipient[4:6].upper(), recipient = r[0]
recipient[2:].upper(),
) user_file = 'new/{}/{}/{}.json'.format(
filepath = os.path.join(self.user_dir, user_file) recipient[2:4].upper(),
o = None recipient[4:6].upper(),
try: recipient[2:].upper(),
f = open(filepath, 'r') )
o = json.load(f) filepath = os.path.join(self.user_dir, user_file)
f.close() o = None
except FileNotFoundError: try:
logg.error('no import record of address {}'.format(recipient)) f = open(filepath, 'r')
return o = json.load(f)
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() f.close()
# except TypeError as e: except FileNotFoundError:
# logg.warning('typerror {}'.format(e)) logg.error('no import record of address {}'.format(recipient))
# pass return
# except IndexError as e: u = Person.deserialize(o)
# logg.warning('indexerror {}'.format(e)) original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0]
# pass try:
# except EthException as e: balance = self.balances[original_address]
# logg.error('send error {}'.format(e).ljust(200)) except KeyError as e:
#except KeyError as e: logg.error('balance get fail orig {} new {}'.format(original_address, recipient))
# logg.error('key record not found in imports: {}'.format(e).ljust(200)) 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): def progress_callback(block_number, tx_index):
@@ -196,45 +207,31 @@ def main():
nonce_oracle = RPCNonceOracle(signer_address, conn) nonce_oracle = RPCNonceOracle(signer_address, conn)
# Get Token registry address # Get Token registry address
txf = TxFactory(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=None) registry = Registry(chain_spec)
tx = txf.template(signer_address, config.get('CIC_REGISTRY_ADDRESS')) o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry')
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)
r = conn.do(o) 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)) 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 # Get Sarafu token address
tx = txf.template(signer_address, token_index_address) token_index = TokenUniqueSymbolIndex(chain_spec)
data = add_0x(registry_addressof_method) o = token_index.address_of(token_index_address, token_symbol)
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)
r = conn.do(o) r = conn.do(o)
token_address = token_index.parse_address_of(r)
try: 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: except ValueError as e:
logg.critical('lookup failed for token {}: {}'.format(token_symbol, e)) logg.critical('lookup failed for token {}: {}'.format(token_symbol, e))
sys.exit(1) 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) syncer_backend = MemBackend(chain_str, 0)
@@ -242,22 +239,6 @@ def main():
o = block_latest() o = block_latest()
r = conn.do(o) r = conn.do(o)
block_offset = int(strip_0x(r), 16) + 1 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 # TODO get decimals from token
balances = {} balances = {}
@@ -282,7 +263,7 @@ def main():
syncer_backend.set(block_offset, 0) syncer_backend.set(block_offset, 0)
syncer = HeadSyncer(syncer_backend, chain_interface, block_callback=progress_callback) 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.add_filter(handler)
syncer.loop(1, conn) syncer.loop(1, conn)

View File

@@ -6,7 +6,7 @@
"": { "": {
"dependencies": { "dependencies": {
"@cicnet/cic-client-meta": "^0.0.11", "@cicnet/cic-client-meta": "^0.0.11",
"@cicnet/crdt-meta": "^0.0.10", "@cicnet/crdt-meta": "^0.0.12",
"vcard-parser": "^1.0.0" "vcard-parser": "^1.0.0"
} }
}, },
@@ -34,7 +34,7 @@
"node": ">=14.16.1" "node": ">=14.16.1"
} }
}, },
"node_modules/@cicnet/crdt-meta": { "node_modules/@cicnet/cic-client-meta/node_modules/@cicnet/crdt-meta": {
"version": "0.0.10", "version": "0.0.10",
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.10.tgz", "resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.10.tgz",
"integrity": "sha512-f+H6BQA2tE718KuNYiNzrDJN4wY00zeuhXM6aPKJUX6nryzX9g2r0yf8iDhkz+Fts1R6M7Riz73MfFEa8fgvsw==", "integrity": "sha512-f+H6BQA2tE718KuNYiNzrDJN4wY00zeuhXM6aPKJUX6nryzX9g2r0yf8iDhkz+Fts1R6M7Riz73MfFEa8fgvsw==",
@@ -48,22 +48,36 @@
"node": ">=14.16.1" "node": ">=14.16.1"
} }
}, },
"node_modules/@cicnet/crdt-meta": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.12.tgz",
"integrity": "sha512-wPX86P1Lsq4RxkVUlhlouhLkMOtkqzHgpNuXicHvWuhH3ks2Nsg7yqvTw9yt+kqj+N8a5pPMrNhKvUEFW8rJjA==",
"dependencies": {
"automerge": "^0.14.2",
"ini": "^1.3.8",
"openpgp": "^4.10.8",
"readline-sync": "^1.4.10"
},
"engines": {
"node": ">=14.16.1"
}
},
"node_modules/@ethereumjs/common": { "node_modules/@ethereumjs/common": {
"version": "2.3.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.3.0.tgz", "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.4.0.tgz",
"integrity": "sha512-Fmi15MdVptsC85n6NcUXIFiiXCXWEfZNgPWP+OGAQOC6ZtdzoNawtxH/cYpIgEgSuIzfOeX3VKQP/qVI1wISHg==", "integrity": "sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==",
"dependencies": { "dependencies": {
"crc-32": "^1.2.0", "crc-32": "^1.2.0",
"ethereumjs-util": "^7.0.10" "ethereumjs-util": "^7.1.0"
} }
}, },
"node_modules/@ethereumjs/tx": { "node_modules/@ethereumjs/tx": {
"version": "3.2.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.2.0.tgz", "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.3.0.tgz",
"integrity": "sha512-D3X/XtZ3ldUg34hr99Jvj7NxW3NxVKdUKrwQnEWlAp4CmCQpvYoyn7NF4lk34rHEt7ScS+Agu01pcDHoOcd19A==", "integrity": "sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==",
"dependencies": { "dependencies": {
"@ethereumjs/common": "^2.3.0", "@ethereumjs/common": "^2.4.0",
"ethereumjs-util": "^7.0.10" "ethereumjs-util": "^7.1.0"
} }
}, },
"node_modules/@types/bn.js": { "node_modules/@types/bn.js": {
@@ -75,9 +89,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "15.12.0", "version": "16.3.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz",
"integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==" "integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw=="
}, },
"node_modules/@types/pbkdf2": { "node_modules/@types/pbkdf2": {
"version": "3.1.0", "version": "3.1.0",
@@ -88,9 +102,9 @@
} }
}, },
"node_modules/@types/secp256k1": { "node_modules/@types/secp256k1": {
"version": "4.0.2", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz",
"integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==", "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==",
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
@@ -273,9 +287,9 @@
} }
}, },
"node_modules/blakejs": { "node_modules/blakejs": {
"version": "1.1.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz",
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" "integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg=="
}, },
"node_modules/block-stream": { "node_modules/block-stream": {
"version": "0.0.9", "version": "0.0.9",
@@ -639,9 +653,9 @@
} }
}, },
"node_modules/ethereumjs-util": { "node_modules/ethereumjs-util": {
"version": "7.0.10", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz",
"integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", "integrity": "sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==",
"dependencies": { "dependencies": {
"@types/bn.js": "^5.1.0", "@types/bn.js": "^5.1.0",
"bn.js": "^5.1.2", "bn.js": "^5.1.2",
@@ -1148,9 +1162,9 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}, },
"node_modules/needle": { "node_modules/needle": {
"version": "2.6.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz",
"integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==",
"dependencies": { "dependencies": {
"debug": "^3.2.6", "debug": "^3.2.6",
"iconv-lite": "^0.4.4", "iconv-lite": "^0.4.4",
@@ -2125,9 +2139,9 @@
} }
}, },
"node_modules/yargs-parser": { "node_modules/yargs-parser": {
"version": "20.2.7", "version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
} }
@@ -2189,12 +2203,25 @@
"pg": "^8.4.2", "pg": "^8.4.2",
"sqlite3": "^5.0.0", "sqlite3": "^5.0.0",
"yargs": "^16.1.0" "yargs": "^16.1.0"
},
"dependencies": {
"@cicnet/crdt-meta": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.10.tgz",
"integrity": "sha512-f+H6BQA2tE718KuNYiNzrDJN4wY00zeuhXM6aPKJUX6nryzX9g2r0yf8iDhkz+Fts1R6M7Riz73MfFEa8fgvsw==",
"requires": {
"automerge": "^0.14.2",
"ini": "^1.3.8",
"openpgp": "^4.10.8",
"readline-sync": "^1.4.10"
}
}
} }
}, },
"@cicnet/crdt-meta": { "@cicnet/crdt-meta": {
"version": "0.0.10", "version": "0.0.12",
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.10.tgz", "resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.12.tgz",
"integrity": "sha512-f+H6BQA2tE718KuNYiNzrDJN4wY00zeuhXM6aPKJUX6nryzX9g2r0yf8iDhkz+Fts1R6M7Riz73MfFEa8fgvsw==", "integrity": "sha512-wPX86P1Lsq4RxkVUlhlouhLkMOtkqzHgpNuXicHvWuhH3ks2Nsg7yqvTw9yt+kqj+N8a5pPMrNhKvUEFW8rJjA==",
"requires": { "requires": {
"automerge": "^0.14.2", "automerge": "^0.14.2",
"ini": "^1.3.8", "ini": "^1.3.8",
@@ -2203,21 +2230,21 @@
} }
}, },
"@ethereumjs/common": { "@ethereumjs/common": {
"version": "2.3.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.3.0.tgz", "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.4.0.tgz",
"integrity": "sha512-Fmi15MdVptsC85n6NcUXIFiiXCXWEfZNgPWP+OGAQOC6ZtdzoNawtxH/cYpIgEgSuIzfOeX3VKQP/qVI1wISHg==", "integrity": "sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==",
"requires": { "requires": {
"crc-32": "^1.2.0", "crc-32": "^1.2.0",
"ethereumjs-util": "^7.0.10" "ethereumjs-util": "^7.1.0"
} }
}, },
"@ethereumjs/tx": { "@ethereumjs/tx": {
"version": "3.2.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.2.0.tgz", "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.3.0.tgz",
"integrity": "sha512-D3X/XtZ3ldUg34hr99Jvj7NxW3NxVKdUKrwQnEWlAp4CmCQpvYoyn7NF4lk34rHEt7ScS+Agu01pcDHoOcd19A==", "integrity": "sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==",
"requires": { "requires": {
"@ethereumjs/common": "^2.3.0", "@ethereumjs/common": "^2.4.0",
"ethereumjs-util": "^7.0.10" "ethereumjs-util": "^7.1.0"
} }
}, },
"@types/bn.js": { "@types/bn.js": {
@@ -2229,9 +2256,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "15.12.0", "version": "16.3.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz",
"integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==" "integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw=="
}, },
"@types/pbkdf2": { "@types/pbkdf2": {
"version": "3.1.0", "version": "3.1.0",
@@ -2242,9 +2269,9 @@
} }
}, },
"@types/secp256k1": { "@types/secp256k1": {
"version": "4.0.2", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz",
"integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==", "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==",
"requires": { "requires": {
"@types/node": "*" "@types/node": "*"
} }
@@ -2412,9 +2439,9 @@
} }
}, },
"blakejs": { "blakejs": {
"version": "1.1.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz",
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" "integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg=="
}, },
"block-stream": { "block-stream": {
"version": "0.0.9", "version": "0.0.9",
@@ -2728,9 +2755,9 @@
} }
}, },
"ethereumjs-util": { "ethereumjs-util": {
"version": "7.0.10", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz",
"integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==", "integrity": "sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==",
"requires": { "requires": {
"@types/bn.js": "^5.1.0", "@types/bn.js": "^5.1.0",
"bn.js": "^5.1.2", "bn.js": "^5.1.2",
@@ -3157,9 +3184,9 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}, },
"needle": { "needle": {
"version": "2.6.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz",
"integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==",
"requires": { "requires": {
"debug": "^3.2.6", "debug": "^3.2.6",
"iconv-lite": "^0.4.4", "iconv-lite": "^0.4.4",
@@ -3944,9 +3971,9 @@
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "20.2.7", "version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==" "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="
} }
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"dependencies": { "dependencies": {
"@cicnet/cic-client-meta": "^0.0.11", "@cicnet/cic-client-meta": "^0.0.11",
"@cicnet/crdt-meta": "^0.0.10", "@cicnet/crdt-meta": "^0.0.12",
"vcard-parser": "^1.0.0" "vcard-parser": "^1.0.0"
} }
} }

View File

@@ -1,4 +1,13 @@
sarafu-faucet==0.0.4a1 sarafu-faucet==0.0.4a3
cic-eth[tools]==0.12.0a1 cic-eth[tools]==0.12.1a1
cic-types==0.1.0a13 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
psycopg2==2.8.6

View File

@@ -14,7 +14,6 @@ import urllib.parse
# external imports # external imports
import celery import celery
import confini import confini
import eth_abi
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainlib.eth.address import to_checksum_address from chainlib.eth.address import to_checksum_address
from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.connection import EthHTTPConnection
@@ -33,6 +32,9 @@ from cic_types.models.person import (
from erc20_faucet import Faucet from erc20_faucet import Faucet
from eth_erc20 import ERC20 from eth_erc20 import ERC20
from hexathon.parse import strip_0x, add_0x 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) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
@@ -43,7 +45,8 @@ custodial_tests = [
'local_key', 'local_key',
'gas', 'gas',
'faucet', 'faucet',
'ussd' 'ussd',
'ussd_pins',
] ]
metadata_tests = [ 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('--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('--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-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('--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('--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') 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: for t in custodial_tests:
if t not in exclude: if t not in exclude:
exclude.append(t) 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: for t in include:
if t not in all_tests: if t not in all_tests:
raise ValueError('Cannot include unknown verification "{}"'.format(t)) raise ValueError('Cannot include unknown verification "{}"'.format(t))
@@ -140,7 +149,7 @@ for t in include:
api = None api = None
for t in custodial_tests: for t in custodial_tests:
if t in active_tests: if t in active_tests:
from cic_eth.api.api_admin import AdminApi from cic_eth.api.admin import AdminApi
api = AdminApi(None) api = AdminApi(None)
logg.info('activating custodial module'.format(t)) logg.info('activating custodial module'.format(t))
break break
@@ -263,19 +272,11 @@ class Verifier:
def verify_accounts_index(self, address, balance=None): def verify_accounts_index(self, address, balance=None):
tx = self.tx_factory.template(ZERO_ADDRESS, self.index_address) accounts_index = AccountsIndex(self.chain_spec)
data = keccak256_string_to_hex('have(address)')[:8] o = accounts_index.have(self.index_address, address)
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)
r = self.conn.do(o) r = self.conn.do(o)
logg.debug('index check for {}: {}'.format(address, r)) n = accounts_index.parse_have(r)
n = eth_abi.decode_single('uint256', bytes.fromhex(strip_0x(r))) logg.debug('index check for {}: {}'.format(address, n))
if n != 1: if n != 1:
raise VerifierError(n, 'accounts index') raise VerifierError(n, 'accounts index')
@@ -289,7 +290,7 @@ class Verifier:
actual_balance = int(r) actual_balance = int(r)
balance = int(balance / 1000000) * 1000000 balance = int(balance / 1000000) * 1000000
balance += self.faucet_amount balance += self.faucet_amount
logg.debug('balance for {}: {}'.format(address, balance)) logg.info('balance for {}: {}'.format(address, balance))
if balance != actual_balance: if balance != actual_balance:
raise VerifierError((actual_balance, balance), 'balance') raise VerifierError((actual_balance, balance), 'balance')
@@ -427,70 +428,39 @@ def main():
gas_oracle = OverrideGasOracle(conn=conn, limit=8000000) gas_oracle = OverrideGasOracle(conn=conn, limit=8000000)
# Get Token registry address # Get Token registry address
txf = TxFactory(chain_spec, signer=None, gas_oracle=gas_oracle, nonce_oracle=None) registry = Registry(chain_spec)
tx = txf.template(ZERO_ADDRESS, config.get('CIC_REGISTRY_ADDRESS')) o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry')
# 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)
r = conn.do(o) 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)) logg.info('found token index address {}'.format(token_index_address))
data = add_0x(registry_addressof_method) # Get Account registry address
data += eth_abi.encode_single('bytes32', b'AccountRegistry').hex() o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'AccountRegistry')
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)
r = conn.do(o) 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)) logg.info('found account index address {}'.format(account_index_address))
data = add_0x(registry_addressof_method) # Get Faucet address
data += eth_abi.encode_single('bytes32', b'Faucet').hex() o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'Faucet')
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)
r = conn.do(o) 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)) logg.info('found faucet {}'.format(faucet_address))
# Get Sarafu token address
token_index = TokenUniqueSymbolIndex(chain_spec)
# Get Sarafu token address o = token_index.address_of(token_index_address, token_symbol)
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)
r = conn.do(o) r = conn.do(o)
sarafu_token_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r)))) token_address = token_index.parse_address_of(r)
logg.info('found token address {}'.format(sarafu_token_address)) 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 = {} balances = {}
f = open('{}/balances.csv'.format(user_dir, 'r')) f = open('{}/balances.csv'.format(user_dir, 'r'))
i = 0 i = 0
@@ -511,7 +481,7 @@ def main():
f.close() 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') user_new_dir = os.path.join(user_dir, 'new')
i = 0 i = 0

View File

@@ -103,14 +103,14 @@ services:
DEV_FAUCET_AMOUNT: ${DEV_FAUCET_AMOUNT:-0} DEV_FAUCET_AMOUNT: ${DEV_FAUCET_AMOUNT:-0}
#DEV_SARAFU_DEMURRAGE_LEVEL: ${DEV_SARAFU_DEMURRAGE_LEVEL:-196454828847045000000000000000000} #DEV_SARAFU_DEMURRAGE_LEVEL: ${DEV_SARAFU_DEMURRAGE_LEVEL:-196454828847045000000000000000000}
DEV_ETH_GAS_PRICE: ${DEV_ETH_GAS_PRICE:-1} 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_NAME: $TOKEN_NAME
TOKEN_DECIMALS: $TOKEN_DECIMALS TOKEN_DECIMALS: $TOKEN_DECIMALS
TOKEN_REDISTRIBUTION_PERIOD: $TOKEN_REDISTRIBUTION_PERIOD TOKEN_REDISTRIBUTION_PERIOD: $TOKEN_REDISTRIBUTION_PERIOD
TOKEN_SUPPLY_LIMIT: $TOKEN_SUPPLY_LIMIT TOKEN_SUPPLY_LIMIT: $TOKEN_SUPPLY_LIMIT
TOKEN_DEMURRAGE_LEVEL: ${TOKEN_DEMURRAGE_LEVEL:-196454828847045000000000000000000} TOKEN_DEMURRAGE_LEVEL: ${TOKEN_DEMURRAGE_LEVEL:-196454828847045000000000000000000}
TOKEN_SINK_ADDRESS: $TOKEN_SINK_ADDRESS TOKEN_SINK_ADDRESS: $TOKEN_SINK_ADDRESS
TOKEN_TYPE: ${TOKEN_TYPE:-default} TOKEN_TYPE: $TOKEN_TYPE
#CONFINI_DIR: ${CONFINI_DIR:-/tmp/cic/config} #CONFINI_DIR: ${CONFINI_DIR:-/tmp/cic/config}
command: ["./run_job.sh"] command: ["./run_job.sh"]
#command: ["./reset.sh"] #command: ["./reset.sh"]