示例#1
0
    def check_path_request_errors(
        self,
        source: Address,
        target: Address,
        value: PaymentAmount,
        reachability_state: AddressReachabilityProtocol,
    ) -> Optional[str]:
        """Checks for basic problems with the path requests. Returns error message or `None`"""

        with opentracing.tracer.start_span("check_path_request_errors"):
            if (reachability_state.get_address_reachability(source)
                    is not AddressReachability.REACHABLE):
                return "Source not online"

            if (reachability_state.get_address_reachability(target)
                    is not AddressReachability.REACHABLE):
                return "Target not online"

            if not any(self.G.edges(source)):
                return "No channel from source"
            if not any(self.G.edges(target)):
                return "No channel to target"

            source_capacities = [
                view.capacity
                for _, _, view in self.G.out_edges(source, data="view")
            ]
            if max(source_capacities) < value:
                debug_capacities = [
                    (to_checksum_address(a), to_checksum_address(b),
                     view.capacity)
                    for a, b, view in self.G.out_edges(source, data="view")
                ]
                log.debug("Insufficient capacities",
                          capacities=debug_capacities)
                message = (
                    f"Source does not have a channel with sufficient capacity "
                    f"(current capacities: {source_capacities} < requested amount: "
                    f" {value})")
                return message
            target_capacities = [
                view.capacity
                for _, _, view in self.G.in_edges(target, data="view")
            ]
            if max(target_capacities) < value:
                return "Target does not have a channel with sufficient capacity (%s < %s)" % (
                    target_capacities,
                    value,
                )

            try:
                next(
                    nx.shortest_simple_paths(G=self.G,
                                             source=source,
                                             target=target))
            except NetworkXNoPath:
                return "No route from source to target"

            return None
示例#2
0
def prune_graph(graph: DiGraph, reachability_state: AddressReachabilityProtocol) -> DiGraph:
    """Prunes the given `graph` of all channels where the participants are not  reachable."""
    pruned_graph = DiGraph()
    for p1, p2 in graph.edges:
        nodes_online = (
            reachability_state.get_address_reachability(p1) == AddressReachability.REACHABLE
            and reachability_state.get_address_reachability(p2) == AddressReachability.REACHABLE
        )
        if nodes_online:
            pruned_graph.add_edge(p1, p2, view=graph[p1][p2]["view"])
            pruned_graph.add_edge(p2, p1, view=graph[p2][p1]["view"])

    return pruned_graph
示例#3
0
    def suggest_partner(self,
                        reachability_state: AddressReachabilityProtocol,
                        limit: int = 5) -> List[Dict[str, Any]]:
        """Suggest good partners for Raiden nodes joining the token network"""

        with opentracing.tracer.start_span("find_centrality"):
            # centrality
            centrality_of_node = nx.algorithms.centrality.closeness_centrality(
                self.G)

        # uptime, only include online nodes
        uptime_of_node = {}
        now = datetime.utcnow()
        for node in self.G.nodes:
            node_reach_state = reachability_state.get_address_reachability_state(
                node)
            if node_reach_state.reachability == AddressReachability.REACHABLE:
                uptime_of_node[node] = (now -
                                        node_reach_state.time).total_seconds()

        # capacity
        capacity_of_node = {}
        for node in uptime_of_node:
            channel_views = [
                channel_data["view"]
                for _, _, channel_data in self.G.edges(node, data=True)
            ]
            capacity_of_node[node] = sum(cv.capacity for cv in channel_views)

        # sort by overall score
        suggestions = [
            dict(
                address=to_checksum_address(node),
                score=centrality_of_node[node] * uptime *
                capacity_of_node[node],
                centrality=centrality_of_node[node],
                uptime=uptime,
                capacity=capacity_of_node[node],
            ) for node, uptime in uptime_of_node.items()
        ]
        return sorted(suggestions, key=lambda n: -n["score"])[:limit]