Esempio n. 1
0
def wait_for_network_state(
    raiden: "RaidenService",
    node_address: Address,
    network_state: NetworkState,
    retry_timeout: float,
) -> None:  # pragma: no unittest
    """Wait until `node_address` becomes healthy.

    Note:
        This does not time out, use gevent.Timeout.
    """
    network_statuses = views.get_networkstatuses(
        views.state_from_raiden(raiden))
    current = network_statuses.get(node_address)

    log_details = {
        "node_address": to_checksum_address(node_address),
        "target_network_state": network_state,
    }
    while current != network_state:
        assert raiden, TRANSPORT_ERROR_MSG
        assert raiden.transport, TRANSPORT_ERROR_MSG

        log.debug("wait_for_network_state",
                  current_network_state=current,
                  **log_details)
        gevent.sleep(retry_timeout)
        network_statuses = views.get_networkstatuses(
            views.state_from_raiden(raiden))
        current = network_statuses.get(node_address)
Esempio n. 2
0
def wait_for_healthy(raiden: "RaidenService", node_address: Address, retry_timeout: float) -> None:
    """Wait until `node_address` becomes healthy.

    Note:
        This does not time out, use gevent.Timeout.
    """
    network_statuses = views.get_networkstatuses(views.state_from_raiden(raiden))

    while network_statuses.get(node_address) != NODE_NETWORK_REACHABLE:
        gevent.sleep(retry_timeout)
        network_statuses = views.get_networkstatuses(views.state_from_raiden(raiden))
Esempio n. 3
0
def wait_for_healthy(raiden, node_address, poll_timeout):
    """Wait until `node_address` becomes healthy.

    Note:
        This does not time out, use gevent.Timeout.
    """
    network_statuses = views.get_networkstatuses(
        views.state_from_raiden(raiden), )

    while network_statuses.get(node_address) != NODE_NETWORK_REACHABLE:
        gevent.sleep(poll_timeout)
        network_statuses = views.get_networkstatuses(
            views.state_from_raiden(raiden), )
Esempio n. 4
0
def wait_for_healthy(
        raiden: RaidenService,
        node_address: typing.Address,
        retry_timeout: float,
) -> None:
    """Wait until `node_address` becomes healthy.

    Note:
        This does not time out, use gevent.Timeout.
    """
    network_statuses = views.get_networkstatuses(
        views.state_from_raiden(raiden),
    )

    while network_statuses.get(node_address) != NODE_NETWORK_REACHABLE:
        gevent.sleep(retry_timeout)
        network_statuses = views.get_networkstatuses(
            views.state_from_raiden(raiden),
        )
Esempio n. 5
0
def wait_for_partners(app_list, sleep=0.5, timeout=10):
    waiting = list(app_list)

    while waiting:
        # Poll the events to register the new channels
        app = waiting[0]
        app.raiden.poll_blockchain_events()

        node_state = views.state_from_app(app)
        network_statuses = views.get_networkstatuses(node_state)

        all_healthy = all(status == NODE_NETWORK_REACHABLE
                          for status in network_statuses.values())

        if timeout <= 0:
            raise RuntimeError('fixture setup failed, nodes are unreachable')

        if all_healthy:
            waiting.pop(0)
        else:
            timeout -= sleep
            gevent.sleep(sleep)
Esempio n. 6
0
def get_best_routes(
        node_state: NodeState,
        token_network_id: typing.Address,
        from_address: typing.Address,
        to_address: typing.Address,
        amount: int,
        previous_address: typing.Address,
) -> List[RouteState]:
    """ Returns a list of channels that can be used to make a transfer.

    This will filter out channels that are not open and don't have enough
    capacity.
    """
    # TODO: Route ranking.
    # Rate each route to optimize the fee price/quality of each route and add a
    # rate from in the range [0.0,1.0].

    available_routes = list()

    token_network = views.get_token_network_by_identifier(
        node_state,
        token_network_id,
    )

    network_statuses = views.get_networkstatuses(node_state)

    neighbors_heap = get_ordered_partners(
        token_network.network_graph.network,
        from_address,
        to_address,
    )

    if not neighbors_heap:
        log.warning(
            'No routes available from %s to %s' % (pex(from_address), pex(to_address)),
        )

    while neighbors_heap:
        _, partner_address = heappop(neighbors_heap)

        channel_state = views.get_channelstate_by_token_network_and_partner(
            node_state,
            token_network_id,
            partner_address,
        )

        # don't send the message backwards
        if partner_address == previous_address:
            continue

        if channel.get_status(channel_state) != CHANNEL_STATE_OPENED:
            log.info(
                'channel %s - %s is not opened, ignoring' %
                (pex(from_address), pex(partner_address)),
            )
            continue

        distributable = channel.get_distributable(
            channel_state.our_state,
            channel_state.partner_state,
        )

        if amount > distributable:
            log.info(
                'channel %s - %s doesnt have enough funds [%s], ignoring' %
                (pex(from_address), pex(partner_address), amount),
            )
            continue

        network_state = network_statuses.get(partner_address, NODE_NETWORK_UNKNOWN)
        if network_state != NODE_NETWORK_REACHABLE:
            log.info(
                'partner for channel %s - %s is not %s, ignoring' %
                (pex(from_address), pex(partner_address), NODE_NETWORK_REACHABLE),
            )
            continue

        route_state = RouteState(partner_address, channel_state.identifier)
        available_routes.append(route_state)

    return available_routes
Esempio n. 7
0
def get_best_routes_pfs(
    chain_state: ChainState,
    token_network_id: typing.TokenNetworkID,
    from_address: typing.InitiatorAddress,
    to_address: typing.TargetAddress,
    amount: int,
    previous_address: typing.Optional[typing.Address],
    config: Dict[str, Any],
) -> Tuple[bool, List[RouteState]]:
    pfs_path = '{}/api/v1/{}/paths'.format(
        config['pathfinding_service_address'],
        to_checksum_address(token_network_id),
    )
    payload = {
        'from': to_checksum_address(from_address),
        'to': to_checksum_address(to_address),
        'value': amount,
        'max_paths': config['pathfinding_max_paths'],
    }

    # check that the response is successful
    try:
        response = requests.get(pfs_path,
                                params=payload,
                                timeout=DEFAULT_HTTP_REQUEST_TIMEOUT)
    except requests.RequestException:
        log.warning(
            'Could not connect to Pathfinding Service',
            request=pfs_path,
            parameters=payload,
            exc_info=True,
        )
        return False, []

    # check that the response contains valid json
    try:
        response_json = response.json()
    except ValueError:
        log.warning(
            'Pathfinding Service returned invalid JSON',
            response_text=response.text,
            exc_info=True,
        )
        return False, []

    if response.status_code != 200:
        log_info = {
            'error_code': response.status_code,
        }

        error = response_json.get('errors')
        if error is not None:
            log_info['pfs_error'] = error

        log.info(
            'Pathfinding Service returned error code',
            **log_info,
        )
        return False, []

    if response_json.get('result') is None:
        log.info(
            'Pathfinding Service returned unexpected result',
            result=response_json,
        )
        return False, []

    paths = []
    network_statuses = views.get_networkstatuses(chain_state)
    for path_object in response_json['result']:
        path = path_object['path']

        # get the second entry, as the first one is the node itself
        # also needs to be converted to canonical representation
        partner_address = to_canonical_address(path[1])

        # don't route back
        if partner_address == previous_address:
            continue

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state=chain_state,
            token_network_id=token_network_id,
            partner_address=partner_address,
        )

        channel_constraints_fulfilled = check_channel_constraints(
            channel_state=channel_state,
            from_address=from_address,
            partner_address=partner_address,
            amount=amount,
            network_statuses=network_statuses,
            routing_module='Pathfinding Service',
        )
        if not channel_constraints_fulfilled:
            continue

        paths.append(
            RouteState(
                node_address=partner_address,
                channel_identifier=channel_state.identifier,
            ))

    return True, paths
Esempio n. 8
0
def get_best_routes_internal(
    chain_state: ChainState,
    token_network_id: typing.TokenNetworkID,
    from_address: typing.InitiatorAddress,
    to_address: typing.TargetAddress,
    amount: int,
    previous_address: typing.Optional[typing.Address],
) -> List[RouteState]:
    """ Returns a list of channels that can be used to make a transfer.

    This will filter out channels that are not open and don't have enough
    capacity.
    """
    # TODO: Route ranking.
    # Rate each route to optimize the fee price/quality of each route and add a
    # rate from in the range [0.0,1.0].

    available_routes = list()

    token_network = views.get_token_network_by_identifier(
        chain_state,
        token_network_id,
    )

    network_statuses = views.get_networkstatuses(chain_state)

    neighbors_heap = list()
    try:
        all_neighbors = networkx.all_neighbors(
            token_network.network_graph.network, from_address)
    except networkx.NetworkXError:
        # If `our_address` is not in the graph, no channels opened with the
        # address
        return list()

    for partner_address in all_neighbors:
        # don't send the message backwards
        if partner_address == previous_address:
            continue

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state,
            token_network_id,
            partner_address,
        )

        channel_constraints_fulfilled = check_channel_constraints(
            channel_state=channel_state,
            from_address=from_address,
            partner_address=partner_address,
            amount=amount,
            network_statuses=network_statuses,
            routing_module='Internal Routing',
        )
        if not channel_constraints_fulfilled:
            continue

        nonrefundable = amount > channel.get_distributable(
            channel_state.partner_state,
            channel_state.our_state,
        )

        try:
            length = networkx.shortest_path_length(
                token_network.network_graph.network,
                partner_address,
                to_address,
            )
            heappush(
                neighbors_heap,
                (length, nonrefundable, partner_address,
                 channel_state.identifier),
            )
        except (networkx.NetworkXNoPath, networkx.NodeNotFound):
            pass

    if not neighbors_heap:
        log.warning(
            'No routes available',
            from_address=pex(from_address),
            to_address=pex(to_address),
        )
        return list()

    while neighbors_heap:
        *_, partner_address, channel_state_id = heappop(neighbors_heap)
        route_state = RouteState(partner_address, channel_state_id)
        available_routes.append(route_state)
    return available_routes
Esempio n. 9
0
def get_best_routes(
        chain_state: ChainState,
        token_network_id: typing.TokenNetworkID,
        from_address: typing.InitiatorAddress,
        to_address: typing.TargetAddress,
        amount: int,
        previous_address: typing.Optional[typing.Address],
) -> List[RouteState]:
    """ Returns a list of channels that can be used to make a transfer.

    This will filter out channels that are not open and don't have enough
    capacity.
    """
    # TODO: Route ranking.
    # Rate each route to optimize the fee price/quality of each route and add a
    # rate from in the range [0.0,1.0].

    available_routes = list()

    token_network = views.get_token_network_by_identifier(
        chain_state,
        token_network_id,
    )

    network_statuses = views.get_networkstatuses(chain_state)

    neighbors_heap = list()
    try:
        all_neighbors = networkx.all_neighbors(token_network.network_graph.network, from_address)
    except networkx.NetworkXError:
        # If `our_address` is not in the graph, no channels opened with the
        # address
        return list()

    for partner_address in all_neighbors:
        # don't send the message backwards
        if partner_address == previous_address:
            continue

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state,
            token_network_id,
            partner_address,
        )

        assert channel_state is not None

        if channel.get_status(channel_state) != CHANNEL_STATE_OPENED:
            log.info(
                'channel is not opened, ignoring',
                from_address=pex(from_address),
                partner_address=pex(partner_address),
            )
            continue

        distributable = channel.get_distributable(
            channel_state.our_state,
            channel_state.partner_state,
        )

        if amount > distributable:
            log.info(
                'channel doesnt have enough funds, ignoring',
                from_address=pex(from_address),
                partner_address=pex(partner_address),
                amount=amount,
                distributable=distributable,
            )
            continue

        network_state = network_statuses.get(partner_address, NODE_NETWORK_UNKNOWN)

        if network_state != NODE_NETWORK_REACHABLE:
            log.info(
                'partner for channel state isn\'t reachable, ignoring',
                from_address=pex(from_address),
                partner_address=pex(partner_address),
                status=network_state,
            )
            continue

        nonrefundable = amount > channel.get_distributable(
            channel_state.partner_state,
            channel_state.our_state,
        )

        try:
            length = networkx.shortest_path_length(
                token_network.network_graph.network,
                partner_address,
                to_address,
            )
            heappush(
                neighbors_heap,
                (length, nonrefundable, partner_address, channel_state.identifier),
            )
        except (networkx.NetworkXNoPath, networkx.NodeNotFound):
            pass

    if not neighbors_heap:
        log.warning(
            'No routes available',
            from_address=pex(from_address),
            to_address=pex(to_address),
        )
        return list()

    while neighbors_heap:
        *_, partner_address, channel_state_id = heappop(neighbors_heap)
        route_state = RouteState(partner_address, channel_state_id)
        available_routes.append(route_state)
    return available_routes
Esempio n. 10
0
def get_best_routes_pfs(
        chain_state: ChainState,
        token_network_id: typing.TokenNetworkID,
        from_address: typing.InitiatorAddress,
        to_address: typing.TargetAddress,
        amount: int,
        previous_address: typing.Optional[typing.Address],
        config: Dict[str, Any],
) -> Tuple[bool, List[RouteState]]:
    pfs_path = '{}/api/v1/{}/paths'.format(
        config['pathfinding_service_address'],
        to_checksum_address(token_network_id),
    )
    payload = {
        'from': to_checksum_address(from_address),
        'to': to_checksum_address(to_address),
        'value': amount,
        'max_paths': config['pathfinding_max_paths'],
    }

    # check that the response is successful
    try:
        response = requests.get(pfs_path, params=payload, timeout=DEFAULT_HTTP_REQUEST_TIMEOUT)
    except requests.RequestException:
        log.warning(
            'Could not connect to Pathfinding Service',
            request=pfs_path,
            parameters=payload,
            exc_info=True,
        )
        return False, []

    # check that the response contains valid json
    try:
        response_json = response.json()
    except ValueError:
        log.warning(
            'Pathfinding Service returned invalid JSON',
            response_text=response.text,
            exc_info=True,
        )
        return False, []

    if response.status_code != 200:
        log_info = {
            'error_code': response.status_code,
        }

        error = response_json.get('errors')
        if error is not None:
            log_info['pfs_error'] = error

        log.info(
            'Pathfinding Service returned error code',
            **log_info,
        )
        return False, []

    if response_json.get('result') is None:
        log.info(
            'Pathfinding Service returned unexpected result',
            result=response_json,
        )
        return False, []

    paths = []
    network_statuses = views.get_networkstatuses(chain_state)
    for path_object in response_json['result']:
        path = path_object['path']

        # get the second entry, as the first one is the node itself
        # also needs to be converted to canonical representation
        partner_address = to_canonical_address(path[1])

        # don't route back
        if partner_address == previous_address:
            continue

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state=chain_state,
            token_network_id=token_network_id,
            partner_address=partner_address,
        )

        channel_constraints_fulfilled = check_channel_constraints(
            channel_state=channel_state,
            from_address=from_address,
            partner_address=partner_address,
            amount=amount,
            network_statuses=network_statuses,
            routing_module='Pathfinding Service',
        )
        if not channel_constraints_fulfilled:
            continue

        paths.append(RouteState(
            node_address=partner_address,
            channel_identifier=channel_state.identifier,
        ))

    return True, paths
Esempio n. 11
0
def get_best_routes_internal(
        chain_state: ChainState,
        token_network_id: typing.TokenNetworkID,
        from_address: typing.InitiatorAddress,
        to_address: typing.TargetAddress,
        amount: int,
        previous_address: typing.Optional[typing.Address],
) -> List[RouteState]:
    """ Returns a list of channels that can be used to make a transfer.

    This will filter out channels that are not open and don't have enough
    capacity.
    """
    # TODO: Route ranking.
    # Rate each route to optimize the fee price/quality of each route and add a
    # rate from in the range [0.0,1.0].

    available_routes = list()

    token_network = views.get_token_network_by_identifier(
        chain_state,
        token_network_id,
    )

    network_statuses = views.get_networkstatuses(chain_state)

    neighbors_heap = list()
    try:
        all_neighbors = networkx.all_neighbors(token_network.network_graph.network, from_address)
    except networkx.NetworkXError:
        # If `our_address` is not in the graph, no channels opened with the
        # address
        return list()

    for partner_address in all_neighbors:
        # don't send the message backwards
        if partner_address == previous_address:
            continue

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state,
            token_network_id,
            partner_address,
        )

        channel_constraints_fulfilled = check_channel_constraints(
            channel_state=channel_state,
            from_address=from_address,
            partner_address=partner_address,
            amount=amount,
            network_statuses=network_statuses,
            routing_module='Internal Routing',
        )
        if not channel_constraints_fulfilled:
            continue

        nonrefundable = amount > channel.get_distributable(
            channel_state.partner_state,
            channel_state.our_state,
        )

        try:
            length = networkx.shortest_path_length(
                token_network.network_graph.network,
                partner_address,
                to_address,
            )
            heappush(
                neighbors_heap,
                (length, nonrefundable, partner_address, channel_state.identifier),
            )
        except (networkx.NetworkXNoPath, networkx.NodeNotFound):
            pass

    if not neighbors_heap:
        log.warning(
            'No routes available',
            from_address=pex(from_address),
            to_address=pex(to_address),
        )
        return list()

    while neighbors_heap:
        *_, partner_address, channel_state_id = heappop(neighbors_heap)
        route_state = RouteState(partner_address, channel_state_id)
        available_routes.append(route_state)
    return available_routes
Esempio n. 12
0
def get_best_routes(
        chain_state: ChainState,
        token_network_id: typing.Address,
        from_address: typing.Address,
        to_address: typing.Address,
        amount: int,
        previous_address: typing.Address,
) -> List[RouteState]:
    """ Returns a list of channels that can be used to make a transfer.

    This will filter out channels that are not open and don't have enough
    capacity.
    """
    # TODO: Route ranking.
    # Rate each route to optimize the fee price/quality of each route and add a
    # rate from in the range [0.0,1.0].

    available_routes = list()

    token_network = views.get_token_network_by_identifier(
        chain_state,
        token_network_id,
    )

    network_statuses = views.get_networkstatuses(chain_state)

    neighbors_heap = get_ordered_partners(
        token_network.network_graph.network,
        from_address,
        to_address,
    )

    if not neighbors_heap:
        log.warning(
            'No routes available from %s to %s' % (pex(from_address), pex(to_address)),
        )

    while neighbors_heap:
        _, partner_address = heappop(neighbors_heap)

        channel_state = views.get_channelstate_by_token_network_and_partner(
            chain_state,
            token_network_id,
            partner_address,
        )

        # don't send the message backwards
        if partner_address == previous_address:
            continue

        if channel.get_status(channel_state) != CHANNEL_STATE_OPENED:
            log.info(
                'channel %s - %s is not opened, ignoring' %
                (pex(from_address), pex(partner_address)),
            )
            continue

        distributable = channel.get_distributable(
            channel_state.our_state,
            channel_state.partner_state,
        )

        if amount > distributable:
            log.info(
                'channel %s - %s doesnt have enough funds [%s], ignoring' %
                (pex(from_address), pex(partner_address), amount),
            )
            continue

        network_state = network_statuses.get(partner_address, NODE_NETWORK_UNKNOWN)
        if network_state != NODE_NETWORK_REACHABLE:
            log.info(
                'partner for channel %s - %s is not %s, ignoring' %
                (pex(from_address), pex(partner_address), NODE_NETWORK_REACHABLE),
            )
            continue

        route_state = RouteState(partner_address, channel_state.identifier)
        available_routes.append(route_state)

    return available_routes