def _serve_webui(self, file_name='index.html'): # pylint: disable=redefined-builtin try: if not file_name: raise NotFound web3 = self.flask_app.config.get('WEB3_ENDPOINT') if 'config.' in file_name and file_name.endswith('.json'): environment_type = self.rest_api.raiden_api.raiden.config[ 'environment_type' ].name.lower() config = { 'raiden': self._api_prefix, 'web3': web3, 'settle_timeout': self.rest_api.raiden_api.raiden.config['settle_timeout'], 'reveal_timeout': self.rest_api.raiden_api.raiden.config['reveal_timeout'], 'environment_type': environment_type, } # if raiden sees eth rpc endpoint as localhost, replace it by Host header, # which is the hostname by which the client/browser sees/access the raiden node host = request.headers.get('Host') if web3 and host: web3_host, web3_port = split_endpoint(web3) if web3_host in ('localhost', '127.0.0.1'): host, _ = split_endpoint(host) web3 = f'http://{host}:{web3_port}' config['web3'] = web3 response = jsonify(config) else: response = send_from_directory(self.flask_app.config['WEBUI_PATH'], file_name) except (NotFound, AssertionError): response = send_from_directory(self.flask_app.config['WEBUI_PATH'], 'index.html') return response
def run(ctx, **kwargs): if ctx.invoked_subcommand is None: from raiden.api.python import RaidenAPI from raiden.ui.console import Console slogging.configure(kwargs['logging'], log_file=kwargs['logfile']) # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) with socket_factory(listen_host, listen_port) as mapped_socket: kwargs['mapped_socket'] = mapped_socket app_ = ctx.invoke(app, **kwargs) domain_list = [] if kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) http_server = None if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api, cors_domain_list=domain_list) (api_host, api_port) = split_endpoint(kwargs["api_address"]) http_server = WSGIServer((api_host, api_port), api_server.flask_app, log=slogging.getLogger('flask')) http_server.start() print( "The Raiden API RPC server is now running at http://{}:{}/.\n\n" "See the Raiden documentation for all available endpoints at\n" "https://github.com/raiden-network/raiden/blob/master" "/docs/Rest-Api.rst".format( api_host, api_port, )) if ctx.params['console']: console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() if http_server: http_server.stop(5) app_.stop(leave_channels=False)
def test_split_endpoint_valid(): host, port = split_endpoint("https://rpc.slock.it/goerli") assert host == "rpc.slock.it" assert port == 0 host, port = split_endpoint("https://rpc.slock.it:443/goerli") assert host == "rpc.slock.it" assert port == 443
def app(privatekey, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, external_listen_address, logging, logfile): slogging.configure(logging, log_file=logfile) if not external_listen_address: # notify('if you are behind a NAT, you should set # `external_listen_address` and configure port forwarding on your router') external_listen_address = listen_address # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey endpoint = eth_rpc_endpoint use_ssl = False if eth_rpc_endpoint.startswith("http://"): endpoint = eth_rpc_endpoint[len("http://"):] rpc_port = 80 elif eth_rpc_endpoint.startswith("https://"): endpoint = eth_rpc_endpoint[len("https://"):] use_ssl = True rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) jsonrpc_client = JSONRPCClient( privkey=privatekey, host=rpc_host, port=rpc_port, print_communication=False, use_ssl=use_ssl, ) blockchain_service = BlockChainService( privatekey.decode('hex'), registry_contract_address.decode('hex'), ) discovery = ContractDiscovery( jsonrpc_client, discovery_contract_address.decode('hex')) # FIXME: double encoding app = App(config, blockchain_service, discovery) discovery.register(app.raiden.address, *split_endpoint(external_listen_address)) app.raiden.register_registry(blockchain_service.default_registry) return app
def app(privatekey, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, external_listen_address, logging): slogging.configure(logging) if not external_listen_address: # notify('if you are behind a NAT, you should set # `external_listen_address` and configure port forwarding on your router') external_listen_address = listen_address # config_file = args.config_file rpc_connection = split_endpoint(eth_rpc_endpoint) (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey jsonrpc_client = JSONRPCClient( privkey=privatekey, host=rpc_connection[0], port=rpc_connection[1], print_communication=False, ) blockchain_service = BlockChainService( jsonrpc_client, registry_contract_address.decode('hex'), ) discovery = ContractDiscovery( jsonrpc_client, discovery_contract_address.decode('hex')) # FIXME: double encoding app = App(config, blockchain_service, discovery) discovery.register(app.raiden.address, *split_endpoint(external_listen_address)) app.raiden.register_registry(blockchain_service.default_registry) # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. console = Console(app) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()
def app(privatekey, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, external_listen_address, logging): slogging.configure(logging) if not external_listen_address: # notify('if you are behind a NAT, you should set # `external_listen_address` and configure port forwarding on your router') external_listen_address = listen_address # config_file = args.config_file rpc_connection = split_endpoint(eth_rpc_endpoint) (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey jsonrpc_client = JSONRPCClient( privkey=privatekey, host=rpc_connection[0], port=rpc_connection[1], print_communication=False, ) blockchain_service = BlockChainService( jsonrpc_client, registry_contract_address.decode('hex'), ) discovery = ContractDiscovery(jsonrpc_client, discovery_contract_address.decode('hex')) # FIXME: double encoding app = App(config, blockchain_service, discovery) discovery.register(app.raiden.address, *split_endpoint(external_listen_address)) app.raiden.register_registry(blockchain_service.default_registry) # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. console = Console(app) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()
def run(ctx, external_listen_address, **kwargs): # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. if not external_listen_address: # notify('if you are behind a NAT, you should set # `external_listen_address` and configure port forwarding on your router') external_listen_address = kwargs['listen_address'] ctx.params.pop('external_listen_address') app_ = ctx.invoke(app, **kwargs) app_.discovery.register( app_.raiden.address, *split_endpoint(external_listen_address) ) app_.raiden.register_registry(app_.raiden.chain.default_registry) console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()
def run(ctx, **kwargs): from raiden.api.python import RaidenAPI from raiden.ui.console import Console # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) with socket_factory(listen_host, listen_port) as mapped_socket: kwargs['socket'] = mapped_socket.socket app_ = ctx.invoke(app, **kwargs) # spawn address registration to avoid block while waiting for the next block registry_event = gevent.spawn( app_.discovery.register, app_.raiden.address, mapped_socket.external_ip, mapped_socket.external_port, ) app_.raiden.register_registry( app_.raiden.chain.default_registry.address) domain_list = [] if kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api, cors_domain_list=domain_list) Greenlet.spawn(api_server.run, ctx.params['api_port'], debug=False, use_evalex=False) print( "The RPC server is now running at http://localhost:{}/.\n\n" "See the Raiden documentation for all available endpoints at\n" "https://github.com/raiden-network/raiden/blob/master/docs/Rest-Api.rst" .format(ctx.params['api_port'], )) if ctx.params['console']: console = Console(app_) console.start() registry_event.join() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app_.stop(graceful=True)
def run(ctx, external_listen_address, **kwargs): # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. if not external_listen_address: # notify('if you are behind a NAT, you should set # `external_listen_address` and configure port forwarding on your router') external_listen_address = kwargs['listen_address'] ctx.params.pop('external_listen_address') app_ = ctx.invoke(app, **kwargs) app_.discovery.register(app_.raiden.address, *split_endpoint(external_listen_address)) app_.raiden.register_registry(app_.raiden.chain.default_registry) console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()
def _serve_webui(self, file_name='index.html'): # pylint: disable=redefined-builtin try: assert file_name web3 = self.flask_app.config.get('WEB3_ENDPOINT') if web3 and 'config.' in file_name and file_name.endswith('.json'): host = request.headers.get('Host') if any(h in web3 for h in ('localhost', '127.0.0.1')) and host: _, _port = split_endpoint(web3) _host, _ = split_endpoint(host) web3 = 'http://{}:{}'.format(_host, _port) response = jsonify({'raiden': self._api_prefix, 'web3': web3}) else: response = send_from_directory(self.flask_app.config['WEBUI_PATH'], file_name) except (NotFound, AssertionError): response = send_from_directory(self.flask_app.config['WEBUI_PATH'], 'index.html') return response
def get(self, nodeid): endpoint = self.find_endpoint(nodeid) if endpoint is '': raise KeyError('Unknow address {}'.format(pex(nodeid))) host, port = split_endpoint(endpoint) port = int(port) return (host, port)
def _run_smoketest(): print_step('Starting Raiden') config = deepcopy(App.DEFAULT_CONFIG) if args.get('extra_config', dict()): merge_dict(config, args['extra_config']) del args['extra_config'] args['config'] = config # invoke the raiden app app = run_app(**args) raiden_api = RaidenAPI(app.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api) (api_host, api_port) = split_endpoint(args['api_address']) api_server.start(api_host, api_port) raiden_api.channel_open( registry_address=contract_addresses[ CONTRACT_TOKEN_NETWORK_REGISTRY], token_address=to_canonical_address(token.contract.address), partner_address=to_canonical_address(TEST_PARTNER_ADDRESS), ) raiden_api.set_total_channel_deposit( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY], to_canonical_address(token.contract.address), to_canonical_address(TEST_PARTNER_ADDRESS), TEST_DEPOSIT_AMOUNT, ) token_addresses = [to_checksum_address(token.contract.address)] success = False try: print_step('Running smoketest') error = run_smoketests( app.raiden, args['transport'], token_addresses, contract_addresses[CONTRACT_ENDPOINT_REGISTRY], debug=debug, ) if error is not None: append_report('Smoketest assertion error', error) else: success = True finally: app.stop() node = ethereum[0] node.send_signal(2) err, out = node.communicate() append_report('Ethereum stdout', out) append_report('Ethereum stderr', err) if success: print_step(f'Smoketest successful') else: print_step(f'Smoketest had errors', error=True) return success
def get(self, nodeid): # check whether to encode or decode nodeid endpoint = self.discovery_proxy.findEndpointByAddress.call(nodeid.encode('hex')) if endpoint is '': raise KeyError('Unknow address {}'.format(pex(nodeid))) return split_endpoint(endpoint)
def _run_app(): # this catches exceptions raised when waiting for the stalecheck to complete try: app_ = ctx.invoke(app, **kwargs) except EthNodeCommunicationError as err: sys.exit(1) domain_list = [] if kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) api_server = None if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer( rest_api, cors_domain_list=domain_list, web_ui=ctx.params['web_ui'], eth_rpc_endpoint=ctx.params['eth_rpc_endpoint'], ) (api_host, api_port) = split_endpoint(kwargs['api_address']) api_server.start(api_host, api_port) 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 ctx.params['console']: console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) gevent.signal(signal.SIGUSR1, toogle_cpu_profiler) gevent.signal(signal.SIGUSR2, toggle_trace_profiler) event.wait() print('Signal received. Shutting down ...') if api_server: api_server.stop() return app_
def app(privatekey, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, logging, logfile): slogging.configure(logging, log_file=logfile) # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey endpoint = eth_rpc_endpoint if eth_rpc_endpoint.startswith("http://"): endpoint = eth_rpc_endpoint[len("http://"):] rpc_port = 80 elif eth_rpc_endpoint.startswith("https://"): endpoint = eth_rpc_endpoint[len("https://"):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) blockchain_service = BlockChainService( decode_hex(privatekey), decode_hex(registry_contract_address), host=rpc_host, port=rpc_port, ) discovery = ContractDiscovery( blockchain_service, decode_hex(discovery_contract_address) # FIXME: double encoding ) return App(config, blockchain_service, discovery)
def _serve_webui(self, file_name="index.html"): # pylint: disable=redefined-builtin try: if not file_name: raise NotFound web3 = self.flask_app.config.get("WEB3_ENDPOINT") if "config." in file_name and file_name.endswith(".json"): environment_type = self.rest_api.raiden_api.raiden.config[ "environment_type"].name.lower() config = { "raiden": self._api_prefix, "web3": web3, "settle_timeout": self.rest_api.raiden_api.raiden.config["settle_timeout"], "reveal_timeout": self.rest_api.raiden_api.raiden.config["reveal_timeout"], "environment_type": environment_type, } # if raiden sees eth rpc endpoint as localhost, replace it by Host header, # which is the hostname by which the client/browser sees/access the raiden node host = request.headers.get("Host") if web3 and host: web3_host, web3_port = split_endpoint(web3) if web3_host in ("localhost", "127.0.0.1"): host, _ = split_endpoint(host) web3 = f"http://{host}:{web3_port}" config["web3"] = web3 response = jsonify(config) else: response = send_from_directory( self.flask_app.config["WEBUI_PATH"], file_name) except (NotFound, AssertionError): response = send_from_directory(self.flask_app.config["WEBUI_PATH"], "index.html") return response
def run(ctx, external_listen_address, **kwargs): # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. if not external_listen_address: # notify('if you are behind a NAT, you should set # `external_listen_address` and configure port forwarding on your router') external_listen_address = kwargs['listen_address'] ctx.params.pop('external_listen_address') app_ = ctx.invoke(app, **kwargs) app_.discovery.register( app_.raiden.address, *split_endpoint(external_listen_address) ) app_.raiden.register_registry(app_.raiden.chain.default_registry.address) if ctx.params['rpc']: # instance of the raiden-api raiden_api = app_.raiden.api # wrap the raiden-api with rest-logic and encoding rest_api = RestAPI(raiden_api) # create the server and link the api-endpoints with flask / flask-restful middleware api_server = APIServer(rest_api) # run the server Greenlet.spawn(api_server.run, ctx.params['api_port'], debug=False, use_evalex=False) print( "The RPC server is now running", "at http://localhost:{0}/.".format(ctx.params['api_port']) ) print( "See the Raiden documentation for all available endpoints at", "https://github.com/raiden-network/raiden/blob/master/docs/api.rst" ) if ctx.params['console']: console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app_.stop()
def run(ctx, **kwargs): # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) with socket_factory(listen_host, listen_port) as mapped_socket: kwargs['socket'] = mapped_socket.socket app_ = ctx.invoke(app, **kwargs) app_.discovery.register( app_.raiden.address, mapped_socket.external_ip, mapped_socket.external_port, ) app_.raiden.register_registry( app_.raiden.chain.default_registry.address) if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api) Greenlet.spawn(api_server.run, ctx.params['api_port'], debug=False, use_evalex=False) print( "The RPC server is now running at http://localhost:{}/.\n\n" "See the Raiden documentation for all available endpoints at\n" "https://github.com/raiden-network/raiden/blob/master/docs/api.rst" .format(ctx.params['api_port'], )) if ctx.params['console']: console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app_.stop()
def run(self): super().run() (listen_host, listen_port) = split_endpoint(self._options['listen_address']) try: with SocketFactory( listen_host, listen_port, strategy=self._options['nat'], ) as mapped_socket: self._options['mapped_socket'] = mapped_socket app = self._start_services() except RaidenServicePortInUseError: click.secho( 'ERROR: Address %s:%s is in use. ' 'Use --listen-address <host:port> to specify port to listen on.' % (listen_host, listen_port), fg='red', ) sys.exit(1) return app
def _run_smoketest(): # invoke the raiden app app_ = ctx.invoke(app, **args) raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api) (api_host, api_port) = split_endpoint(args['api_address']) api_server.start(api_host, api_port) success = False try: print('[4/5] running smoketests...') error = run_smoketests(app_.raiden, smoketest_config, debug=debug) if error is not None: append_report('smoketest assertion error', error) else: success = True finally: app_.stop() ethereum.send_signal(2) err, out = ethereum.communicate() append_report('geth init stdout', ethereum_config['init_log_out'].decode('utf-8')) append_report('geth init stderr', ethereum_config['init_log_err'].decode('utf-8')) append_report('ethereum stdout', out) append_report('ethereum stderr', err) append_report('smoketest configuration', json.dumps(smoketest_config)) if success: print( '[5/5] smoketest successful, report was written to {}'.format( report_file)) else: print( '[5/5] smoketest had errors, report was written to {}'.format( report_file)) return success
def run(self): super().run() (listen_host, listen_port) = split_endpoint(self._options["listen_address"]) try: factory = SocketFactory(listen_host, listen_port, strategy=self._options["nat"]) with factory as mapped_socket: self._options["mapped_socket"] = mapped_socket app = self._start_services() except RaidenServicePortInUseError: click.secho( "ERROR: Address %s:%s is in use. " "Use --listen-address <host:port> to specify port to listen on." % (listen_host, listen_port), fg="red", ) sys.exit(1) return app
def run(self): super().run() (listen_host, listen_port) = split_endpoint(self._options['listen_address']) try: factory = SocketFactory( listen_host, listen_port, strategy=self._options['nat'], ) with factory as mapped_socket: self._options['mapped_socket'] = mapped_socket app = self._start_services() except RaidenServicePortInUseError: click.secho( 'ERROR: Address %s:%s is in use. ' 'Use --listen-address <host:port> to specify port to listen on.' % (listen_host, listen_port), fg='red', ) sys.exit(1) return app
def run(ctx, **kwargs): # pylint: disable=too-many-locals,too-many-branches,too-many-statements if ctx.invoked_subcommand is None: print('Welcome to Raiden, version {}!'.format(get_system_spec()['raiden'])) from raiden.ui.console import Console from raiden.api.python import RaidenAPI slogging.configure( kwargs['logging'], log_json=kwargs['log_json'], log_file=kwargs['logfile'] ) if kwargs['logfile']: # Disable stream logging root = slogging.getLogger() for handler in root.handlers: if isinstance(handler, slogging.logging.StreamHandler): root.handlers.remove(handler) break # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) try: with SocketFactory(listen_host, listen_port, strategy=kwargs['nat']) as mapped_socket: kwargs['mapped_socket'] = mapped_socket app_ = ctx.invoke(app, **kwargs) domain_list = [] if kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer( rest_api, cors_domain_list=domain_list, web_ui=ctx.params['web_ui'], eth_rpc_endpoint=ctx.params['eth_rpc_endpoint'], ) (api_host, api_port) = split_endpoint(kwargs['api_address']) api_server.start(api_host, api_port) 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 ctx.params['console']: console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) gevent.signal(signal.SIGUSR1, toogle_cpu_profiler) gevent.signal(signal.SIGUSR2, toggle_trace_profiler) event.wait() print('Signal received. Shutting down ...') try: api_server.stop() except NameError: pass except socket.error as v: if v.args[0] == errno.EADDRINUSE: print('ERROR: Address %s:%s is in use. ' 'Use --listen-address <host:port> to specify port to listen on.' % (listen_host, listen_port)) sys.exit(1) raise app_.stop(leave_channels=False) else: # Pass parsed args on to subcommands. ctx.obj = kwargs
def run(privatekey, registry_contract_address, discovery_contract_address, listen_address, logging, logfile, scenario, stage_prefix, results_filename): # pylint: disable=unused-argument # TODO: only enabled logging on "initiators" slogging.configure(logging, log_file=logfile) (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey blockchain_service = BlockChainService( decode_hex(privatekey), decode_hex(registry_contract_address), host="127.0.0.1", port="8545", ) discovery = ContractDiscovery(blockchain_service, decode_hex(discovery_contract_address)) app = App(config, blockchain_service, discovery) app.discovery.register( app.raiden.address, listen_host, listen_port, ) app.raiden.register_registry(app.raiden.chain.default_registry) if scenario: script = json.load(scenario) tools = ConsoleTools( app.raiden, app.discovery, app.config['settle_timeout'], app.config['reveal_timeout'], ) transfers_by_peer = {} tokens = script['tokens'] token_address = None peer = None our_node = app.raiden.address.encode('hex') log.warning("our address is {}".format(our_node)) for token in tokens: # skip tokens that we're not part of nodes = token['channels'] if not our_node in nodes: continue # allow for prefunded tokens if 'token_address' in token: token_address = token['token_address'] else: token_address = tools.create_token() 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") while not all( tools.ping(node) for node in nodes if node != our_node): 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] channel_manager = tools.register_token(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)) app.raiden.api.open(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)) channel = app.raiden.api.deposit( 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) else: peer = nodes[-2] if stage_prefix is not None: open('{}.stage1'.format(stage_prefix), 'a').close() log.warning("Done with initialization, waiting to continue...") event = gevent.event.Event() 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 xrange(total_transfers): app.raiden.api.transfer( 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 = gevent.event.Event() gevent.signal(signal.SIGUSR2, event.set) event.wait() results = tools.channel_stats_for(token_address, peer) if transfer_results['total_time'] != 0: results['total_time'] = transfer_results['total_time'] if len(transfer_results['timestamps']) > 0: results['timestamps'] = transfer_results['timestamps'] results['channel'] = repr(results['channel']) # FIXME log.warning("Results: {}".format(results)) with open(results_filename, 'w') as fp: json.dump(results, fp, indent=2) open('{}.stage3'.format(stage_prefix), 'a').close() event = gevent.event.Event() 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 = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()
def smoketest(ctx, debug, **kwargs): """ Test, that the raiden installation is sane. """ from raiden.api.python import RaidenAPI from raiden.blockchain.abi import get_static_or_compile from raiden.utils import get_contract_path # Check the solidity compiler early in the smoketest. # # Binary distributions don't need the solidity compiler but source # distributions do. Since this is checked by `get_static_or_compile` # function, use it as a proxy for validating the setup. get_static_or_compile( get_contract_path('HumanStandardToken.sol'), 'HumanStandardToken', ) report_file = tempfile.mktemp(suffix='.log') open(report_file, 'w+') def append_report(subject, data): with open(report_file, 'a', encoding='UTF-8') as handler: handler.write('{:=^80}'.format(' %s ' % subject.upper()) + os.linesep) if data is not None: if isinstance(data, bytes): data = data.decode() handler.writelines([data + os.linesep]) append_report('raiden version', json.dumps(get_system_spec())) append_report('raiden log', None) print('[1/5] getting smoketest configuration') smoketest_config = load_or_create_smoketest_config() print('[2/5] starting ethereum') ethereum, ethereum_config = start_ethereum(smoketest_config['genesis']) print('[3/5] starting raiden') # setup logging to log only into our report file slogging.configure(':DEBUG', log_file=report_file) root = slogging.getLogger() for handler in root.handlers: if isinstance(handler, slogging.logging.StreamHandler): root.handlers.remove(handler) break # setup cli arguments for starting raiden args = dict( discovery_contract_address=smoketest_config['contracts'] ['discovery_address'], registry_contract_address=smoketest_config['contracts'] ['registry_address'], eth_rpc_endpoint='http://127.0.0.1:{}'.format(ethereum_config['rpc']), keystore_path=ethereum_config['keystore'], address=ethereum_config['address'], ) for option in app.params: if option.name in args.keys(): args[option.name] = option.process_value(ctx, args[option.name]) else: args[option.name] = option.default password_file = os.path.join(args['keystore_path'], 'password') with open(password_file, 'w') as handler: handler.write('password') args['mapped_socket'] = None args['password_file'] = click.File()(password_file) args['datadir'] = args['keystore_path'] args['api_address'] = 'localhost:' + str( next(get_free_port('127.0.0.1', 5001))) args['sync_check'] = False # invoke the raiden app app_ = ctx.invoke(app, **args) raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api) (api_host, api_port) = split_endpoint(args['api_address']) api_server.start(api_host, api_port) success = False try: print('[4/5] running smoketests...') error = run_smoketests(app_.raiden, smoketest_config, debug=debug) if error is not None: append_report('smoketest assertion error', error) else: success = True finally: app_.stop() ethereum.send_signal(2) err, out = ethereum.communicate() append_report('geth init stdout', ethereum_config['init_log_out'].decode('utf-8')) append_report('geth init stderr', ethereum_config['init_log_err'].decode('utf-8')) append_report('ethereum stdout', out) append_report('ethereum stderr', err) append_report('smoketest configuration', json.dumps(smoketest_config)) if success: print('[5/5] smoketest successful, report was written to {}'.format( report_file)) else: print('[5/5] smoketest had errors, report was written to {}'.format( report_file)) sys.exit(1)
def app(address, keystore_path, gas_price, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, rpccorsdomain, mapped_socket, logging, logfile, log_json, max_unresponsive_time, send_ping_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, eth_client_communication, nat): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App from raiden.network.blockchain_service import BlockChainService (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config = App.DEFAULT_CONFIG.copy() config['host'] = listen_host config['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['external_ip'] = mapped_socket.external_ip config['external_port'] = mapped_socket.external_port else: config['socket'] = None config['external_ip'] = listen_host config['external_port'] = listen_port config['protocol']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['protocol']['nat_keepalive_timeout'] = timeout address_hex = address_encoder(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) address = address_decoder(address_hex) privatekey_hex = hexlify(privatekey_bin) config['privatekey_hex'] = privatekey_hex endpoint = eth_rpc_endpoint # Fallback to default port if only an IP address is given rpc_port = 8545 if eth_rpc_endpoint.startswith('http://'): endpoint = eth_rpc_endpoint[len('http://'):] rpc_port = 80 elif eth_rpc_endpoint.startswith('https://'): endpoint = eth_rpc_endpoint[len('https://'):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) rpc_client = JSONRPCClient( rpc_host, rpc_port, privatekey_bin, gas_price, ) # this assumes the eth node is already online if not check_json_rpc(rpc_client): sys.exit(1) blockchain_service = BlockChainService( privatekey_bin, rpc_client, gas_price, ) if sync_check: check_synced(blockchain_service) discovery_tx_cost = rpc_client.gasprice() * DISCOVERY_TX_GAS_LIMIT while True: balance = blockchain_service.client.balance(address) if discovery_tx_cost <= balance: break print('Account has insufficient funds for discovery registration.\n' 'Needed: {} ETH\n' 'Available: {} ETH.\n' 'Please deposit additional funds into this account.'.format( discovery_tx_cost / denoms.ether, balance / denoms.ether)) if not click.confirm('Try again?'): sys.exit(1) registry = blockchain_service.registry(registry_contract_address, ) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address)) if datadir is None: # default database directory raiden_directory = os.path.join(os.path.expanduser('~'), '.raiden') else: raiden_directory = datadir if not os.path.exists(raiden_directory): os.makedirs(raiden_directory) user_db_dir = os.path.join(raiden_directory, address_hex[:8]) if not os.path.exists(user_db_dir): os.makedirs(user_db_dir) database_path = os.path.join(user_db_dir, 'log.db') config['database_path'] = database_path return App( config, blockchain_service, registry, discovery, )
def _run_smoketest(): print_step('Starting Raiden') config = deepcopy(App.DEFAULT_CONFIG) if args.get('extra_config', dict()): merge_dict(config, args['extra_config']) del args['extra_config'] args['config'] = config raiden_stdout = StringIO() with contextlib.redirect_stdout(raiden_stdout): try: # invoke the raiden app app = run_app(**args) raiden_api = RaidenAPI(app.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api) (api_host, api_port) = split_endpoint(args['api_address']) api_server.start(api_host, api_port) raiden_api.channel_open( registry_address=contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY], token_address=to_canonical_address(token.contract.address), partner_address=to_canonical_address(TEST_PARTNER_ADDRESS), ) raiden_api.set_total_channel_deposit( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY], to_canonical_address(token.contract.address), to_canonical_address(TEST_PARTNER_ADDRESS), TEST_DEPOSIT_AMOUNT, ) token_addresses = [to_checksum_address(token.contract.address)] success = False print_step('Running smoketest') error = run_smoketests( app.raiden, args['transport'], token_addresses, contract_addresses[CONTRACT_ENDPOINT_REGISTRY], debug=debug, ) if error is not None: append_report('Smoketest assertion error', error) else: success = True finally: app.stop() app.raiden.get() node = ethereum[0] node.send_signal(2) err, out = node.communicate() append_report('Ethereum stdout', out) append_report('Ethereum stderr', err) append_report('Raiden Node stdout', raiden_stdout.getvalue()) if success: print_step(f'Smoketest successful') else: print_step(f'Smoketest had errors', error=True) return success
def run_app( address, keystore_path, gas_price, eth_rpc_endpoint, tokennetwork_registry_contract_address, secret_registry_contract_address, endpoint_registry_contract_address, listen_address, mapped_socket, max_unresponsive_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, transport, matrix_server, network_id, environment_type, unrecoverable_error_should_crash, pathfinding_service_address, config=None, extra_config=None, **kwargs, ): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App _assert_sql_version() if transport == 'udp' and not mapped_socket: raise RuntimeError('Missing socket') if datadir is None: datadir = os.path.join(os.path.expanduser('~'), '.raiden') address_hex = to_normalized_address(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) address = to_canonical_address(address_hex) (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config['transport']['udp']['host'] = listen_host config['transport']['udp']['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['transport']['udp']['external_ip'] = mapped_socket.external_ip config['transport']['udp'][ 'external_port'] = mapped_socket.external_port config['transport_type'] = transport config['transport']['matrix']['server'] = matrix_server config['transport']['udp'][ 'nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['transport']['udp']['nat_keepalive_timeout'] = timeout config['privatekey_hex'] = encode_hex(privatekey_bin) config[ 'unrecoverable_error_should_crash'] = unrecoverable_error_should_crash config['services'][ 'pathfinding_service_address'] = pathfinding_service_address parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint) if not parsed_eth_rpc_endpoint.scheme: eth_rpc_endpoint = f'http://{eth_rpc_endpoint}' web3 = _setup_web3(eth_rpc_endpoint) rpc_client = JSONRPCClient( web3, privatekey_bin, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, uses_infura='infura.io' in eth_rpc_endpoint, ) blockchain_service = BlockChainService( privatekey_bin=privatekey_bin, jsonrpc_client=rpc_client, # Not giving the contract manager here, but injecting it later # since we first need blockchain service to calculate the network id ) given_network_id = network_id node_network_id = blockchain_service.network_id known_given_network_id = given_network_id in ID_TO_NETWORKNAME known_node_network_id = node_network_id in ID_TO_NETWORKNAME if node_network_id != given_network_id: if known_given_network_id and known_node_network_id: click.secho( f"The chosen ethereum network '{ID_TO_NETWORKNAME[given_network_id]}' " f"differs from the ethereum client '{ID_TO_NETWORKNAME[node_network_id]}'. " "Please update your settings.", fg='red', ) else: click.secho( f"The chosen ethereum network id '{given_network_id}' differs " f"from the ethereum client '{node_network_id}'. " "Please update your settings.", fg='red', ) sys.exit(1) config['chain_id'] = given_network_id # interpret the provided string argument if environment_type == Environment.PRODUCTION: # Safe configuration: restrictions for mainnet apply and matrix rooms have to be private config['environment_type'] = Environment.PRODUCTION config['transport']['matrix']['private_rooms'] = True else: config['environment_type'] = Environment.DEVELOPMENT environment_type = config['environment_type'] print(f'Raiden is running in {environment_type.value.lower()} mode') chain_config = {} contract_addresses_known = False contracts = dict() contracts_version = 'pre_limits' if environment_type == Environment.DEVELOPMENT else None config['contracts_path'] = contracts_precompiled_path(contracts_version) if node_network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[ node_network_id] != 'smoketest': deployment_data = get_contracts_deployed(node_network_id, contracts_version) not_allowed = ( # for now we only disallow mainnet with test configuration network_id == 1 and environment_type == Environment.DEVELOPMENT) if not_allowed: click.secho( f'The chosen network ({ID_TO_NETWORKNAME[node_network_id]}) is not a testnet, ' 'but the "development" environment was selected.\n' 'This is not allowed. Please start again with a safe environment setting ' '(--environment production).', fg='red', ) sys.exit(1) contracts = deployment_data['contracts'] contract_addresses_known = True blockchain_service.inject_contract_manager( ContractManager(config['contracts_path'])) if sync_check: check_synced(blockchain_service, known_node_network_id) contract_addresses_given = ( tokennetwork_registry_contract_address is not None and secret_registry_contract_address is not None and endpoint_registry_contract_address is not None) if not contract_addresses_given and not contract_addresses_known: click.secho( f"There are no known contract addresses for network id '{given_network_id}'. " "Please provide them on the command line or in the configuration file.", fg='red', ) sys.exit(1) try: token_network_registry = blockchain_service.token_network_registry( tokennetwork_registry_contract_address or to_canonical_address( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('token network registry', tokennetwork_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address( 'token network registry', tokennetwork_registry_contract_address, ) try: secret_registry = blockchain_service.secret_registry( secret_registry_contract_address or to_canonical_address( contracts[CONTRACT_SECRET_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('secret registry', secret_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address('secret registry', secret_registry_contract_address) database_path = os.path.join( datadir, f'node_{pex(address)}', f'netid_{given_network_id}', f'network_{pex(token_network_registry.address)}', f'v{RAIDEN_DB_VERSION}_log.db', ) config['database_path'] = database_path print( '\nYou are connected to the \'{}\' network and the DB path is: {}'. format( ID_TO_NETWORKNAME.get(given_network_id, given_network_id), database_path, ), ) discovery = None if transport == 'udp': transport, discovery = _setup_udp( config, blockchain_service, address, contracts, endpoint_registry_contract_address, ) elif transport == 'matrix': transport = _setup_matrix(config) else: raise RuntimeError(f'Unknown transport type "{transport}" given') raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() try: if 'contracts' in chain_config: start_block = chain_config['contracts']['TokenNetworkRegistry'][ 'block_number'] else: start_block = 0 raiden_app = App( config=config, chain=blockchain_service, query_start_block=start_block, default_registry=token_network_registry, default_secret_registry=secret_registry, transport=transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, discovery=discovery, ) except RaidenError as e: click.secho(f'FATAL: {e}', fg='red') sys.exit(1) try: raiden_app.start() except RuntimeError as e: click.secho(f'FATAL: {e}', fg='red') sys.exit(1) except filelock.Timeout: name_or_id = ID_TO_NETWORKNAME.get(given_network_id, given_network_id) click.secho( f'FATAL: Another Raiden instance already running for account {address_hex} on ' f'network id {name_or_id}', fg='red', ) sys.exit(1) return raiden_app
def app( address, keystore_path, gas_price, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, rpccorsdomain, mapped_socket, logging, logfile, log_json, max_unresponsive_time, send_ping_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, eth_client_communication, nat): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App from raiden.network.blockchain_service import BlockChainService (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config = App.DEFAULT_CONFIG.copy() config['host'] = listen_host config['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['external_ip'] = mapped_socket.external_ip config['external_port'] = mapped_socket.external_port else: config['socket'] = None config['external_ip'] = listen_host config['external_port'] = listen_port config['protocol']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['protocol']['nat_keepalive_timeout'] = timeout address_hex = address_encoder(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) address = address_decoder(address_hex) privatekey_hex = hexlify(privatekey_bin) config['privatekey_hex'] = privatekey_hex endpoint = eth_rpc_endpoint # Fallback to default port if only an IP address is given rpc_port = 8545 if eth_rpc_endpoint.startswith('http://'): endpoint = eth_rpc_endpoint[len('http://'):] rpc_port = 80 elif eth_rpc_endpoint.startswith('https://'): endpoint = eth_rpc_endpoint[len('https://'):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) rpc_client = JSONRPCClient( rpc_host, rpc_port, privatekey_bin, ) # this assumes the eth node is already online if not check_json_rpc(rpc_client): sys.exit(1) blockchain_service = BlockChainService( privatekey_bin, rpc_client, GAS_LIMIT, gas_price, ) if sync_check: check_synced(blockchain_service) discovery_tx_cost = gas_price * DISCOVERY_REGISTRATION_GAS while True: balance = blockchain_service.client.balance(address) if discovery_tx_cost <= balance: break print( 'Account has insufficient funds for discovery registration.\n' 'Needed: {} ETH\n' 'Available: {} ETH.\n' 'Please deposit additional funds into this account.' .format(discovery_tx_cost / denoms.ether, balance / denoms.ether) ) if not click.confirm('Try again?'): sys.exit(1) registry = blockchain_service.registry( registry_contract_address, ) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address) ) if datadir is None: # default database directory raiden_directory = os.path.join(os.path.expanduser('~'), '.raiden') else: raiden_directory = datadir if not os.path.exists(raiden_directory): os.makedirs(raiden_directory) user_db_dir = os.path.join(raiden_directory, address_hex[:8]) if not os.path.exists(user_db_dir): os.makedirs(user_db_dir) database_path = os.path.join(user_db_dir, 'log.db') config['database_path'] = database_path return App( config, blockchain_service, registry, discovery, )
def _run_app(): # this catches exceptions raised when waiting for the stalecheck to complete try: app_ = ctx.invoke(app, **kwargs) 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 kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) api_server = None if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer( rest_api, cors_domain_list=domain_list, web_ui=ctx.params['web_ui'], eth_rpc_endpoint=ctx.params['eth_rpc_endpoint'], ) (api_host, api_port) = split_endpoint(kwargs['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 ctx.params['console']: console = Console(app_) console.start() # spawning a thread to handle the version checking gevent.spawn(check_version) # wait for interrupt event = gevent.event.Event() 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='raiden-exception', 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', ) if api_server: api_server.stop() return app_
def app(address, keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, logging, logfile, max_unresponsive_time, send_ping_time): slogging.configure(logging, log_file=logfile) # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['max_unresponsive_time'] = max_unresponsive_time config['send_ping_time'] = send_ping_time accmgr = AccountManager(keystore_path) if not accmgr.accounts: raise RuntimeError('No Ethereum accounts found in the user\'s system') if not accmgr.address_in_keystore(address): addresses = list(accmgr.accounts.keys()) formatted_addresses = [ '[{:3d}] - 0x{}'.format(idx, addr) for idx, addr in enumerate(addresses) ] should_prompt = True while should_prompt: idx = click.prompt( "The following accounts were found in your machine:\n\n{}" "\nSelect one of them by index to continue: ".format( "\n".join(formatted_addresses)), type=int ) if idx >= 0 and idx < len(addresses): should_prompt = False else: print("\nError: Provided index '{}' is out of bounds\n".format(idx)) address = addresses[idx] privatekey = accmgr.get_privkey(address) config['privatekey_hex'] = encode_hex(privatekey) endpoint = eth_rpc_endpoint if eth_rpc_endpoint.startswith("http://"): endpoint = eth_rpc_endpoint[len("http://"):] rpc_port = 80 elif eth_rpc_endpoint.startswith("https://"): endpoint = eth_rpc_endpoint[len("https://"):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) blockchain_service = BlockChainService( privatekey, decode_hex(registry_contract_address), host=rpc_host, port=rpc_port, ) discovery = ContractDiscovery( blockchain_service, decode_hex(discovery_contract_address) # FIXME: double encoding ) return App(config, blockchain_service, discovery)
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['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey privatekey_bin = decode_hex(privatekey) rpc_client = JSONRPCClient( '127.0.0.1', 8545, 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['protocol'], ) app = App( config=config, chain=blockchain_service, query_start_block=0, default_registry=registry, default_secret_registry=secret_registry, transport=transport, discovery=discovery, ) 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'], app.config['reveal_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 = gevent.event.Event() 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 = gevent.event.Event() gevent.signal(signal.SIGUSR2, event.set) event.wait() open('{}.stage3'.format(stage_prefix), 'a').close() event = gevent.event.Event() 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 = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()
def app(address, keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, rpccorsdomain, # pylint: disable=unused-argument mapped_socket, logging, logfile, log_json, max_unresponsive_time, send_ping_time, api_address, rpc, console, password_file, web_ui, datadir): from raiden.app import App from raiden.network.rpc.client import BlockChainService # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config = App.DEFAULT_CONFIG.copy() config['host'] = listen_host config['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['external_ip'] = mapped_socket.external_ip config['external_port'] = mapped_socket.external_port else: config['socket'] = None config['external_ip'] = listen_host config['external_port'] = listen_port retries = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['protocol']['nat_keepalive_retries'] = retries config['protocol']['nat_keepalive_timeout'] = send_ping_time address_hex = address_encoder(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) privatekey_hex = privatekey_bin.encode('hex') config['privatekey_hex'] = privatekey_hex endpoint = eth_rpc_endpoint # Fallback default port if only an IP address is given rpc_port = 8545 if eth_rpc_endpoint.startswith("http://"): endpoint = eth_rpc_endpoint[len("http://"):] rpc_port = 80 elif eth_rpc_endpoint.startswith("https://"): endpoint = eth_rpc_endpoint[len("https://"):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) try: blockchain_service = BlockChainService( privatekey_bin, registry_contract_address, host=rpc_host, port=rpc_port, ) except ValueError as e: # ValueError exception raised if: # - The registry contract address doesn't have code, this might happen # if the connected geth process is not synced or if the wrong address # is provided (e.g. using the address from a smart contract deployed on # ropsten with a geth node connected to morden) print(e.message) sys.exit(1) discovery_tx_cost = GAS_PRICE * DISCOVERY_REGISTRATION_GAS while True: balance = blockchain_service.client.balance(address_hex) if discovery_tx_cost <= balance: break print( 'Account has insufficient funds for discovery registration.\n' 'Needed: {} ETH\n' 'Available: {} ETH.\n' 'Please deposit additional funds on this account.' .format(discovery_tx_cost / float(denoms.ether), balance / float(denoms.ether)) ) if not click.confirm('Try again?'): sys.exit(1) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address) ) if datadir is None: # default database directory raiden_directory = os.path.join(os.path.expanduser('~'), '.raiden') else: raiden_directory = datadir if not os.path.exists(raiden_directory): os.makedirs(raiden_directory) user_db_dir = os.path.join(raiden_directory, address_hex[:8]) if not os.path.exists(user_db_dir): os.makedirs(user_db_dir) database_path = os.path.join(user_db_dir, 'log.db') config['database_path'] = database_path return App(config, blockchain_service, discovery)
def run(ctx, **kwargs): if ctx.invoked_subcommand is None: from raiden.api.python import RaidenAPI from raiden.ui.console import Console slogging.configure( kwargs['logging'], log_json=kwargs['log_json'], log_file=kwargs['logfile'] ) # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) try: with socket_factory(listen_host, listen_port) as mapped_socket: kwargs['mapped_socket'] = mapped_socket app_ = ctx.invoke(app, **kwargs) domain_list = [] if kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer( rest_api, cors_domain_list=domain_list, web_ui=ctx.params['web_ui'], ) (api_host, api_port) = split_endpoint(kwargs["api_address"]) api_server.start(api_host, api_port) print( "The Raiden API RPC server is now running at http://{}:{}/.\n\n" "See the Raiden documentation for all available endpoints at\n" "https://github.com/raiden-network/raiden/blob/master" "/docs/Rest-Api.rst".format( api_host, api_port, ) ) if ctx.params['console']: console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) gevent.signal(signal.SIGUSR1, toogle_cpu_profiler) gevent.signal(signal.SIGUSR2, toggle_trace_profiler) event.wait() try: api_server.stop() except NameError: pass except socket.error as v: if v.args[0] == errno.EADDRINUSE: print("ERROR: Address %s:%s is in use. " "Use --listen-address <host:port> to specify port to listen on." % (listen_host, listen_port)) sys.exit(1) raise app_.stop(leave_channels=False) else: # Pass parsed args on to subcommands. ctx.obj = kwargs
def run(ctx, **kwargs): # pylint: disable=too-many-locals,too-many-branches,too-many-statements if ctx.invoked_subcommand is not None: # Pass parsed args on to subcommands. ctx.obj = kwargs return click.secho('Welcome to Raiden, version {}!'.format(get_system_spec()['raiden']), fg='green') click.secho( ''' ---------------------------------------------------------------------- | This is an Alpha version of experimental open source software | | released under the MIT license and may contain errors and/or bugs. | | Use of the software is at your own risk and discretion. No | | guarantee whatsoever is made regarding its suitability for your | | intended purposes and its compliance with applicable law and | | regulations. It is up to the user to determine the software´s | | quality and suitability and whether its use is compliant with its | | respective regulatory regime, especially in the case that you are | | operating in a commercial context. | ----------------------------------------------------------------------''', fg='yellow', ) from raiden.ui.console import Console from raiden.api.python import RaidenAPI if kwargs['config_file']: paramname_to_param = {param.name: param for param in run.params} path_params = { param.name for param in run.params if isinstance(param.type, (click.Path, click.File)) } config_file_path = Path(kwargs['config_file']) config_file_values = dict() try: with config_file_path.open() as config_file: config_file_values = pytoml.load(config_file) except OSError as ex: # Silently ignore if 'file not found' and the config file path is the default config_file_param = paramname_to_param['config_file'] config_file_default_path = Path( config_file_param.type.expand_default(config_file_param.get_default(ctx), kwargs), ) default_config_missing = ( ex.errno == errno.ENOENT and config_file_path.resolve() == config_file_default_path.resolve() ) if default_config_missing: kwargs['config_file'] = None else: click.secho(f"Error opening config file: {ex}", fg='red') sys.exit(2) except TomlError as ex: click.secho(f'Error loading config file: {ex}', fg='red') sys.exit(2) for config_name, config_value in config_file_values.items(): config_name_int = config_name.replace('-', '_') if config_name_int not in paramname_to_param: click.secho( f"Unknown setting '{config_name}' found in config file - ignoring.", fg='yellow', ) continue if config_name_int in path_params: # Allow users to use `~` in paths in the config file config_value = os.path.expanduser(config_value) if config_name_int == LOG_CONFIG_OPTION_NAME: # Uppercase log level names config_value = {k: v.upper() for k, v in config_value.items()} else: # Pipe config file values through cli converter to ensure correct types # We exclude `log-config` because it already is a dict when loading from toml try: config_value = paramname_to_param[config_name_int].type.convert( config_value, paramname_to_param[config_name_int], ctx, ) except click.BadParameter as ex: click.secho(f"Invalid config file setting '{config_name}': {ex}", fg='red') sys.exit(2) # Use the config file value if the value from the command line is the default if kwargs[config_name_int] == paramname_to_param[config_name_int].get_default(ctx): kwargs[config_name_int] = config_value configure_logging( kwargs['log_config'], log_json=kwargs['log_json'], log_file=kwargs['log_file'], ) # Do this here so logging is configured if kwargs['config_file']: log.debug('Using config file', config_file=kwargs['config_file']) # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. def _run_app(): # this catches exceptions raised when waiting for the stalecheck to complete try: app_ = ctx.invoke(app, **kwargs) 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 kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) api_server = None if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer( rest_api, cors_domain_list=domain_list, web_ui=ctx.params['web_ui'], eth_rpc_endpoint=ctx.params['eth_rpc_endpoint'], ) (api_host, api_port) = split_endpoint(kwargs['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 ctx.params['console']: console = Console(app_) console.start() # spawning a thread to handle the version checking gevent.spawn(check_version) # wait for interrupt event = gevent.event.Event() 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='raiden-exception', 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', ) if api_server: api_server.stop() return app_ # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. try: if kwargs['transport'] == 'udp': (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) try: with SocketFactory( listen_host, listen_port, strategy=kwargs['nat'], ) as mapped_socket: kwargs['mapped_socket'] = mapped_socket app_ = _run_app() except RaidenServicePortInUseError: print( 'ERROR: Address %s:%s is in use. ' 'Use --listen-address <host:port> to specify port to listen on.' % (listen_host, listen_port), ) sys.exit(1) elif kwargs['transport'] == 'matrix': kwargs['mapped_socket'] = None app_ = _run_app() else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'") app_.stop(leave_channels=False) except ReplacementTransactionUnderpriced as e: print( '{}. Please make sure that this Raiden node is the ' 'only user of the selected account'.format(str(e)), ) sys.exit(1)
def get(self, node_address): endpoint = self.discovery_proxy.endpoint_by_address(node_address) host_port = split_endpoint(endpoint) return host_port
def app( address, keystore_path, gas_price, eth_rpc_endpoint, registry_contract_address, secret_registry_contract_address, discovery_contract_address, listen_address, rpccorsdomain, mapped_socket, log_config, log_file, log_json, max_unresponsive_time, send_ping_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, nat, transport, matrix_server, network_id, config_file, extra_config=None, ): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App if transport == 'udp' and not mapped_socket: raise RuntimeError('Missing socket') address_hex = to_normalized_address(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) address = to_canonical_address(address_hex) (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) if datadir is None: datadir = os.path.join(os.path.expanduser('~'), '.raiden') config = deepcopy(App.DEFAULT_CONFIG) if extra_config: merge_dict(config, extra_config) config['host'] = listen_host config['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['external_ip'] = mapped_socket.external_ip config['external_port'] = mapped_socket.external_port config['transport_type'] = transport config['matrix']['server'] = matrix_server config['transport']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['transport']['nat_keepalive_timeout'] = timeout privatekey_hex = hexlify(privatekey_bin) config['privatekey_hex'] = privatekey_hex rpc_host, rpc_port = eth_endpoint_to_hostport(eth_rpc_endpoint) rpc_client = JSONRPCClient( rpc_host, rpc_port, privatekey_bin, gas_price, ) blockchain_service = BlockChainService(privatekey_bin, rpc_client) net_id = blockchain_service.network_id if net_id != network_id: if network_id in constants.ID_TO_NETWORKNAME and net_id in constants.ID_TO_NETWORKNAME: print(( "The chosen ethereum network '{}' differs from the ethereum client '{}'. " 'Please update your settings.' ).format(constants.ID_TO_NETWORKNAME[network_id], constants.ID_TO_NETWORKNAME[net_id])) else: print(( "The chosen ethereum network id '{}' differs from the ethereum client '{}'. " 'Please update your settings.' ).format(network_id, net_id)) sys.exit(1) config['chain_id'] = network_id if sync_check: check_synced(blockchain_service) database_path = os.path.join(datadir, 'netid_%s' % net_id, address_hex[:8], 'log.db') config['database_path'] = database_path print( '\nYou are connected to the \'{}\' network and the DB path is: {}'.format( constants.ID_TO_NETWORKNAME.get(net_id) or net_id, database_path, ), ) try: token_network_registry = blockchain_service.token_network_registry( registry_contract_address, ) except ContractVersionMismatch: print( 'Deployed registry contract version mismatch. ' 'Please update your Raiden installation.', ) sys.exit(1) try: secret_registry = blockchain_service.secret_registry( secret_registry_contract_address, ) except ContractVersionMismatch: print( 'Deployed secret registry contract version mismatch. ' 'Please update your Raiden installation.', ) sys.exit(1) discovery = None if transport == 'udp': check_discovery_registration_gas(blockchain_service, address) try: discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address), ) except ContractVersionMismatch: print('Deployed discovery contract version mismatch. ' 'Please update your Raiden installation.') sys.exit(1) throttle_policy = TokenBucket( config['transport']['throttle_capacity'], config['transport']['throttle_fill_rate'], ) transport = UDPTransport( discovery, mapped_socket.socket, throttle_policy, config['transport'], ) elif transport == 'matrix': # matrix gets spammed with the default retry-interval of 1s, wait a little more if config['transport']['retry_interval'] == DEFAULT_TRANSPORT_RETRY_INTERVAL: config['transport']['retry_interval'] *= 5 try: transport = MatrixTransport(config['matrix']) except RaidenError as ex: click.secho(f'FATAL: {ex}', fg='red') sys.exit(1) else: raise RuntimeError(f'Unknown transport type "{transport}" given') try: raiden_app = App( config=config, chain=blockchain_service, query_start_block=constants.ID_TO_QUERY_BLOCK[net_id], default_registry=token_network_registry, default_secret_registry=secret_registry, transport=transport, discovery=discovery, ) except RaidenError as e: click.secho(f'FATAL: {e}', fg='red') sys.exit(1) return raiden_app
def run_app( address, keystore_path, gas_price, eth_rpc_endpoint, tokennetwork_registry_contract_address, secret_registry_contract_address, service_registry_contract_address, endpoint_registry_contract_address, user_deposit_contract_address, listen_address, mapped_socket, max_unresponsive_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, transport, matrix_server, network_id, environment_type, unrecoverable_error_should_crash, pathfinding_service_address, pathfinding_eth_address, pathfinding_max_paths, enable_monitoring, resolver_endpoint, routing_mode, config=None, extra_config=None, **kwargs, ): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App check_sql_version() if transport == "udp" and not mapped_socket: raise RuntimeError("Missing socket") if datadir is None: datadir = os.path.join(os.path.expanduser("~"), ".raiden") account_manager = AccountManager(keystore_path) check_has_accounts(account_manager) if not address: address_hex = prompt_account(account_manager) else: address_hex = to_normalized_address(address) if password_file: privatekey_bin = unlock_account_with_passwordfile( account_manager=account_manager, address_hex=address_hex, password_file=password_file) else: privatekey_bin = unlock_account_with_passwordprompt( account_manager=account_manager, address_hex=address_hex) address = to_canonical_address(address_hex) (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config["transport"]["udp"]["host"] = listen_host config["transport"]["udp"]["port"] = listen_port config["console"] = console config["rpc"] = rpc config["web_ui"] = rpc and web_ui config["api_host"] = api_host config["api_port"] = api_port config["resolver_endpoint"] = resolver_endpoint if mapped_socket: config["socket"] = mapped_socket.socket config["transport"]["udp"]["external_ip"] = mapped_socket.external_ip config["transport"]["udp"][ "external_port"] = mapped_socket.external_port config["transport_type"] = transport config["transport"]["matrix"]["server"] = matrix_server config["transport"]["udp"][ "nat_keepalive_retries"] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config["transport"]["udp"]["nat_keepalive_timeout"] = timeout config[ "unrecoverable_error_should_crash"] = unrecoverable_error_should_crash config["services"]["pathfinding_max_paths"] = pathfinding_max_paths config["services"]["monitoring_enabled"] = enable_monitoring parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint) if not parsed_eth_rpc_endpoint.scheme: eth_rpc_endpoint = f"http://{eth_rpc_endpoint}" web3 = Web3(HTTPProvider(eth_rpc_endpoint)) check_ethereum_version(web3) check_network_id(network_id, web3) config["chain_id"] = network_id setup_environment(config, environment_type) contracts = setup_contracts_or_exit(config, network_id) rpc_client = JSONRPCClient( web3, privatekey_bin, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, uses_infura="infura.io" in eth_rpc_endpoint, ) blockchain_service = BlockChainService(jsonrpc_client=rpc_client, contract_manager=ContractManager( config["contracts_path"])) if sync_check: check_synced(blockchain_service) proxies = setup_proxies_or_exit( config=config, tokennetwork_registry_contract_address= tokennetwork_registry_contract_address, secret_registry_contract_address=secret_registry_contract_address, endpoint_registry_contract_address=endpoint_registry_contract_address, user_deposit_contract_address=user_deposit_contract_address, service_registry_contract_address=service_registry_contract_address, blockchain_service=blockchain_service, contracts=contracts, routing_mode=routing_mode, pathfinding_service_address=pathfinding_service_address, pathfinding_eth_address=pathfinding_eth_address, ) database_path = os.path.join( datadir, f"node_{pex(address)}", f"netid_{network_id}", f"network_{pex(proxies.token_network_registry.address)}", f"v{RAIDEN_DB_VERSION}_log.db", ) config["database_path"] = database_path print("\nYou are connected to the '{}' network and the DB path is: {}". format(ID_TO_NETWORKNAME.get(network_id, network_id), database_path)) discovery = None if transport == "udp": transport, discovery = setup_udp_or_exit( config, blockchain_service, address, contracts, endpoint_registry_contract_address) elif transport == "matrix": transport = _setup_matrix(config) else: raise RuntimeError(f'Unknown transport type "{transport}" given') raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() try: start_block = 0 if "TokenNetworkRegistry" in contracts: start_block = contracts["TokenNetworkRegistry"]["block_number"] raiden_app = App( config=config, chain=blockchain_service, query_start_block=start_block, default_registry=proxies.token_network_registry, default_secret_registry=proxies.secret_registry, default_service_registry=proxies.service_registry, transport=transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, discovery=discovery, user_deposit=proxies.user_deposit, ) except RaidenError as e: click.secho(f"FATAL: {e}", fg="red") sys.exit(1) try: raiden_app.start() except RuntimeError as e: click.secho(f"FATAL: {e}", fg="red") sys.exit(1) except filelock.Timeout: name_or_id = ID_TO_NETWORKNAME.get(network_id, network_id) click.secho( f"FATAL: Another Raiden instance already running for account {address_hex} on " f"network id {name_or_id}", fg="red", ) sys.exit(1) return raiden_app
def _run_smoketest(): print_step('Starting Raiden') # invoke the raiden app app_ = ctx.invoke(app, **args) raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api) (api_host, api_port) = split_endpoint(args['api_address']) api_server.start(api_host, api_port) raiden_api.channel_open( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY], to_canonical_address(token.contract.address), to_canonical_address(TEST_PARTNER_ADDRESS), None, None, ) raiden_api.set_total_channel_deposit( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY], to_canonical_address(token.contract.address), to_canonical_address(TEST_PARTNER_ADDRESS), TEST_DEPOSIT_AMOUNT, ) smoketest_config['contracts']['registry_address'] = to_checksum_address( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY], ) smoketest_config['contracts']['secret_registry_address'] = to_checksum_address( contract_addresses[CONTRACT_SECRET_REGISTRY], ) smoketest_config['contracts']['discovery_address'] = to_checksum_address( contract_addresses[CONTRACT_ENDPOINT_REGISTRY], ) smoketest_config['contracts']['token_address'] = to_checksum_address( token.contract.address, ) success = False try: print_step('Running smoketest') error = run_smoketests(app_.raiden, smoketest_config, debug=debug) if error is not None: append_report('Smoketest assertion error', error) else: success = True finally: app_.stop() ethereum.send_signal(2) err, out = ethereum.communicate() append_report('Ethereum init stdout', ethereum_config['init_log_out'].decode('utf-8')) append_report('Ethereum init stderr', ethereum_config['init_log_err'].decode('utf-8')) append_report('Ethereum stdout', out) append_report('Ethereum stderr', err) append_report('Smoketest configuration', json.dumps(smoketest_config)) if success: print_step(f'Smoketest successful, report was written to {report_file}') else: print_step(f'Smoketest had errors, report was written to {report_file}', error=True) return success
def run(ctx, **kwargs): # pylint: disable=too-many-locals,too-many-branches,too-many-statements if ctx.invoked_subcommand is None: print('Welcome to Raiden, version {}!'.format( get_system_spec()['raiden'])) from raiden.ui.console import Console from raiden.api.python import RaidenAPI slogging.configure(kwargs['logging'], log_json=kwargs['log_json'], log_file=kwargs['logfile']) if kwargs['logfile']: # Disable stream logging root = slogging.getLogger() for handler in root.handlers: if isinstance(handler, slogging.logging.StreamHandler): root.handlers.remove(handler) break # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) try: with SocketFactory(listen_host, listen_port, strategy=kwargs['nat']) as mapped_socket: kwargs['mapped_socket'] = mapped_socket app_ = ctx.invoke(app, **kwargs) domain_list = [] if kwargs['rpccorsdomain']: if ',' in kwargs['rpccorsdomain']: for domain in kwargs['rpccorsdomain'].split(','): domain_list.append(str(domain)) else: domain_list.append(str(kwargs['rpccorsdomain'])) if ctx.params['rpc']: raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer( rest_api, cors_domain_list=domain_list, web_ui=ctx.params['web_ui'], eth_rpc_endpoint=ctx.params['eth_rpc_endpoint'], ) (api_host, api_port) = split_endpoint(kwargs['api_address']) api_server.start(api_host, api_port) 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 ctx.params['console']: console = Console(app_) console.start() # wait for interrupt event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) gevent.signal(signal.SIGUSR1, toogle_cpu_profiler) gevent.signal(signal.SIGUSR2, toggle_trace_profiler) event.wait() print('Signal received. Shutting down ...') try: api_server.stop() except NameError: pass except socket.error as v: if v.args[0] == errno.EADDRINUSE: print( 'ERROR: Address %s:%s is in use. ' 'Use --listen-address <host:port> to specify port to listen on.' % (listen_host, listen_port)) sys.exit(1) raise app_.stop(leave_channels=False) else: # Pass parsed args on to subcommands. ctx.obj = kwargs
def app(address, keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, logging, logfile, max_unresponsive_time, send_ping_time): slogging.configure(logging, log_file=logfile) # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['max_unresponsive_time'] = max_unresponsive_time config['send_ping_time'] = send_ping_time accmgr = AccountManager(keystore_path) if not accmgr.accounts: raise RuntimeError('No Ethereum accounts found in the user\'s system') if not accmgr.address_in_keystore(address): addresses = list(accmgr.accounts.keys()) formatted_addresses = [ '[{:3d}] - 0x{}'.format(idx, addr) for idx, addr in enumerate(addresses) ] should_prompt = True while should_prompt: idx = click.prompt( "The following accounts were found in your machine:\n\n{}" "\nSelect one of them by index to continue: ".format( "\n".join(formatted_addresses)), type=int) if idx >= 0 and idx < len(addresses): should_prompt = False else: print("\nError: Provided index '{}' is out of bounds\n".format( idx)) address = addresses[idx] privatekey = accmgr.get_privkey(address) config['privatekey_hex'] = encode_hex(privatekey) endpoint = eth_rpc_endpoint if eth_rpc_endpoint.startswith("http://"): endpoint = eth_rpc_endpoint[len("http://"):] rpc_port = 80 elif eth_rpc_endpoint.startswith("https://"): endpoint = eth_rpc_endpoint[len("https://"):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) blockchain_service = BlockChainService( privatekey, decode_hex(registry_contract_address), host=rpc_host, port=rpc_port, ) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address)) return App(config, blockchain_service, discovery)
def get(self, node_address: bytes): endpoint = self.discovery_proxy.endpoint_by_address(node_address) host_port = split_endpoint(endpoint) return host_port
def _start_services(self): from raiden.api.python import RaidenAPI config = deepcopy(App.DEFAULT_CONFIG) config["reveal_timeout"] = self._options["default_reveal_timeout"] config["settle_timeout"] = self._options["default_settle_timeout"] if self._options.get("extra_config", dict()): merge_dict(config, self._options["extra_config"]) del self._options["extra_config"] self._options["config"] = config if self._options["showconfig"]: print("Configuration Dump:") dump_config(config) dump_cmd_options(self._options) dump_module("settings", settings) dump_module("constants", constants) # this catches exceptions raised when waiting for the stalecheck to complete try: app_ = run_app(**self._options) except (ConnectionError, ConnectTimeout, RequestsConnectionError): print(ETHEREUM_NODE_COMMUNICATION_ERROR) sys.exit(1) except RuntimeError as e: click.secho(str(e), fg="red") sys.exit(1) except EthNodeInterfaceError as e: click.secho(str(e), fg="red") sys.exit(1) tasks = [app_.raiden] # RaidenService takes care of Transport and AlarmTask 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) if self._options["rpc"]: rest_api = RestAPI(self._raiden_api) (api_host, api_port) = split_endpoint(self._options["api_address"]) if not api_port: api_port = Port(settings.DEFAULT_HTTP_SERVER_PORT) api_server = APIServer( rest_api, config={"host": api_host, "port": api_port}, cors_domain_list=domain_list, web_ui=self._options["web_ui"], eth_rpc_endpoint=self._options["eth_rpc_endpoint"], ) try: api_server.start() except APIServerPortInUseError: click.secho( f"ERROR: API Address {api_host}:{api_port} is in use. " f"Use --api-address <host:port> to specify a different port.", fg="red", ) 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 ) ) tasks.append(api_server) if self._options["console"]: from raiden.ui.console import Console console = Console(app_) console.start() tasks.append(console) # spawn a greenlet to handle the version checking version = get_system_spec()["raiden"] tasks.append(gevent.spawn(check_version, version)) # spawn a greenlet to handle the gas reserve check tasks.append(gevent.spawn(check_gas_reserve, app_.raiden)) # spawn a greenlet to handle the periodic check for the network id tasks.append( gevent.spawn( check_network_id, app_.raiden.rpc_client.chain_id, app_.raiden.rpc_client.web3 ) ) spawn_user_deposit_task = app_.user_deposit and ( self._options["pathfinding_service_address"] or self._options["enable_monitoring"] ) if spawn_user_deposit_task: # spawn a greenlet to handle RDN deposits check tasks.append(gevent.spawn(check_rdn_deposits, app_.raiden, app_.user_deposit)) # spawn a greenlet to handle the functions self._startup_hook() # wait for interrupt event: "AsyncResult[None]" = AsyncResult() def sig_set(sig=None, _frame=None): event.set(sig) gevent.signal(signal.SIGQUIT, sig_set) gevent.signal(signal.SIGTERM, sig_set) gevent.signal(signal.SIGINT, sig_set) # quit if any task exits, successfully or not for task in tasks: task.link(event) try: event.get() print("Signal received. Shutting down ...") except (ConnectionError, ConnectTimeout, RequestsConnectionError): print(ETHEREUM_NODE_COMMUNICATION_ERROR) sys.exit(1) except RaidenError as ex: click.secho(f"FATAL: {ex}", fg="red") except Exception as ex: file = NamedTemporaryFile( "w", prefix=f"raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}", suffix=".txt", delete=False, ) with file 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() app_.stop() def stop_task(task): try: if isinstance(task, Runnable): task.stop() else: task.kill() finally: task.get() # re-raise gevent.joinall( [gevent.spawn(stop_task, task) for task in tasks], app_.config.get("shutdown_timeout", settings.DEFAULT_SHUTDOWN_TIMEOUT), raise_error=True, ) return app_
def smoketest(ctx, debug, **kwargs): """ Test, that the raiden installation is sane. """ from raiden.api.python import RaidenAPI from raiden.blockchain.abi import get_static_or_compile from raiden.utils import get_contract_path # Check the solidity compiler early in the smoketest. # # Binary distributions don't need the solidity compiler but source # distributions do. Since this is checked by `get_static_or_compile` # function, use it as a proxy for validating the setup. get_static_or_compile( get_contract_path('HumanStandardToken.sol'), 'HumanStandardToken', ) report_file = tempfile.mktemp(suffix='.log') open(report_file, 'w+') def append_report(subject, data): with open(report_file, 'a') as handler: handler.write('{:=^80}'.format(' %s ' % subject.upper()) + os.linesep) if data is not None: if isinstance(data, bytes): data = data.decode() handler.writelines([data + os.linesep]) append_report('raiden version', json.dumps(get_system_spec())) append_report('raiden log', None) print('[1/5] getting smoketest configuration') smoketest_config = load_or_create_smoketest_config() print('[2/5] starting ethereum') ethereum, ethereum_config = start_ethereum(smoketest_config['genesis']) print('[3/5] starting raiden') # setup logging to log only into our report file slogging.configure(':DEBUG', log_file=report_file) root = slogging.getLogger() for handler in root.handlers: if isinstance(handler, slogging.logging.StreamHandler): root.handlers.remove(handler) break # setup cli arguments for starting raiden args = dict( discovery_contract_address=smoketest_config['contracts']['discovery_address'], registry_contract_address=smoketest_config['contracts']['registry_address'], eth_rpc_endpoint='http://127.0.0.1:{}'.format(ethereum_config['rpc']), keystore_path=ethereum_config['keystore'], address=ethereum_config['address'], ) for option in app.params: if option.name in args.keys(): args[option.name] = option.process_value(ctx, args[option.name]) else: args[option.name] = option.default password_file = os.path.join(args['keystore_path'], 'password') with open(password_file, 'w') as handler: handler.write('password') args['mapped_socket'] = None args['password_file'] = click.File()(password_file) args['datadir'] = args['keystore_path'] args['api_address'] = 'localhost:' + str(next(get_free_port('127.0.0.1', 5001))) args['sync_check'] = False # invoke the raiden app app_ = ctx.invoke(app, **args) raiden_api = RaidenAPI(app_.raiden) rest_api = RestAPI(raiden_api) api_server = APIServer(rest_api) (api_host, api_port) = split_endpoint(args['api_address']) api_server.start(api_host, api_port) success = False try: print('[4/5] running smoketests...') error = run_smoketests(app_.raiden, smoketest_config, debug=debug) if error is not None: append_report('smoketest assertion error', error) else: success = True finally: app_.stop() ethereum.send_signal(2) err, out = ethereum.communicate() append_report('geth init stdout', ethereum_config['init_log_out'].decode('utf-8')) append_report('geth init stderr', ethereum_config['init_log_err'].decode('utf-8')) append_report('ethereum stdout', out) append_report('ethereum stderr', err) append_report('smoketest configuration', json.dumps(smoketest_config)) if success: print('[5/5] smoketest successful, report was written to {}'.format(report_file)) else: print('[5/5] smoketest had errors, report was written to {}'.format(report_file)) sys.exit(1)
def run(privatekey, registry_contract_address, discovery_contract_address, listen_address, logging, logfile, scenario, stage_prefix, results_filename): # pylint: disable=unused-argument # TODO: only enabled logging on "initiators" slogging.configure(logging, log_file=logfile) (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey blockchain_service = BlockChainService( decode_hex(privatekey), decode_hex(registry_contract_address), host="127.0.0.1", port="8545", ) discovery = ContractDiscovery( blockchain_service, decode_hex(discovery_contract_address) ) app = App(config, blockchain_service, discovery) app.discovery.register( app.raiden.address, listen_host, listen_port, ) app.raiden.register_registry(app.raiden.chain.default_registry) if scenario: script = json.load(scenario) tools = ConsoleTools( app.raiden, app.discovery, app.config['settle_timeout'], app.config['reveal_timeout'], ) transfers_by_peer = {} tokens = script['assets'] token_address = None peer = None our_node = app.raiden.address.encode('hex') log.warning("our address is {}".format(our_node)) for token in tokens: # skip tokens/assets that we're not part of nodes = token['channels'] if not our_node in nodes: continue # allow for prefunded tokens if 'token_address' in token: token_address = token['token_address'] else: token_address = tools.create_token() 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") while not all(tools.ping(node) for node in nodes if node != our_node): 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] channel_manager = tools.register_asset(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)) app.raiden.api.open(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)) channel = app.raiden.api.deposit(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) else: peer = nodes[-2] if stage_prefix is not None: open('{}.stage1'.format(stage_prefix), 'a').close() log.warning("Done with initialization, waiting to continue...") event = gevent.event.Event() 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 xrange(total_transfers): app.raiden.api.transfer( 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 = gevent.event.Event() gevent.signal(signal.SIGUSR2, event.set) event.wait() results = tools.channel_stats_for(token_address, peer) if transfer_results['total_time'] != 0: results['total_time'] = transfer_results['total_time'] if len(transfer_results['timestamps']) > 0: results['timestamps'] = transfer_results['timestamps'] results['channel'] = repr(results['channel']) # FIXME log.warning("Results: {}".format(results)) with open(results_filename, 'w') as fp: json.dump(results, fp, indent=2) open('{}.stage3'.format(stage_prefix), 'a').close() event = gevent.event.Event() 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 = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()
def run_app( address, keystore_path, gas_price, eth_rpc_endpoint, tokennetwork_registry_contract_address, secret_registry_contract_address, endpoint_registry_contract_address, listen_address, mapped_socket, max_unresponsive_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, transport, matrix_server, network_id, environment_type, unrecoverable_error_should_crash, pathfinding_service_address, pathfinding_max_paths, config=None, extra_config=None, **kwargs, ): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App _assert_sql_version() if transport == 'udp' and not mapped_socket: raise RuntimeError('Missing socket') if datadir is None: datadir = os.path.join(os.path.expanduser('~'), '.raiden') address_hex = to_normalized_address(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) address = to_canonical_address(address_hex) (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config['transport']['udp']['host'] = listen_host config['transport']['udp']['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['transport']['udp']['external_ip'] = mapped_socket.external_ip config['transport']['udp']['external_port'] = mapped_socket.external_port config['transport_type'] = transport config['transport']['matrix']['server'] = matrix_server config['transport']['udp']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['transport']['udp']['nat_keepalive_timeout'] = timeout config['privatekey_hex'] = encode_hex(privatekey_bin) config['unrecoverable_error_should_crash'] = unrecoverable_error_should_crash config['services']['pathfinding_service_address'] = pathfinding_service_address config['services']['pathfinding_max_paths'] = pathfinding_max_paths parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint) if not parsed_eth_rpc_endpoint.scheme: eth_rpc_endpoint = f'http://{eth_rpc_endpoint}' web3 = _setup_web3(eth_rpc_endpoint) rpc_client = JSONRPCClient( web3, privatekey_bin, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, uses_infura='infura.io' in eth_rpc_endpoint, ) blockchain_service = BlockChainService( privatekey_bin=privatekey_bin, jsonrpc_client=rpc_client, # Not giving the contract manager here, but injecting it later # since we first need blockchain service to calculate the network id ) given_network_id = network_id node_network_id = blockchain_service.network_id known_given_network_id = given_network_id in ID_TO_NETWORKNAME known_node_network_id = node_network_id in ID_TO_NETWORKNAME if node_network_id != given_network_id: if known_given_network_id and known_node_network_id: click.secho( f"The chosen ethereum network '{ID_TO_NETWORKNAME[given_network_id]}' " f"differs from the ethereum client '{ID_TO_NETWORKNAME[node_network_id]}'. " "Please update your settings.", fg='red', ) else: click.secho( f"The chosen ethereum network id '{given_network_id}' differs " f"from the ethereum client '{node_network_id}'. " "Please update your settings.", fg='red', ) sys.exit(1) config['chain_id'] = given_network_id # interpret the provided string argument if environment_type == Environment.PRODUCTION: # Safe configuration: restrictions for mainnet apply and matrix rooms have to be private config['environment_type'] = Environment.PRODUCTION config['transport']['matrix']['private_rooms'] = True else: config['environment_type'] = Environment.DEVELOPMENT environment_type = config['environment_type'] print(f'Raiden is running in {environment_type.value.lower()} mode') chain_config = {} contract_addresses_known = False contracts = dict() contracts_version = 'pre_limits' if environment_type == Environment.DEVELOPMENT else None config['contracts_path'] = contracts_precompiled_path(contracts_version) if node_network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[node_network_id] != 'smoketest': deployment_data = get_contracts_deployed(node_network_id, contracts_version) not_allowed = ( # for now we only disallow mainnet with test configuration network_id == 1 and environment_type == Environment.DEVELOPMENT ) if not_allowed: click.secho( f'The chosen network ({ID_TO_NETWORKNAME[node_network_id]}) is not a testnet, ' 'but the "development" environment was selected.\n' 'This is not allowed. Please start again with a safe environment setting ' '(--environment production).', fg='red', ) sys.exit(1) contracts = deployment_data['contracts'] contract_addresses_known = True blockchain_service.inject_contract_manager(ContractManager(config['contracts_path'])) if sync_check: check_synced(blockchain_service, known_node_network_id) contract_addresses_given = ( tokennetwork_registry_contract_address is not None and secret_registry_contract_address is not None and endpoint_registry_contract_address is not None ) if not contract_addresses_given and not contract_addresses_known: click.secho( f"There are no known contract addresses for network id '{given_network_id}'. " "Please provide them on the command line or in the configuration file.", fg='red', ) sys.exit(1) try: token_network_registry = blockchain_service.token_network_registry( tokennetwork_registry_contract_address or to_canonical_address( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('token network registry', tokennetwork_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address( 'token network registry', tokennetwork_registry_contract_address, ) try: secret_registry = blockchain_service.secret_registry( secret_registry_contract_address or to_canonical_address( contracts[CONTRACT_SECRET_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('secret registry', secret_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address('secret registry', secret_registry_contract_address) database_path = os.path.join( datadir, f'node_{pex(address)}', f'netid_{given_network_id}', f'network_{pex(token_network_registry.address)}', f'v{RAIDEN_DB_VERSION}_log.db', ) config['database_path'] = database_path print( '\nYou are connected to the \'{}\' network and the DB path is: {}'.format( ID_TO_NETWORKNAME.get(given_network_id, given_network_id), database_path, ), ) discovery = None if transport == 'udp': transport, discovery = _setup_udp( config, blockchain_service, address, contracts, endpoint_registry_contract_address, ) elif transport == 'matrix': transport = _setup_matrix(config) else: raise RuntimeError(f'Unknown transport type "{transport}" given') raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() try: if 'contracts' in chain_config: start_block = chain_config['contracts']['TokenNetworkRegistry']['block_number'] else: start_block = 0 raiden_app = App( config=config, chain=blockchain_service, query_start_block=start_block, default_registry=token_network_registry, default_secret_registry=secret_registry, transport=transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, discovery=discovery, ) except RaidenError as e: click.secho(f'FATAL: {e}', fg='red') sys.exit(1) try: raiden_app.start() except RuntimeError as e: click.secho(f'FATAL: {e}', fg='red') sys.exit(1) except filelock.Timeout: name_or_id = ID_TO_NETWORKNAME.get(given_network_id, given_network_id) click.secho( f'FATAL: Another Raiden instance already running for account {address_hex} on ' f'network id {name_or_id}', fg='red', ) sys.exit(1) return raiden_app
def _start_services(self): from raiden.ui.console import Console from raiden.api.python import RaidenAPI config = deepcopy(App.DEFAULT_CONFIG) if self._options.get('extra_config', dict()): merge_dict(config, self._options['extra_config']) del self._options['extra_config'] self._options['config'] = config if self._options['showconfig']: print('Configuration Dump:') dump_config(config) dump_cmd_options(self._options) dump_module('settings', settings) dump_module('constants', constants) # this catches exceptions raised when waiting for the stalecheck to complete try: app_ = run_app(**self._options) except (EthNodeCommunicationError, RequestsConnectionError): print(ETHEREUM_NODE_COMMUNICATION_ERROR) sys.exit(1) except RuntimeError as e: click.secho(str(e), fg='red') sys.exit(1) except EthNodeInterfaceError as e: click.secho(str(e), fg='red') sys.exit(1) tasks = [app_.raiden] # RaidenService takes care of Transport and AlarmTask 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) 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: click.secho( f'ERROR: API Address {api_host}:{api_port} is in use. ' f'Use --api-address <host:port> to specify a different port.', fg='red', ) 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, ), ) tasks.append(api_server) if self._options['console']: console = Console(app_) console.start() tasks.append(console) # spawn a greenlet to handle the version checking version = get_system_spec()['raiden'] tasks.append(gevent.spawn(check_version, version)) # spawn a greenlet to handle the gas reserve check tasks.append(gevent.spawn(check_gas_reserve, app_.raiden)) self._startup_hook() # wait for interrupt event = AsyncResult() def sig_set(sig=None, _frame=None): event.set(sig) gevent.signal(signal.SIGQUIT, sig_set) gevent.signal(signal.SIGTERM, sig_set) gevent.signal(signal.SIGINT, sig_set) # quit if any task exits, successfully or not for task in tasks: task.link(event) try: event.get() print('Signal received. Shutting down ...') except (EthNodeCommunicationError, RequestsConnectionError): print(ETHEREUM_NODE_COMMUNICATION_ERROR) sys.exit(1) except RaidenError as ex: click.secho(f'FATAL: {ex}', fg='red') except Exception as ex: file = NamedTemporaryFile( 'w', prefix=f'raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}', suffix='.txt', delete=False, ) with file 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() def stop_task(task): try: if isinstance(task, Runnable): task.stop() else: task.kill() finally: task.get() # re-raise gevent.joinall( [gevent.spawn(stop_task, task) for task in tasks], app_.config.get('shutdown_timeout', settings.DEFAULT_SHUTDOWN_TIMEOUT), raise_error=True, ) return app_