Esempio n. 1
0
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
Esempio n. 2
0
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()
Esempio n. 3
0
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()
Esempio n. 4
0
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()