示例#1
0
def run(ctx, **kwargs):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements

    if kwargs['config_file']:
        apply_config_file(run, kwargs, ctx)

    if ctx.invoked_subcommand is not None:
        # Pass parsed args on to subcommands.
        ctx.obj = kwargs
        return

    NodeRunner(kwargs, ctx).run()
示例#2
0
def run(ctx, **kwargs):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements

    if kwargs["config_file"]:
        apply_config_file(run, kwargs, ctx)

    validate_option_dependencies(run, ctx, kwargs, OPTION_DEPENDENCIES)

    if ctx.invoked_subcommand is not None:
        # Pass parsed args on to subcommands.
        ctx.obj = kwargs
        return

    if kwargs["transport"] == "udp":
        runner = UDPRunner(kwargs, ctx)
    elif kwargs["transport"] == "matrix":
        runner = MatrixRunner(kwargs, ctx)
    else:
        # Shouldn't happen
        raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'")

    click.secho(runner.welcome_string, fg="green")
    click.secho(
        textwrap.dedent(
            '''\
            ---------------------------------------------------------------------------------------------------------------
            | This is an Alpha version of experimental open source software released under the MIT license. By using the  |
            | RIF Lumino Payments Protocol (the “Software”), you acknowledge that this is a test version of the Software  |
            | and assume the risk that the Software may contain errors and/or bugs. RIF Labs Limited (“RIF Labs”) makes   |
            | no guarantees or representations  whatsoever, including as to the suitability or use of the Software for    |
            | any  purpose or regarding its compliance with any applicable laws or regulations. By using the Software,    |
            | you acknowledge that you have read this disclosure agreement, understand its contents, and assume all risks |
            | related to the use of of the software; further, by answering yes below and accepting the terms of this      | 
            | Agreement, you release and discharge RIF Labs, its officers, employees, or affiliates from, waive  any      | 
            | claims you might have against RIF Labs, its officers, employees, or affiliates in connection with, and      | 
            | agree not to sue RIF Labs or any of its officers, employees, or affiliates for any direct or indirect       | 
            | liability arising from the use of this Software.                                                            |
            |                                                                                                             |  
            |                                                                                                             |  
            | Privacy Warning:                                                                                            |  
            |                                                                                                             |  
            | By using the RIF Lumino Payments Protocol, you acknowledge that your RSK address, channels, channel deposits| 
            | settlements, and the RSK address of your channel counterparty will be stored on the RSK blockchain—that is, |
            | on servers of RSK node operators—and therefore will be publicly available. The parties running nodes on the |
            | RIF Lumino network may also download and store this same or related information or data, and information or |
            | data stored on Lumino nodes and  network channels will be publicly visible, including on a RIF Lumino block |
            | explorer. By using the Software and by answering yes below, you acknowledge that information or data stored | 
            | on the Lumino network is extremely difficult to alter, remove, or delete; you further acknowledge that      |
            | information or data related to individual tokens transfers will be made available via  the Lumino Payments  |
            | Protocol to the recipient intermediating nodes of a specific transfer as well as to the Lumino server       |
            | operators.                                                                                                  |
            ---------------------------------------------------------------------------------------------------------------''',
        ),
        fg="yellow",
    )
    if not kwargs["accept_disclaimer"]:
        click.confirm(
            'Have you read and understood and do you accept the RIF Lumino Disclosure Agreement and Privacy Warning?',
            abort=True,
        )

    # TODO:
    # - Ask for confirmation to quit if there are any locked transfers that did
    # not timeout.
    try:
        app = runner.run()
        app.stop()
    except (ReplacementTransactionUnderpriced, TransactionAlreadyPending) as e:
        click.secho(
            "{}. Please make sure that this Raiden node is the "
            "only user of the selected account".format(str(e)),
            fg="red",
        )
        sys.exit(1)
示例#3
0
def run(ctx, **kwargs):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements

    if kwargs["config_file"]:
        apply_config_file(run, kwargs, ctx)

    validate_option_dependencies(run, ctx, kwargs, OPTION_DEPENDENCIES)

    if ctx.invoked_subcommand is not None:
        # Pass parsed args on to subcommands.
        ctx.obj = kwargs
        return

    if kwargs["transport"] == "udp":
        runner = UDPRunner(kwargs, ctx)
    elif kwargs["transport"] == "matrix":
        runner = MatrixRunner(kwargs, ctx)
    else:
        # Shouldn't happen
        raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'")

    click.secho(runner.welcome_string, fg="green")
    click.secho(
        textwrap.dedent("""\
            ----------------------------------------------------------------------
            | This is an Alpha version of experimental open source software      |
            | released as a test version under an MIT license and may contain    |
            | errors and/or bugs. No guarantee or representations whatsoever is  |
            | made regarding its suitability (or its use) for any purpose or     |
            | regarding its compliance with any applicable laws and regulations. |
            | Use of the software is at your own risk and discretion and by      |
            | using the software you acknowledge that you have read this         |
            | disclaimer, understand its contents, assume all risk related       |
            | thereto and hereby release, waive, discharge and covenant not to   |
            | sue Brainbot Labs Establishment or any officers, employees or      |
            | affiliates from and for any direct or indirect liability resulting |
            | from the use of the software as permissible by applicable laws and |
            | regulations.                                                       |
            |                                                                    |
            | Privacy Warning: Please be aware, that by using the Raiden Client, |
            | among others, your Ethereum address, channels, channel deposits,   |
            | settlements and the Ethereum address of your channel counterparty  |
            | will be stored on the Ethereum chain, i.e. on servers of Ethereum  |
            | node operators and ergo are to a certain extent publicly available.|
            | The same might also be stored on systems of parties running Raiden |
            | nodes connected to the same token network. Data present in the     |
            | Ethereum chain is very unlikely to be able to be changed, removed  |
            | or deleted from the public arena.                                  |
            |                                                                    |
            | Also be aware, that data on individual Raiden token transfers will |
            | be made available via the Matrix protocol to the recipient,        |
            | intermediating nodes of a specific transfer as well as to the      |
            | Matrix server operators.                                           |
            ----------------------------------------------------------------------"""
                        ),
        fg="yellow",
    )
    if not kwargs["accept_disclaimer"]:
        click.confirm(
            "\nHave you read, understood and hereby accept the above "
            "disclaimer and privacy warning?",
            abort=True,
        )

    # TODO:
    # - Ask for confirmation to quit if there are any locked transfers that did
    # not timeout.
    try:
        app = runner.run()
        app.stop()
    except (ReplacementTransactionUnderpriced, TransactionAlreadyPending) as e:
        click.secho(
            "{}. Please make sure that this Raiden node is the "
            "only user of the selected account".format(str(e)),
            fg="red",
        )
        sys.exit(1)
示例#4
0
def run(ctx: Context, **kwargs: Any) -> None:
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements

    flamegraph = kwargs.pop("flamegraph", None)
    switch_tracing = kwargs.pop("switch_tracing", None)
    profiler = None
    switch_monitor = None

    enable_gevent_monitoring_signal()

    if flamegraph:
        os.makedirs(flamegraph, exist_ok=True)

        now = datetime.datetime.now().isoformat()
        address = to_checksum_address(kwargs["address"])
        stack_path = os.path.join(flamegraph, f"{address}_{now}_stack.data")
        stack_stream = open(stack_path, "w")
        flame = FlameGraphCollector(stack_stream)
        profiler = TraceSampler(flame)

    if switch_tracing is True:
        switch_monitor = SwitchMonitoring()

    memory_logger = None
    log_memory_usage_interval = kwargs.pop("log_memory_usage_interval", 0)
    if log_memory_usage_interval > 0:
        memory_logger = MemoryLogger(log_memory_usage_interval)
        memory_logger.start()

    if kwargs.pop("version", False):
        click.echo(
            click.style("Hint: Use ", fg="green")
            + click.style(f"'{os.path.basename(sys.argv[0])} version'", fg="yellow")
            + click.style(" instead", fg="green")
        )
        ctx.invoke(version, short=True)
        return

    if kwargs["config_file"]:
        apply_config_file(run, kwargs, ctx)

    validate_option_dependencies(run, ctx, kwargs, OPTION_DEPENDENCIES)

    if ctx.invoked_subcommand is not None:
        # Pass parsed args on to subcommands.
        ctx.obj = kwargs
        return

    if kwargs["transport"] == "matrix":
        runner = MatrixRunner(kwargs, ctx)
    else:
        # Shouldn't happen
        raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'")

    click.secho(runner.welcome_string, fg="green")
    click.secho(
        textwrap.dedent(
            """\
            ----------------------------------------------------------------------
            | This is an Alpha version of experimental open source software      |
            | released as a test version under an MIT license and may contain    |
            | errors and/or bugs. No guarantee or representations whatsoever is  |
            | made regarding its suitability (or its use) for any purpose or     |
            | regarding its compliance with any applicable laws and regulations. |
            | Use of the software is at your own risk and discretion and by      |
            | using the software you acknowledge that you have read this         |
            | disclaimer, understand its contents, assume all risk related       |
            | thereto and hereby release, waive, discharge and covenant not to   |
            | sue Brainbot Labs Establishment or any officers, employees or      |
            | affiliates from and for any direct or indirect liability resulting |
            | from the use of the software as permissible by applicable laws and |
            | regulations.                                                       |
            |                                                                    |
            | Privacy Warning: Please be aware, that by using the Raiden Client, |
            | among others, your Ethereum address, channels, channel deposits,   |
            | settlements and the Ethereum address of your channel counterparty  |
            | will be stored on the Ethereum chain, i.e. on servers of Ethereum  |
            | node operators and ergo are to a certain extent publicly available.|
            | The same might also be stored on systems of parties running Raiden |
            | nodes connected to the same token network. Data present in the     |
            | Ethereum chain is very unlikely to be able to be changed, removed  |
            | or deleted from the public arena.                                  |
            |                                                                    |
            | Also be aware, that data on individual Raiden token transfers will |
            | be made available via the Matrix protocol to the recipient,        |
            | intermediating nodes of a specific transfer as well as to the      |
            | Matrix server operators.                                           |
            ----------------------------------------------------------------------"""
        ),
        fg="yellow",
    )
    if not kwargs["accept_disclaimer"]:
        click.confirm(
            "\nHave you read, understood and hereby accept the above "
            "disclaimer and privacy warning?",
            abort=True,
        )

    # TODO:
    # - Ask for confirmation to quit if there are any locked transfers that did
    # not timeout.
    try:
        runner.run()
    except (ReplacementTransactionUnderpriced, EthereumNonceTooLow) as ex:
        click.secho(
            f"{ex}. Please make sure that this Raiden node is the "
            f"only user of the selected account",
            fg="red",
        )
        sys.exit(ReturnCode.ETH_ACCOUNT_ERROR)
    except (ConnectionError, ConnectTimeout, RequestsConnectionError, ReadTimeoutError):
        print(COMMUNICATION_ERROR.format(kwargs["eth_rpc_endpoint"]))
        sys.exit(ReturnCode.GENERIC_COMMUNICATION_ERROR)
    except EthNodeInterfaceError as e:
        click.secho(str(e), fg="red")
        sys.exit(ReturnCode.ETH_INTERFACE_ERROR)
    except RaidenUnrecoverableError as ex:
        click.secho(f"FATAL: An un-recoverable error happen, Raiden is bailing {ex}", fg="red")
        write_stack_trace(ex)
        sys.exit(ReturnCode.FATAL)
    except APIServerPortInUseError as ex:
        click.secho(
            f"ERROR: API Address {ex} is in use. Use --api-address <host:port> "
            f"to specify a different port.",
            fg="red",
        )
        sys.exit(ReturnCode.PORT_ALREADY_IN_USE)
    except (KeystoreAuthenticationError, KeystoreFileNotFound) as e:
        click.secho(str(e), fg="red")
        sys.exit(ReturnCode.ETH_ACCOUNT_ERROR)
    except ConfigurationError as e:
        click.secho(str(e), fg="red")
        sys.exit(ReturnCode.CONFIGURATION_ERROR)
    except filelock.Timeout:
        name_or_id = ID_TO_NETWORKNAME.get(kwargs["network_id"], kwargs["network_id"])
        click.secho(
            f"FATAL: Another Raiden instance already running for account "
            f"{to_checksum_address(address)} on network id {name_or_id}",
            fg="red",
        )
        sys.exit(ReturnCode.CONFIGURATION_ERROR)
    except Exception as ex:
        write_stack_trace(ex)
        sys.exit(ReturnCode.FATAL)
    finally:
        # teardown order is important because of side-effects, both the
        # switch_monitor and profiler could use the tracing api, for the
        # teardown code to work correctly the teardown has to be done in the
        # reverse order of the initialization.
        if switch_monitor is not None:
            switch_monitor.stop()
        if memory_logger is not None:
            memory_logger.stop()
        if profiler is not None:
            profiler.stop()
示例#5
0
文件: cli.py 项目: onyb/raiden
def run(ctx, **kwargs):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements

    if kwargs['config_file']:
        apply_config_file(run, kwargs, ctx)

    if ctx.invoked_subcommand is not None:
        # Pass parsed args on to subcommands.
        ctx.obj = kwargs
        return

    runner = None
    if kwargs['transport'] == 'udp':
        runner = UDPRunner(kwargs, ctx)
    elif kwargs['transport'] == 'matrix':
        runner = MatrixRunner(kwargs, ctx)
    else:
        # Shouldn't happen
        raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'")

    click.secho(runner.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.                                      |
            |                                                                    |
            | Privacy notice: Please be aware, that by using the Raiden Client,  |
            | your Ethereum address, channels, channel deposits, settlements and |
            | the Ethereum address of your settlement counterparty will be       |
            | stored on the Ethereum chain, i.e. on servers of Ethereum node     |
            | operators and ergo made publicly available. The same will also be  |
            | stored on systems of parties running other Raiden nodes connected  |
            | to the same token network.                                         |
            |                                                                    |
            | Also be aware, that data on individual Raiden token transfers will |
            | be made available via the Matrix protocol to the recipient,        |
            | intermediating nodes of a specific transfer as well as to the      |
            | Matrix server operators.                                           |
            ----------------------------------------------------------------------''',
        ),
        fg='yellow',
    )
    if not kwargs['accept_disclaimer']:
        click.confirm('\nHave you read and acknowledged the above disclaimer?',
                      abort=True)

    # TODO:
    # - Ask for confirmation to quit if there are any locked transfers that did
    # not timeout.
    try:
        app = runner.run()
        app.stop()
    except (ReplacementTransactionUnderpriced, TransactionAlreadyPending) as e:
        click.secho(
            '{}. Please make sure that this Raiden node is the '
            'only user of the selected account'.format(str(e)),
            fg='red',
        )
        sys.exit(1)
示例#6
0
文件: cli.py 项目: sekmet/raiden
def run(ctx: Context, **kwargs: Any) -> None:
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements

    if kwargs["config_file"]:
        apply_config_file(run, kwargs, ctx)

    configure_logging(
        kwargs["log_config"],
        log_json=kwargs["log_json"],
        log_file=kwargs["log_file"],
        disable_debug_logfile=kwargs["disable_debug_logfile"],
        debug_log_file_path=kwargs["debug_logfile_path"],
    )

    flamegraph = kwargs.pop("flamegraph", None)
    switch_tracing = kwargs.pop("switch_tracing", None)
    profiler = None
    switch_monitor = None

    enable_gevent_monitoring_signal()

    if flamegraph:  # pragma: no cover
        windows_not_supported("flame graph")
        from raiden.utils.profiling.sampler import FlameGraphCollector, TraceSampler

        os.makedirs(flamegraph, exist_ok=True)

        now = datetime.datetime.now().isoformat()
        address = to_checksum_address(kwargs["address"])
        stack_path = os.path.join(flamegraph, f"{address}_{now}_stack.data")
        stack_stream = open(stack_path, "w")
        flame = FlameGraphCollector(stack_stream)
        profiler = TraceSampler(flame)

    if switch_tracing is True:  # pragma: no cover
        windows_not_supported("switch tracing")
        from raiden.utils.profiling.greenlets import SwitchMonitoring

        switch_monitor = SwitchMonitoring()

    if kwargs["environment_type"] == Environment.DEVELOPMENT:
        IDLE.enable()

    memory_logger = None
    log_memory_usage_interval = kwargs.pop("log_memory_usage_interval", 0)
    if log_memory_usage_interval > 0:  # pragma: no cover
        windows_not_supported("memory usage logging")
        from raiden.utils.profiling.memory import MemoryLogger

        memory_logger = MemoryLogger(log_memory_usage_interval)
        memory_logger.start()

    if ctx.invoked_subcommand is not None:
        # Pass parsed args on to subcommands.
        ctx.obj = kwargs
        return

    raiden_version = get_system_spec()["raiden"]
    click.secho(f"Welcome to Raiden, version {raiden_version}!", fg="green")

    click.secho(
        textwrap.dedent("""\
            +------------------------------------------------------------------------+
            | This is a Beta version of experimental open source software released   |
            | as a test version under an MIT license and may contain errors and/or   |
            | bugs. No guarantee or representation whatsoever is made regarding its  |
            | suitability (or its use) for any purpose or regarding its compliance   |
            | with any applicable laws and regulations. Use of the software is at    |
            | your own risk and discretion and by using the software you warrant and |
            | represent that you have read this disclaimer, understand its contents, |
            | assume all risk related thereto and hereby release, waive, discharge   |
            | and covenant not to hold liable Brainbot Labs Establishment or any of  |
            | its officers, employees or affiliates from and for any direct or       |
            | indirect damage resulting from the software or the use thereof.        |
            | Such to the extent as permissible by applicable laws and regulations.  |
            |                                                                        |
            | Privacy warning: Please be aware, that by using the Raiden Client,     |
            | among others your Ethereum address, channels, channel deposits,        |
            | settlements and the Ethereum address of your channel counterparty will |
            | be stored on the Ethereum chain, i.e. on servers of Ethereum node      |
            | operators and ergo are to a certain extent publicly available. The     |
            | same might also be stored on systems of parties running Raiden nodes   |
            | connected to the same token network. Data present in the Ethereum      |
            | chain is very unlikely to be able to be changed, removed or deleted    |
            | from the public arena.                                                 |
            |                                                                        |
            | Also be aware, that data on individual Raiden token transfers will be  |
            | made available via the Matrix protocol to the recipient,               |
            | intermediating nodes of a specific transfer as well as to the Matrix   |
            | server operators, see Raiden Transport Specification.                  |
            +------------------------------------------------------------------------+"""
                        ),
        fg="yellow",
    )
    if not kwargs["accept_disclaimer"]:
        click.confirm(
            "\nHave you read, understood and hereby accept the above "
            "disclaimer and privacy warning?",
            abort=True,
        )

    # Name used in the exception handlers, make sure the kwargs contains the
    # key with the correct name by always running it.
    name_or_id = ID_TO_CHAINNAME.get(kwargs["chain_id"], kwargs["chain_id"])

    # TODO:
    # - Ask for confirmation to quit if there are any locked transfers that did
    # not timeout.
    try:
        run_services(kwargs)
    except KeyboardInterrupt:
        # The user requested a shutdown. Assume that if the exception
        # propagated all the way to the top-level everything was shutdown
        # properly.
        #
        # Notes about edge cases:
        # - It could happen the exception was handled somewhere else in the
        # code, and did not reach the top-level, ideally that should result in
        # an exit with a non-zero code, but currently there is not way to
        # detect that.
        # - Just because the exception reached main, it doesn't mean that all
        # services were properly cleaned up. Ideally at this stage we should
        # run extra code to verify the state of the main services, and if any
        # of the is not properly shutdown exit with a non-zero code.
        pass
    except (ReplacementTransactionUnderpriced, EthereumNonceTooLow) as ex:
        click.secho(
            f"{ex}. Please make sure that this Raiden node is the "
            f"only user of the selected account",
            fg="red",
        )
        sys.exit(ReturnCode.ETH_ACCOUNT_ERROR)
    except (ConnectionError, ConnectTimeout, RequestsConnectionError,
            ReadTimeoutError):
        print(COMMUNICATION_ERROR.format(kwargs["eth_rpc_endpoint"]))
        sys.exit(ReturnCode.GENERIC_COMMUNICATION_ERROR)
    except EthNodeInterfaceError as e:
        click.secho(str(e), fg="red")
        sys.exit(ReturnCode.ETH_INTERFACE_ERROR)
    except RaidenUnrecoverableError as ex:
        write_stack_trace(ex)
        sys.exit(ReturnCode.FATAL)
    except APIServerPortInUseError as ex:
        click.secho(
            f"ERROR: API Address {ex} is in use. Use --api-address <host:port> "
            f"to specify a different port.",
            fg="red",
        )
        sys.exit(ReturnCode.PORT_ALREADY_IN_USE)
    except (KeystoreAuthenticationError, KeystoreFileNotFound) as e:
        click.secho(str(e), fg="red")
        sys.exit(ReturnCode.ETH_ACCOUNT_ERROR)
    except ConfigurationError as e:
        click.secho(str(e), fg="red")
        sys.exit(ReturnCode.RAIDEN_CONFIGURATION_ERROR)
    except ContractCodeMismatch as e:
        click.secho(
            f"{e}. This may happen if Raiden is configured to use an "
            f"unsupported version of the contracts.",
            fg="red",
        )
        sys.exit(ReturnCode.SMART_CONTRACTS_CONFIGURATION_ERROR)
    except AddressWithoutCode as e:
        click.secho(
            f"{e}. This may happen if an external ERC20 smart contract "
            f"selfdestructed, or if the configured address is misconfigured, make "
            f"sure the used address is not a normal account but a smart contract, "
            f"and that it is deployed to {name_or_id}.",
            fg="red",
        )
        sys.exit(ReturnCode.SMART_CONTRACTS_CONFIGURATION_ERROR)
    except filelock.Timeout:
        click.secho(
            f"FATAL: Another Raiden instance already running for account "
            f"{to_checksum_address(kwargs['address'])} on network id {name_or_id}",
            fg="red",
        )
        sys.exit(ReturnCode.RAIDEN_CONFIGURATION_ERROR)
    except Exception as ex:
        write_stack_trace(ex)
        sys.exit(ReturnCode.FATAL)
    finally:  # pragma: no cover
        # teardown order is important because of side-effects, both the
        # switch_monitor and profiler could use the tracing api, for the
        # teardown code to work correctly the teardown has to be done in the
        # reverse order of the initialization.
        if switch_monitor is not None:
            switch_monitor.stop()
        if memory_logger is not None:
            memory_logger.stop()
        if profiler is not None:
            profiler.stop()
示例#7
0
文件: cli.py 项目: hackaugusto/raiden
def run(ctx, **kwargs):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements

    if kwargs['config_file']:
        apply_config_file(run, kwargs, ctx)

    if ctx.invoked_subcommand is not None:
        # Pass parsed args on to subcommands.
        ctx.obj = kwargs
        return

    runner = None
    if kwargs['transport'] == 'udp':
        runner = UDPRunner(kwargs, ctx)
    elif kwargs['transport'] == 'matrix':
        runner = MatrixRunner(kwargs, ctx)
    else:
        # Shouldn't happen
        raise RuntimeError(f"Invalid transport type '{kwargs['transport']}'")

    click.secho(runner.welcome_string, fg='green')
    click.secho(
        textwrap.dedent(
            '''\
            ----------------------------------------------------------------------
            | This is an Alpha version of experimental open source software      |
            | released as a test version under an MIT license and may contain    |
            | errors and/or bugs. No guarantee or representations whatsoever is  |
            | made regarding its suitability (or its use) for any purpose or     |
            | regarding its compliance with any applicable laws and regulations. |
            | Use of the software is at your own risk and discretion and by      |
            | using the software you acknowledge that you have read this         |
            | disclaimer, understand its contents, assume all risk related       |
            | thereto and hereby release, waive, discharge and covenant not to   |
            | sue Brainbot Labs Establishment or any officers, employees or      |
            | affiliates from and for any direct or indirect liability resulting |
            | from the use of the software as permissible by applicable laws and |
            | regulations.                                                       |
            |                                                                    |
            | Privacy Warning: Please be aware, that by using the Raiden Client, |
            | among others, your Ethereum address, channels, channel deposits,   |
            | settlements and the Ethereum address of your channel counterparty  |
            | will be stored on the Ethereum chain, i.e. on servers of Ethereum  |
            | node operators and ergo are to a certain extent publicly available.|
            | The same might also be stored on systems of parties running Raiden |
            | nodes connected to the same token network. Data present in the     |
            | Ethereum chain is very unlikely to be able to be changed, removed  |
            | or deleted from the public arena.                                  |
            |                                                                    |
            | Also be aware, that data on individual Raiden token transfers will |
            | be made available via the Matrix protocol to the recipient,        |
            | intermediating nodes of a specific transfer as well as to the      |
            | Matrix server operators.                                           |
            ----------------------------------------------------------------------''',
        ),
        fg='yellow',
    )
    if not kwargs['accept_disclaimer']:
        click.confirm(
            '\nHave you read, understood and hereby accept the above '
            'disclaimer and privacy warning?',
            abort=True,
        )

    # TODO:
    # - Ask for confirmation to quit if there are any locked transfers that did
    # not timeout.
    try:
        app = runner.run()
        app.stop()
    except (ReplacementTransactionUnderpriced, TransactionAlreadyPending) as e:
        click.secho(
            '{}. Please make sure that this Raiden node is the '
            'only user of the selected account'.format(str(e)),
            fg='red',
        )
        sys.exit(1)