<commit_before># -*- coding: utf-8 -*-
import logging
from collections import namedtuple
from heapq import heappush, heappop

import networkx
from ethereum import slogging

from raiden.utils import isaddress, pex
from raiden.transfer.state import (
    RouteState,
    CHANNEL_STATE_OPENED,
    CHANNEL_STATE_CLOSED,
)
from raiden.channel.netting_channel import (
    Channel,
)
from raiden.network.protocol import (
    NODE_NETWORK_UNKNOWN,
    NODE_NETWORK_REACHABLE,
)

log = slogging.getLogger(__name__)  # pylint: disable=invalid-name

ChannelDetails = namedtuple(
    'ChannelDetails',
    (
        'channel_address',
        'our_state',
        'partner_state',
        'external_state',
        'reveal_timeout',
        'settle_timeout',
    )
)


def make_graph(edge_list):
    """ Return a graph that represents the connections among the netting
    contracts.

    Args:
        edge_list (List[(address1, address2)]): All the channels that compose
            the graph.

    Returns:
        Graph A networkx.Graph instance were the graph nodes are nodes in the
            network and the edges are nodes that have a channel between them.
    """

    for edge in edge_list:
        if len(edge) != 2:
            raise ValueError('All values in edge_list must be of length two (origin, destination)')

        origin, destination = edge

        if not isaddress(origin) or not isaddress(destination):
            raise ValueError('All values in edge_list must be valid addresses')

    graph = networkx.Graph()  # undirected graph, for bidirectional channels

    for first, second in edge_list:
        graph.add_edge(first, second)

    return graph


def channel_to_routestate(channel, node_address):
    state = channel.state
    channel_address = channel.external_state.netting_channel.address
    distributable = channel.distributable
    settle_timeout = channel.settle_timeout
    reveal_timeout = channel.reveal_timeout

    if state == CHANNEL_STATE_CLOSED:
        closed_block = channel.external_state.closed_block
    else:
        closed_block = None

    state = RouteState(
        state=state,
        node_address=node_address,
        channel_address=channel_address,
        available_balance=distributable,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=closed_block,
    )

    return state


def ordered_neighbors(nx_graph, our_address, target_address):
    paths = list()

    try:
        all_neighbors = networkx.all_neighbors(nx_graph, our_address)
    except networkx.NetworkXError:
        # If `our_address` is not in the graph, no channels opened with the
        # address
        return []

    for neighbor in all_neighbors:
        try:
            length = networkx.shortest_path_length(
                nx_graph,
                neighbor,
                target_address,
            )
            heappush(paths, (length, neighbor))
        except networkx.NetworkXNoPath:
            pass

    return paths


def get_best_routes(
        channel_graph,
        nodeaddresses_statuses,
        our_address,
        target_address,
        amount,
        previous_address=None):

    """ Yield a two-tuple (path, channel) that can be used to mediate the
    transfer. The result is ordered from the best to worst path.
    """

    # XXX: consider using multiple channels for a single transfer. Useful
    # for cases were the `amount` is larger than what is available
    # individually in any of the channels.
    #
    # One possible approach is to _not_ filter these channels based on the
    # distributable amount, but to sort them based on available balance and
    # let the task use as many as required to finish the transfer.

    online_nodes = list()
    unknown_nodes = list()

    neighbors_heap = ordered_neighbors(
        channel_graph.graph,
        our_address,
        target_address,
    )

    while neighbors_heap:
        _, partner_address = heappop(neighbors_heap)
        channel = channel_graph.partneraddress_to_channel[partner_address]

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

        if not channel.can_transfer:
            if log.isEnabledFor(logging.INFO):
                log.info(
                    'channel %s - %s is closed or has zero funding, ignoring',
                    pex(our_address),
                    pex(partner_address),
                )

            continue

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

        if channel.state != CHANNEL_STATE_OPENED:
            continue

        network_state = nodeaddresses_statuses[partner_address]
        route_state = channel_to_routestate(channel, partner_address)

        if network_state == NODE_NETWORK_REACHABLE:
            online_nodes.append(route_state)

        elif network_state == NODE_NETWORK_UNKNOWN:
            unknown_nodes.append(route_state)

    return online_nodes + unknown_nodes


class ChannelGraph(object):
    """ Has Graph based on the channels and can find path between participants. """

    def __init__(
            self,
            our_address,
            channelmanager_address,
            token_address,
            edge_list,
            channels_details,
            block_number):

        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        graph = make_graph(edge_list)
        self.address_to_channel = dict()
        self.graph = graph
        self.our_address = our_address
        self.partneraddress_to_channel = dict()
        self.token_address = token_address
        self.channelmanager_address = channelmanager_address

        for details in channels_details:
            self.add_channel(details)<commit_msg>Ignore channels with invalid parameters<commit_after># -*- coding: utf-8 -*-
import logging
from collections import namedtuple
from heapq import heappush, heappop

import networkx
from ethereum import slogging

from raiden.utils import isaddress, pex
from raiden.transfer.state import (
    RouteState,
    CHANNEL_STATE_OPENED,
    CHANNEL_STATE_CLOSED,
)
from raiden.channel.netting_channel import (
    Channel,
)
from raiden.network.protocol import (
    NODE_NETWORK_UNKNOWN,
    NODE_NETWORK_REACHABLE,
)

log = slogging.getLogger(__name__)  # pylint: disable=invalid-name

ChannelDetails = namedtuple(
    'ChannelDetails',
    (
        'channel_address',
        'our_state',
        'partner_state',
        'external_state',
        'reveal_timeout',
        'settle_timeout',
    )
)


def make_graph(edge_list):
    """ Return a graph that represents the connections among the netting
    contracts.

    Args:
        edge_list (List[(address1, address2)]): All the channels that compose
            the graph.

    Returns:
        Graph A networkx.Graph instance were the graph nodes are nodes in the
            network and the edges are nodes that have a channel between them.
    """

    for edge in edge_list:
        if len(edge) != 2:
            raise ValueError('All values in edge_list must be of length two (origin, destination)')

        origin, destination = edge

        if not isaddress(origin) or not isaddress(destination):
            raise ValueError('All values in edge_list must be valid addresses')

    graph = networkx.Graph()  # undirected graph, for bidirectional channels

    for first, second in edge_list:
        graph.add_edge(first, second)

    return graph


def channel_to_routestate(channel, node_address):
    state = channel.state
    channel_address = channel.external_state.netting_channel.address
    distributable = channel.distributable
    settle_timeout = channel.settle_timeout
    reveal_timeout = channel.reveal_timeout

    if state == CHANNEL_STATE_CLOSED:
        closed_block = channel.external_state.closed_block
    else:
        closed_block = None

    state = RouteState(
        state=state,
        node_address=node_address,
        channel_address=channel_address,
        available_balance=distributable,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=closed_block,
    )

    return state


def ordered_neighbors(nx_graph, our_address, target_address):
    paths = list()

    try:
        all_neighbors = networkx.all_neighbors(nx_graph, our_address)
    except networkx.NetworkXError:
        # If `our_address` is not in the graph, no channels opened with the
        # address
        return []

    for neighbor in all_neighbors:
        try:
            length = networkx.shortest_path_length(
                nx_graph,
                neighbor,
                target_address,
            )
            heappush(paths, (length, neighbor))
        except networkx.NetworkXNoPath:
            pass

    return paths


def get_best_routes(
        channel_graph,
        nodeaddresses_statuses,
        our_address,
        target_address,
        amount,
        previous_address=None):

    """ Yield a two-tuple (path, channel) that can be used to mediate the
    transfer. The result is ordered from the best to worst path.
    """

    # XXX: consider using multiple channels for a single transfer. Useful
    # for cases were the `amount` is larger than what is available
    # individually in any of the channels.
    #
    # One possible approach is to _not_ filter these channels based on the
    # distributable amount, but to sort them based on available balance and
    # let the task use as many as required to finish the transfer.

    online_nodes = list()
    unknown_nodes = list()

    neighbors_heap = ordered_neighbors(
        channel_graph.graph,
        our_address,
        target_address,
    )

    while neighbors_heap:
        _, partner_address = heappop(neighbors_heap)
        channel = channel_graph.partneraddress_to_channel[partner_address]

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

        if not channel.can_transfer:
            if log.isEnabledFor(logging.INFO):
                log.info(
                    'channel %s - %s is closed or has zero funding, ignoring',
                    pex(our_address),
                    pex(partner_address),
                )

            continue

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

        if channel.state != CHANNEL_STATE_OPENED:
            continue

        network_state = nodeaddresses_statuses[partner_address]
        route_state = channel_to_routestate(channel, partner_address)

        if network_state == NODE_NETWORK_REACHABLE:
            online_nodes.append(route_state)

        elif network_state == NODE_NETWORK_UNKNOWN:
            unknown_nodes.append(route_state)

    return online_nodes + unknown_nodes


class ChannelGraph(object):
    """ Has Graph based on the channels and can find path between participants. """

    def __init__(
            self,
            our_address,
            channelmanager_address,
            token_address,
            edge_list,
            channels_details,
            block_number):

        if not isaddress(token_address):
            raise ValueError('token_address must be a valid address')

        graph = make_graph(edge_list)
        self.address_to_channel = dict()
        self.graph = graph
        self.our_address = our_address
        self.partneraddress_to_channel = dict()
        self.token_address = token_address
        self.channelmanager_address = channelmanager_address

        for details in channels_details:
            try:
                self.add_channel(details)
            except ValueError as e:
                log.warn(
                    "Error at registering opened channel contract. Perhaps contract is invalid?",
                    error=str(e),
                    channel_address=pex(details.channel_address)
                )
{'fraction_non_alphanumeric': 0.06413529036375239, 'fraction_numerical': 0.0006381620931716656, 'mean_word_length': 2.2656941911956237, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5875686', 'n_tokens_mistral': 3431, 'n_tokens_neox': 3283, 'n_words': 937}