def run_smoketest( print_step: Callable, append_report: Callable, args: Dict[str, Any], contract_addresses: List[Address], token: ContractProxy, debug: bool, ethereum_nodes: List[HTTPExecutor], ): print_step('Starting Raiden') config = deepcopy(App.DEFAULT_CONFIG) extra_config = args.pop('extra_config', None) if extra_config: merge_dict(config, extra_config) args['config'] = config # Should use basic routing in the smoke test for now # TODO: If we ever utilize a PFS in the smoke test we # need to use the deployed service registry, register the # PFS service there and then change this argument. args['routing_mode'] = RoutingMode.BASIC raiden_stdout = StringIO() maybe_redirect_stdout = contextlib.redirect_stdout(raiden_stdout) if debug: maybe_redirect_stdout = contextlib.nullcontext() with maybe_redirect_stdout: success = False app = None try: app = run_app(**args) 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() block = app.raiden.get_block_number( ) + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS # Proxies now use the confirmed block hash to query the chain for # prerequisite checks. Wait a bit here to make sure that the confirmed # block hash contains the deployed token network or else things break wait_for_block( raiden=app.raiden, block_number=block, retry_timeout=1.0, ) 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)] print_step('Running smoketest') error = smoketest_perform_tests( app.raiden, args['transport'], token_addresses, contract_addresses[CONTRACT_ENDPOINT_REGISTRY], ) if error is not None: append_report('Smoketest assertion error', error) else: success = True except: # noqa pylint: disable=bare-except if debug: import pdb # The pylint comment is required when pdbpp is installed pdb.post_mortem() # pylint: disable=no-member else: error = traceback.format_exc() append_report('Smoketest execution error', error) finally: if app is not None: app.stop() app.raiden.get() node_executor = ethereum_nodes[0] node = node_executor.process node.send_signal(signal.SIGINT) try: node.wait(10) except TimeoutExpired: print_step('Ethereum node shutdown unclean, check log!', error=True) node.kill() if isinstance(node_executor.stdio, tuple): logfile = node_executor.stdio[1] logfile.flush() logfile.seek(0) append_report('Ethereum Node log output', logfile.read()) 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_smoketest(print_step: Callable, setup: RaidenTestSetup) -> None: print_step("Starting Raiden") app = None try: app = run_app(**setup.args) raiden_api = app.raiden.raiden_api assert raiden_api is not None # for mypy block = BlockNumber(app.raiden.get_block_number() + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS) # Proxies now use the confirmed block hash to query the chain for # prerequisite checks. Wait a bit here to make sure that the confirmed # block hash contains the deployed token network or else things break wait_for_block(raiden=app.raiden, block_number=block, retry_timeout=1.0) raiden_api.channel_open( registry_address=TokenNetworkRegistryAddress( setup.contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]), token_address=TokenAddress( to_canonical_address(setup.token.address)), partner_address=ConnectionManager.BOOTSTRAP_ADDR, ) raiden_api.set_total_channel_deposit( registry_address=TokenNetworkRegistryAddress( setup.contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]), token_address=TokenAddress( to_canonical_address(setup.token.address)), partner_address=ConnectionManager.BOOTSTRAP_ADDR, total_deposit=TEST_DEPOSIT_AMOUNT, ) token_addresses = [to_checksum_address(setup.token.address) ] # type: ignore print_step("Running smoketest") raiden_service = app.raiden token_network_added_events = raiden_service.default_registry.filter_token_added_events( ) events_token_addresses = [ event["args"]["token_address"] for event in token_network_added_events ] assert events_token_addresses == token_addresses token_networks = views.get_token_identifiers( views.state_from_raiden(raiden_service), raiden_service.default_registry.address) assert len(token_networks) == 1 channel_state = views.get_channelstate_for( chain_state=views.state_from_raiden(raiden_service), token_network_registry_address=raiden_service.default_registry. address, token_address=token_networks[0], partner_address=ConnectionManager.BOOTSTRAP_ADDR, ) assert channel_state distributable = channel.get_distributable(channel_state.our_state, channel_state.partner_state) assert distributable == TEST_DEPOSIT_AMOUNT assert Balance( distributable) == channel_state.our_state.contract_balance assert channel.get_status(channel_state) == ChannelState.STATE_OPENED port_number = raiden_service.config.rest_api.port response = requests.get( f"http://localhost:{port_number}/api/v1/channels") assert response.status_code == HTTPStatus.OK response_json = json.loads(response.content) assert response_json[0]["partner_address"] == to_checksum_address( ConnectionManager.BOOTSTRAP_ADDR) assert response_json[0]["state"] == "opened" assert int(response_json[0]["balance"]) > 0 finally: if app is not None: app.stop() app.raiden.greenlet.get()
def run_services(options: Dict[str, Any]) -> None: if options["config_file"]: log.debug("Using config file", config_file=options["config_file"]) app = run_app(**options) gevent_tasks: List[gevent.Greenlet] = list() if options["console"]: from raiden.ui.console import Console console = Console(app) console.start() gevent_tasks.append(console) gevent_tasks.append(spawn_named("check_version", check_version, get_system_spec()["raiden"])) gevent_tasks.append(spawn_named("check_gas_reserve", check_gas_reserve, app.raiden)) gevent_tasks.append( spawn_named( "check_network_id", check_network_id, app.raiden.rpc_client.chain_id, app.raiden.rpc_client.web3, ) ) spawn_user_deposit_task = app.user_deposit and ( options["pathfinding_service_address"] or options["enable_monitoring"] ) if spawn_user_deposit_task: gevent_tasks.append( spawn_named("check_rdn_deposits", check_rdn_deposits, app.raiden, app.user_deposit) ) stop_event: AsyncResult[Optional[signal.Signals]] # pylint: disable=no-member stop_event = AsyncResult() def sig_set(sig: int, _frame: Any = None) -> None: stop_event.set(signal.Signals(sig)) # pylint: disable=no-member gevent.signal.signal(signal.SIGQUIT, sig_set) # pylint: disable=no-member gevent.signal.signal(signal.SIGTERM, sig_set) # pylint: disable=no-member gevent.signal.signal(signal.SIGINT, sig_set) # pylint: disable=no-member # The SIGPIPE handler should not be installed. It is handled by the python # runtime, and an exception will be raised at the call site that triggered # the error. # # The default SIGPIPE handler set by the libc will terminate the process # [4]. However, the CPython interpreter changes the handler to IGN [3]. # This allows for error reporting by the system calls that write to files. # Because of this, calling `send` to a closed socket will return an `EPIPE` # error [2], the error is then converted to an exception [5,6]. # # 1 - https://github.com/python/cpython/blob/3.8/Modules/socketmodule.c#L4088 # 2 - http://man7.org/linux/man-pages/man2/send.2.html # 3 - https://github.com/python/cpython/blob/3.8/Python/pylifecycle.c#L2306-L2307 # 4 - https://www.gnu.org/software/libc/manual/html_node/Operation-Error-Signals.html # 5 - https://github.com/python/cpython/blob/3.8/Modules/socketmodule.c#L836-L838 # 6 - https://github.com/python/cpython/blob/3.8/Modules/socketmodule.c#L627-L628 # 7 - https://docs.python.org/3/library/signal.html#note-on-sigpipe # # gevent.signal.signal(signal.SIGPIPE, sig_set) # pylint: disable=no-member # quit if any task exits, successfully or not app.raiden.greenlet.link(stop_event) for task in gevent_tasks: task.link(stop_event) try: signal_received = stop_event.get() if signal_received: print("\r", end="") # Reset cursor to overwrite a possibly printed "^C" log.info("Signal received. Shutting down.", signal=signal_received) finally: for task in gevent_tasks: task.kill() app.raiden.stop() gevent.joinall( set(gevent_tasks + [app.raiden]), app.config.shutdown_timeout, raise_error=True ) app.stop()
def run_smoketest( print_step: Callable, args: Dict[str, Any], contract_addresses: Dict[str, Address], token: ContractProxy, ): print_step("Starting Raiden") app = None api_server = None try: app = run_app(**args) 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() block = app.raiden.get_block_number( ) + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS # Proxies now use the confirmed block hash to query the chain for # prerequisite checks. Wait a bit here to make sure that the confirmed # block hash contains the deployed token network or else things break wait_for_block(raiden=app.raiden, block_number=block, retry_timeout=1.0) raiden_api.channel_open( registry_address=TokenNetworkRegistryAddress( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]), token_address=TokenAddress( to_canonical_address(token.contract.address)), partner_address=ConnectionManager.BOOTSTRAP_ADDR, ) raiden_api.set_total_channel_deposit( registry_address=TokenNetworkRegistryAddress( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]), token_address=TokenAddress( to_canonical_address(token.contract.address)), partner_address=ConnectionManager.BOOTSTRAP_ADDR, total_deposit=TEST_DEPOSIT_AMOUNT, ) token_addresses = [to_checksum_address(token.contract.address)] print_step("Running smoketest") raiden_service = app.raiden token_network_added_events = raiden_service.default_registry.filter_token_added_events( ) events_token_addresses = [ event["args"]["token_address"] for event in token_network_added_events ] assert events_token_addresses == token_addresses token_networks = views.get_token_identifiers( views.state_from_raiden(raiden_service), raiden_service.default_registry.address) assert len(token_networks) == 1 channel_state = views.get_channelstate_for( chain_state=views.state_from_raiden(raiden_service), token_network_registry_address=raiden_service.default_registry. address, token_address=token_networks[0], partner_address=ConnectionManager.BOOTSTRAP_ADDR, ) assert channel_state distributable = channel.get_distributable(channel_state.our_state, channel_state.partner_state) assert distributable == TEST_DEPOSIT_AMOUNT assert distributable == channel_state.our_state.contract_balance assert channel.get_status(channel_state) == ChannelState.STATE_OPENED port_number = raiden_service.config["api_port"] response = requests.get( f"http://localhost:{port_number}/api/v1/channels") assert response.status_code == HTTPStatus.OK response_json = json.loads(response.content) assert response_json[0]["partner_address"] == to_checksum_address( ConnectionManager.BOOTSTRAP_ADDR) assert response_json[0]["state"] == "opened" assert response_json[0]["balance"] > 0 finally: if api_server is not None: api_server.stop() api_server.get() if app is not None: app.stop() app.raiden.get()