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