def test_routing_simple( token_network_model: TokenNetwork, populate_token_network_case_1: None, addresses: List[Address], ): view01: ChannelView = token_network_model.G[addresses[0]][ addresses[1]]["view"] view10: ChannelView = token_network_model.G[addresses[1]][ addresses[0]]["view"] assert view01.deposit == 100 assert view01.absolute_fee == 0 assert view01.capacity == 90 assert view10.capacity == 60 # 0->2->3 is the shortest path, but has no capacity, so 0->1->4->3 is used paths = token_network_model.get_paths(addresses[0], addresses[3], value=TokenAmount(10), max_paths=1, hop_bias=1) assert len(paths) == 1 assert paths[0] == { "path": [addresses[0], addresses[1], addresses[4], addresses[3]], "estimated_fee": 0, } # Not connected. with pytest.raises(NetworkXNoPath): token_network_model.get_paths(addresses[0], addresses[5], value=TokenAmount(10), max_paths=1)
def test_routing_simple( token_network_model: TokenNetwork, populate_token_network_case_1: None, addresses: List[Address], ): view01: ChannelView = token_network_model.G[addresses[0]][ addresses[1]]['view'] view10: ChannelView = token_network_model.G[addresses[1]][ addresses[0]]['view'] assert view01.deposit == 100 assert isclose(view01.relative_fee, DEFAULT_PERCENTAGE_FEE) assert view01.capacity == 90 assert view10.capacity == 60 # 0->2->3 is the shortest path, but has no capacity, so 0->1->4->3 is used paths = token_network_model.get_paths( addresses[0], addresses[3], value=10, max_paths=1, hop_bias=1, ) assert len(paths) == 1 assert paths[0] == { 'path': [addresses[0], addresses[1], addresses[4], addresses[3]], 'estimated_fee': 0, } # Not connected. with pytest.raises(NetworkXNoPath): token_network_model.get_paths(addresses[0], addresses[5], value=10, max_paths=1)
def test_routing_result_order( token_network_model: TokenNetwork, reachability_state: SimpleReachabilityContainer, addresses: List[Address], ): hex_addrs = [to_checksum_address(addr) for addr in addresses] paths = token_network_model.get_paths( source=addresses[0], target=addresses[2], value=PaymentAmount(10), max_paths=5, reachability_state=reachability_state, ) # 5 paths requested, but only 2 are available assert len(paths) == 2 assert paths[0].to_dict()["path"] == [ hex_addrs[0], hex_addrs[1], hex_addrs[2] ] assert paths[0].to_dict()["estimated_fee"] == 0 assert paths[1].to_dict()["path"] == [ hex_addrs[0], hex_addrs[1], hex_addrs[4], hex_addrs[3], hex_addrs[2], ] assert paths[1].to_dict()["estimated_fee"] == 0
def test_capacity_check( token_network_model: TokenNetwork, reachability_state: SimpleReachabilityContainer, addresses: List[Address], ): """Test that the mediation fees are included in the capacity check""" # First get a path without mediation fees. This must return the shortest path: 4->1->0 paths = token_network_model.get_paths( source=addresses[4], target=addresses[0], value=PaymentAmount(35), max_paths=1, reachability_state=reachability_state, ) index_paths = [addresses_to_indexes(p.nodes, addresses) for p in paths] assert index_paths == [[4, 1, 0]] # New let's add mediation fees to the channel 0->1. model_with_fees = deepcopy(token_network_model) model_with_fees.G[addresses[1]][ addresses[0]]["view"].fee_schedule_sender.flat = 1 # The transfer from 4->1 must now include 1 Token for the mediation fee # which will be payed for the 1->0 channel in addition to the payment # value of 35. But 35 + 1 exceeds the capacity for channel 4->1, which is # 35. So we should now get the next best route instead. paths = model_with_fees.get_paths( source=addresses[4], target=addresses[0], value=PaymentAmount(35), max_paths=1, reachability_state=reachability_state, fee_penalty=0, ) index_paths = [addresses_to_indexes(p.nodes, addresses) for p in paths] assert index_paths == [[4, 1, 2, 0]]
def test_routing_benchmark( token_network_model: TokenNetwork, populate_token_network_random: None, ): value = 100 G = token_network_model.G times = [] start = time.time() for _ in range(100): tic = time.time() source, target = random.sample(G.nodes, 2) paths = token_network_model.get_paths(source, target, value=value, max_paths=5, bias=0.0) toc = time.time() times.append(toc - tic) end = time.time() for path_object in paths: path = path_object['path'] fees = path_object['estimated_fee'] for node1, node2 in zip(path[:-1], path[1:]): view: ChannelView = G[node1][node2]['view'] print('fee = ', view.relative_fee, 'capacity = ', view.capacity) print('fee sum = ', fees) print('Paths: ', paths) print('Mean runtime: ', sum(times) / len(times)) print('Min runtime: ', min(times)) print('Max runtime: ', max(times)) print('Total runtime: ', end - start)
def test_routing_benchmark(token_network_model: TokenNetwork, populate_token_network_random: None): value = TokenAmount(100) G = token_network_model.G times = [] start = time.time() for _ in range(100): tic = time.time() source, target = random.sample(G.nodes, 2) paths = token_network_model.get_paths(source, target, value=value, max_paths=5, bias=0.0) toc = time.time() times.append(toc - tic) end = time.time() for path_object in paths: path = path_object["path"] fees = path_object["estimated_fee"] for node1, node2 in zip(path[:-1], path[1:]): view: ChannelView = G[node1][node2]["view"] print("fee = ", view.absolute_fee, "capacity = ", view.capacity) print("fee sum = ", fees) print("Paths: ", paths) print("Mean runtime: ", sum(times) / len(times)) print("Min runtime: ", min(times)) print("Max runtime: ", max(times)) print("Total runtime: ", end - start)
def test_routing_result_order( token_network_model: TokenNetwork, populate_token_network_case_1: None, addresses: List[Address], ): paths = token_network_model.get_paths( addresses[0], addresses[2], value=10, max_paths=5, hop_bias=1, ) # 5 paths requested, but only 3 are available assert len(paths) == 3 assert paths[0] == { 'path': [addresses[0], addresses[2]], 'estimated_fee': 0, } assert paths[1] == { 'path': [addresses[0], addresses[1], addresses[2]], 'estimated_fee': 0, } assert paths[2] == { 'path': [addresses[0], addresses[1], addresses[4], addresses[3], addresses[2]], 'estimated_fee': 0, }
def test_routing_simple( token_network_model: TokenNetwork, reachability_state: SimpleReachabilityContainer, addresses: List[Address], ): hex_addrs = [to_checksum_address(addr) for addr in addresses] view01: ChannelView = token_network_model.G[addresses[0]][ addresses[1]]["view"] view10: ChannelView = token_network_model.G[addresses[1]][ addresses[0]]["view"] assert view01.fee_schedule_sender.flat == 0 assert view01.capacity == 90 assert view10.capacity == 60 # 0->2->3 is the shortest path, but has no capacity. # The remaining paths are 0->1->2->3 and 0->1->4->3. paths = token_network_model.get_paths( source=addresses[0], target=addresses[3], value=PaymentAmount(10), max_paths=2, reachability_state=reachability_state, ) assert len(paths) == 2 assert paths[0].to_dict()["path"] == [ hex_addrs[0], hex_addrs[1], hex_addrs[2], hex_addrs[3] ] assert paths[0].to_dict()["estimated_fee"] == 0 assert paths[1].to_dict()["path"] == [ hex_addrs[0], hex_addrs[1], hex_addrs[4], hex_addrs[3] ] assert paths[1].to_dict()["estimated_fee"] == 0 # Not connected. no_paths = token_network_model.get_paths( source=addresses[0], target=addresses[5], value=PaymentAmount(10), max_paths=1, reachability_state=reachability_state, ) assert [] == no_paths
def test_routing_result_order(token_network_model: TokenNetwork, addresses: List[Address]): paths = token_network_model.get_paths(addresses[0], addresses[2], value=TokenAmount(10), max_paths=5) # 5 paths requested, but only 1 is available assert len(paths) == 1 assert paths[0] == { "path": [addresses[0], addresses[1], addresses[2]], "estimated_fee": 0 }
def test_routing_simple( token_network_model: TokenNetwork, address_to_reachability: Dict[Address, AddressReachability], addresses: List[Address], ): hex_addrs = [to_checksum_address(addr) for addr in addresses] view01: ChannelView = token_network_model.G[addresses[0]][ addresses[1]]["view"] view10: ChannelView = token_network_model.G[addresses[1]][ addresses[0]]["view"] assert view01.deposit == 100 assert view01.fee_schedule_sender.flat == 0 assert view01.capacity == 90 assert view10.capacity == 60 # 0->2->3 is the shortest path, but has no capacity, so 0->1->4->3 is used paths = token_network_model.get_paths( source=addresses[0], target=addresses[3], value=TokenAmount(10), max_paths=1, address_to_reachability=address_to_reachability, ) assert len(paths) == 1 assert paths[0] == { "path": [hex_addrs[0], hex_addrs[1], hex_addrs[4], hex_addrs[3]], "estimated_fee": 0, } # Not connected. with pytest.raises(NetworkXNoPath): token_network_model.get_paths( source=addresses[0], target=addresses[5], value=TokenAmount(10), max_paths=1, address_to_reachability=address_to_reachability, )
def test_routing_result_order( token_network_model: TokenNetwork, address_to_reachability: Dict[Address, AddressReachability], addresses: List[Address], ): hex_addrs = [to_checksum_address(addr) for addr in addresses] paths = token_network_model.get_paths( addresses[0], addresses[2], value=PaymentAmount(10), max_paths=5, address_to_reachability=address_to_reachability, ) # 5 paths requested, but only 1 is available assert len(paths) == 1 assert paths[0] == {"path": [hex_addrs[0], hex_addrs[1], hex_addrs[2]], "estimated_fee": 0}
def test_routing_benchmark(token_network_model: TokenNetwork): # pylint: disable=too-many-locals value = PaymentAmount(100) G = token_network_model.G addresses_to_reachabilities = SimpleReachabilityContainer({ node: random.choice(( AddressReachability.REACHABLE, AddressReachability.UNKNOWN, AddressReachability.UNREACHABLE, )) for node in G.nodes }) times = [] start = time.time() for _ in range(100): tic = time.time() source, target = random.sample(G.nodes, 2) paths = token_network_model.get_paths( source=source, target=target, value=value, max_paths=5, reachability_state=addresses_to_reachabilities, ) toc = time.time() times.append(toc - tic) end = time.time() for path_object in paths: path = path_object.nodes fees = path_object.estimated_fee for node1, node2 in zip(path[:-1], path[1:]): view: ChannelView = G[to_canonical_address(node1)][ to_canonical_address(node2)]["view"] print("capacity = ", view.capacity) print("fee sum = ", fees) print("Paths: ", paths) print("Mean runtime: ", sum(times) / len(times)) print("Min runtime: ", min(times)) print("Max runtime: ", max(times)) print("Total runtime: ", end - start)
def get_paths( # pylint: disable=too-many-arguments token_network_model: TokenNetwork, reachability_state: SimpleReachabilityContainer, addresses: List[Address], source_index: int = 0, target_index: int = 8, value: PaymentAmount = PaymentAmount(10), max_paths: int = 5, diversity_penalty: float = DIVERSITY_PEN_DEFAULT, ) -> List: paths = token_network_model.get_paths( diversity_penalty=diversity_penalty, source=addresses[source_index], target=addresses[target_index], value=value, max_paths=max_paths, reachability_state=reachability_state, ) index_paths = [addresses_to_indexes(p.nodes, addresses) for p in paths] return index_paths
def get_paths( # pylint: disable=too-many-arguments token_network_model: TokenNetwork, address_to_reachability: Dict[Address, AddressReachability], addresses: List[Address], source_index: int = 0, target_index: int = 8, value: TokenAmount = TokenAmount(10), max_paths: int = 5, diversity_penalty: float = DIVERSITY_PEN_DEFAULT, ) -> List: paths = token_network_model.get_paths( diversity_penalty=diversity_penalty, source=addresses[source_index], target=addresses[target_index], value=value, max_paths=max_paths, address_to_reachability=address_to_reachability, ) index_paths = [addresses_to_indexes(p["path"], addresses) for p in paths] return index_paths