Compare commits
9 Commits
lash/add-o
...
lash/conne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e0388c47a
|
||
|
|
d874e0a6a7
|
||
|
|
3c203851a9
|
||
|
|
473ead26f8
|
||
|
|
80d0bfe234 | ||
|
|
21fd034478 | ||
|
|
74457790a4 | ||
|
|
fd5e208acd | ||
|
|
2cb1d6d9fb |
@@ -31,7 +31,10 @@ from cic_eth.db.models.tx import TxCache
|
||||
from cic_eth.db.models.nonce import Nonce
|
||||
from cic_eth.db.enum import (
|
||||
StatusEnum,
|
||||
StatusBits,
|
||||
is_alive,
|
||||
is_error_status,
|
||||
status_str,
|
||||
)
|
||||
from cic_eth.error import InitializationError
|
||||
from cic_eth.db.error import TxStateChangeError
|
||||
@@ -42,6 +45,8 @@ app = celery.current_app
|
||||
#logg = logging.getLogger(__file__)
|
||||
logg = logging.getLogger()
|
||||
|
||||
local_fail = StatusBits.LOCAL_ERROR | StatusBits.NODE_ERROR | StatusBits.UNKNOWN_ERROR
|
||||
|
||||
|
||||
class AdminApi:
|
||||
"""Provides an interface to view and manipulate existing transaction tasks and system runtime settings.
|
||||
@@ -195,6 +200,7 @@ class AdminApi:
|
||||
blocking_tx = None
|
||||
blocking_nonce = None
|
||||
nonce_otx = 0
|
||||
last_nonce = -1
|
||||
for k in txs.keys():
|
||||
s_get_tx = celery.signature(
|
||||
'cic_eth.queue.tx.get_tx',
|
||||
@@ -205,18 +211,25 @@ class AdminApi:
|
||||
)
|
||||
tx = s_get_tx.apply_async().get()
|
||||
#tx = get_tx(k)
|
||||
logg.debug('checking nonce {}'.format(tx['nonce']))
|
||||
if tx['status'] in [StatusEnum.REJECTED, StatusEnum.FUBAR]:
|
||||
blocking_tx = k
|
||||
blocking_nonce = tx['nonce']
|
||||
logg.debug('checking nonce {} (previous {})'.format(tx['nonce'], last_nonce))
|
||||
nonce_otx = tx['nonce']
|
||||
if not is_alive(tx['status']) and tx['status'] & local_fail > 0:
|
||||
logg.info('permanently errored {} nonce {} status {}'.format(k, nonce_otx, status_str(tx['status'])))
|
||||
blocking_tx = k
|
||||
blocking_nonce = nonce_otx
|
||||
elif nonce_otx - last_nonce > 1:
|
||||
logg.error('nonce gap; {} followed {}'.format(nonce_otx, last_nonce))
|
||||
blocking_tx = k
|
||||
blocking_nonce = nonce_otx
|
||||
break
|
||||
last_nonce = nonce_otx
|
||||
|
||||
nonce_cache = Nonce.get(address)
|
||||
#nonce_cache = Nonce.get(address)
|
||||
#nonce_w3 = self.w3.eth.getTransactionCount(address, 'pending')
|
||||
|
||||
return {
|
||||
'nonce': {
|
||||
'network': nonce_cache,
|
||||
#'network': nonce_cache,
|
||||
'queue': nonce_otx,
|
||||
#'cache': nonce_cache,
|
||||
'blocking': blocking_nonce,
|
||||
@@ -270,16 +283,15 @@ class AdminApi:
|
||||
# self.w3.eth.sign(addr, text='666f6f')
|
||||
|
||||
|
||||
def account(self, chain_spec, address, cols=['tx_hash', 'sender', 'recipient', 'nonce', 'block', 'tx_index', 'status', 'network_status', 'date_created'], include_sender=True, include_recipient=True):
|
||||
def account(self, chain_spec, address, include_sender=True, include_recipient=True, renderer=None, w=sys.stdout):
|
||||
"""Lists locally originated transactions for the given Ethereum address.
|
||||
|
||||
Performs a synchronous call to the Celery task responsible for performing the query.
|
||||
|
||||
:param address: Ethereum address to return transactions for
|
||||
:type address: str, 0x-hex
|
||||
:param cols: Data columns to include
|
||||
:type cols: list of str
|
||||
"""
|
||||
last_nonce = -1
|
||||
s = celery.signature(
|
||||
'cic_eth.queue.tx.get_account_tx',
|
||||
[
|
||||
@@ -291,33 +303,45 @@ class AdminApi:
|
||||
|
||||
tx_dict_list = []
|
||||
for tx_hash in txs.keys():
|
||||
errors = []
|
||||
s = celery.signature(
|
||||
'cic_eth.queue.tx.get_tx_cache',
|
||||
[tx_hash],
|
||||
queue=self.queue,
|
||||
)
|
||||
tx_dict = s.apply_async().get()
|
||||
if tx_dict['sender'] == address and not include_sender:
|
||||
logg.debug('skipping sender tx {}'.format(tx_dict['tx_hash']))
|
||||
continue
|
||||
if tx_dict['sender'] == address:
|
||||
if tx_dict['nonce'] - last_nonce > 1:
|
||||
logg.error('nonce gap; {} followed {} for tx {}'.format(tx_dict['nonce'], last_nonce, tx_dict['hash']))
|
||||
errors.append('nonce')
|
||||
elif tx_dict['nonce'] == last_nonce:
|
||||
logg.warning('nonce {} duplicate in tx {}'.format(tx_dict['nonce'], tx_dict['hash']))
|
||||
last_nonce = tx_dict['nonce']
|
||||
if not include_sender:
|
||||
logg.debug('skipping sender tx {}'.format(tx_dict['tx_hash']))
|
||||
continue
|
||||
elif tx_dict['recipient'] == address and not include_recipient:
|
||||
logg.debug('skipping recipient tx {}'.format(tx_dict['tx_hash']))
|
||||
continue
|
||||
|
||||
logg.debug(tx_dict)
|
||||
o = {
|
||||
'nonce': tx_dict['nonce'],
|
||||
'tx_hash': tx_dict['tx_hash'],
|
||||
'status': tx_dict['status'],
|
||||
'date_updated': tx_dict['date_updated'],
|
||||
'errors': errors,
|
||||
}
|
||||
tx_dict_list.append(o)
|
||||
if renderer != None:
|
||||
r = renderer(o)
|
||||
w.write(r + '\n')
|
||||
else:
|
||||
tx_dict_list.append(o)
|
||||
|
||||
return tx_dict_list
|
||||
|
||||
|
||||
# TODO: Add exception upon non-existent tx aswell as invalid tx data to docstring
|
||||
def tx(self, chain_spec, tx_hash=None, tx_raw=None, registry=None):
|
||||
def tx(self, chain_spec, tx_hash=None, tx_raw=None, registry=None, renderer=None, w=sys.stdout):
|
||||
"""Output local and network details about a given transaction with local origin.
|
||||
|
||||
If the transaction hash is given, the raw trasnaction data will be retrieved from the local transaction queue backend. Otherwise the raw transaction data must be provided directly. Only one of transaction hash and transaction data can be passed.
|
||||
@@ -511,4 +535,9 @@ class AdminApi:
|
||||
for p in problems:
|
||||
sys.stderr.write('!!!{}\n'.format(p))
|
||||
|
||||
return tx
|
||||
if renderer == None:
|
||||
return tx
|
||||
|
||||
r = renderer(tx)
|
||||
w.write(r + '\n')
|
||||
return None
|
||||
|
||||
@@ -281,6 +281,7 @@ def send(self, txs, chain_spec_dict):
|
||||
o = raw(tx_hex)
|
||||
conn = RPCConnection.connect(chain_spec, 'default')
|
||||
conn.do(o)
|
||||
|
||||
s_set_sent.apply_async()
|
||||
|
||||
tx_tail = txs[1:]
|
||||
|
||||
33
apps/cic-eth/cic_eth/registry.py
Normal file
33
apps/cic-eth/cic_eth/registry.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# external imports
|
||||
from cic_eth_registry import CICRegistry
|
||||
from cic_eth_registry.lookup.declarator import AddressDeclaratorLookup
|
||||
from cic_eth_registry.lookup.tokenindex import TokenIndexLookup
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def connect_token_registry(rpc, chain_spec):
|
||||
registry = CICRegistry(chain_spec, rpc)
|
||||
token_registry_address = registry.by_name('TokenRegistry')
|
||||
logg.debug('using token registry address {}'.format(token_registry_address))
|
||||
lookup = TokenIndexLookup(token_registry_address)
|
||||
CICRegistry.add_lookup(lookup)
|
||||
|
||||
|
||||
def connect_declarator(rpc, chain_spec, trusted_addresses):
|
||||
registry = CICRegistry(chain_spec, rpc)
|
||||
declarator_address = registry.by_name('AddressDeclarator')
|
||||
logg.debug('using declarator address {}'.format(declarator_address))
|
||||
lookup = AddressDeclaratorLookup(declarator_address, trusted_addresses)
|
||||
CICRegistry.add_lookup(lookup)
|
||||
|
||||
|
||||
def connect(rpc, chain_spec, registry_address):
|
||||
CICRegistry.address = registry_address
|
||||
registry = CICRegistry(chain_spec, rpc)
|
||||
registry_address = registry.by_name('ContractRegistry')
|
||||
|
||||
return registry
|
||||
@@ -16,8 +16,6 @@ from chainlib.eth.connection import EthUnixSignerConnection
|
||||
from chainlib.chain import ChainSpec
|
||||
|
||||
# local imports
|
||||
from cic_eth_registry import CICRegistry
|
||||
|
||||
from cic_eth.eth import erc20
|
||||
from cic_eth.eth import tx
|
||||
from cic_eth.eth import account
|
||||
@@ -33,6 +31,11 @@ from cic_eth.db.models.base import SessionBase
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.db import dsn_from_config
|
||||
from cic_eth.ext import tx
|
||||
from cic_eth.registry import (
|
||||
connect as connect_registry,
|
||||
connect_declarator,
|
||||
connect_token_registry,
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
@@ -121,8 +124,6 @@ RPCConnection.register_location(config.get('SIGNER_SOCKET_PATH'), chain_spec, 's
|
||||
|
||||
Otx.tracing = config.true('TASKS_TRACE_QUEUE_STATUS')
|
||||
|
||||
CICRegistry.address = config.get('CIC_REGISTRY_ADDRESS')
|
||||
|
||||
|
||||
def main():
|
||||
argv = ['worker']
|
||||
@@ -145,8 +146,8 @@ def main():
|
||||
# Callback.ssl_ca_file = config.get('SSL_CA_FILE')
|
||||
|
||||
rpc = RPCConnection.connect(chain_spec, 'default')
|
||||
registry = CICRegistry(chain_spec, rpc)
|
||||
registry_address = registry.by_name('ContractRegistry')
|
||||
|
||||
connect_registry(rpc, chain_spec, config.get('CIC_REGISTRY_ADDRESS'))
|
||||
|
||||
trusted_addresses_src = config.get('CIC_TRUST_ADDRESS')
|
||||
if trusted_addresses_src == None:
|
||||
@@ -155,6 +156,8 @@ def main():
|
||||
trusted_addresses = trusted_addresses_src.split(',')
|
||||
for address in trusted_addresses:
|
||||
logg.info('using trusted address {}'.format(address))
|
||||
connect_declarator(rpc, chain_spec, trusted_addresses)
|
||||
connect_token_registry(rpc, chain_spec)
|
||||
|
||||
current_app.worker_main(argv)
|
||||
|
||||
|
||||
100
apps/cic-eth/cic_eth/runnable/transfer.py
Normal file
100
apps/cic-eth/cic_eth/runnable/transfer.py
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/python
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
import uuid
|
||||
import json
|
||||
import argparse
|
||||
|
||||
# external imports
|
||||
import celery
|
||||
import confini
|
||||
import redis
|
||||
from xdg.BaseDirectory import xdg_config_home
|
||||
from chainlib.eth.address import to_checksum_address
|
||||
|
||||
# local imports
|
||||
from cic_eth.api import Api
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger('create_account_script')
|
||||
logging.getLogger('confini').setLevel(logging.WARNING)
|
||||
logging.getLogger('gnupg').setLevel(logging.WARNING)
|
||||
|
||||
default_config_dir = os.environ.get('CONFINI_DIR', '/usr/local/etc/cic')
|
||||
|
||||
argparser = argparse.ArgumentParser()
|
||||
argparser.add_argument('--no-register', dest='no_register', action='store_true', help='Do not register new account in on-chain accounts index')
|
||||
argparser.add_argument('-c', type=str, default=default_config_dir, help='config file')
|
||||
argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='chain spec')
|
||||
argparser.add_argument('--token-symbol', dest='token_symbol', type=str, help='Symbol of token to transfer')
|
||||
argparser.add_argument('--redis-host', dest='redis_host', type=str, help='redis host to use for task submission')
|
||||
argparser.add_argument('--redis-port', dest='redis_port', type=int, help='redis host to use for task submission')
|
||||
argparser.add_argument('--redis-db', dest='redis_db', type=int, help='redis db to use for task submission and callback')
|
||||
argparser.add_argument('--redis-host-callback', dest='redis_host_callback', default='localhost', type=str, help='redis host to use for callback')
|
||||
argparser.add_argument('--redis-port-callback', dest='redis_port_callback', default=6379, type=int, help='redis port to use for callback')
|
||||
argparser.add_argument('--timeout', default=20.0, type=float, help='Callback timeout')
|
||||
argparser.add_argument('-q', type=str, default='cic-eth', help='Task queue')
|
||||
argparser.add_argument('-v', action='store_true', help='Be verbose')
|
||||
argparser.add_argument('-vv', action='store_true', help='Be more verbose')
|
||||
argparser.add_argument('sender', type=str, help='Transaction sender')
|
||||
argparser.add_argument('recipient', type=str, help='Transaction recipient')
|
||||
argparser.add_argument('value', type=int, help='Transaction value with decimals')
|
||||
args = argparser.parse_args()
|
||||
|
||||
if args.vv:
|
||||
logg.setLevel(logging.DEBUG)
|
||||
if args.v:
|
||||
logg.setLevel(logging.INFO)
|
||||
|
||||
config_dir = args.c
|
||||
config = confini.Config(config_dir, os.environ.get('CONFINI_ENV_PREFIX'))
|
||||
config.process()
|
||||
args_override = {
|
||||
'CIC_CHAIN_SPEC': getattr(args, 'i'),
|
||||
'REDIS_HOST': getattr(args, 'redis_host'),
|
||||
'REDIS_PORT': getattr(args, 'redis_port'),
|
||||
'REDIS_DB': getattr(args, 'redis_db'),
|
||||
}
|
||||
config.dict_override(args_override, 'cli')
|
||||
config.add(to_checksum_address(args.sender), '_SENDER', True)
|
||||
config.add(to_checksum_address(args.recipient), '_RECIPIENT', True)
|
||||
config.add(args.value, '_VALUE', True)
|
||||
config.add(args.token_symbol, '_SYMBOL', True)
|
||||
if config.get('_SYMBOL') == None:
|
||||
raise ValueError('gas transfers not yet supported; token symbol required')
|
||||
celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL'))
|
||||
|
||||
|
||||
def main():
|
||||
redis_host = config.get('REDIS_HOST')
|
||||
redis_port = config.get('REDIS_PORT')
|
||||
redis_db = config.get('REDIS_DB')
|
||||
redis_channel = str(uuid.uuid4())
|
||||
r = redis.Redis(redis_host, redis_port, redis_db)
|
||||
|
||||
ps = r.pubsub()
|
||||
ps.subscribe(redis_channel)
|
||||
ps.get_message()
|
||||
|
||||
api = Api(
|
||||
config.get('CIC_CHAIN_SPEC'),
|
||||
queue=args.q,
|
||||
callback_param='{}:{}:{}:{}'.format(args.redis_host_callback, args.redis_port_callback, redis_db, redis_channel),
|
||||
callback_task='cic_eth.callbacks.redis.redis',
|
||||
callback_queue=args.q,
|
||||
)
|
||||
|
||||
#register = not args.no_register
|
||||
#logg.debug('register {}'.format(register))
|
||||
#t = api.create_account(register=register)
|
||||
t = api.transfer(config.get('_SENDER'), config.get('_RECIPIENT'), config.get('_VALUE'), config.get('_SYMBOL'))
|
||||
|
||||
ps.get_message()
|
||||
o = ps.get_message(timeout=args.timeout)
|
||||
m = json.loads(o['data'])
|
||||
print(m['result'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -14,8 +14,6 @@ import datetime
|
||||
# external imports
|
||||
import confini
|
||||
import celery
|
||||
from cic_eth_registry import CICRegistry
|
||||
from cic_eth_registry.lookup.declarator import AddressDeclaratorLookup
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from hexathon import add_0x
|
||||
@@ -27,6 +25,7 @@ from cic_eth.db.enum import (
|
||||
status_str,
|
||||
LockEnum,
|
||||
)
|
||||
from cic_eth.registry import connect as connect_registry
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
@@ -116,12 +115,16 @@ def render_tx(o, **kwargs):
|
||||
return content
|
||||
|
||||
def render_account(o, **kwargs):
|
||||
return '{} {} {} {}'.format(
|
||||
s = '{} {} {} {}'.format(
|
||||
o['date_updated'],
|
||||
o['nonce'],
|
||||
o['tx_hash'],
|
||||
o['status'],
|
||||
)
|
||||
if len(o['errors']) > 0:
|
||||
s += ' !{}'.format(','.join(o['errors']))
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def render_lock(o, **kwargs):
|
||||
@@ -143,44 +146,31 @@ def render_lock(o, **kwargs):
|
||||
return s
|
||||
|
||||
|
||||
def connect_registry(registry_address, chain_spec, rpc):
|
||||
CICRegistry.address = registry_address
|
||||
registry = CICRegistry(chain_spec, rpc)
|
||||
declarator_address = registry.by_name('AddressDeclarator')
|
||||
lookup = AddressDeclaratorLookup(declarator_address, trusted_addresses)
|
||||
registry.add_lookup(lookup)
|
||||
return registry
|
||||
|
||||
|
||||
# TODO: move each command to submodule
|
||||
def main():
|
||||
txs = []
|
||||
renderer = render_tx
|
||||
if len(config.get('_QUERY')) > 66:
|
||||
registry = connect_registry(registry_address, chain_spec, rpc)
|
||||
txs = [admin_api.tx(chain_spec, tx_raw=config.get('_QUERY'), registry=registry)]
|
||||
registry = connect_registry(rpc, chain_spec, registry_address)
|
||||
admin_api.tx(chain_spec, tx_raw=config.get('_QUERY'), registry=registry, renderer=renderer)
|
||||
elif len(config.get('_QUERY')) > 42:
|
||||
registry = connect_registry(registry_address, chain_spec, rpc)
|
||||
txs = [admin_api.tx(chain_spec, tx_hash=config.get('_QUERY'), registry=registry)]
|
||||
registry = connect_registry(rpc, chain_spec, registry_address)
|
||||
admin_api.tx(chain_spec, tx_hash=config.get('_QUERY'), registry=registry, renderer=renderer)
|
||||
|
||||
elif len(config.get('_QUERY')) == 42:
|
||||
registry = connect_registry(registry_address, chain_spec, rpc)
|
||||
txs = admin_api.account(chain_spec, config.get('_QUERY'), include_recipient=False)
|
||||
registry = connect_registry(rpc, chain_spec, registry_address)
|
||||
txs = admin_api.account(chain_spec, config.get('_QUERY'), include_recipient=False, renderer=render_account)
|
||||
renderer = render_account
|
||||
elif len(config.get('_QUERY')) >= 4 and config.get('_QUERY')[:4] == 'lock':
|
||||
t = admin_api.get_lock()
|
||||
txs = t.get()
|
||||
renderer = render_lock
|
||||
for tx in txs:
|
||||
r = renderer(txs)
|
||||
sys.stdout.write(r + '\n')
|
||||
else:
|
||||
raise ValueError('cannot parse argument {}'.format(config.get('_QUERY')))
|
||||
|
||||
|
||||
if len(txs) == 0:
|
||||
logg.info('no matches found')
|
||||
else:
|
||||
if fmt == 'json':
|
||||
sys.stdout.write(json.dumps(txs))
|
||||
else:
|
||||
m = map(renderer, txs)
|
||||
print(*m, sep="\n")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -10,7 +10,7 @@ version = (
|
||||
0,
|
||||
10,
|
||||
1,
|
||||
'beta.1',
|
||||
'beta.2',
|
||||
)
|
||||
|
||||
version_object = semver.VersionInfo(
|
||||
|
||||
@@ -54,3 +54,4 @@ console_scripts =
|
||||
# TODO: Merge this with ctl when subcmds sorted to submodules
|
||||
cic-eth-tag = cic_eth.runnable.tag:main
|
||||
cic-eth-resend = cic_eth.runnable.resend:main
|
||||
cic-eth-transfer = cic_eth.runnable.transfer:main
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
alembic~=1.4.2
|
||||
celery~=4.4.7
|
||||
confini~=0.3.6rc3
|
||||
redis~=3.5.3
|
||||
semver==2.13.0
|
||||
cic_base[full_graph]~=0.1.2a46
|
||||
@@ -1,7 +1,7 @@
|
||||
# standard imports
|
||||
import semver
|
||||
|
||||
version = (0, 3, 0, 'alpha.5')
|
||||
version = (0, 3, 0, 'alpha.7')
|
||||
|
||||
version_object = semver.VersionInfo(
|
||||
major=version[0],
|
||||
|
||||
@@ -1,49 +1,4 @@
|
||||
#cic_base[full_graph]~=0.1.1a24
|
||||
africastalking==1.2.3
|
||||
alembic==1.4.2
|
||||
amqp==2.6.1
|
||||
attrs==20.2.0
|
||||
bcrypt==3.2.0
|
||||
betterpath==0.2.2
|
||||
billiard==3.6.3.0
|
||||
celery==4.4.7
|
||||
cffi==1.14.3
|
||||
cic_base[full_graph]~=0.1.2a46
|
||||
cic-eth~=0.10.1b1
|
||||
cic-notify~=0.4.0a3
|
||||
cic-types~=0.1.0a8
|
||||
click==7.1.2
|
||||
confini~=0.3.6rc3
|
||||
cryptography==3.2.1
|
||||
faker==4.17.1
|
||||
iniconfig==1.1.1
|
||||
kombu==4.6.11
|
||||
Mako==1.1.3
|
||||
MarkupSafe==1.1.1
|
||||
mirakuru==2.3.0
|
||||
more-itertools==8.5.0
|
||||
packaging==20.4
|
||||
phonenumbers==8.12.12
|
||||
pluggy==0.13.1
|
||||
port-for==0.4
|
||||
psutil==5.7.3
|
||||
psycopg2==2.8.6
|
||||
py==1.9.0
|
||||
pycparser==2.20
|
||||
pyparsing==2.4.7
|
||||
python-dateutil==2.8.1
|
||||
python-editor==1.0.4
|
||||
python-gnupg==0.4.6
|
||||
python-i18n==0.3.9
|
||||
pytz==2020.1
|
||||
PyYAML==5.3.1
|
||||
redis==3.5.3
|
||||
semver==2.13.0
|
||||
six==1.15.0
|
||||
SQLAlchemy==1.3.20
|
||||
tinydb==4.2.0
|
||||
toml==0.10.1
|
||||
transitions==0.8.4
|
||||
uWSGI==2.0.19.1
|
||||
vcversioner==2.16.0.0
|
||||
vine==1.3.0
|
||||
zope.interface==5.1.2
|
||||
cic-types~=0.1.0a8
|
||||
@@ -32,7 +32,10 @@ from chainlib.eth.block import (
|
||||
from chainlib.eth.hash import keccak256_string_to_hex
|
||||
from chainlib.eth.address import to_checksum_address
|
||||
from chainlib.eth.erc20 import ERC20
|
||||
from chainlib.eth.gas import OverrideGasOracle
|
||||
from chainlib.eth.gas import (
|
||||
OverrideGasOracle,
|
||||
balance,
|
||||
)
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.eth.rpc import jsonrpc_template
|
||||
from chainlib.eth.error import EthException
|
||||
@@ -41,6 +44,7 @@ from cic_types.models.person import (
|
||||
Person,
|
||||
generate_metadata_pointer,
|
||||
)
|
||||
from erc20_single_shot_faucet import SingleShotFaucet
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
@@ -127,17 +131,19 @@ class VerifierError(Exception):
|
||||
class Verifier:
|
||||
|
||||
# TODO: what an awful function signature
|
||||
def __init__(self, conn, cic_eth_api, gas_oracle, chain_spec, index_address, token_address, data_dir, exit_on_error=False):
|
||||
def __init__(self, conn, cic_eth_api, gas_oracle, chain_spec, index_address, token_address, faucet_address, data_dir, exit_on_error=False):
|
||||
self.conn = conn
|
||||
self.gas_oracle = gas_oracle
|
||||
self.chain_spec = chain_spec
|
||||
self.index_address = index_address
|
||||
self.token_address = token_address
|
||||
self.faucet_address = faucet_address
|
||||
self.erc20_tx_factory = ERC20(chain_id=chain_spec.chain_id(), gas_oracle=gas_oracle)
|
||||
self.tx_factory = TxFactory(chain_id=chain_spec.chain_id(), gas_oracle=gas_oracle)
|
||||
self.api = cic_eth_api
|
||||
self.data_dir = data_dir
|
||||
self.exit_on_error = exit_on_error
|
||||
self.faucet_tx_factory = SingleShotFaucet(chain_id=chain_spec.chain_id(), gas_oracle=gas_oracle)
|
||||
|
||||
verifymethods = []
|
||||
for k in dir(self):
|
||||
@@ -182,6 +188,21 @@ class Verifier:
|
||||
raise VerifierError((address, r), 'local key')
|
||||
|
||||
|
||||
def verify_gas(self, address, balance_token=None):
|
||||
o = balance(address)
|
||||
r = self.conn.do(o)
|
||||
actual_balance = int(strip_0x(r), 16)
|
||||
if actual_balance == 0:
|
||||
raise VerifierError((address, actual_balance), 'gas')
|
||||
|
||||
|
||||
def verify_faucet(self, address, balance_token=None):
|
||||
o = self.faucet_tx_factory.usable_for(self.faucet_address, address)
|
||||
r = self.conn.do(o)
|
||||
if self.faucet_tx_factory.parse_usable_for(r):
|
||||
raise VerifierError((address, r), 'faucet')
|
||||
|
||||
|
||||
def verify_metadata(self, address, balance=None):
|
||||
k = generate_metadata_pointer(bytes.fromhex(strip_0x(address)), ':cic.person')
|
||||
url = os.path.join(meta_url, k)
|
||||
@@ -220,6 +241,8 @@ class Verifier:
|
||||
'accounts_index',
|
||||
'balance',
|
||||
'metadata',
|
||||
'gas',
|
||||
'faucet',
|
||||
]
|
||||
|
||||
for k in methods:
|
||||
@@ -257,6 +280,7 @@ def main():
|
||||
txf = TxFactory(signer=None, gas_oracle=gas_oracle, nonce_oracle=None, chain_id=chain_spec.chain_id())
|
||||
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()
|
||||
@@ -283,6 +307,18 @@ def main():
|
||||
account_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
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 = jsonrpc_template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
r = conn.do(o)
|
||||
faucet_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
logg.info('found faucet {}'.format(faucet_address))
|
||||
|
||||
|
||||
# Get Sarafu token address
|
||||
tx = txf.template(ZERO_ADDRESS, token_index_address)
|
||||
@@ -323,7 +359,7 @@ def main():
|
||||
|
||||
api = AdminApi(MockClient())
|
||||
|
||||
verifier = Verifier(conn, api, gas_oracle, chain_spec, account_index_address, sarafu_token_address, user_dir, exit_on_error)
|
||||
verifier = Verifier(conn, api, gas_oracle, chain_spec, account_index_address, sarafu_token_address, faucet_address, user_dir, exit_on_error)
|
||||
|
||||
user_new_dir = os.path.join(user_dir, 'new')
|
||||
for x in os.walk(user_new_dir):
|
||||
|
||||
@@ -22,7 +22,7 @@ abi_dir=${ETH_ABI_DIR:-/usr/local/share/cic/solidity/abi}
|
||||
gas_amount=100000000000000000000000
|
||||
token_amount=${gas_amount}
|
||||
#faucet_amount=1000000000
|
||||
faucet_amount=0
|
||||
faucet_amount=${DEV_FAUCET_AMOUNT:-0}
|
||||
env_out_file=${CIC_DATA_DIR}/.env_seed
|
||||
init_level_file=${CIC_DATA_DIR}/.init
|
||||
truncate $env_out_file -s 0
|
||||
|
||||
@@ -102,6 +102,7 @@ services:
|
||||
CELERY_RESULT_URL: ${CELERY_RESULT_URL:-redis://redis:6379}
|
||||
DEV_PIP_EXTRA_INDEX_URL: ${DEV_PIP_EXTRA_INDEX_URL:-https://pip.grassrootseconomics.net:8433}
|
||||
RUN_MASK: ${RUN_MASK:-0} # bit flags; 1: contract migrations 2: seed data
|
||||
DEV_FAUCET_AMOUNT: ${DEV_FAUCET_AMOUNT:-0}
|
||||
command: ["./run_job.sh"]
|
||||
#command: ["./reset.sh"]
|
||||
depends_on:
|
||||
|
||||
Reference in New Issue
Block a user