From 2a9c74080f6f29fb74aa2cef4d59c1fc1ffb53eb Mon Sep 17 00:00:00 2001 From: nolash Date: Fri, 19 Feb 2021 21:12:33 +0100 Subject: [PATCH] WIP hacking together traffic generator --- .../cic_eth/runnable/daemons/tasker.py | 2 +- .../contract-migration/scripts/config/cic.ini | 1 + .../scripts/requirements.txt | 3 +- apps/contract-migration/scripts/traffic.py | 211 ++++++++++++++++++ 4 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 apps/contract-migration/scripts/traffic.py diff --git a/apps/cic-eth/cic_eth/runnable/daemons/tasker.py b/apps/cic-eth/cic_eth/runnable/daemons/tasker.py index 6b9c4bf5..cb456761 100644 --- a/apps/cic-eth/cic_eth/runnable/daemons/tasker.py +++ b/apps/cic-eth/cic_eth/runnable/daemons/tasker.py @@ -228,7 +228,7 @@ def main(): for address in trusted_addresses: logg.info('using trusted address {}'.format(address)) oracle = DeclaratorOracleAdapter(declarator.contract, trusted_addresses) - chain_registry.add_oracle('naive_erc20_oracle', oracle) + chain_registry.add_oracle(oracle, 'naive_erc20_oracle') #chain_spec = CICRegistry.default_chain_spec diff --git a/apps/contract-migration/scripts/config/cic.ini b/apps/contract-migration/scripts/config/cic.ini index ffb51250..b2e0b80c 100644 --- a/apps/contract-migration/scripts/config/cic.ini +++ b/apps/contract-migration/scripts/config/cic.ini @@ -6,3 +6,4 @@ declarator_address = approval_escrow_address = chain_spec = evm:bloxberg:8996 tx_retry_delay = +trust_address = 0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C diff --git a/apps/contract-migration/scripts/requirements.txt b/apps/contract-migration/scripts/requirements.txt index d8107f14..d3215c14 100644 --- a/apps/contract-migration/scripts/requirements.txt +++ b/apps/contract-migration/scripts/requirements.txt @@ -1,6 +1,6 @@ psycopg2==2.8.6 chainlib~=0.0.1a15 -chainsyncer==0.0.1a8 +chainsyncer==0.0.1a9 cic-eth==0.10.0a28 cic-registry==0.5.3a19 confini==0.3.6rc1 @@ -9,3 +9,4 @@ redis==3.5.3 hexathon==0.0.1a3 faker==4.17.1 cic-types==0.1.0a7+build.1c254367 +eth-accounts-index==0.0.10a10 diff --git a/apps/contract-migration/scripts/traffic.py b/apps/contract-migration/scripts/traffic.py new file mode 100644 index 00000000..f28df63d --- /dev/null +++ b/apps/contract-migration/scripts/traffic.py @@ -0,0 +1,211 @@ +# standard imports +import os +import logging +import argparse +import re +import sys + +# external imports +import confini +import web3 +from cic_registry import CICRegistry +from cic_registry.chain import ChainRegistry +from chainlib.chain import ChainSpec +from eth_token_index import TokenUniqueSymbolIndex +from eth_accounts_index import AccountRegistry +from cic_registry.helper.declarator import DeclaratorOracleAdapter +from chainsyncer.backend import MemBackend +from chainsyncer.driver import HeadSyncer +from chainlib.eth.connection import HTTPConnection +from chainlib.eth.gas import DefaultGasOracle +from chainlib.eth.nonce import DefaultNonceOracle +from chainlib.eth.block import block_latest +from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer +from crypto_dev_signer.keystore import DictKeystore +from hexathon import strip_0x + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +script_dir = os.path.realpath(os.path.dirname(__file__)) +default_data_dir = '/usr/local/share/cic/solidity/abi' + +argparser = argparse.ArgumentParser() +argparser.add_argument('-p', type=str, help='Ethereum provider url') +argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') +argparser.add_argument('-c', type=str, default='./config', help='config file') +argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='chain spec') +argparser.add_argument('-v', action='store_true', help='be verbose') +argparser.add_argument('-vv', action='store_true', help='be more verbose') +argparser.add_argument('--abi-dir', dest='abi_dir', type=str, help='Directory containing bytecode and abi') +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('-r', type=str, help='cic-registry address') +argparser.add_argument('--batch-size', dest='batch_size', default=10, type=int, help='number of events to process simultaneously') +args = argparser.parse_args() + + +# handle logging input +if args.vv: + logging.getLogger().setLevel(logging.DEBUG) +elif args.v: + logging.getLogger().setLevel(logging.INFO) + +# handle config input +config = confini.Config(args.c, args.env_prefix) +config.process() +args_override = { + 'ETH_ABI_DIR': getattr(args, 'abi_dir'), + 'ETH_PROVIDER': getattr(args, 'p'), + 'CIC_CHAIN_SPEC': getattr(args, 'i'), + 'CIC_REGISTRY_ADDRESS': getattr(args, 'r'), + } +config.dict_override(args_override, 'cli flag') +config.validate() + +# handle batch size input +batchsize = args.batch_size +if batchsize < 1: + batchsize = 1 +logg.info('batch size {}'.format(batchsize)) +config.add(batchsize, '_BATCH_SIZE', True) + +# signer +keystore = DictKeystore() +if args.y == None: + logg.critical('please specify signer keystore file') + sys.exit(1) + +logg.debug('loading keystore file {}'.format(args.y)) +__signer_address = keystore.import_keystore_file(args.y) +config.add(__signer_address, '_SIGNER_ADDRESS') +logg.debug('now have key for signer address {}'.format(config.get('_SIGNER_ADDRESS'))) +signer = EIP155Signer(keystore) + + +# web3 input +# TODO: Replace with chainlib +re_websocket = r'^wss?:' +re_http = r'^https?:' +blockchain_provider = None +if re.match(re_websocket, config.get('ETH_PROVIDER')): + blockchain_provider = web3.Web3.WebsocketProvider(config.get('ETH_PROVIDER')) +elif re.match(re_http, config.get('ETH_PROVIDER')): + blockchain_provider = web3.Web3.HTTPProvider(config.get('ETH_PROVIDER')) +w3 = web3.Web3(blockchain_provider) + + +logg.debug('config:\n{}'.format(config)) + + +class TokenOracle: + + def __init__(self, chain_spec, registry): + self.tokens = [] + self.chain_spec = chain_spec + self.registry = registry + + token_registry_contract = CICRegistry.get_contract(chain_spec, 'TokenRegistry', 'Registry') + self.getter = TokenUniqueSymbolIndex(w3, token_registry_contract.address()) + + + def get_tokens(self): + token_count = self.getter.count() + if token_count == len(self.tokens): + return self.tokens + + for i in range(len(self.tokens), token_count): + token_address = self.getter.get_index(i) + t = self.registry.get_address(self.chain_spec, token_address) + token_symbol = t.symbol() + self.tokens.append(token_address) + + logg.debug('adding token idx {} symbol {} address {}'.format(i, token_symbol, token_address)) + + return self.tokens + + +class AccountsOracle: + + def __init__(self, chain_spec, registry): + self.accounts = [] + self.chain_spec = chain_spec + self.registry = registry + + accounts_registry_contract = CICRegistry.get_contract(chain_spec, 'AccountRegistry', 'Registry') + self.getter = AccountRegistry(w3, accounts_registry_contract.address()) + + + def get_accounts(self): + accounts_count = self.getter.count() + if accounts_count == len(self.accounts): + return self.accounts + + for i in range(len(self.accounts), accounts_count): + account = self.getter.get_index(i) + self.accounts.append(account) + logg.debug('adding account {}'.format(account)) + + return self.accounts + + +class Refresher: + + def __init__(self, chain_spec, registry): + self.chain_spec = chain_spec + self.registry = registry + self.token_oracle = TokenOracle(self.chain_spec, self.registry) + self.accounts_oracle = AccountsOracle(self.chain_spec, self.registry) + + def refresh(self, block_number, tx_index): + tokens = self.token_oracle.get_tokens() + accounts = self.accounts_oracle.get_accounts() + + if len(accounts) == 0: + logg.error('no accounts yet') + + elif len(tokens) == 0: + logg.error('no tokens yet') + + +def main(local_config=None): + + if local_config != None: + config = local_config + + chain_spec = ChainSpec.from_chain_str(config.get('CIC_CHAIN_SPEC')) + CICRegistry.init(w3, config.get('CIC_REGISTRY_ADDRESS'), chain_spec) + CICRegistry.add_path(config.get('ETH_ABI_DIR')) + + chain_registry = ChainRegistry(chain_spec) + CICRegistry.add_chain_registry(chain_registry, True) + + declarator = CICRegistry.get_contract(chain_spec, 'AddressDeclarator', interface='Declarator') + trusted_addresses_src = config.get('CIC_TRUST_ADDRESS') + if trusted_addresses_src == None: + logg.critical('At least one trusted address must be declared in CIC_TRUST_ADDRESS') + sys.exit(1) + trusted_addresses = trusted_addresses_src.split(',') + for address in trusted_addresses: + logg.info('using trusted address {}'.format(address)) + + oracle = DeclaratorOracleAdapter(declarator.contract, trusted_addresses) + chain_registry.add_oracle(oracle, 'naive_erc20_oracle') + + # Connect to blockchain + conn = HTTPConnection(config.get('ETH_PROVIDER')) + gas_oracle = DefaultGasOracle(conn) + nonce_oracle = DefaultNonceOracle(config.get('_SIGNER_ADDRESS'), conn) + + # Set up syncer + syncer_backend = MemBackend(str(chain_spec), 0) + o = block_latest() + r = conn.do(o) + block_offset = int(strip_0x(r), 16) + 1 + syncer_backend.set(block_offset, 0) + refresher_callback = Refresher(chain_spec, CICRegistry) + syncer = HeadSyncer(syncer_backend, loop_callback=refresher_callback.refresh) + syncer.loop(1, conn) + +if __name__ == '__main__': + main(config)