def initiator_init( raiden: 'RaidenService', transfer_identifier: PaymentID, transfer_amount: PaymentAmount, transfer_secret: Secret, token_network_identifier: TokenNetworkID, target_address: TargetAddress, ): msg = 'Should never end up initiating transfer with Secret 0x0' assert transfer_secret != constants.EMPTY_HASH, msg transfer_state = TransferDescriptionWithSecretState( raiden.default_registry.address, transfer_identifier, transfer_amount, token_network_identifier, InitiatorAddress(raiden.address), target_address, transfer_secret, ) previous_address = None routes = routing.get_best_routes( chain_state=views.state_from_raiden(raiden), token_network_id=token_network_identifier, from_address=InitiatorAddress(raiden.address), to_address=target_address, amount=transfer_amount, previous_address=previous_address, config=raiden.config, ) init_initiator_statechange = ActionInitInitiator( transfer_state, routes, ) return init_initiator_statechange
def initiator_init( raiden, transfer_identifier, transfer_amount, transfer_secret, token_network_identifier, target_address, ): transfer_state = TransferDescriptionWithSecretState( transfer_identifier, transfer_amount, token_network_identifier, raiden.address, target_address, transfer_secret, ) previous_address = None routes = routing.get_best_routes( views.state_from_raiden(raiden), token_network_identifier, raiden.address, target_address, transfer_amount, previous_address, ) init_initiator_statechange = ActionInitInitiator( transfer_state, routes, ) return init_initiator_statechange
def handle_message_refundtransfer(raiden: RaidenService, message: RefundTransfer): token_network_address = message.token_network_address from_transfer = lockedtransfersigned_from_message(message) chain_state = views.state_from_raiden(raiden) routes = get_best_routes( chain_state, token_network_address, raiden.address, from_transfer.target, from_transfer.lock.amount, message.sender, ) role = views.get_transfer_role( chain_state, from_transfer.lock.secrethash, ) if role == 'initiator': secret = random_secret() state_change = ReceiveTransferRefundCancelRoute( message.sender, routes, from_transfer, secret, ) else: state_change = ReceiveTransferRefund( message.sender, from_transfer, routes, ) raiden.handle_state_change(state_change)
def test_routing_mocked_pfs_bad_http_code( chain_state, payment_network_state, token_network_state, our_address, ): token_network_state, addresses, channel_states = create_square_network_topology( payment_network_state=payment_network_state, token_network_state=token_network_state, our_address=our_address, ) address1, address2, address3 = addresses channel_state1, channel_state2 = channel_states # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } # channel 1 and 2 are flipped here, to see when the PFS gets called json_data = { 'result': [ { 'path': [to_checksum_address(our_address), to_checksum_address(address2)], 'fees': 0, }, { 'path': [to_checksum_address(our_address), to_checksum_address(address1)], 'fees': 0, }, ], } response = Mock() response.configure_mock(status_code=400) response.json = Mock(return_value=json_data) with patch.object(requests, 'get', return_value=response): routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={ 'services': { 'pathfinding_service_address': 'my-pfs', 'pathfinding_max_paths': 3, }, }, ) assert routes[0].node_address == address1 assert routes[0].channel_identifier == channel_state1.identifier assert routes[1].node_address == address2 assert routes[1].channel_identifier == channel_state2.identifier
def test_routing_mocked_pfs_invalid_json_structure( chain_state, payment_network_state, token_network_state, our_address, ): token_network_state, addresses, channel_states = create_square_network_topology( payment_network_state=payment_network_state, token_network_state=token_network_state, our_address=our_address, ) address1, address2, address3 = addresses channel_state1, channel_state2 = channel_states # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } response = Mock() response.configure_mock(status_code=400) response.json = Mock(return_value={}) with patch.object(requests, 'get', return_value=response): routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={ 'services': { 'pathfinding_service_address': 'my-pfs', 'pathfinding_max_paths': 3, }, }, ) assert routes[0].node_address == address1 assert routes[0].channel_identifier == channel_state1.identifier assert routes[1].node_address == address2 assert routes[1].channel_identifier == channel_state2.identifier
def mediator_init(raiden, transfer: LockedTransfer): from_transfer = lockedtransfersigned_from_message(transfer) routes = routing.get_best_routes( views.state_from_raiden(raiden), from_transfer.balance_proof.token_network_identifier, raiden.address, from_transfer.target, from_transfer.lock.amount, transfer.sender, ) from_route = RouteState( transfer.sender, from_transfer.balance_proof.channel_address, ) init_mediator_statechange = ActionInitMediator( routes, from_route, from_transfer, ) return init_mediator_statechange
def test_routing_mocked_pfs_request_error( chain_state, payment_network_state, token_network_state, our_address, ): token_network_state, addresses, channel_states = create_square_network_topology( payment_network_state=payment_network_state, token_network_state=token_network_state, our_address=our_address, ) address1, address2, address3 = addresses channel_state1, channel_state2 = channel_states # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } with patch.object(requests, 'get', side_effect=requests.RequestException()): routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={ 'services': { 'pathfinding_service_address': 'my-pfs', 'pathfinding_max_paths': 3, }, }, ) assert routes[0].node_address == address1 assert routes[0].channel_identifier == channel_state1.identifier assert routes[1].node_address == address2 assert routes[1].channel_identifier == channel_state2.identifier
def test_routing_priority(chain_state, token_network_state, one_to_n_address, our_address): open_block_number = factories.make_block_number() open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() pseudo_random_generator = random.Random() # Create a network with the following topology # # our ----- 1/1 ----> (1) # | | # | | # 2/0 x # | | # v v # (2) ----- x -----> (3) # | | # | | # x x # | | # v v # (4) (4) channel_state1 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=1, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=1, address=address1), )) channel_state2 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=2, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address2), )) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change1, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) channel_new_iteration2 = token_network.state_transition( token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=3), participant1=address2, participant2=address3, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration3 = token_network.state_transition( token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration4 = token_network.state_transition( token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration5 = token_network.state_transition( token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) channel_new_state_change6 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address2, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) token_network.state_transition( token_network_state=channel_new_iteration5.new_state, state_change=channel_new_state_change6, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) # test routing priority with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, } error_msg, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address3, amount=1, previous_address=None, pfs_config=None, privkey=b"", ) assert routes, error_msg assert routes[0].next_hop_address == address1, error_msg assert routes[1].next_hop_address == address2, error_msg # number of hops overwrites refunding capacity (route over node 2 involves less hops) chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } _, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=1, previous_address=None, pfs_config=None, privkey=b"", ) assert routes[0].next_hop_address == address2 assert routes[1].next_hop_address == address1
def test_routing_issue2663(chain_state, token_network_state, one_to_n_address, our_address): open_block_number = 10 open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() pseudo_random_generator = random.Random() # Create a network with the following topology # # our ----- 50 ----> (1) <------50------ # | | # | | # 100 (4) # | ^ # v | # (2) ----- 100 ---> (3) <-------100--- channel_state1 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=50, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address1), )) channel_state2 = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=100, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address2), )) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration1 = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change1, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) channel_new_iteration2 = token_network.state_transition( token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration2.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=3), participant1=address2, participant2=address3, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration3 = token_network.state_transition( token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration3.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 3 assert len(graph_state.network.edges()) == 3 channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address3, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration4 = token_network.state_transition( token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration4.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 4 assert len(graph_state.network.edges()) == 4 channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=5), participant1=address1, participant2=address4, block_number=open_block_number, block_hash=open_block_number_hash, ) channel_new_iteration5 = token_network.state_transition( token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = channel_new_iteration5.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 5 assert len(graph_state.network.edges()) == 5 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } error_msg, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes1, error_msg assert routes1[0].next_hop_address == address1, error_msg assert routes1[1].next_hop_address == address2, error_msg # test routing with node 2 offline chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.UNREACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } _, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, pfs_config=None, privkey=b"", ) assert routes1[0].next_hop_address == address1 # test routing with node 3 offline # the routing doesn't care as node 3 is not directly connected chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.UNREACHABLE, address4: NetworkState.REACHABLE, } _, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address4, amount=50, previous_address=None, pfs_config=None, privkey=b"", ) assert routes1[0].next_hop_address == address1 assert routes1[1].next_hop_address == address2 # test routing with node 1 offline chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.UNREACHABLE, address2: NetworkState.REACHABLE, address3: NetworkState.REACHABLE, address4: NetworkState.REACHABLE, } _, routes1, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address3, amount=50, previous_address=None, pfs_config=None, privkey=b"", ) # right now the channel to 1 gets filtered out as it is offline assert routes1[0].next_hop_address == address2
def test_internal_routing_mediation_fees(chain_state, token_network_state, one_to_n_address, our_address): """ Checks that requesting a route for a single-hop transfer will return the route with estimated_fee of zero. """ open_block_number = 10 open_block_number_hash = factories.make_block_hash() address1 = factories.make_address() address2 = factories.make_address() pseudo_random_generator = random.Random() direct_channel_state = factories.create( factories.NettingChannelStateProperties( our_state=factories.NettingChannelEndStateProperties( balance=50, address=our_address), partner_state=factories.NettingChannelEndStateProperties( balance=0, address=address1), )) # create new channels as participant direct_channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=direct_channel_state, block_number=open_block_number, block_hash=open_block_number_hash, ) direct_channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=direct_channel_new_state_change, block_number=open_block_number, block_hash=open_block_number_hash, pseudo_random_generator=pseudo_random_generator, ) route_new_state_change = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_state.address, channel_identifier=4), participant1=address1, participant2=address2, block_number=open_block_number, block_hash=open_block_number_hash, ) route_new_iteration = token_network.state_transition( token_network_state=direct_channel_new_iteration.new_state, state_change=route_new_state_change, block_number=open_block_number + 10, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) graph_state = route_new_iteration.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NetworkState.REACHABLE, address2: NetworkState.REACHABLE, } # Routing to our direct partner would require 0 mediation fees.x _, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address1, amount=50, previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes[0].estimated_fee == 0 # Routing to our address2 through address1 would charge 2% error_msg, routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address2, amount=50, previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes, error_msg assert routes[0].estimated_fee == round(INTERNAL_ROUTING_DEFAULT_FEE_PERC * 50), error_msg
def test_routing_priority( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() address4 = factories.make_address() # Create a network with the following topology # # our ----- 1/1 ----> (1) # | | # | | # 2/0 x # | | # v v # (2) ----- x -----> (3) # | | # | | # x x # | | # v v # (4) (4) channel_state1 = factories.make_channel( our_balance=1, our_address=our_address, partner_balance=1, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=2, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address4, block_number=open_block_number, ) channel_new_iteration5 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change6 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address2, participant2=address4, block_number=open_block_number, ) token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration5.new_state, state_change=channel_new_state_change6, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) # test routing priority with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address1 assert routes[1].node_address == address2 # number of hops overwrites refunding capacity (route over node 2 involves less hops) chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, address4: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address4, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address2 assert routes[1].node_address == address1 # sufficient routing capacity overwrites refunding capacity chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=2, previous_address=None, config={}, ) assert routes[0].node_address == address2 # availability overwrites refunding capacity (node 1 offline) chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_UNREACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address2
def test_routing_issue2663( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() address1 = factories.make_address() address2 = factories.make_address() address3 = factories.make_address() # Create a network with the following topology # # our ----- 50 ----> (1) # | ^ # | | # 100 100 # | | # v | # (2) ----- 100 ---> (3) channel_state1 = factories.make_channel( our_balance=50, our_address=our_address, partner_balance=0, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=100, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) graph_state = channel_new_iteration2.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) graph_state = channel_new_iteration3.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 3 assert len(graph_state.network.edges()) == 3 channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) graph_state = channel_new_iteration4.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 4 assert len(graph_state.network.edges()) == 4 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2 # test routing with node 2 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_UNREACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2 == [] # test routing with node 3 offline # the routing doesn't care as node 3 is not directly connected chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_UNREACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2 # test routing with node 1 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_UNREACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) # right now the channel to 1 gets filtered out as it is offline assert routes1[0].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2
def test_participant_selection(raiden_network, token_addresses): # pylint: disable=too-many-locals registry_address = raiden_network[0].raiden.default_registry.address one_to_n_address = raiden_network[0].raiden.default_one_to_n_address token_address = token_addresses[0] # connect the first node - this will register the token and open the first channel # Since there is no other nodes available to connect to this call will do nothing more RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(100)) # Test invalid argument values with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(-1)) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(100), joinable_funds_target=2, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(100), joinable_funds_target=-1, ) # Call the connect endpoint for all but the first node connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_address_by_token_address( views.state_from_raiden(raiden_network[0].raiden), token_network_registry_address=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address) for app in raiden_network ] unsaturated_connection_managers = connection_managers[:] exception = AssertionError("Unsaturated connection managers", unsaturated_connection_managers) with gevent.Timeout(120, exception): while unsaturated_connection_managers: for manager in unsaturated_connection_managers: if is_manager_saturated(manager, registry_address, token_address): unsaturated_connection_managers.remove(manager) gevent.sleep(1) assert saturated_count(connection_managers, registry_address, token_address) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue _, routes, _ = routing.get_best_routes( chain_state=node_state, token_network_address=network_state.address, one_to_n_address=one_to_n_address, from_address=app.raiden.address, to_address=target.raiden.address, amount=PaymentAmount(1), previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle for app in raiden_network: sender = app.raiden sender_channel = next( (channel_state for channel_state in RaidenAPI( sender).get_channel_list(registry_address=registry_address, token_address=token_address) if channel_state.our_state.contract_balance > 0 and channel_state.partner_state.contract_balance > 0), None, ) # choose a fully funded channel from sender if sender_channel: break assert sender_channel registry_address = sender.default_registry.address receiver = next( app.raiden for app in raiden_network if app.raiden.address == sender_channel.partner_state.address) # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 with gevent.Timeout(30, exception=ValueError("partner not reachable")): waiting.wait_for_healthy(sender, receiver.address, PaymentAmount(1)) with watch_for_unlock_failures(*raiden_network): amount = PaymentAmount(1) RaidenAPI(sender).transfer_and_wait(registry_address, token_address, amount, receiver.address, transfer_timeout=10) with gevent.Timeout( 30, exception=ValueError( "timeout while waiting for incoming transaction")): wait_for_transaction(receiver, registry_address, token_address, sender.address) # test `leave()` method connection_manager = connection_managers[0] timeout = (sender_channel.settle_timeout * estimate_blocktime(connection_manager.raiden.rpc_client) * 10) assert timeout > 0 channels = views.list_channelstate_for_tokennetwork( chain_state=views.state_from_raiden(connection_manager.raiden), token_network_registry_address=registry_address, token_address=token_address, ) channel_identifiers = [channel.identifier for channel in channels] with gevent.Timeout( timeout, exception=ValueError("timeout while waiting for leave")): # sender leaves the network RaidenAPI(sender).token_network_leave(registry_address, token_address) with gevent.Timeout(timeout, exception=ValueError( f"Channels didnt get settled after {timeout}")): waiting.wait_for_settle( raiden=connection_manager.raiden, token_network_registry_address=registry_address, token_address=token_address, channel_ids=channel_identifiers, retry_timeout=0.1, )
def test_routing_issue2663( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey1, address1 = factories.make_privkey_address() pkey2, address2 = factories.make_privkey_address() pkey3, address3 = factories.make_privkey_address() # Create a network with the following topology # # our ----- 50 ----> (1) # | ^ # | | # 100 100 # | | # v | # (2) ----- 100 ---> (3) channel_state1 = factories.make_channel( our_balance=50, our_address=our_address, partner_balance=0, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=100, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) graph_state = channel_new_iteration2.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 2 assert len(graph_state.network.edges()) == 2 # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) graph_state = channel_new_iteration3.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 3 assert len(graph_state.network.edges()) == 3 channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) graph_state = channel_new_iteration4.new_state.network_graph assert len(graph_state.channel_identifier_to_participants) == 4 assert len(graph_state.network.edges()) == 4 # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2 # test routing with node 2 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_UNREACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2 == [] # test routing with node 3 offline # the routing doesn't care as node 3 is not directly connected chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_UNREACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) assert routes1[0].node_address == address1 assert routes1[1].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2 # test routing with node 1 offline chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_UNREACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes1 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={}, ) # right now the channel to 1 gets filtered out as it is offline assert routes1[0].node_address == address2 routes2 = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=51, previous_address=None, config={}, ) assert routes2[0].node_address == address2
def get_best_routes_with_iou_request_mocked( chain_state, token_network_state, one_to_n_address, from_address, to_address, amount, iou_json_data=None, ): def iou_side_effect(*args, **kwargs): if args[0].endswith("/info"): return mocked_json_response({ "price_info": 5, "network_info": { "chain_id": 42, "token_network_registry_address": to_checksum_address( factories.make_token_network_registry_address()), "user_deposit_address": to_checksum_address(factories.make_address()), "confirmed_block": { "number": 11 }, }, "version": "0.0.3", "operator": "John Doe", "message": "This is your favorite pathfinding service", "payment_address": to_checksum_address(factories.make_address()), "matrix_server": "http://matrix.example.com", }) else: assert "params" in kwargs body = kwargs["params"] assert is_hex_address(body["sender"]) assert is_hex_address(body["receiver"]) assert "timestamp" in body assert is_hex(body["signature"]) assert len(body["signature"] ) == 65 * 2 + 2 # 65 hex encoded bytes with 0x prefix return mocked_json_response(response_data=iou_json_data) with patch.object(session, "get", side_effect=iou_side_effect) as patched: _, best_routes, feedback_token = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=from_address, to_address=to_address, amount=amount, previous_address=None, pfs_config=PFS_CONFIG, privkey=PRIVKEY, ) assert_checksum_address_in_url(patched.call_args[0][0]) return best_routes, feedback_token
def get_best_routes_with_fees(*args, **kwargs): error_msg, routes, uuid = get_best_routes(*args, **kwargs) for r in routes: r.estimated_fee = fee_without_margin return error_msg, routes, uuid
def test_participant_selection(raiden_network, token_addresses, skip_if_tester): registry_address = raiden_network[0].raiden.default_registry.address # pylint: disable=too-many-locals token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address, token_address, 100, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_identifier_by_token_address( views.state_from_raiden(raiden_network[0].raiden), payment_network_id=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address, ) for app in raiden_network ] assert wait_for_saturated( connection_managers, registry_address, token_address, ) is True assert saturated_count( connection_managers, registry_address, token_address, ) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address, ) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue routes = routing.get_best_routes( node_state, network_state.address, app.raiden.address, target.raiden.address, 1, None, ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle sender = raiden_network[-1].raiden receiver = raiden_network[0].raiden registry_address = sender.default_registry.address # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] # assert there is a direct channel sender -> receiver sender_channel = RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=receiver.address, ) assert len(sender_channel) == 1 sender_channel = sender_channel[0] exception = ValueError('partner not reachable') with gevent.Timeout(30, exception=exception): waiting.wait_for_healthy(sender, receiver.address, 1) amount = 1 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, amount, receiver.address, transfer_timeout=10, ) exception = ValueError('timeout while waiting for incoming transaction') with gevent.Timeout(30, exception=exception): wait_for_transaction( receiver, registry_address, token_address, sender.address, ) # test `leave()` method connection_manager = connection_managers[0] timeout = ( sender_channel.settle_timeout * connection_manager.raiden.chain.estimate_blocktime() * 10 ) assert timeout > 0 exception = ValueError('timeout while waiting for leave') with gevent.Timeout(timeout, exception=exception): RaidenAPI(raiden_network[0].raiden).token_network_leave( registry_address, token_address, ) before_block = connection_manager.raiden.chain.block_number() wait_blocks = sender_channel.settle_timeout + 10 # wait until both chains are synced? wait_until_block( connection_manager.raiden.chain, before_block + wait_blocks, ) wait_until_block( receiver.chain, before_block + wait_blocks, ) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert receiver_channel[0].settle_transaction is not None
def test_participant_selection(raiden_network, token_addresses, skip_if_tester): registry_address = raiden_network[0].raiden.default_registry.address # pylint: disable=too-many-locals token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address, token_address, 100, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_identifier_by_token_address( views.state_from_raiden(raiden_network[0].raiden), payment_network_id=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address, ) for app in raiden_network ] unsaturated_connection_managers = connection_managers[:] with gevent.Timeout( 120, AssertionError('Unsaturated connection managers', unsaturated_connection_managers), ): while unsaturated_connection_managers: for manager in unsaturated_connection_managers: if is_manager_saturated(manager, registry_address, token_address): unsaturated_connection_managers.remove(manager) gevent.sleep(1) assert saturated_count( connection_managers, registry_address, token_address, ) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address, ) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue routes = routing.get_best_routes( node_state, network_state.address, app.raiden.address, target.raiden.address, 1, None, ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle sender = raiden_network[-1].raiden receiver = raiden_network[0].raiden registry_address = sender.default_registry.address # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] # assert there is a direct channel sender -> receiver sender_channel = RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=receiver.address, ) assert len(sender_channel) == 1 sender_channel = sender_channel[0] exception = ValueError('partner not reachable') with gevent.Timeout(30, exception=exception): waiting.wait_for_healthy(sender, receiver.address, 1) amount = 1 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, amount, receiver.address, transfer_timeout=10, ) exception = ValueError('timeout while waiting for incoming transaction') with gevent.Timeout(30, exception=exception): wait_for_transaction( receiver, registry_address, token_address, sender.address, ) # test `leave()` method connection_manager = connection_managers[0] timeout = ( sender_channel.settle_timeout * connection_manager.raiden.chain.estimate_blocktime() * 10 ) assert timeout > 0 exception = ValueError('timeout while waiting for leave') with gevent.Timeout(timeout, exception=exception): RaidenAPI(raiden_network[0].raiden).token_network_leave( registry_address, token_address, ) before_block = connection_manager.raiden.chain.block_number() wait_blocks = sender_channel.settle_timeout + 10 # wait until both chains are synced? wait_until_block( connection_manager.raiden.chain, before_block + wait_blocks, ) wait_until_block( receiver.chain, before_block + wait_blocks, ) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert receiver_channel[0].settle_transaction is not None
def run_test_participant_selection(raiden_network, token_addresses): # pylint: disable=too-many-locals registry_address = raiden_network[0].raiden.default_registry.address token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, ) # Test invalid argument values with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=-1, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, joinable_funds_target=2, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, joinable_funds_target=-1, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_identifier_by_token_address( views.state_from_raiden(raiden_network[0].raiden), payment_network_id=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address, ) for app in raiden_network ] unsaturated_connection_managers = connection_managers[:] exception = AssertionError('Unsaturated connection managers', unsaturated_connection_managers) with gevent.Timeout(120, exception): while unsaturated_connection_managers: for manager in unsaturated_connection_managers: if is_manager_saturated(manager, registry_address, token_address): unsaturated_connection_managers.remove(manager) gevent.sleep(1) assert saturated_count( connection_managers, registry_address, token_address, ) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address, ) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue routes = routing.get_best_routes( chain_state=node_state, token_network_id=network_state.address, from_address=app.raiden.address, to_address=target.raiden.address, amount=1, previous_address=None, config={}, privkey=b'', # not used if pfs is not configured ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle for app in raiden_network: sender = app.raiden sender_channel = next( (channel_state for channel_state in RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, ) if channel_state.our_state.contract_balance > 0 and channel_state.partner_state.contract_balance > 0), None, ) # choose a fully funded channel from sender if sender_channel: break registry_address = sender.default_registry.address receiver = next( app.raiden for app in raiden_network if app.raiden.address == sender_channel.partner_state.address) # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] exception = ValueError('partner not reachable') with gevent.Timeout(30, exception=exception): waiting.wait_for_healthy(sender, receiver.address, 1) amount = 1 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, amount, receiver.address, transfer_timeout=10, ) exception = ValueError('timeout while waiting for incoming transaction') with gevent.Timeout(30, exception=exception): wait_for_transaction( receiver, registry_address, token_address, sender.address, ) # test `leave()` method connection_manager = connection_managers[0] timeout = (sender_channel.settle_timeout * connection_manager.raiden.chain.estimate_blocktime() * 10) assert timeout > 0 channels = views.list_channelstate_for_tokennetwork( chain_state=views.state_from_raiden(connection_manager.raiden), payment_network_id=registry_address, token_address=token_address, ) channel_identifiers = [channel.identifier for channel in channels] exception = ValueError('timeout while waiting for leave') with gevent.Timeout(timeout, exception=exception): # sender leaves the network RaidenAPI(sender).token_network_leave( registry_address, token_address, ) exception = ValueError(f'Channels didnt get settled after {timeout}') with gevent.Timeout(timeout, exception=exception): waiting.wait_for_settle( raiden=connection_manager.raiden, payment_network_id=registry_address, token_address=token_address, channel_ids=channel_identifiers, retry_timeout=0.1, )
def test_participant_selection(raiden_network, token_addresses): registry_address = raiden_network[0].raiden.default_registry.address # pylint: disable=too-many-locals token_address = token_addresses[0] # connect the first node (will register the token if necessary) RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, ) # Test invalid argument values with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=-1, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, joinable_funds_target=2, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=100, joinable_funds_target=-1, ) # connect the other nodes connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100, ) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_identifier_by_token_address( views.state_from_raiden(raiden_network[0].raiden), payment_network_id=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address, ) for app in raiden_network ] unsaturated_connection_managers = connection_managers[:] with gevent.Timeout( 120, AssertionError('Unsaturated connection managers', unsaturated_connection_managers), ): while unsaturated_connection_managers: for manager in unsaturated_connection_managers: if is_manager_saturated(manager, registry_address, token_address): unsaturated_connection_managers.remove(manager) gevent.sleep(1) assert saturated_count( connection_managers, registry_address, token_address, ) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address, ) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue routes = routing.get_best_routes( node_state, network_state.address, app.raiden.address, target.raiden.address, 1, None, ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle for app in raiden_network: sender = app.raiden sender_channel = next(( channel_state for channel_state in RaidenAPI(sender).get_channel_list( registry_address=registry_address, token_address=token_address, ) if channel_state.our_state.contract_balance > 0 and channel_state.partner_state.contract_balance > 0 ), None) # choose a fully funded channel from sender if sender_channel: break registry_address = sender.default_registry.address receiver = next( app.raiden for app in raiden_network if app.raiden.address == sender_channel.partner_state.address ) # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 receiver_channel = receiver_channel[0] exception = ValueError('partner not reachable') with gevent.Timeout(30, exception=exception): waiting.wait_for_healthy(sender, receiver.address, 1) amount = 1 RaidenAPI(sender).transfer_and_wait( registry_address, token_address, amount, receiver.address, transfer_timeout=10, ) exception = ValueError('timeout while waiting for incoming transaction') with gevent.Timeout(30, exception=exception): wait_for_transaction( receiver, registry_address, token_address, sender.address, ) # test `leave()` method connection_manager = connection_managers[0] timeout = ( sender_channel.settle_timeout * connection_manager.raiden.chain.estimate_blocktime() * 10 ) assert timeout > 0 exception = ValueError('timeout while waiting for leave') with gevent.Timeout(timeout, exception=exception): # sender leaves the network RaidenAPI(sender).token_network_leave( registry_address, token_address, ) before_block = connection_manager.raiden.chain.block_number() wait_blocks = sender_channel.settle_timeout + 10 # wait until both chains are synced? wait_until_block( connection_manager.raiden.chain, before_block + wait_blocks, ) wait_until_block( receiver.chain, before_block + wait_blocks, ) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) # because of timing, channel may already have been cleaned assert not receiver_channel or receiver_channel[0].settle_transaction is not None
def test_routing_priority( chain_state, payment_network_state, token_network_state, our_address, ): open_block_number = 10 pseudo_random_generator = random.Random() pkey1, address1 = factories.make_privkey_address() pkey2, address2 = factories.make_privkey_address() pkey3, address3 = factories.make_privkey_address() pkey4, address4 = factories.make_privkey_address() # Create a network with the following topology # # our ----- 1/1 ----> (1) # | | # | | # 2/0 x # | | # v v # (2) ----- x -----> (3) # | | # | | # x x # | | # v v # (4) (4) channel_state1 = factories.make_channel( our_balance=1, our_address=our_address, partner_balance=1, partner_address=address1, ) channel_state2 = factories.make_channel( our_balance=2, our_address=our_address, partner_balance=0, partner_address=address2, ) # create new channels as participant channel_new_state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state1, block_number=open_block_number, ) channel_new_state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_state=channel_state2, block_number=open_block_number, ) channel_new_iteration1 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=token_network_state, state_change=channel_new_state_change1, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) channel_new_iteration2 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration1.new_state, state_change=channel_new_state_change2, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number, ) # create new channels without being participant channel_new_state_change3 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=3, participant1=address2, participant2=address3, block_number=open_block_number, ) channel_new_iteration3 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration2.new_state, state_change=channel_new_state_change3, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change4 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address1, block_number=open_block_number, ) channel_new_iteration4 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration3.new_state, state_change=channel_new_state_change4, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change5 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address3, participant2=address4, block_number=open_block_number, ) channel_new_iteration5 = token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration4.new_state, state_change=channel_new_state_change5, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) channel_new_state_change6 = ContractReceiveRouteNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_state.address, channel_identifier=4, participant1=address2, participant2=address4, block_number=open_block_number, ) token_network.state_transition( payment_network_identifier=payment_network_state.address, token_network_state=channel_new_iteration5.new_state, state_change=channel_new_state_change6, pseudo_random_generator=pseudo_random_generator, block_number=open_block_number + 10, ) # test routing priority with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address1 assert routes[1].node_address == address2 # number of hops overwrites refunding capacity (route over node 2 involves less hops) chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, address4: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address4, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address2 assert routes[1].node_address == address1 # sufficient routing capacity overwrites refunding capacity chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=2, previous_address=None, config={}, ) assert routes[0].node_address == address2 # availability overwrites refunding capacity (node 1 offline) chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_UNREACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address3, amount=1, previous_address=None, config={}, ) assert routes[0].node_address == address2
def test_routing_mocked_pfs_unavailabe_peer( chain_state, payment_network_state, token_network_state, our_address, ): token_network_state, addresses, channel_states = create_square_network_topology( payment_network_state=payment_network_state, token_network_state=token_network_state, our_address=our_address, ) address1, address2, address3 = addresses _, channel_state2 = channel_states # test routing with all nodes available chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_REACHABLE, address3: NODE_NETWORK_REACHABLE, } # channel 1 and 2 are flipped here, to see when the PFS gets called json_data = { 'result': [ { 'path': [ to_checksum_address(our_address), to_checksum_address(address2) ], 'fees': 0, }, { 'path': [ to_checksum_address(our_address), to_checksum_address(address1) ], 'fees': 0, }, ], } # test routing with node 2 unavailable chain_state.nodeaddresses_to_networkstates = { address1: NODE_NETWORK_REACHABLE, address2: NODE_NETWORK_UNREACHABLE, address3: NODE_NETWORK_REACHABLE, } response = Mock() response.configure_mock(status_code=200) response.json = Mock(return_value=json_data) with patch.object(requests, 'post', return_value=response): routes = get_best_routes( chain_state=chain_state, token_network_id=token_network_state.address, from_address=our_address, to_address=address1, amount=50, previous_address=None, config={ 'services': { 'pathfinding_service_address': 'my-pfs', 'pathfinding_max_paths': 3, }, }, ) assert routes[0].node_address == address2 assert routes[0].channel_identifier == channel_state2.identifier