def _run_app(self): from raiden.ui.console import Console from raiden.api.python import RaidenAPI # this catches exceptions raised when waiting for the stalecheck to complete try: app_ = run_app(**self._options) except EthNodeCommunicationError: print( '\n' 'Could not contact the ethereum node through JSON-RPC.\n' 'Please make sure that JSON-RPC is enabled for these interfaces:\n' '\n' ' eth_*, net_*, web3_*\n' '\n' 'geth: https://github.com/ethereum/go-ethereum/wiki/Management-APIs\n', ) sys.exit(1) domain_list = [] if self._options['rpccorsdomain']: if ',' in self._options['rpccorsdomain']: for domain in self._options['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(self._options['rpccorsdomain'])) self._raiden_api = RaidenAPI(app_.raiden) api_server = None if self._options['rpc']: rest_api = RestAPI(self._raiden_api) api_server = APIServer( rest_api, cors_domain_list=domain_list, web_ui=self._options['web_ui'], eth_rpc_endpoint=self._options['eth_rpc_endpoint'], ) (api_host, api_port) = split_endpoint(self._options['api_address']) try: api_server.start(api_host, api_port) except APIServerPortInUseError: print( 'ERROR: API Address %s:%s is in use. ' 'Use --api-address <host:port> to specify port to listen on.' % (api_host, api_port), ) sys.exit(1) print( 'The Raiden API RPC server is now running at http://{}:{}/.\n\n' 'See the Raiden documentation for all available endpoints at\n' 'http://raiden-network.readthedocs.io/en/stable/rest_api.html'. format( api_host, api_port, ), ) if self._options['console']: console = Console(app_) console.start() # spawn a greenlet to handle the version checking gevent.spawn(check_version) # spawn a greenlet to handle the gas reserve check gevent.spawn(check_gas_reserve, app_.raiden) self._startup_hook() # wait for interrupt event = RaidenGreenletEvent() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) try: event.wait() print('Signal received. Shutting down ...') except RaidenError as ex: click.secho(f'FATAL: {ex}', fg='red') except Exception as ex: with NamedTemporaryFile( 'w', prefix= f'raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}', suffix='.txt', delete=False, ) as traceback_file: traceback.print_exc(file=traceback_file) click.secho( f'FATAL: An unexpected exception occured. ' f'A traceback has been written to {traceback_file.name}\n' f'{ex}', fg='red', ) finally: self._shutdown_hook() if api_server: api_server.stop() return app_
def run( privatekey, registry_contract_address, secret_registry_contract_address, discovery_contract_address, listen_address, structlog, logfile, scenario, stage_prefix, ): # pylint: disable=unused-argument # TODO: only enabled structlog on "initiators" structlog.configure(structlog, log_file=logfile) (listen_host, listen_port) = split_endpoint(listen_address) config = App.DEFAULT_CONFIG.copy() config['transport']['udp']['host'] = listen_host config['transport']['udp']['port'] = listen_port config['privatekey_hex'] = privatekey privatekey_bin = decode_hex(privatekey) web3 = Web3(HTTPProvider(f'http://127.0.0.1:8545')) rpc_client = JSONRPCClient(web3, privatekey_bin) blockchain_service = BlockChainService(privatekey_bin, rpc_client) discovery = ContractDiscovery( blockchain_service, decode_hex(discovery_contract_address), ) registry = blockchain_service.token_network_registry( registry_contract_address, ) secret_registry = blockchain_service.secret_registry( secret_registry_contract_address, ) throttle_policy = TokenBucket( config['protocol']['throttle_capacity'], config['protocol']['throttle_fill_rate'], ) transport = UDPTransport( discovery=discovery, udpsocket=gevent.server._udp_socket((listen_host, listen_port)), throttle_policy=throttle_policy, config=config['transport']['udp'], ) raiden_event_handler = RaidenEventHandler() app = App( config=config, chain=blockchain_service, query_start_block=0, default_registry=registry, default_secret_registry=secret_registry, transport=transport, raiden_event_handler=raiden_event_handler, discovery=discovery, ) app.start() app.discovery.register( app.raiden.address, listen_host, listen_port, ) from_block = 0 app.raiden.install_all_blockchain_filters( app.raiden.default_registry, app.raiden.default_secret_registry, from_block, ) if scenario: script = json.load(scenario) tools = ConsoleTools( app.raiden, app.discovery, app.config['settle_timeout'], ) transfers_by_peer = {} tokens = script['tokens'] token_address = None peer = None our_node = hexlify(app.raiden.address) log.warning('our address is {}'.format(our_node)) for token in tokens: # skip tokens that we're not part of nodes = token['channels'] if our_node not in nodes: continue partner_nodes = [node for node in nodes if node != our_node] # allow for prefunded tokens if 'token_address' in token: token_address = token['token_address'] else: token_address = tools.create_token(registry_contract_address) transfers_with_amount = token['transfers_with_amount'] # FIXME: in order to do bidirectional channels, only one side # (i.e. only token['channels'][0]) should # open; others should join by calling # raiden.api.deposit, AFTER the channel came alive! # NOTE: leaving unidirectional for now because it most # probably will get to higher throughput log.warning('Waiting for all nodes to come online') api = RaidenAPI(app.raiden) for node in partner_nodes: api.start_health_check_for(node) while True: all_reachable = all( api.get_node_network_state(node) == NODE_NETWORK_REACHABLE for node in partner_nodes) if all_reachable: break gevent.sleep(5) log.warning('All nodes are online') if our_node != nodes[-1]: our_index = nodes.index(our_node) peer = nodes[our_index + 1] tools.token_network_register( app.raiden.default_registry.address, token_address) amount = transfers_with_amount[nodes[-1]] while True: try: app.discovery.get(peer.decode('hex')) break except KeyError: log.warning( 'Error: peer {} not found in discovery'.format( peer)) time.sleep(random.randrange(30)) while True: try: log.warning('Opening channel with {} for {}'.format( peer, token_address)) api.channel_open(app.raiden.default_registry.address, token_address, peer) break except KeyError: log.warning( 'Error: could not open channel with {}'.format( peer)) time.sleep(random.randrange(30)) while True: try: log.warning('Funding channel with {} for {}'.format( peer, token_address)) api.channel_deposit( app.raiden.default_registry.address, token_address, peer, amount, ) break except Exception: log.warning( 'Error: could not deposit {} for {}'.format( amount, peer)) time.sleep(random.randrange(30)) if our_index == 0: last_node = nodes[-1] transfers_by_peer[last_node] = int(amount) if stage_prefix is not None: open('{}.stage1'.format(stage_prefix), 'a').close() log.warning('Done with initialization, waiting to continue...') event = RaidenGreenletEvent() gevent.signal(signal.SIGUSR2, event.set) event.wait() transfer_results = {'total_time': 0, 'timestamps': []} def transfer(token_address, amount_per_transfer, total_transfers, peer, is_async): def transfer_(): log.warning('Making {} transfers to {}'.format( total_transfers, peer)) initial_time = time.time() times = [0] * total_transfers for index in range(total_transfers): RaidenAPI(app.raiden).transfer( app.raiden.default_registry.address, token_address.decode('hex'), amount_per_transfer, peer, ) times[index] = time.time() transfer_results['total_time'] = time.time() - initial_time transfer_results['timestamps'] = times log.warning('Making {} transfers took {}'.format( total_transfers, transfer_results['total_time'])) log.warning('Times: {}'.format(times)) if is_async: return gevent.spawn(transfer_) else: transfer_() # If sending to multiple targets, do it asynchronously, otherwise # keep it simple and just send to the single target on my thread. if len(transfers_by_peer) > 1: greenlets = [] for peer_, amount in transfers_by_peer.items(): greenlet = transfer(token_address, 1, amount, peer_, True) if greenlet is not None: greenlets.append(greenlet) gevent.joinall(greenlets) elif len(transfers_by_peer) == 1: for peer_, amount in transfers_by_peer.items(): transfer(token_address, 1, amount, peer_, False) log.warning('Waiting for termination') open('{}.stage2'.format(stage_prefix), 'a').close() log.warning('Waiting for transfers to finish, will write results...') event = RaidenGreenletEvent() gevent.signal(signal.SIGUSR2, event.set) event.wait() open('{}.stage3'.format(stage_prefix), 'a').close() event = RaidenGreenletEvent() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() else: log.warning('No scenario file supplied, doing nothing!') open('{}.stage2'.format(stage_prefix), 'a').close() event = RaidenGreenletEvent() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()