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(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 print('Welcome to Raiden, version {}!'.format(get_system_spec()['raiden'])) from raiden.ui.console import Console from raiden.api.python import RaidenAPI if kwargs['config_file']: try: config_file = toml.load(kwargs['config_file']) optionname_to_default = { param.name: param.get_default(ctx) for param in run.params } addr_options = { param.name for param in run.params if param.type == ADDRESS_TYPE } for option_name, option_value in config_file.items(): option_name = option_name.replace('-', '_') if option_name in addr_options: option_value = address_checksum_and_decode(option_value) if (option_name not in kwargs or option_name not in optionname_to_default or kwargs[option_name] == optionname_to_default[option_name]): kwargs[option_name] = option_value except TypeError: print('Invalid config file') sys.exit(1) except toml.TomlDecodeError: print('Error occurs while decoding config file') sys.exit(1) configure_logging( kwargs['log_config'], log_json=kwargs['log_json'], log_file=kwargs['log_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: 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() # 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() print('Signal received. Shutting down ...') if api_server: api_server.stop() return app_ # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. 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': print('WARNING: The Matrix transport is experimental') kwargs['mapped_socket'] = None app_ = _run_app() else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'") app_.stop(leave_channels=False)
def smoketest(ctx, debug, local_matrix, **kwargs): # pylint: disable=unused-argument """ Test, that the raiden installation is sane. """ import binascii from web3 import Web3, HTTPProvider from web3.middleware import geth_poa_middleware from raiden.api.python import RaidenAPI from raiden.blockchain.abi import get_static_or_compile from raiden.network.proxies.registry import Registry from raiden.tests.utils.geth import geth_wait_and_check from raiden.tests.integration.contracts.fixtures.contracts import deploy_token from raiden.tests.utils.smoketest import ( TEST_PARTNER_ADDRESS, TEST_DEPOSIT_AMOUNT, deploy_smoketest_contracts, get_private_key, load_smoketest_config, start_ethereum, run_smoketests, ) 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') configure_logging({'': 'DEBUG'}, log_file=report_file) def append_report(subject, data): with open(report_file, 'a', encoding='UTF-8') as handler: handler.write(f'{f" {subject.upper()} ":=^80}{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) step_count = 7 if ctx.parent.params['transport'] == 'matrix': step_count = 8 step = 0 def print_step(description, error=False): nonlocal step step += 1 click.echo( '{} {}'.format( click.style(f'[{step}/{step_count}]', fg='blue'), click.style(description, fg='green' if not error else 'red'), ), ) print_step('Getting smoketest configuration') smoketest_config = load_smoketest_config() if not smoketest_config: append_report( 'Smoketest configuration', 'Could not load the smoketest genesis configuration file.', ) print_step('Starting Ethereum node') ethereum, ethereum_config = start_ethereum(smoketest_config['genesis']) port = ethereum_config['rpc'] web3_client = Web3(HTTPProvider(f'http://0.0.0.0:{port}')) web3_client.middleware_stack.inject(geth_poa_middleware, layer=0) random_marker = binascii.hexlify(b'raiden').decode() privatekeys = [] geth_wait_and_check(web3_client, privatekeys, random_marker) print_step('Deploying Raiden contracts') host = '0.0.0.0' client = JSONRPCClient( host, ethereum_config['rpc'], get_private_key(), web3=web3_client, ) contract_addresses = deploy_smoketest_contracts(client) token_contract = deploy_token(None, client) token = token_contract(1000, 0, 'TKN', 'TKN') registry = Registry( client, contract_addresses['Registry'], ) registry.add_token(to_canonical_address(token.contract.address)) print_step('Setting up Raiden') # setup cli arguments for starting raiden args = dict( discovery_contract_address=to_checksum_address( contract_addresses['EndpointRegistry']), registry_contract_address=to_checksum_address( contract_addresses['Registry']), secret_registry_contract_address=to_checksum_address( contract_addresses['SecretRegistry']), eth_rpc_endpoint='http://127.0.0.1:{}'.format(port), keystore_path=ethereum_config['keystore'], address=ethereum_config['address'], network_id='627', transport=ctx.parent.params['transport'], matrix_server='http://localhost:8008' if ctx.parent.params['matrix_server'] == 'auto' else ctx.parent.params['matrix_server'], ) smoketest_config['transport'] = args['transport'] 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') port = next(get_free_port('127.0.0.1', 5001)) args['password_file'] = click.File()(password_file) args['datadir'] = args['keystore_path'] args['api_address'] = 'localhost:' + str(port) args['sync_check'] = False 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['Registry'], to_canonical_address(token.contract.address), to_canonical_address(TEST_PARTNER_ADDRESS), None, None, ) raiden_api.set_total_channel_deposit( contract_addresses['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['Registry'], ) smoketest_config['contracts'][ 'discovery_address'] = to_checksum_address( contract_addresses['EndpointRegistry'], ) 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 if args['transport'] == 'udp': with SocketFactory('127.0.0.1', port, strategy='none') as mapped_socket: args['mapped_socket'] = mapped_socket success = _run_smoketest() elif args['transport'] == 'matrix' and local_matrix.lower() != 'none': print('WARNING: The Matrix transport is experimental') args['mapped_socket'] = None print_step('Starting Matrix transport') try: with HTTPExecutor( local_matrix, status=r'^[24]\d\d$', url=urljoin(args['matrix_server'], '/_matrix/client/versions'), shell=True, ): args['extra_config'] = { 'matrix': { 'discovery_room': { 'server': 'matrix.local.raiden' }, 'server_name': 'matrix.local.raiden', }, } success = _run_smoketest() except (PermissionError, ProcessExitedWithError): append_report('Matrix server start exception', traceback.format_exc()) print_step( f'Error during smoketest setup, report was written to {report_file}', error=True, ) success = False elif args['transport'] == 'matrix' and local_matrix.lower() == "none": print('WARNING: The Matrix transport is experimental') args['mapped_socket'] = None success = _run_smoketest() else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{args['transport']}'") if not success: sys.exit(1)
def smoketest(ctx, debug, **kwargs): # pylint: disable=unused-argument """ 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') port = next(get_free_port('127.0.0.1', 5001)) args['password_file'] = click.File()(password_file) args['datadir'] = args['keystore_path'] args['api_address'] = 'localhost:' + str(port) args['sync_check'] = False with SocketFactory('127.0.0.1', port, strategy='none') as mapped_socket: args['mapped_socket'] = mapped_socket # 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 smoketest(ctx, debug, local_matrix, **kwargs): # pylint: disable=unused-argument """ Test, that the raiden installation is sane. """ from raiden.api.python import RaidenAPI from raiden.tests.utils.smoketest import ( TEST_PARTNER_ADDRESS, TEST_DEPOSIT_AMOUNT, run_smoketests, setup_testchain_and_raiden, ) report_file = mktemp(suffix='.log') configure_logging({'': 'DEBUG'}, log_file=report_file) def append_report(subject, data): with open(report_file, 'a', encoding='UTF-8') as handler: handler.write(f'{f" {subject.upper()} ":=^80}{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) step_count = 7 if ctx.parent.params['transport'] == 'matrix': step_count = 8 step = 0 def print_step(description, error=False): nonlocal step step += 1 click.echo( '{} {}'.format( click.style(f'[{step}/{step_count}]', fg='blue'), click.style(description, fg='green' if not error else 'red'), ), ) print_step('Getting smoketest configuration') result = setup_testchain_and_raiden( ctx.parent.params['transport'], ctx.parent.params['matrix_server'], print_step, ) args = result['args'] contract_addresses = result['contract_addresses'] token = result['token'] ethereum = result['ethereum'] for option_ in run.params: if option_.name in args.keys(): args[option_.name] = option_.process_value(ctx, args[option_.name]) else: args[option_.name] = option_.default port = next(get_free_port('127.0.0.1', 5001)) args['api_address'] = 'localhost:' + str(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, report was written to {report_file}') else: print_step( f'Smoketest had errors, report was written to {report_file}', error=True) return success if args['transport'] == 'udp': with SocketFactory('127.0.0.1', port, strategy='none') as mapped_socket: args['mapped_socket'] = mapped_socket success = _run_smoketest() elif args['transport'] == 'matrix' and local_matrix.lower() != 'none': args['mapped_socket'] = None print_step('Starting Matrix transport') try: with HTTPExecutor( local_matrix, url=urljoin(args['matrix_server'], '/_matrix/client/versions'), method='GET', io=DEVNULL, timeout=30, shell=True, ): args['extra_config'] = { 'transport': { 'matrix': { 'server_name': 'matrix.local.raiden', 'available_servers': [], }, }, } success = _run_smoketest() except (PermissionError, ProcessExitedWithError, FileNotFoundError): append_report('Matrix server start exception', traceback.format_exc()) print_step( f'Error during smoketest setup, report was written to {report_file}', error=True, ) success = False elif args['transport'] == 'matrix' and local_matrix.lower() == "none": args['mapped_socket'] = None args['extra_config'] = { 'transport': { 'matrix': { 'server_name': 'matrix.local.raiden', 'available_servers': [], }, }, } success = _run_smoketest() else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{args['transport']}'") if not success: sys.exit(1)
def run(self): click.secho(self._welcome_string, fg='green') click.secho( textwrap.dedent( '''\ ---------------------------------------------------------------------- | 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', ) configure_logging( self._options['log_config'], log_json=self._options['log_json'], log_file=self._options['log_file'], disable_debug_logfile=self._options['disable_debug_logfile'], ) if self._options['config_file']: log.debug('Using config file', config_file=self._options['config_file']) # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. try: if self._options['transport'] == 'udp': (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._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 self._options['transport'] == 'matrix': self._options['mapped_socket'] = None app = self._run_app() else: # Shouldn't happen raise RuntimeError( f"Invalid transport type '{self._options['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 smoketest(ctx, debug, eth_client): """ Test, that the raiden installation is sane. """ from raiden.tests.utils.smoketest import setup_testchain_and_raiden, run_smoketest from raiden.tests.utils.transport import make_requests_insecure, matrix_server_starter report_file = mktemp(suffix=".log") configure_logging( logger_level_config={"": "DEBUG"}, log_file=report_file, disable_debug_logfile=ctx.parent.params["disable_debug_logfile"], ) free_port_generator = get_free_port() click.secho(f"Report file: {report_file}", fg="yellow") def append_report(subject: str, data: Optional[AnyStr] = None): with open(report_file, "a", encoding="UTF-8") as handler: handler.write(f'{f" {subject.upper()} ":=^80}{os.linesep}') if data is not None: write_data: str if isinstance(data, bytes): write_data = data.decode() else: write_data = data handler.writelines([write_data + os.linesep]) append_report("Raiden version", json.dumps(get_system_spec())) append_report("Raiden log") step_count = 7 if ctx.parent.params["transport"] == "matrix": step_count = 8 step = 0 stdout = sys.stdout def print_step(description: str, error: bool = False) -> None: nonlocal step step += 1 click.echo( "{} {}".format( click.style(f"[{step}/{step_count}]", fg="blue"), click.style(description, fg="green" if not error else "red"), ), file=stdout, ) print_step("Getting smoketest configuration") contracts_version = environment_type_to_contracts_version( ctx.parent.params["environment_type"]) with setup_testchain_and_raiden( transport=ctx.parent.params["transport"], eth_client=eth_client, matrix_server=ctx.parent.params["matrix_server"], contracts_version=contracts_version, print_step=print_step, free_port_generator=free_port_generator, ) as result: args = result["args"] contract_addresses = result["contract_addresses"] token = result["token"] ethereum_nodes = result["ethereum_nodes"] # Also respect environment type args["environment_type"] = ctx.parent.params["environment_type"] for option_ in run.params: if option_.name in args.keys(): args[option_.name] = option_.process_value( ctx, args[option_.name]) else: args[option_.name] = option_.default port = next(free_port_generator) args["api_address"] = "localhost:" + str(port) if args["transport"] == "udp": with SocketFactory("127.0.0.1", port, strategy="none") as mapped_socket: args["mapped_socket"] = mapped_socket success = run_smoketest( print_step=print_step, append_report=append_report, args=args, contract_addresses=contract_addresses, token=token, debug=debug, ethereum_nodes=ethereum_nodes, ) elif args["transport"] == "matrix": args["mapped_socket"] = None print_step("Starting Matrix transport") try: with matrix_server_starter( free_port_generator=free_port_generator ) as server_urls: # Disable TLS verification so we can connect to the self signed certificate make_requests_insecure() urllib3.disable_warnings(InsecureRequestWarning) args["extra_config"] = { "transport": { "matrix": { "available_servers": server_urls } } } success = run_smoketest( print_step=print_step, append_report=append_report, args=args, contract_addresses=contract_addresses, token=token, debug=debug, ethereum_nodes=ethereum_nodes, ) except (PermissionError, ProcessExitedWithError, FileNotFoundError): append_report("Matrix server start exception", traceback.format_exc()) print_step( f"Error during smoketest setup, report was written to {report_file}", error=True, ) success = False else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{args['transport']}'") if not success: sys.exit(1)
def smoketest(ctx, debug, eth_client): """ Test, that the raiden installation is sane. """ from raiden.tests.utils.smoketest import setup_testchain_and_raiden, run_smoketest from raiden.tests.utils.transport import make_requests_insecure, matrix_server_starter report_file = mktemp(suffix='.log') configure_logging( logger_level_config={'': 'DEBUG'}, log_file=report_file, disable_debug_logfile=ctx.parent.params['disable_debug_logfile'], ) click.secho(f'Report file: {report_file}', fg='yellow') def append_report(subject: str, data: Optional[AnyStr] = None): with open(report_file, 'a', encoding='UTF-8') as handler: handler.write(f'{f" {subject.upper()} ":=^80}{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') step_count = 7 if ctx.parent.params['transport'] == 'matrix': step_count = 8 step = 0 stdout = sys.stdout def print_step(description: str, error: bool = False) -> None: nonlocal step step += 1 click.echo( '{} {}'.format( click.style(f'[{step}/{step_count}]', fg='blue'), click.style(description, fg='green' if not error else 'red'), ), file=stdout, ) print_step('Getting smoketest configuration') contracts_version = environment_type_to_contracts_version( ctx.parent.params['environment_type'], ) with setup_testchain_and_raiden( transport=ctx.parent.params['transport'], eth_client=eth_client, matrix_server=ctx.parent.params['matrix_server'], contracts_version=contracts_version, print_step=print_step, ) as result: args = result['args'] contract_addresses = result['contract_addresses'] token = result['token'] ethereum_nodes = result['ethereum_nodes'] # Also respect environment type args['environment_type'] = ctx.parent.params['environment_type'] for option_ in run.params: if option_.name in args.keys(): args[option_.name] = option_.process_value( ctx, args[option_.name]) else: args[option_.name] = option_.default port = next(get_free_port(5001)) args['api_address'] = 'localhost:' + str(port) if args['transport'] == 'udp': with SocketFactory('127.0.0.1', port, strategy='none') as mapped_socket: args['mapped_socket'] = mapped_socket success = run_smoketest( print_step=print_step, append_report=append_report, args=args, contract_addresses=contract_addresses, token=token, debug=debug, ethereum_nodes=ethereum_nodes, ) elif args['transport'] == 'matrix': args['mapped_socket'] = None print_step('Starting Matrix transport') try: with matrix_server_starter() as server_urls: # Disable TLS verification so we can connect to the self signed certificate make_requests_insecure() urllib3.disable_warnings(InsecureRequestWarning) args['extra_config'] = { 'transport': { 'matrix': { 'available_servers': server_urls, }, }, } success = run_smoketest( print_step=print_step, append_report=append_report, args=args, contract_addresses=contract_addresses, token=token, debug=debug, ethereum_nodes=ethereum_nodes, ) except (PermissionError, ProcessExitedWithError, FileNotFoundError): append_report('Matrix server start exception', traceback.format_exc()) print_step( f'Error during smoketest setup, report was written to {report_file}', error=True, ) success = False else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{args['transport']}'") if not success: sys.exit(1)
def runner(ctx, **kwargs): """ Start a raiden Echo Node that will send received transfers back to the initiator. """ # This is largely a copy&paste job from `raiden.ui.cli::run`, with the difference that # an `EchoNode` is instantiated from the App's `RaidenAPI`. print('Welcome to Raiden, version {} [Echo Node]'.format( get_system_spec()['raiden'])) structlog.configure( kwargs['structlog'], log_json=kwargs['log_json'], log_file=kwargs['logfile'], ) if kwargs['logfile']: # Disable stream structlog root = structlog.get_logger() for handler in root.handlers: if isinstance(handler, structlog.structlog.StreamHandler): root.handlers.remove(handler) break token_address = kwargs.pop('token_address') (listen_host, listen_port) = split_endpoint(kwargs['listen_address']) 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'])) raiden_api = RaidenAPI(app_.raiden) if ctx.params['rpc']: 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' 'http://raiden-network.readthedocs.io/en/stable/rest_api.html'. format( api_host, api_port, ), ) # This will install the EchoNode callback in the alarm task: echo = EchoNode(raiden_api, token_address) event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() # This will remove the EchoNode callback from the alarm task: echo.stop() try: api_server.stop() except NameError: pass app_.stop(leave_channels=False)
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 smoketest(ctx, debug): """ Test, that the raiden installation is sane. """ from raiden.api.python import RaidenAPI from raiden.tests.utils.smoketest import ( TEST_PARTNER_ADDRESS, TEST_DEPOSIT_AMOUNT, run_smoketests, setup_testchain_and_raiden, ) report_file = mktemp(suffix='.log') configure_logging( logger_level_config={'': 'DEBUG'}, log_file=report_file, disable_debug_logfile=ctx.parent.params['disable_debug_logfile'], ) click.secho( f'Report file: {report_file}', fg='yellow', ) def append_report(subject, data): with open(report_file, 'a', encoding='UTF-8') as handler: handler.write(f'{f" {subject.upper()} ":=^80}{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) step_count = 7 if ctx.parent.params['transport'] == 'matrix': step_count = 8 step = 0 def print_step(description, error=False): nonlocal step step += 1 click.echo( '{} {}'.format( click.style(f'[{step}/{step_count}]', fg='blue'), click.style(description, fg='green' if not error else 'red'), ), ) print_step('Getting smoketest configuration') result = setup_testchain_and_raiden( ctx.parent.params['transport'], ctx.parent.params['matrix_server'], print_step, # smoke test should work with pre-limits contract version DEVELOPMENT_CONTRACT_VERSION, ) args = result['args'] contract_addresses = result['contract_addresses'] token = result['token'] ethereum = result['ethereum'] for option_ in run.params: if option_.name in args.keys(): args[option_.name] = option_.process_value(ctx, args[option_.name]) else: args[option_.name] = option_.default port = next(get_free_port('127.0.0.1', 5001)) args['api_address'] = 'localhost:' + str(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 raiden_stdout = StringIO() with contextlib.redirect_stdout(raiden_stdout): app = run_app(**args) try: raiden_api = RaidenAPI(app.raiden) rest_api = RestAPI(raiden_api) (api_host, api_port) = split_endpoint(args['api_address']) api_server = APIServer(rest_api, config={'host': api_host, 'port': api_port}) api_server.start() 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 if args['transport'] == 'udp': with SocketFactory('127.0.0.1', port, strategy='none') as mapped_socket: args['mapped_socket'] = mapped_socket success = _run_smoketest() elif args['transport'] == 'matrix': args['mapped_socket'] = None print_step('Starting Matrix transport') try: with matrix_server_starter() as server_urls: # Disable TLS verification so we can connect to the self signed certificate make_requests_insecure() urllib3.disable_warnings(InsecureRequestWarning) args['extra_config'] = { 'transport': { 'matrix': { 'available_servers': server_urls, }, }, } success = _run_smoketest() except (PermissionError, ProcessExitedWithError, FileNotFoundError): append_report('Matrix server start exception', traceback.format_exc()) print_step( f'Error during smoketest setup, report was written to {report_file}', error=True, ) success = False else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{args['transport']}'") if not success: sys.exit(1)
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') 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) } 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: 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() # 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() print('Signal received. Shutting down ...') if api_server: api_server.stop() return app_ # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. 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': print('WARNING: The Matrix transport is experimental') kwargs['mapped_socket'] = None app_ = _run_app() else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'") app_.stop(leave_channels=False)
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 print('Welcome to Raiden, version {}!'.format(get_system_spec()['raiden'])) from raiden.ui.console import Console from raiden.api.python import RaidenAPI configure_logging( kwargs['log_config'], log_json=kwargs['log_json'], log_file=kwargs['log_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 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_ # TODO: # - Ask for confirmation to quit if there are any locked transfers that did # not timeout. 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 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 elif kwargs['transport'] == 'matrix': print('WARNING: The Matrix transport is experimental') kwargs['mapped_socket'] = None app_ = _run_app() else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'") app_.stop(leave_channels=False)
def smoketest(ctx, debug, local_matrix, **kwargs): # pylint: disable=unused-argument """ Test, that the raiden installation is sane. """ import binascii from raiden.api.python import RaidenAPI from raiden.blockchain.abi import get_static_or_compile from raiden.tests.utils.blockchain import geth_wait_and_check from raiden.tests.integration.fixtures.backend_geth import web3 from raiden.tests.utils.smoketest import ( load_smoketest_config, start_ethereum, run_smoketests, ) 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') configure_logging({'': 'DEBUG'}, log_file=report_file) def append_report(subject, data): with open(report_file, 'a', encoding='UTF-8') as handler: handler.write(f'{f" {subject.upper()} ":=^80}{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_smoketest_config() if not smoketest_config: append_report( 'smoketest configuration', 'Could not load the smoketest genesis configuration file.', ) print('[2/5] starting ethereum') ethereum, ethereum_config = start_ethereum(smoketest_config['genesis']) port = ethereum_config['rpc'] web3_client = web3([port]) random_marker = binascii.hexlify(b'raiden').decode() privatekeys = [] geth_wait_and_check(web3_client, privatekeys, random_marker) print('[3/5] starting raiden') # setup cli arguments for starting raiden args = dict( discovery_contract_address=smoketest_config['contracts'] ['discovery_address'], registry_contract_address=smoketest_config['contracts'] ['registry_address'], secret_registry_contract_address=smoketest_config['contracts'] ['secret_registry_address'], eth_rpc_endpoint='http://127.0.0.1:{}'.format(port), keystore_path=ethereum_config['keystore'], address=ethereum_config['address'], network_id='627', transport=ctx.parent.params['transport'], matrix_server='http://localhost:8008' if ctx.parent.params['matrix_server'] == 'auto' else ctx.parent.params['matrix_server'], ) smoketest_config['transport'] = args['transport'] 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') port = next(get_free_port('127.0.0.1', 5001)) args['password_file'] = click.File()(password_file) args['datadir'] = args['keystore_path'] args['api_address'] = 'localhost:' + str(port) args['sync_check'] = False 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 if args['transport'] == 'udp': with SocketFactory('127.0.0.1', port, strategy='none') as mapped_socket: args['mapped_socket'] = mapped_socket success = _run_smoketest() elif args['transport'] == 'matrix' and local_matrix.lower() != 'none': print('WARNING: The Matrix transport is experimental') args['mapped_socket'] = None with HTTPExecutor( local_matrix, status=r'^[24]\d\d$', url=urljoin(args['matrix_server'], '/_matrix/client/versions'), ): args['extra_config'] = { 'matrix': { 'discovery_room': { 'server': 'matrix.local.raiden' }, 'server_name': 'matrix.local.raiden', }, } success = _run_smoketest() elif args['transport'] == 'matrix' and local_matrix.lower() == "none": print('WARNING: The Matrix transport is experimental') args['mapped_socket'] = None success = _run_smoketest() else: # Shouldn't happen raise RuntimeError(f"Invalid transport type '{args['transport']}'") if not success: sys.exit(1)