예제 #1
0
파일: cli.py 프로젝트: sufimerchant/raiden
    def _run_smoketest():
        print_step('Starting Raiden')

        config = deepcopy(App.DEFAULT_CONFIG)
        if args.get('extra_config', dict()):
            merge_dict(config, args['extra_config'])
            del args['extra_config']
        args['config'] = config

        # invoke the raiden app
        app = run_app(**args)

        raiden_api = RaidenAPI(app.raiden)
        rest_api = RestAPI(raiden_api)
        api_server = APIServer(rest_api)
        (api_host, api_port) = split_endpoint(args['api_address'])
        api_server.start(api_host, api_port)

        raiden_api.channel_open(
            registry_address=contract_addresses[
                CONTRACT_TOKEN_NETWORK_REGISTRY],
            token_address=to_canonical_address(token.contract.address),
            partner_address=to_canonical_address(TEST_PARTNER_ADDRESS),
        )
        raiden_api.set_total_channel_deposit(
            contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY],
            to_canonical_address(token.contract.address),
            to_canonical_address(TEST_PARTNER_ADDRESS),
            TEST_DEPOSIT_AMOUNT,
        )
        token_addresses = [to_checksum_address(token.contract.address)]

        success = False
        try:
            print_step('Running smoketest')
            error = run_smoketests(
                app.raiden,
                args['transport'],
                token_addresses,
                contract_addresses[CONTRACT_ENDPOINT_REGISTRY],
                debug=debug,
            )
            if error is not None:
                append_report('Smoketest assertion error', error)
            else:
                success = True
        finally:
            app.stop()
            node = ethereum[0]
            node.send_signal(2)
            err, out = node.communicate()

            append_report('Ethereum stdout', out)
            append_report('Ethereum stderr', err)
        if success:
            print_step(f'Smoketest successful')
        else:
            print_step(f'Smoketest had errors', error=True)
        return success
예제 #2
0
def run_app(
    address,
    keystore_path,
    gas_price,
    eth_rpc_endpoint,
    registry_contract_address,
    secret_registry_contract_address,
    discovery_contract_address,
    listen_address,
    mapped_socket,
    max_unresponsive_time,
    api_address,
    rpc,
    sync_check,
    console,
    password_file,
    web_ui,
    datadir,
    transport,
    matrix_server,
    network_id,
    extra_config=None,
    **kwargs,
):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    from raiden.app import App

    if transport == 'udp' and not mapped_socket:
        raise RuntimeError('Missing socket')

    address_hex = to_normalized_address(address) if address else None
    address_hex, privatekey_bin = prompt_account(address_hex, keystore_path,
                                                 password_file)
    address = to_canonical_address(address_hex)

    (listen_host, listen_port) = split_endpoint(listen_address)
    (api_host, api_port) = split_endpoint(api_address)

    if datadir is None:
        datadir = os.path.join(os.path.expanduser('~'), '.raiden')

    config = deepcopy(App.DEFAULT_CONFIG)
    if extra_config:
        merge_dict(config, extra_config)

    config['transport']['udp']['host'] = listen_host
    config['transport']['udp']['port'] = listen_port
    config['console'] = console
    config['rpc'] = rpc
    config['web_ui'] = rpc and web_ui
    config['api_host'] = api_host
    config['api_port'] = api_port
    if mapped_socket:
        config['socket'] = mapped_socket.socket
        config['transport']['udp']['external_ip'] = mapped_socket.external_ip
        config['transport']['udp'][
            'external_port'] = mapped_socket.external_port
    config['transport_type'] = transport
    config['transport']['matrix']['server'] = matrix_server
    config['transport']['udp'][
        'nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES
    timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES
    config['transport']['udp']['nat_keepalive_timeout'] = timeout

    privatekey_hex = hexlify(privatekey_bin)
    config['privatekey_hex'] = privatekey_hex

    parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint)
    if not parsed_eth_rpc_endpoint.scheme:
        eth_rpc_endpoint = f'http://{eth_rpc_endpoint}'

    web3 = Web3(HTTPProvider(eth_rpc_endpoint))

    try:
        node_version = web3.version.node  # pylint: disable=no-member
    except ConnectTimeout:
        raise EthNodeCommunicationError(
            "Couldn't connect to the ethereum node")

    supported, _ = is_supported_client(node_version)
    if not supported:
        print(
            'You need a Byzantium enabled ethereum node. Parity >= 1.7.6 or Geth >= 1.7.2'
        )
        sys.exit(1)

    rpc_client = JSONRPCClient(
        web3,
        privatekey_bin,
        gasprice=gas_price,
    )

    blockchain_service = BlockChainService(privatekey_bin, rpc_client)

    net_id = blockchain_service.network_id
    if net_id != network_id:
        if network_id in constants.ID_TO_NETWORKNAME and net_id in constants.ID_TO_NETWORKNAME:
            print((
                "The chosen ethereum network '{}' differs from the ethereum client '{}'. "
                'Please update your settings.').format(
                    constants.ID_TO_NETWORKNAME[network_id],
                    constants.ID_TO_NETWORKNAME[net_id]))
        else:
            print((
                "The chosen ethereum network id '{}' differs from the ethereum client '{}'. "
                'Please update your settings.').format(network_id, net_id))
        sys.exit(1)

    config['chain_id'] = network_id

    if sync_check:
        check_synced(blockchain_service)

    database_path = os.path.join(datadir, 'netid_%s' % net_id, address_hex[:8],
                                 'log.db')
    config['database_path'] = database_path
    print(
        '\nYou are connected to the \'{}\' network and the DB path is: {}'.
        format(
            constants.ID_TO_NETWORKNAME.get(net_id) or net_id,
            database_path,
        ), )

    contract_addresses_given = (registry_contract_address is not None and
                                secret_registry_contract_address is not None
                                and discovery_contract_address is not None)
    contract_addresses_known = net_id in constants.ID_TO_NETWORK_CONFIG

    if not contract_addresses_given and not contract_addresses_known:
        print((
            "There are known contract addresses for network id '{}'. Please provide "
            'them in the command line or the configuration file.'
        ).format(net_id))
        sys.exit(1)

    contract_addresses = constants.ID_TO_NETWORK_CONFIG.get(net_id, dict())

    try:
        token_network_registry = blockchain_service.token_network_registry(
            registry_contract_address
            or contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY], )
    except ContractVersionMismatch:
        handle_contract_version_mismatch('token network registry',
                                         registry_contract_address)
    except AddressWithoutCode:
        handle_contract_no_code('token network registry',
                                registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address('token network registry',
                                      registry_contract_address)

    try:
        secret_registry = blockchain_service.secret_registry(
            secret_registry_contract_address
            or contract_addresses[CONTRACT_SECRET_REGISTRY], )
    except ContractVersionMismatch:
        handle_contract_version_mismatch('secret registry',
                                         secret_registry_contract_address)
    except AddressWithoutCode:
        handle_contract_no_code('secret registry',
                                secret_registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address('secret registry',
                                      secret_registry_contract_address)

    discovery = None
    if transport == 'udp':
        check_discovery_registration_gas(blockchain_service, address)
        try:
            dicovery_proxy = blockchain_service.discovery(
                discovery_contract_address
                or contract_addresses[CONTRACT_ENDPOINT_REGISTRY], )
            discovery = ContractDiscovery(
                blockchain_service.node_address,
                dicovery_proxy,
            )
        except ContractVersionMismatch:
            handle_contract_version_mismatch('discovery',
                                             discovery_contract_address)
        except AddressWithoutCode:
            handle_contract_no_code('discovery', discovery_contract_address)
        except AddressWrongContract:
            handle_contract_wrong_address('discovery',
                                          discovery_contract_address)

        throttle_policy = TokenBucket(
            config['transport']['udp']['throttle_capacity'],
            config['transport']['udp']['throttle_fill_rate'],
        )

        transport = UDPTransport(
            discovery,
            mapped_socket.socket,
            throttle_policy,
            config['transport']['udp'],
        )
    elif transport == 'matrix':
        try:
            transport = MatrixTransport(config['transport']['matrix'])
        except RaidenError as ex:
            click.secho(f'FATAL: {ex}', fg='red')
            sys.exit(1)
    else:
        raise RuntimeError(f'Unknown transport type "{transport}" given')

    try:
        chain_config = constants.ID_TO_NETWORK_CONFIG.get(net_id, {})
        start_block = chain_config.get(constants.START_QUERY_BLOCK_KEY, 0)
        raiden_app = App(
            config=config,
            chain=blockchain_service,
            query_start_block=start_block,
            default_registry=token_network_registry,
            default_secret_registry=secret_registry,
            transport=transport,
            discovery=discovery,
        )
    except RaidenError as e:
        click.secho(f'FATAL: {e}', fg='red')
        sys.exit(1)

    try:
        raiden_app.start()
    except filelock.Timeout:
        name_or_id = constants.ID_TO_NETWORKNAME.get(network_id, network_id)
        print(
            f'FATAL: Another Raiden instance already running for account {address_hex} on '
            f'network id {name_or_id}', )
        sys.exit(1)

    return raiden_app
예제 #3
0
    def _start_services(self):
        from raiden.ui.console import Console
        from raiden.api.python import RaidenAPI

        config = deepcopy(App.DEFAULT_CONFIG)
        if self._options.get('extra_config', dict()):
            merge_dict(config, self._options['extra_config'])
            del self._options['extra_config']
        self._options['config'] = config

        if self._options['showconfig']:
            print('Configuration Dump:')
            dump_config(config)
            dump_cmd_options(self._options)
            dump_module('settings', settings)
            dump_module('constants', constants)

        # this catches exceptions raised when waiting for the stalecheck to complete
        try:
            app_ = run_app(**self._options)
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except EthNodeInterfaceError as e:
            click.secho(str(e), fg='red')
            sys.exit(1)

        tasks = [app_.raiden]  # RaidenService takes care of Transport and AlarmTask

        domain_list = []
        if self._options['rpccorsdomain']:
            if ',' in self._options['rpccorsdomain']:
                for domain in self._options['rpccorsdomain'].split(','):
                    domain_list.append(str(domain))
            else:
                domain_list.append(str(self._options['rpccorsdomain']))

        self._raiden_api = RaidenAPI(app_.raiden)

        if self._options['rpc']:
            rest_api = RestAPI(self._raiden_api)
            api_server = APIServer(
                rest_api,
                cors_domain_list=domain_list,
                web_ui=self._options['web_ui'],
                eth_rpc_endpoint=self._options['eth_rpc_endpoint'],
            )
            (api_host, api_port) = split_endpoint(self._options['api_address'])

            try:
                api_server.start(api_host, api_port)
            except APIServerPortInUseError:
                click.secho(
                    f'ERROR: API Address {api_host}:{api_port} is in use. '
                    f'Use --api-address <host:port> to specify a different port.',
                    fg='red',
                )
                sys.exit(1)

            print(
                'The Raiden API RPC server is now running at http://{}:{}/.\n\n'
                'See the Raiden documentation for all available endpoints at\n'
                'http://raiden-network.readthedocs.io/en/stable/rest_api.html'.format(
                    api_host,
                    api_port,
                ),
            )
            tasks.append(api_server)

        if self._options['console']:
            console = Console(app_)
            console.start()
            tasks.append(console)

        # spawn a greenlet to handle the version checking
        version = get_system_spec()['raiden']
        if version is not None:
            tasks.append(gevent.spawn(check_version, version))

        # spawn a greenlet to handle the gas reserve check
        tasks.append(gevent.spawn(check_gas_reserve, app_.raiden))

        self._startup_hook()

        # wait for interrupt
        event = AsyncResult()

        def sig_set(sig=None, _frame=None):
            event.set(sig)

        gevent.signal(signal.SIGQUIT, sig_set)
        gevent.signal(signal.SIGTERM, sig_set)
        gevent.signal(signal.SIGINT, sig_set)

        # quit if any task exits, successfully or not
        for task in tasks:
            task.link(event)

        try:
            event.get()
            print('Signal received. Shutting down ...')
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RaidenError as ex:
            click.secho(f'FATAL: {ex}', fg='red')
        except Exception as ex:
            with NamedTemporaryFile(
                'w',
                prefix=f'raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}',
                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',
                )
        finally:
            self._shutdown_hook()

            def stop_task(task):
                try:
                    if isinstance(task, Runnable):
                        task.stop()
                    else:
                        task.kill()
                finally:
                    task.get()  # re-raise

            gevent.joinall(
                [gevent.spawn(stop_task, task) for task in tasks],
                app_.config.get('shutdown_timeout', settings.DEFAULT_SHUTDOWN_TIMEOUT),
                raise_error=True,
            )

        return app_
예제 #4
0
def create_apps(
    chain_id: ChainID,
    contracts_path: str,
    blockchain_services: BlockchainServices,
    token_network_registry_address: TokenNetworkRegistryAddress,
    one_to_n_address: Optional[Address],
    secret_registry_address: SecretRegistryAddress,
    service_registry_address: Optional[Address],
    user_deposit_address: Address,
    monitoring_service_contract_address: Address,
    reveal_timeout: BlockTimeout,
    settle_timeout: BlockTimeout,
    database_basedir: str,
    retry_interval: float,
    retries_before_backoff: int,
    environment_type: Environment,
    unrecoverable_error_should_crash: bool,
    local_matrix_url: Optional[ParsedURL],
    broadcast_rooms: List[str],
    routing_mode: RoutingMode,
    blockchain_query_interval: float,
    resolver_ports: List[Optional[int]],
) -> List[App]:
    """ Create the apps."""
    # pylint: disable=too-many-locals
    services = blockchain_services

    apps = []
    for idx, proxy_manager in enumerate(services):
        database_path = database_from_privatekey(base_dir=database_basedir,
                                                 app_number=idx)
        assert len(resolver_ports) > idx
        resolver_port = resolver_ports[idx]

        config = {
            "chain_id": chain_id,
            "environment_type": environment_type,
            "unrecoverable_error_should_crash":
            unrecoverable_error_should_crash,
            "reveal_timeout": reveal_timeout,
            "settle_timeout": settle_timeout,
            "contracts_path": contracts_path,
            "database_path": database_path,
            "blockchain": {
                "confirmation_blocks": DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
                "query_interval": blockchain_query_interval,
            },
            "transport": {},
            "rpc": True,
            "console": False,
            "mediation_fees": MediationFeeConfig(),
        }

        if local_matrix_url is not None:
            merge_dict(
                config,
                {
                    "transport_type": "matrix",
                    "transport": {
                        "matrix": {
                            "broadcast_rooms": broadcast_rooms,
                            "retries_before_backoff": retries_before_backoff,
                            "retry_interval": retry_interval,
                            "server": local_matrix_url,
                            "server_name": local_matrix_url.netloc,
                            "available_servers": [],
                        }
                    },
                },
            )

        if resolver_port is not None:
            merge_dict(config, {
                "resolver_endpoint":
                "http://localhost:" + str(resolver_port)
            })

        config_copy = deepcopy(App.DEFAULT_CONFIG)
        config_copy.update(config)

        registry = proxy_manager.token_network_registry(
            token_network_registry_address)
        secret_registry = proxy_manager.secret_registry(
            secret_registry_address)

        service_registry = None
        if service_registry_address:
            service_registry = proxy_manager.service_registry(
                service_registry_address)

        user_deposit = None
        if user_deposit_address:
            user_deposit = proxy_manager.user_deposit(user_deposit_address)

        transport = MatrixTransport(config["transport"]["matrix"])

        raiden_event_handler = RaidenEventHandler()
        hold_handler = HoldRaidenEventHandler(raiden_event_handler)
        message_handler = WaitForMessage()

        app = App(
            config=config_copy,
            rpc_client=proxy_manager.client,
            proxy_manager=proxy_manager,
            query_start_block=BlockNumber(0),
            default_registry=registry,
            default_one_to_n_address=one_to_n_address,
            default_secret_registry=secret_registry,
            default_service_registry=service_registry,
            default_msc_address=monitoring_service_contract_address,
            transport=transport,
            raiden_event_handler=hold_handler,
            message_handler=message_handler,
            user_deposit=user_deposit,
            routing_mode=routing_mode,
        )
        apps.append(app)

    return apps
예제 #5
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
예제 #6
0
    def _start_services(self):
        from raiden.api.python import RaidenAPI

        config = deepcopy(App.DEFAULT_CONFIG)
        if self._options.get("extra_config", dict()):
            merge_dict(config, self._options["extra_config"])
            del self._options["extra_config"]
        self._options["config"] = config

        if self._options["showconfig"]:
            print("Configuration Dump:")
            dump_config(config)
            dump_cmd_options(self._options)
            dump_module("settings", settings)
            dump_module("constants", constants)

        # this catches exceptions raised when waiting for the stalecheck to complete
        try:
            app_ = run_app(**self._options)
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RuntimeError as e:
            click.secho(str(e), fg="red")
            sys.exit(1)
        except EthNodeInterfaceError as e:
            click.secho(str(e), fg="red")
            sys.exit(1)

        tasks = [app_.raiden
                 ]  # RaidenService takes care of Transport and AlarmTask

        domain_list = ['http://localhost:*/*']

        self._raiden_api = RaidenAPI(app_.raiden)

        if self._options['discoverable']:
            node_address = to_checksum_address(self._raiden_api.address)
            rns_domain = None
            if self._options['rnsdomain']:
                rns_domain = self._options['rnsdomain']
                try:
                    rns_resolved_address = self._raiden_api.raiden.chain.get_address_from_rns(
                        self._options['rnsdomain'])
                    if rns_resolved_address == RNS_ADDRESS_ZERO:
                        click.secho(
                            'Cannot register into the Lumino Explorer. Your RNS domain is not registered'
                        )
                        sys.exit(1)
                    elif rns_resolved_address != node_address:
                        click.secho(
                            'Cannot register into the Lumino Explorer. '
                            'Your RNS domain does not match with the node RSK address. '
                            'The RNS domain is owned by ' +
                            rns_resolved_address)
                        sys.exit(1)
                except BadFunctionCallOutput:
                    click.secho(
                        "Unable to interact with RNS Public Resolver. Your node will be registered without RNS domain."
                    )
            register(self._options["explorer_endpoint"], node_address,
                     rns_domain)
        else:
            if self._options['rnsdomain']:
                try:
                    self._raiden_api.raiden.chain.get_address_from_rns(
                        self._options['rnsdomain'])

                except BadFunctionCallOutput:
                    click.secho(
                        "Unable to interact with RNS Public Resolver. "
                        "Please check youre interacting with the correct contract."
                    )
                    sys.exit(1)

        if self._options["rpc"]:
            rest_api = RestAPI(self._raiden_api)
            (api_host, api_port) = split_endpoint(self._options["api_address"])
            api_server = APIServer(
                rest_api,
                config={
                    'host': api_host,
                    'port': api_port,
                    'rnsdomain': self._options['rnsdomain'],
                    'rskendpoint': self._options['eth_rpc_endpoint'],
                    'explorerendpoint': self._options["explorer_endpoint"],
                    'discoverable': self._options['discoverable']
                },
                cors_domain_list=domain_list,
                web_ui=self._options["web_ui"],
                eth_rpc_endpoint=self._options["eth_rpc_endpoint"],
                hub_mode=self._options["hub_mode"],
            )

            try:
                api_server.start()
            except APIServerPortInUseError:
                click.secho(
                    f"ERROR: API Address {api_host}:{api_port} is in use. "
                    f"Use --api-address <host:port> to specify a different port.",
                    fg="red",
                )
                sys.exit(1)

            print(
                'The Lumino API RPC server is now running at http://{}:{}/.\n\n'
                .format(
                    api_host,
                    api_port,
                ), )
            tasks.append(api_server)

        if self._options["console"]:
            from raiden.ui.console import Console

            console = Console(app_)
            console.start()
            tasks.append(console)

        config_path = os.path.join(ROOT_DIR, 'config.json')

        with open(config_path) as json_data_file:
            config_data = json.load(json_data_file)

        project_data = config_data['project']
        project_version = project_data['version']

        # spawn a greenlet to handle the version checking
        tasks.append(gevent.spawn(check_version, project_version))

        # spawn a greenlet to handle the gas reserve check
        tasks.append(gevent.spawn(check_gas_reserve, app_.raiden))
        # spawn a greenlet to handle the periodic check for the network id
        tasks.append(
            gevent.spawn(check_network_id, app_.raiden.chain.network_id,
                         app_.raiden.chain.client.web3))

        spawn_user_deposit_task = app_.user_deposit and (
            self._options["pathfinding_service_address"]
            or self._options["enable_monitoring"])
        if spawn_user_deposit_task:
            # spawn a greenlet to handle RDN deposits check
            tasks.append(
                gevent.spawn(check_rdn_deposits, app_.raiden,
                             app_.user_deposit))

        # spawn a greenlet to handle the functions

        self._startup_hook()

        # wait for interrupt
        event = AsyncResult()

        def sig_set(sig=None, _frame=None):
            event.set(sig)

        gevent.signal(signal.SIGQUIT, sig_set)
        gevent.signal(signal.SIGTERM, sig_set)
        gevent.signal(signal.SIGINT, sig_set)

        # quit if any task exits, successfully or not
        for task in tasks:
            task.link(event)

        try:
            event.get()
            print("Signal received. Shutting down ...")
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RaidenError as ex:
            click.secho(f"FATAL: {ex}", fg="red")
        except Exception as ex:
            file = NamedTemporaryFile(
                "w",
                prefix=f"raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}",
                suffix=".txt",
                delete=False,
            )
            with file as traceback_file:
                traceback.print_exc(file=traceback_file)
                click.secho(
                    f"FATAL: An unexpected exception occured. "
                    f"A traceback has been written to {traceback_file.name}\n"
                    f"{ex}",
                    fg="red",
                )
        finally:
            self._shutdown_hook()

            def stop_task(task):
                try:
                    if isinstance(task, Runnable):
                        task.stop()
                    else:
                        task.kill()
                finally:
                    task.get()  # re-raise

            gevent.joinall(
                [gevent.spawn(stop_task, task) for task in tasks],
                app_.config.get("shutdown_timeout",
                                settings.DEFAULT_SHUTDOWN_TIMEOUT),
                raise_error=True,
            )

        return app_
예제 #7
0
def create_apps(
    chain_id,
    blockchain_services,
    endpoint_discovery_services,
    token_network_registry_address,
    secret_registry_address,
    raiden_udp_ports,
    reveal_timeout,
    settle_timeout,
    database_paths,
    retry_interval,
    retries_before_backoff,
    throttle_capacity,
    throttle_fill_rate,
    nat_invitation_timeout,
    nat_keepalive_retries,
    nat_keepalive_timeout,
    local_matrix_url=None,
):
    """ Create the apps."""
    # pylint: disable=too-many-locals
    services = zip(blockchain_services, endpoint_discovery_services)

    apps = []
    for idx, (blockchain, discovery) in enumerate(services):
        port = raiden_udp_ports[idx]
        private_key = blockchain.private_key

        host = '127.0.0.1'

        config = {
            'chain_id': chain_id,
            'privatekey_hex': hexlify(private_key),
            'reveal_timeout': reveal_timeout,
            'settle_timeout': settle_timeout,
            'database_path': database_paths[idx],
            'transport': {
                'udp': {
                    'external_ip': host,
                    'external_port': port,
                    'host': host,
                    'nat_invitation_timeout': nat_invitation_timeout,
                    'nat_keepalive_retries': nat_keepalive_retries,
                    'nat_keepalive_timeout': nat_keepalive_timeout,
                    'port': port,
                    'retries_before_backoff': retries_before_backoff,
                    'retry_interval': retry_interval,
                    'throttle_capacity': throttle_capacity,
                    'throttle_fill_rate': throttle_fill_rate,
                },
            },
            'rpc': True,
            'console': False,
        }

        use_matrix = local_matrix_url is not None
        if use_matrix:
            merge_dict(
                config,
                {
                    'transport_type': 'matrix',
                    'transport': {
                        'matrix': {
                            'discovery_room': {
                                'alias_fragment': 'discovery',
                                'server': 'matrix.local.raiden',
                            },
                            'retries_before_backoff': retries_before_backoff,
                            'retry_interval': retry_interval,
                            'server': local_matrix_url,
                            'server_name': 'matrix.local.raiden',
                        },
                    },
                },
            )
            if 'TRAVIS' in environ:
                config['transport']['matrix']['login_retry_wait'] = 1.5

        config_copy = App.DEFAULT_CONFIG.copy()
        config_copy.update(config)

        registry = blockchain.token_network_registry(
            token_network_registry_address)
        secret_registry = blockchain.secret_registry(secret_registry_address)

        if use_matrix:
            transport = MatrixTransport(config['transport']['matrix'])
        else:
            throttle_policy = TokenBucket(
                config['transport']['udp']['throttle_capacity'],
                config['transport']['udp']['throttle_fill_rate'],
            )

            transport = UDPTransport(
                discovery,
                server._udp_socket((host, port)),  # pylint: disable=protected-access
                throttle_policy,
                config['transport']['udp'],
            )

        app = App(
            config=config_copy,
            chain=blockchain,
            query_start_block=0,
            default_registry=registry,
            default_secret_registry=secret_registry,
            transport=transport,
            discovery=discovery,
        )
        apps.append(app)

    return apps
예제 #8
0
def app(
    address,
    keystore_path,
    gas_price,
    eth_rpc_endpoint,
    registry_contract_address,
    secret_registry_contract_address,
    discovery_contract_address,
    listen_address,
    rpccorsdomain,
    mapped_socket,
    log_config,
    log_file,
    log_json,
    max_unresponsive_time,
    send_ping_time,
    api_address,
    rpc,
    sync_check,
    console,
    password_file,
    web_ui,
    datadir,
    nat,
    transport,
    matrix_server,
    network_id,
    extra_config=None,
):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    from raiden.app import App
    from raiden.network.blockchain_service import BlockChainService

    if transport == 'udp' and not mapped_socket:
        raise RuntimeError('Missing socket')

    address_hex = to_normalized_address(address) if address else None
    address_hex, privatekey_bin = prompt_account(address_hex, keystore_path,
                                                 password_file)
    address = to_canonical_address(address_hex)

    (listen_host, listen_port) = split_endpoint(listen_address)
    (api_host, api_port) = split_endpoint(api_address)

    if datadir is None:
        datadir = os.path.join(os.path.expanduser('~'), '.raiden')

    config = deepcopy(App.DEFAULT_CONFIG)
    if extra_config:
        merge_dict(config, extra_config)

    config['host'] = listen_host
    config['port'] = listen_port
    config['console'] = console
    config['rpc'] = rpc
    config['web_ui'] = rpc and web_ui
    config['api_host'] = api_host
    config['api_port'] = api_port
    if mapped_socket:
        config['socket'] = mapped_socket.socket
        config['external_ip'] = mapped_socket.external_ip
        config['external_port'] = mapped_socket.external_port
    config['transport_type'] = transport
    config['matrix']['server'] = matrix_server
    config['transport'][
        'nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES
    timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES
    config['transport']['nat_keepalive_timeout'] = timeout

    privatekey_hex = hexlify(privatekey_bin)
    config['privatekey_hex'] = privatekey_hex

    endpoint = eth_rpc_endpoint

    # Fallback to default port if only an IP address is given
    rpc_port = 8545
    if eth_rpc_endpoint.startswith('http://'):
        endpoint = eth_rpc_endpoint[len('http://'):]
        rpc_port = 80
    elif eth_rpc_endpoint.startswith('https://'):
        endpoint = eth_rpc_endpoint[len('https://'):]
        rpc_port = 443

    if ':' not in endpoint:  # no port was given in url
        rpc_host = endpoint
    else:
        rpc_host, rpc_port = split_endpoint(endpoint)

    rpc_client = JSONRPCClient(
        rpc_host,
        rpc_port,
        privatekey_bin,
        gas_price,
    )

    blockchain_service = BlockChainService(
        privatekey_bin,
        rpc_client,
        gas_price,
    )

    # this assumes the eth node is already online
    check_json_rpc(rpc_client)

    net_id = blockchain_service.network_id
    if net_id != network_id:
        if network_id in ID_TO_NETWORKNAME and net_id in ID_TO_NETWORKNAME:
            print((
                "The chosen ethereum network '{}' differs from the ethereum client '{}'. "
                'Please update your settings.').format(
                    ID_TO_NETWORKNAME[network_id], ID_TO_NETWORKNAME[net_id]))
        else:
            print((
                "The chosen ethereum network id '{}' differs from the ethereum client '{}'. "
                'Please update your settings.').format(network_id, net_id))
        sys.exit(1)

    if sync_check:
        check_synced(blockchain_service)

    database_path = os.path.join(datadir, 'netid_%s' % net_id, address_hex[:8],
                                 'log.db')
    config['database_path'] = database_path
    print(
        'You are connected to the \'{}\' network and the DB path is: {}'.
        format(
            ID_TO_NETWORKNAME.get(net_id) or net_id,
            database_path,
        ), )

    try:
        registry = blockchain_service.registry(registry_contract_address, )
    except ContractVersionMismatch:
        print(
            'Deployed registry contract version mismatch. '
            'Please update your Raiden installation.', )
        sys.exit(1)

    try:
        secret_registry = blockchain_service.secret_registry(
            secret_registry_contract_address, )
    except ContractVersionMismatch:
        print(
            'Deployed registry contract version mismatch. '
            'Please update your Raiden installation.', )
        sys.exit(1)

    discovery = None
    if transport == 'udp':
        check_discovery_registration_gas(blockchain_service, address)
        try:
            discovery = ContractDiscovery(
                blockchain_service.node_address,
                blockchain_service.discovery(discovery_contract_address),
            )
        except ContractVersionMismatch:
            print('Deployed discovery contract version mismatch. '
                  'Please update your Raiden installation.')
            sys.exit(1)
        throttle_policy = TokenBucket(
            config['transport']['throttle_capacity'],
            config['transport']['throttle_fill_rate'],
        )

        transport = UDPTransport(
            discovery,
            mapped_socket.socket,
            throttle_policy,
            config['transport'],
        )
    elif transport == 'matrix':
        transport = MatrixTransport(config['matrix'])
    else:
        raise RuntimeError(f'Unknown transport type "{transport}" given')

    raiden_app = App(
        config,
        blockchain_service,
        registry,
        secret_registry,
        transport,
        discovery,
    )

    return raiden_app
예제 #9
0
파일: cli.py 프로젝트: LitexGit/raiden
def run_app(
        address,
        keystore_path,
        gas_price,
        eth_rpc_endpoint,
        registry_contract_address,
        secret_registry_contract_address,
        discovery_contract_address,
        listen_address,
        mapped_socket,
        max_unresponsive_time,
        api_address,
        rpc,
        sync_check,
        console,
        password_file,
        web_ui,
        datadir,
        transport,
        matrix_server,
        network_id,
        lnd_address,
        extra_config=None,
        **kwargs,
):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    from raiden.app import App

    if transport == 'udp' and not mapped_socket:
        raise RuntimeError('Missing socket')

    address_hex = to_normalized_address(address) if address else None
    address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file)
    address = to_canonical_address(address_hex)

    (listen_host, listen_port) = split_endpoint(listen_address)
    (api_host, api_port) = split_endpoint(api_address)

    if datadir is None:
        datadir = os.path.join(os.path.expanduser('~'), '.raiden')

    config = deepcopy(App.DEFAULT_CONFIG)
    if extra_config:
        merge_dict(config, extra_config)

    config['host'] = listen_host
    config['port'] = listen_port
    config['console'] = console
    config['rpc'] = rpc
    config['web_ui'] = rpc and web_ui
    config['api_host'] = api_host
    config['api_port'] = api_port
    if mapped_socket:
        config['socket'] = mapped_socket.socket
        config['external_ip'] = mapped_socket.external_ip
        config['external_port'] = mapped_socket.external_port
    config['transport_type'] = transport
    config['matrix']['server'] = matrix_server
    config['transport']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES
    timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES
    config['transport']['nat_keepalive_timeout'] = timeout

    privatekey_hex = hexlify(privatekey_bin)
    config['privatekey_hex'] = privatekey_hex

    rpc_host, rpc_port = eth_endpoint_to_hostport(eth_rpc_endpoint)

    rpc_client = JSONRPCClient(
        rpc_host,
        rpc_port,
        privatekey_bin,
        gas_price,
    )

    blockchain_service = BlockChainService(privatekey_bin, rpc_client)

    net_id = blockchain_service.network_id
    if net_id != network_id:
        if network_id in constants.ID_TO_NETWORKNAME and net_id in constants.ID_TO_NETWORKNAME:
            print((
                "The chosen ethereum network '{}' differs from the ethereum client '{}'. "
                'Please update your settings.'
            ).format(constants.ID_TO_NETWORKNAME[network_id], constants.ID_TO_NETWORKNAME[net_id]))
        else:
            print((
                "The chosen ethereum network id '{}' differs from the ethereum client '{}'. "
                'Please update your settings.'
            ).format(network_id, net_id))
        sys.exit(1)

    config['chain_id'] = network_id

    if sync_check:
        check_synced(blockchain_service)

    database_path = os.path.join(datadir, 'netid_%s' % net_id, address_hex[:8], 'log.db')
    config['database_path'] = database_path
    print(
        '\nYou are connected to the \'{}\' network and the DB path is: {}'.format(
            constants.ID_TO_NETWORKNAME.get(net_id) or net_id,
            database_path,
        ),
    )

    contract_addresses_given = (
        registry_contract_address is not None and
        secret_registry_contract_address is not None and
        discovery_contract_address is not None
    )
    contract_addresses_known = net_id in constants.ID_TO_NETWORK_CONFIG

    if not contract_addresses_given and not contract_addresses_known:
        print((
              "There are known contract addresses for network id '{}'. Please provide "
              'them in the command line or the configuration file.'
              ).format(net_id))
        sys.exit(1)

    contract_addresses = constants.ID_TO_NETWORK_CONFIG.get(net_id, dict())

    try:
        token_network_registry = blockchain_service.token_network_registry(
            registry_contract_address or contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY],
        )
    except ContractVersionMismatch:
        print(
            'Deployed registry contract version mismatch. '
            'Please update your Raiden installation.',
        )
        sys.exit(1)

    try:
        secret_registry = blockchain_service.secret_registry(
            secret_registry_contract_address or contract_addresses[CONTRACT_SECRET_REGISTRY],
        )
    except ContractVersionMismatch:
        print(
            'Deployed secret registry contract version mismatch. '
            'Please update your Raiden installation.',
        )
        sys.exit(1)

    discovery = None
    if transport == 'udp':
        check_discovery_registration_gas(blockchain_service, address)
        try:
            dicovery_proxy = blockchain_service.discovery(
                discovery_contract_address or contract_addresses[CONTRACT_ENDPOINT_REGISTRY],
            )
            discovery = ContractDiscovery(
                blockchain_service.node_address,
                dicovery_proxy,
            )
        except ContractVersionMismatch:
            print('Deployed discovery contract version mismatch. '
                  'Please update your Raiden installation.')
            sys.exit(1)
        throttle_policy = TokenBucket(
            config['transport']['throttle_capacity'],
            config['transport']['throttle_fill_rate'],
        )

        transport = UDPTransport(
            discovery,
            mapped_socket.socket,
            throttle_policy,
            config['transport'],
        )
    elif transport == 'matrix':
        # matrix gets spammed with the default retry-interval of 1s, wait a little more
        if config['transport']['retry_interval'] == DEFAULT_TRANSPORT_RETRY_INTERVAL:
            config['transport']['retry_interval'] *= 5
        try:
            transport = MatrixTransport(config['matrix'])
        except RaidenError as ex:
            click.secho(f'FATAL: {ex}', fg='red')
            sys.exit(1)
    else:
        raise RuntimeError(f'Unknown transport type "{transport}" given')

    try:
        chain_config = constants.ID_TO_NETWORK_CONFIG.get(net_id, {})
        start_block = chain_config.get(constants.START_QUERY_BLOCK_KEY, 0)
        #vincent
        config['lnd_address'] = lnd_address
        raiden_app = App(
            config=config,
            chain=blockchain_service,
            query_start_block=start_block,
            default_registry=token_network_registry,
            default_secret_registry=secret_registry,
            transport=transport,
            discovery=discovery,
        )
    except RaidenError as e:
        click.secho(f'FATAL: {e}', fg='red')
        sys.exit(1)

    return raiden_app
예제 #10
0
def create_apps(
    chain_id,
    contracts_path,
    blockchain_services,
    endpoint_discovery_services,
    token_network_registry_address,
    one_to_n_address: Optional[Address],
    secret_registry_address,
    service_registry_address,
    user_deposit_address,
    raiden_udp_ports,
    reveal_timeout,
    settle_timeout,
    database_basedir,
    retry_interval,
    retries_before_backoff,
    throttle_capacity,
    throttle_fill_rate,
    nat_invitation_timeout,
    nat_keepalive_retries,
    nat_keepalive_timeout,
    environment_type,
    unrecoverable_error_should_crash,
    local_matrix_url=None,
    private_rooms=None,
    global_rooms=None,
):
    """ Create the apps."""
    # pylint: disable=too-many-locals
    services = zip(blockchain_services, endpoint_discovery_services, raiden_udp_ports)

    apps = []
    for idx, (blockchain, discovery, port) in enumerate(services):
        address = blockchain.client.address

        host = "127.0.0.1"
        database_path = database_from_privatekey(base_dir=database_basedir, app_number=idx)

        config = {
            "chain_id": chain_id,
            "environment_type": environment_type,
            "unrecoverable_error_should_crash": unrecoverable_error_should_crash,
            "reveal_timeout": reveal_timeout,
            "settle_timeout": settle_timeout,
            "contracts_path": contracts_path,
            "database_path": database_path,
            "blockchain": {"confirmation_blocks": DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS},
            "transport": {
                "udp": {
                    "external_ip": host,
                    "external_port": port,
                    "host": host,
                    "nat_invitation_timeout": nat_invitation_timeout,
                    "nat_keepalive_retries": nat_keepalive_retries,
                    "nat_keepalive_timeout": nat_keepalive_timeout,
                    "port": port,
                    "retries_before_backoff": retries_before_backoff,
                    "retry_interval": retry_interval,
                    "throttle_capacity": throttle_capacity,
                    "throttle_fill_rate": throttle_fill_rate,
                }
            },
            "rpc": True,
            "console": False,
        }

        use_matrix = local_matrix_url is not None
        if use_matrix:
            merge_dict(
                config,
                {
                    "transport_type": "matrix",
                    "transport": {
                        "matrix": {
                            "global_rooms": global_rooms,
                            "retries_before_backoff": retries_before_backoff,
                            "retry_interval": retry_interval,
                            "server": local_matrix_url,
                            "server_name": local_matrix_url.netloc,
                            "available_servers": [],
                            "private_rooms": private_rooms,
                        }
                    },
                },
            )

        config_copy = deepcopy(App.DEFAULT_CONFIG)
        config_copy.update(config)

        registry = blockchain.token_network_registry(token_network_registry_address)
        secret_registry = blockchain.secret_registry(secret_registry_address)

        service_registry = None
        if service_registry_address:
            service_registry = blockchain.service_registry(service_registry_address)

        user_deposit = None
        if user_deposit_address:
            user_deposit = blockchain.user_deposit(user_deposit_address)

        if use_matrix:
            transport = MatrixTransport(config["transport"]["matrix"])
        else:
            throttle_policy = TokenBucket(
                config["transport"]["udp"]["throttle_capacity"],
                config["transport"]["udp"]["throttle_fill_rate"],
            )

            transport = UDPTransport(
                address,
                discovery,
                server._udp_socket((host, port)),  # pylint: disable=protected-access
                throttle_policy,
                config["transport"]["udp"],
            )

        raiden_event_handler = RaidenEventHandler()
        hold_handler = HoldRaidenEventHandler(raiden_event_handler)
        message_handler = WaitForMessage()

        app = App(
            config=config_copy,
            chain=blockchain,
            query_start_block=BlockNumber(0),
            default_registry=registry,
            default_one_to_n_address=one_to_n_address,
            default_secret_registry=secret_registry,
            default_service_registry=service_registry,
            transport=transport,
            raiden_event_handler=hold_handler,
            message_handler=message_handler,
            discovery=discovery,
            user_deposit=user_deposit,
        )
        apps.append(app)

    return apps
예제 #11
0
    def _start_services(self):
        from raiden.ui.console import Console
        from raiden.api.python import RaidenAPI

        config = deepcopy(App.DEFAULT_CONFIG)
        if self._options.get('extra_config', dict()):
            merge_dict(config, self._options['extra_config'])
            del self._options['extra_config']
        self._options['config'] = config

        if self._options['showconfig']:
            print('Configuration Dump:')
            dump_config(config)
            dump_cmd_options(self._options)
            dump_module('settings', settings)
            dump_module('constants', constants)

        # this catches exceptions raised when waiting for the stalecheck to complete
        try:
            app_ = run_app(**self._options)
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RuntimeError as e:
            click.secho(str(e), fg='red')
            sys.exit(1)
        except EthNodeInterfaceError as e:
            click.secho(str(e), fg='red')
            sys.exit(1)

        tasks = [app_.raiden]  # RaidenService takes care of Transport and AlarmTask

        domain_list = []
        if self._options['rpccorsdomain']:
            if ',' in self._options['rpccorsdomain']:
                for domain in self._options['rpccorsdomain'].split(','):
                    domain_list.append(str(domain))
            else:
                domain_list.append(str(self._options['rpccorsdomain']))

        self._raiden_api = RaidenAPI(app_.raiden)

        if self._options['rpc']:
            rest_api = RestAPI(self._raiden_api)
            api_server = APIServer(
                rest_api,
                cors_domain_list=domain_list,
                web_ui=self._options['web_ui'],
                eth_rpc_endpoint=self._options['eth_rpc_endpoint'],
            )
            (api_host, api_port) = split_endpoint(self._options['api_address'])

            try:
                api_server.start(api_host, api_port)
            except APIServerPortInUseError:
                click.secho(
                    f'ERROR: API Address {api_host}:{api_port} is in use. '
                    f'Use --api-address <host:port> to specify a different port.',
                    fg='red',
                )
                sys.exit(1)

            print(
                'The Raiden API RPC server is now running at http://{}:{}/.\n\n'
                'See the Raiden documentation for all available endpoints at\n'
                'http://raiden-network.readthedocs.io/en/stable/rest_api.html'.format(
                    api_host,
                    api_port,
                ),
            )
            tasks.append(api_server)

        if self._options['console']:
            console = Console(app_)
            console.start()
            tasks.append(console)

        # spawn a greenlet to handle the version checking
        version = get_system_spec()['raiden']
        tasks.append(gevent.spawn(check_version, version))

        # spawn a greenlet to handle the gas reserve check
        tasks.append(gevent.spawn(check_gas_reserve, app_.raiden))

        self._startup_hook()

        # wait for interrupt
        event = AsyncResult()

        def sig_set(sig=None, _frame=None):
            event.set(sig)

        gevent.signal(signal.SIGQUIT, sig_set)
        gevent.signal(signal.SIGTERM, sig_set)
        gevent.signal(signal.SIGINT, sig_set)

        # quit if any task exits, successfully or not
        for task in tasks:
            task.link(event)

        try:
            event.get()
            print('Signal received. Shutting down ...')
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RaidenError as ex:
            click.secho(f'FATAL: {ex}', fg='red')
        except Exception as ex:
            file = NamedTemporaryFile(
                'w',
                prefix=f'raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}',
                suffix='.txt',
                delete=False,
            )
            with file as traceback_file:
                traceback.print_exc(file=traceback_file)
                click.secho(
                    f'FATAL: An unexpected exception occured. '
                    f'A traceback has been written to {traceback_file.name}\n'
                    f'{ex}',
                    fg='red',
                )
        finally:
            self._shutdown_hook()

            def stop_task(task):
                try:
                    if isinstance(task, Runnable):
                        task.stop()
                    else:
                        task.kill()
                finally:
                    task.get()  # re-raise

            gevent.joinall(
                [gevent.spawn(stop_task, task) for task in tasks],
                app_.config.get('shutdown_timeout', settings.DEFAULT_SHUTDOWN_TIMEOUT),
                raise_error=True,
            )

        return app_
예제 #12
0
    def _start_services(self):
        from raiden.ui.console import Console
        from raiden.api.python import RaidenAPI

        config = deepcopy(App.DEFAULT_CONFIG)
        if self._options.get('extra_config', dict()):
            merge_dict(config, self._options['extra_config'])
            del self._options['extra_config']
        self._options['config'] = config

        if self._options['showconfig']:
            print('Configuration Dump:')
            dump_config(config)
            dump_cmd_options(self._options)
            dump_module('settings', settings)
            dump_module('constants', constants)

        # this catches exceptions raised when waiting for the stalecheck to complete
        try:
            app_ = run_app(**self._options)
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RuntimeError as e:
            click.secho(str(e), fg='red')
            sys.exit(1)
        except EthNodeInterfaceError as e:
            click.secho(str(e), fg='red')
            sys.exit(1)

        tasks = [app_.raiden
                 ]  # RaidenService takes care of Transport and AlarmTask

        domain_list = []

        if self._options['rpccorsdomain']:
            if ',' in self._options['rpccorsdomain']:
                for domain in self._options['rpccorsdomain'].split(','):
                    domain_list.append(str(domain))
            else:
                domain_list.append(str(self._options['rpccorsdomain']))

        self._raiden_api = RaidenAPI(app_.raiden)

        if self._options['discoverable']:
            node_address = to_checksum_address(self._raiden_api.address)
            rns_domain = None
            if self._options['rnsdomain']:
                rns_domain = self._options['rnsdomain']
                try:
                    rns_resolved_address = self._raiden_api.raiden.chain.get_address_from_rns(
                        self._options['rnsdomain'])
                    if rns_resolved_address == RNS_ADDRESS_ZERO:
                        click.secho(
                            'Cannot register into the Lumino Explorer. Your RNS domain is not registered'
                        )
                        sys.exit(1)
                    elif rns_resolved_address != node_address:
                        click.secho(
                            'Cannot register into the Lumino Explorer. Your RNS domain does not match with the node RSK address. The RNS domain is owned by '
                            + rns_resolved_address)
                        sys.exit(1)
                except BadFunctionCallOutput:
                    click.secho(
                        "Unable to interact with RNS Public Resolver. Your node will be registered without RNS domain."
                    )
            register(node_address, rns_domain)
        else:
            if self._options['rnsdomain']:
                try:
                    self._raiden_api.raiden.chain.get_address_from_rns(
                        self._options['rnsdomain'])

                except BadFunctionCallOutput:
                    click.secho(
                        "Unable to interact with RNS Public Resolver. Please check youre interacting with the correct contract."
                    )
                    sys.exit(1)

        self._raiden_api = RaidenAPI(app_.raiden)

        if self._options['rpc']:
            rest_api = RestAPI(self._raiden_api)
            (api_host, api_port) = split_endpoint(self._options['api_address'])
            api_server = APIServer(
                rest_api,
                config={
                    'host': api_host,
                    'port': api_port,
                    'rnsdomain': self._options['rnsdomain'],
                    'rskendpoint': self._options['eth_rpc_endpoint']
                },
                cors_domain_list=domain_list,
                web_ui=self._options['web_ui'],
                eth_rpc_endpoint=self._options['eth_rpc_endpoint'],
            )

            try:
                api_server.start()
            except APIServerPortInUseError:
                click.secho(
                    f'ERROR: API Address {api_host}:{api_port} is in use. '
                    f'Use --api-address <host:port> to specify a different port.',
                    fg='red',
                )
                sys.exit(1)

            print(
                'The Lumino API RPC server is now running at http://{}:{}/.\n\n'
                .format(
                    api_host,
                    api_port,
                ), )
            tasks.append(api_server)

        if self._options['console']:
            console = Console(app_)
            console.start()
            tasks.append(console)

        # spawn a greenlet to handle the version checking
        version = get_system_spec()['raiden']
        tasks.append(gevent.spawn(check_version, version))

        # spawn a greenlet to handle the gas reserve check
        tasks.append(gevent.spawn(check_gas_reserve, app_.raiden))

        self._startup_hook()

        # wait for interrupt
        event = AsyncResult()

        def sig_set(sig=None, _frame=None):
            event.set(sig)

        gevent.signal(signal.SIGQUIT, sig_set)
        gevent.signal(signal.SIGTERM, sig_set)
        gevent.signal(signal.SIGINT, sig_set)

        # quit if any task exits, successfully or not
        for task in tasks:
            task.link(event)

        try:
            event.get()
            print('Signal received. Shutting down ...')
        except (EthNodeCommunicationError, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RaidenError as ex:
            click.secho(f'FATAL: {ex}', fg='red')
        except Exception as ex:
            file = NamedTemporaryFile(
                'w',
                prefix=f'raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}',
                suffix='.txt',
                delete=False,
            )
            with file as traceback_file:
                traceback.print_exc(file=traceback_file)
                click.secho(
                    f'FATAL: An unexpected exception occured. '
                    f'A traceback has been written to {traceback_file.name}\n'
                    f'{ex}',
                    fg='red',
                )
        finally:
            self._shutdown_hook()

            def stop_task(task):
                try:
                    if isinstance(task, Runnable):
                        task.stop()
                    else:
                        task.kill()
                finally:
                    task.get()  # re-raise

            gevent.joinall(
                [gevent.spawn(stop_task, task) for task in tasks],
                app_.config.get('shutdown_timeout',
                                settings.DEFAULT_SHUTDOWN_TIMEOUT),
                raise_error=True,
            )

        return app_
예제 #13
0
파일: cli.py 프로젝트: AlphaX-IBS/raiden
def app(
        address,
        keystore_path,
        gas_price,
        eth_rpc_endpoint,
        registry_contract_address,
        secret_registry_contract_address,
        discovery_contract_address,
        listen_address,
        rpccorsdomain,
        mapped_socket,
        log_config,
        log_file,
        log_json,
        max_unresponsive_time,
        send_ping_time,
        api_address,
        rpc,
        sync_check,
        console,
        password_file,
        web_ui,
        datadir,
        nat,
        transport,
        matrix_server,
        network_id,
        config_file,
        extra_config=None,
):
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    from raiden.app import App

    if transport == 'udp' and not mapped_socket:
        raise RuntimeError('Missing socket')

    address_hex = to_normalized_address(address) if address else None
    address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file)
    address = to_canonical_address(address_hex)

    (listen_host, listen_port) = split_endpoint(listen_address)
    (api_host, api_port) = split_endpoint(api_address)

    if datadir is None:
        datadir = os.path.join(os.path.expanduser('~'), '.raiden')

    config = deepcopy(App.DEFAULT_CONFIG)
    if extra_config:
        merge_dict(config, extra_config)

    config['host'] = listen_host
    config['port'] = listen_port
    config['console'] = console
    config['rpc'] = rpc
    config['web_ui'] = rpc and web_ui
    config['api_host'] = api_host
    config['api_port'] = api_port
    if mapped_socket:
        config['socket'] = mapped_socket.socket
        config['external_ip'] = mapped_socket.external_ip
        config['external_port'] = mapped_socket.external_port
    config['transport_type'] = transport
    config['matrix']['server'] = matrix_server
    config['transport']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES
    timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES
    config['transport']['nat_keepalive_timeout'] = timeout

    privatekey_hex = hexlify(privatekey_bin)
    config['privatekey_hex'] = privatekey_hex

    rpc_host, rpc_port = eth_endpoint_to_hostport(eth_rpc_endpoint)

    rpc_client = JSONRPCClient(
        rpc_host,
        rpc_port,
        privatekey_bin,
        gas_price,
    )

    blockchain_service = BlockChainService(privatekey_bin, rpc_client)

    net_id = blockchain_service.network_id
    if net_id != network_id:
        if network_id in constants.ID_TO_NETWORKNAME and net_id in constants.ID_TO_NETWORKNAME:
            print((
                "The chosen ethereum network '{}' differs from the ethereum client '{}'. "
                'Please update your settings.'
            ).format(constants.ID_TO_NETWORKNAME[network_id], constants.ID_TO_NETWORKNAME[net_id]))
        else:
            print((
                "The chosen ethereum network id '{}' differs from the ethereum client '{}'. "
                'Please update your settings.'
            ).format(network_id, net_id))
        sys.exit(1)

    config['chain_id'] = network_id

    if sync_check:
        check_synced(blockchain_service)

    database_path = os.path.join(datadir, 'netid_%s' % net_id, address_hex[:8], 'log.db')
    config['database_path'] = database_path
    print(
        '\nYou are connected to the \'{}\' network and the DB path is: {}'.format(
            constants.ID_TO_NETWORKNAME.get(net_id) or net_id,
            database_path,
        ),
    )

    try:
        token_network_registry = blockchain_service.token_network_registry(
            registry_contract_address,
        )
    except ContractVersionMismatch:
        print(
            'Deployed registry contract version mismatch. '
            'Please update your Raiden installation.',
        )
        sys.exit(1)

    try:
        secret_registry = blockchain_service.secret_registry(
            secret_registry_contract_address,
        )
    except ContractVersionMismatch:
        print(
            'Deployed secret registry contract version mismatch. '
            'Please update your Raiden installation.',
        )
        sys.exit(1)

    discovery = None
    if transport == 'udp':
        check_discovery_registration_gas(blockchain_service, address)
        try:
            discovery = ContractDiscovery(
                blockchain_service.node_address,
                blockchain_service.discovery(discovery_contract_address),
            )
        except ContractVersionMismatch:
            print('Deployed discovery contract version mismatch. '
                  'Please update your Raiden installation.')
            sys.exit(1)
        throttle_policy = TokenBucket(
            config['transport']['throttle_capacity'],
            config['transport']['throttle_fill_rate'],
        )

        transport = UDPTransport(
            discovery,
            mapped_socket.socket,
            throttle_policy,
            config['transport'],
        )
    elif transport == 'matrix':
        # matrix gets spammed with the default retry-interval of 1s, wait a little more
        if config['transport']['retry_interval'] == DEFAULT_TRANSPORT_RETRY_INTERVAL:
            config['transport']['retry_interval'] *= 5
        try:
            transport = MatrixTransport(config['matrix'])
        except RaidenError as ex:
            click.secho(f'FATAL: {ex}', fg='red')
            sys.exit(1)
    else:
        raise RuntimeError(f'Unknown transport type "{transport}" given')

    try:
        raiden_app = App(
            config=config,
            chain=blockchain_service,
            query_start_block=constants.ID_TO_QUERY_BLOCK[net_id],
            default_registry=token_network_registry,
            default_secret_registry=secret_registry,
            transport=transport,
            discovery=discovery,
        )
    except RaidenError as e:
        click.secho(f'FATAL: {e}', fg='red')
        sys.exit(1)

    return raiden_app
예제 #14
0
def create_apps(
        chain_id,
        blockchain_services,
        endpoint_discovery_services,
        token_network_registry_address,
        secret_registry_address,
        raiden_udp_ports,
        reveal_timeout,
        settle_timeout,
        database_paths,
        retry_interval,
        retries_before_backoff,
        throttle_capacity,
        throttle_fill_rate,
        nat_invitation_timeout,
        nat_keepalive_retries,
        nat_keepalive_timeout,
        environment_type,
        unrecoverable_error_should_crash,
        local_matrix_url=None,
        private_rooms=None,
):
    """ Create the apps."""
    # pylint: disable=too-many-locals
    services = zip(blockchain_services, endpoint_discovery_services)

    apps = []
    for idx, (blockchain, discovery) in enumerate(services):
        port = raiden_udp_ports[idx]
        private_key = blockchain.private_key
        address = privatekey_to_address(private_key)

        host = '127.0.0.1'

        config = {
            'chain_id': chain_id,
            'environment_type': environment_type,
            'unrecoverable_error_should_crash': unrecoverable_error_should_crash,
            'privatekey_hex': encode_hex(private_key),
            'reveal_timeout': reveal_timeout,
            'settle_timeout': settle_timeout,
            'database_path': database_paths[idx],
            'blockchain': {
                'confirmation_blocks': DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
            },
            'transport': {
                'udp': {
                    'external_ip': host,
                    'external_port': port,
                    'host': host,
                    'nat_invitation_timeout': nat_invitation_timeout,
                    'nat_keepalive_retries': nat_keepalive_retries,
                    'nat_keepalive_timeout': nat_keepalive_timeout,
                    'port': port,
                    'retries_before_backoff': retries_before_backoff,
                    'retry_interval': retry_interval,
                    'throttle_capacity': throttle_capacity,
                    'throttle_fill_rate': throttle_fill_rate,
                },
            },
            'rpc': True,
            'console': False,
        }

        use_matrix = local_matrix_url is not None
        if use_matrix:
            merge_dict(
                config,
                {
                    'transport_type': 'matrix',
                    'transport': {
                        'matrix': {
                            'discovery_room': 'discovery',
                            'retries_before_backoff': retries_before_backoff,
                            'retry_interval': retry_interval,
                            'server': local_matrix_url,
                            'server_name': local_matrix_url.netloc,
                            'available_servers': [],
                            'private_rooms': private_rooms,
                        },
                    },
                },
            )

        config_copy = App.DEFAULT_CONFIG.copy()
        config_copy.update(config)

        registry = blockchain.token_network_registry(token_network_registry_address)
        secret_registry = blockchain.secret_registry(secret_registry_address)

        if use_matrix:
            transport = MatrixTransport(config['transport']['matrix'])
        else:
            throttle_policy = TokenBucket(
                config['transport']['udp']['throttle_capacity'],
                config['transport']['udp']['throttle_fill_rate'],
            )

            transport = UDPTransport(
                address,
                discovery,
                server._udp_socket((host, port)),  # pylint: disable=protected-access
                throttle_policy,
                config['transport']['udp'],
            )

        raiden_event_handler = RaidenEventHandler()
        message_handler = MessageHandler()

        app = App(
            config=config_copy,
            chain=blockchain,
            query_start_block=0,
            default_registry=registry,
            default_secret_registry=secret_registry,
            transport=transport,
            raiden_event_handler=raiden_event_handler,
            message_handler=message_handler,
            discovery=discovery,
        )
        apps.append(app)

    return apps
예제 #15
0
def create_apps(
    chain_id,
    blockchain_services,
    endpoint_discovery_services,
    token_network_registry_address,
    secret_registry_address,
    raiden_udp_ports,
    reveal_timeout,
    settle_timeout,
    database_paths,
    retry_interval,
    retries_before_backoff,
    throttle_capacity,
    throttle_fill_rate,
    nat_invitation_timeout,
    nat_keepalive_retries,
    nat_keepalive_timeout,
    environment_type,
    unrecoverable_error_should_crash,
    local_matrix_url=None,
    private_rooms=None,
):
    """ Create the apps."""
    # pylint: disable=too-many-locals
    services = zip(blockchain_services, endpoint_discovery_services)

    apps = []
    for idx, (blockchain, discovery) in enumerate(services):
        port = raiden_udp_ports[idx]
        private_key = blockchain.private_key
        address = privatekey_to_address(private_key)

        host = '127.0.0.1'

        config = {
            'chain_id': chain_id,
            'environment_type': environment_type,
            'unrecoverable_error_should_crash':
            unrecoverable_error_should_crash,
            'privatekey_hex': encode_hex(private_key),
            'reveal_timeout': reveal_timeout,
            'settle_timeout': settle_timeout,
            'database_path': database_paths[idx],
            'blockchain': {
                'confirmation_blocks': DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
            },
            'transport': {
                'udp': {
                    'external_ip': host,
                    'external_port': port,
                    'host': host,
                    'nat_invitation_timeout': nat_invitation_timeout,
                    'nat_keepalive_retries': nat_keepalive_retries,
                    'nat_keepalive_timeout': nat_keepalive_timeout,
                    'port': port,
                    'retries_before_backoff': retries_before_backoff,
                    'retry_interval': retry_interval,
                    'throttle_capacity': throttle_capacity,
                    'throttle_fill_rate': throttle_fill_rate,
                },
            },
            'rpc': True,
            'console': False,
        }

        use_matrix = local_matrix_url is not None
        if use_matrix:
            merge_dict(
                config,
                {
                    'transport_type': 'matrix',
                    'transport': {
                        'matrix': {
                            'discovery_room': 'discovery',
                            'retries_before_backoff': retries_before_backoff,
                            'retry_interval': retry_interval,
                            'server': local_matrix_url,
                            'server_name': local_matrix_url.netloc,
                            'available_servers': [],
                            'private_rooms': private_rooms,
                        },
                    },
                },
            )

        config_copy = App.DEFAULT_CONFIG.copy()
        config_copy.update(config)

        registry = blockchain.token_network_registry(
            token_network_registry_address)
        secret_registry = blockchain.secret_registry(secret_registry_address)

        if use_matrix:
            transport = MatrixTransport(config['transport']['matrix'])
        else:
            throttle_policy = TokenBucket(
                config['transport']['udp']['throttle_capacity'],
                config['transport']['udp']['throttle_fill_rate'],
            )

            transport = UDPTransport(
                address,
                discovery,
                server._udp_socket((host, port)),  # pylint: disable=protected-access
                throttle_policy,
                config['transport']['udp'],
            )

        raiden_event_handler = RaidenEventHandler()
        message_handler = MessageHandler()

        app = App(
            config=config_copy,
            chain=blockchain,
            query_start_block=0,
            default_registry=registry,
            default_secret_registry=secret_registry,
            transport=transport,
            raiden_event_handler=raiden_event_handler,
            message_handler=message_handler,
            discovery=discovery,
        )
        apps.append(app)

    return apps
예제 #16
0
파일: cli.py 프로젝트: infuy/lumino_fork
    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()

                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)]

                success = False
                print_step('Running smoketest')
                error = run_smoketests(
                    app.raiden,
                    args['transport'],
                    token_addresses,
                    contract_addresses[CONTRACT_ENDPOINT_REGISTRY],
                    debug=debug,
                    orig_stdout=stdout,
                )
                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
예제 #17
0
    def _start_services(self):
        from raiden.api.python import RaidenAPI

        config = deepcopy(App.DEFAULT_CONFIG)
        config["reveal_timeout"] = self._options["default_reveal_timeout"]
        config["settle_timeout"] = self._options["default_settle_timeout"]
        if self._options.get("extra_config", dict()):
            merge_dict(config, self._options["extra_config"])
            del self._options["extra_config"]
        self._options["config"] = config

        if self._options["showconfig"]:
            print("Configuration Dump:")
            dump_config(config)
            dump_cmd_options(self._options)
            dump_module("settings", settings)
            dump_module("constants", constants)

        # this catches exceptions raised when waiting for the stalecheck to complete
        try:
            app_ = run_app(**self._options)
        except (ConnectionError, ConnectTimeout, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RuntimeError as e:
            click.secho(str(e), fg="red")
            sys.exit(1)
        except EthNodeInterfaceError as e:
            click.secho(str(e), fg="red")
            sys.exit(1)

        tasks = [app_.raiden]  # RaidenService takes care of Transport and AlarmTask

        domain_list = []
        if self._options["rpccorsdomain"]:
            if "," in self._options["rpccorsdomain"]:
                for domain in self._options["rpccorsdomain"].split(","):
                    domain_list.append(str(domain))
            else:
                domain_list.append(str(self._options["rpccorsdomain"]))

        self._raiden_api = RaidenAPI(app_.raiden)

        if self._options["rpc"]:
            rest_api = RestAPI(self._raiden_api)
            (api_host, api_port) = split_endpoint(self._options["api_address"])

            if not api_port:
                api_port = Port(settings.DEFAULT_HTTP_SERVER_PORT)

            api_server = APIServer(
                rest_api,
                config={"host": api_host, "port": api_port},
                cors_domain_list=domain_list,
                web_ui=self._options["web_ui"],
                eth_rpc_endpoint=self._options["eth_rpc_endpoint"],
            )

            try:
                api_server.start()
            except APIServerPortInUseError:
                click.secho(
                    f"ERROR: API Address {api_host}:{api_port} is in use. "
                    f"Use --api-address <host:port> to specify a different port.",
                    fg="red",
                )
                sys.exit(1)

            print(
                "The Raiden API RPC server is now running at http://{}:{}/.\n\n"
                "See the Raiden documentation for all available endpoints at\n"
                "http://raiden-network.readthedocs.io/en/stable/rest_api.html".format(
                    api_host, api_port
                )
            )
            tasks.append(api_server)

        if self._options["console"]:
            from raiden.ui.console import Console

            console = Console(app_)
            console.start()
            tasks.append(console)

        # spawn a greenlet to handle the version checking
        version = get_system_spec()["raiden"]
        tasks.append(gevent.spawn(check_version, version))

        # spawn a greenlet to handle the gas reserve check
        tasks.append(gevent.spawn(check_gas_reserve, app_.raiden))
        # spawn a greenlet to handle the periodic check for the network id
        tasks.append(
            gevent.spawn(
                check_network_id, app_.raiden.rpc_client.chain_id, app_.raiden.rpc_client.web3
            )
        )

        spawn_user_deposit_task = app_.user_deposit and (
            self._options["pathfinding_service_address"] or self._options["enable_monitoring"]
        )
        if spawn_user_deposit_task:
            # spawn a greenlet to handle RDN deposits check
            tasks.append(gevent.spawn(check_rdn_deposits, app_.raiden, app_.user_deposit))

        # spawn a greenlet to handle the functions

        self._startup_hook()

        # wait for interrupt
        event: "AsyncResult[None]" = AsyncResult()

        def sig_set(sig=None, _frame=None):
            event.set(sig)

        gevent.signal(signal.SIGQUIT, sig_set)
        gevent.signal(signal.SIGTERM, sig_set)
        gevent.signal(signal.SIGINT, sig_set)

        # quit if any task exits, successfully or not
        for task in tasks:
            task.link(event)

        try:
            event.get()
            print("Signal received. Shutting down ...")
        except (ConnectionError, ConnectTimeout, RequestsConnectionError):
            print(ETHEREUM_NODE_COMMUNICATION_ERROR)
            sys.exit(1)
        except RaidenError as ex:
            click.secho(f"FATAL: {ex}", fg="red")
        except Exception as ex:
            file = NamedTemporaryFile(
                "w",
                prefix=f"raiden-exception-{datetime.utcnow():%Y-%m-%dT%H-%M}",
                suffix=".txt",
                delete=False,
            )
            with file as traceback_file:
                traceback.print_exc(file=traceback_file)
                click.secho(
                    f"FATAL: An unexpected exception occured. "
                    f"A traceback has been written to {traceback_file.name}\n"
                    f"{ex}",
                    fg="red",
                )
        finally:
            self._shutdown_hook()

            app_.stop()

            def stop_task(task):
                try:
                    if isinstance(task, Runnable):
                        task.stop()
                    else:
                        task.kill()
                finally:
                    task.get()  # re-raise

            gevent.joinall(
                [gevent.spawn(stop_task, task) for task in tasks],
                app_.config.get("shutdown_timeout", settings.DEFAULT_SHUTDOWN_TIMEOUT),
                raise_error=True,
            )

        return app_
예제 #18
0
파일: cli.py 프로젝트: hackaugusto/raiden
    def _run_smoketest():
        print_step('Starting Raiden')

        config = deepcopy(App.DEFAULT_CONFIG)
        if args.get('extra_config', dict()):
            merge_dict(config, args['extra_config'])
            del args['extra_config']
        args['config'] = config

        raiden_stdout = StringIO()
        with contextlib.redirect_stdout(raiden_stdout):
            try:
                # invoke the raiden app
                app = run_app(**args)

                raiden_api = RaidenAPI(app.raiden)
                rest_api = RestAPI(raiden_api)
                api_server = APIServer(rest_api)
                (api_host, api_port) = split_endpoint(args['api_address'])
                api_server.start(api_host, api_port)

                raiden_api.channel_open(
                    registry_address=contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY],
                    token_address=to_canonical_address(token.contract.address),
                    partner_address=to_canonical_address(TEST_PARTNER_ADDRESS),
                )
                raiden_api.set_total_channel_deposit(
                    contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY],
                    to_canonical_address(token.contract.address),
                    to_canonical_address(TEST_PARTNER_ADDRESS),
                    TEST_DEPOSIT_AMOUNT,
                )
                token_addresses = [to_checksum_address(token.contract.address)]

                success = False
                print_step('Running smoketest')
                error = run_smoketests(
                    app.raiden,
                    args['transport'],
                    token_addresses,
                    contract_addresses[CONTRACT_ENDPOINT_REGISTRY],
                    debug=debug,
                )
                if error is not None:
                    append_report('Smoketest assertion error', error)
                else:
                    success = True
            finally:
                app.stop()
                app.raiden.get()
                node = ethereum[0]
                node.send_signal(2)
                err, out = node.communicate()

                append_report('Ethereum stdout', out)
                append_report('Ethereum stderr', err)
        append_report('Raiden Node stdout', raiden_stdout.getvalue())
        if success:
            print_step(f'Smoketest successful')
        else:
            print_step(f'Smoketest had errors', error=True)
        return success