def test_next_route(): target = factories.HOP1 routes = [ factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT), factories.make_route(factories.HOP3, available_balance=factories.UNIT_TRANSFER_AMOUNT - 1), factories.make_route(factories.HOP4, available_balance=factories.UNIT_TRANSFER_AMOUNT), ] state = make_initiator_state(routes, target) assert state.route == routes[0], 'a initialized state must use the first valid route' assert state.routes.available_routes == routes[1:] assert not state.routes.ignored_routes assert not state.routes.refunded_routes assert not state.routes.canceled_routes with pytest.raises(AssertionError, message='cannot try a new route while one is in use'): initiator.try_new_route(state) state.routes.canceled_routes.append(state.route) state.route = None initiator.try_new_route(state) # HOP3 should be ignored because it doesnt have enough balance assert len(state.routes.ignored_routes) == 1 assert not state.routes.available_routes assert not state.routes.refunded_routes assert state.routes.canceled_routes
def handle_cancelroute( payment_state: InitiatorPaymentState, state_change: ActionCancelRoute, channelidentifiers_to_channels: initiator.ChannelMap, pseudo_random_generator: random.Random, block_number: typing.BlockNumber, ) -> TransitionResult: events = list() if can_cancel(payment_state): transfer_description = payment_state.initiator.transfer_description cancel_events = cancel_current_route(payment_state) msg = 'The previous transfer must be cancelled prior to trying a new route' assert payment_state.initiator is None, msg sub_iteration = initiator.try_new_route( channelidentifiers_to_channels, state_change.routes, transfer_description, pseudo_random_generator, block_number, ) events.extend(cancel_events) events.extend(sub_iteration.events) if sub_iteration.new_state: payment_state.initiator = sub_iteration.new_state else: payment_state = None iteration = TransitionResult(payment_state, events) return iteration
def handle_init( payment_state: InitiatorPaymentState, state_change: ActionInitInitiator, channelidentifiers_to_channels: ChannelMap, pseudo_random_generator: random.Random, block_number: BlockNumber, ) -> TransitionResult: events: List[Event] if payment_state is None: sub_iteration = initiator.try_new_route( old_initiator_state=None, channelidentifiers_to_channels=channelidentifiers_to_channels, available_routes=state_change.routes, transfer_description=state_change.transfer, pseudo_random_generator=pseudo_random_generator, block_number=block_number, ) events = sub_iteration.events if sub_iteration.new_state: payment_state = InitiatorPaymentState(sub_iteration.new_state) else: events = list() iteration = TransitionResult(payment_state, events) return iteration
def handle_init( payment_state: InitiatorPaymentState, state_change: ActionInitInitiator, channelidentifiers_to_channels: initiator.ChannelMap, pseudo_random_generator: random.Random, block_number: typing.BlockNumber, ) -> TransitionResult: if payment_state is None: sub_iteration = initiator.try_new_route( channelidentifiers_to_channels, state_change.routes, state_change.transfer, pseudo_random_generator, block_number, ) events = sub_iteration.events if sub_iteration.new_state: payment_state = InitiatorPaymentState(sub_iteration.new_state) else: events = list() iteration = TransitionResult(payment_state, events) return iteration
def handle_transferreroute( payment_state: InitiatorPaymentState, state_change: ActionTransferReroute, channelidentifiers_to_channels: Dict[ChannelID, NettingChannelState], addresses_to_channel: Dict[Tuple[TokenNetworkAddress, Address], NettingChannelState], nodeaddresses_to_networkstates: NodeNetworkStateMap, pseudo_random_generator: random.Random, block_number: BlockNumber, ) -> TransitionResult[InitiatorPaymentState]: try: initiator_state = payment_state.initiator_transfers[ state_change.transfer.lock.secrethash] channel_identifier = initiator_state.channel_identifier channel_state = channelidentifiers_to_channels[channel_identifier] except KeyError: return TransitionResult(payment_state, list()) refund_transfer = state_change.transfer original_transfer = initiator_state.transfer is_valid_lock = ( refund_transfer.lock.secrethash == original_transfer.lock.secrethash and refund_transfer.lock.amount == original_transfer.lock.amount and refund_transfer.lock.expiration == original_transfer.lock.expiration) is_valid_refund = channel.refund_transfer_matches_transfer( refund_transfer, original_transfer) is_valid, channel_events, _ = channel.handle_receive_lockedtransfer( channel_state, refund_transfer) if not is_valid_lock or not is_valid_refund or not is_valid: return TransitionResult(payment_state, list()) events: List[Event] = [] events.extend(channel_events) old_description = initiator_state.transfer_description filtered_route_states = routes.filter_acceptable_routes( route_states=payment_state.routes, blacklisted_channel_ids=payment_state.cancelled_channels, addresses_to_channel=addresses_to_channel, token_network_address=old_description.token_network_address, ) transfer_description = TransferDescriptionWithSecretState( token_network_registry_address=old_description. token_network_registry_address, payment_identifier=old_description.payment_identifier, amount=old_description.amount, token_network_address=old_description.token_network_address, initiator=old_description.initiator, target=old_description.target, secret=state_change.secret, secrethash=state_change.secrethash, ) sub_iteration = initiator.try_new_route( addresses_to_channel=addresses_to_channel, nodeaddresses_to_networkstates=nodeaddresses_to_networkstates, candidate_route_states=filtered_route_states, transfer_description=transfer_description, pseudo_random_generator=pseudo_random_generator, block_number=block_number, ) events.extend(sub_iteration.events) if sub_iteration.new_state is None: # Here we don't delete the initiator state, but instead let it live. # It will be deleted when the lock expires. We do that so that we # still have an initiator payment task around to process the # LockExpired message that our partner will send us. # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046 return TransitionResult(payment_state, events) new_transfer = sub_iteration.new_state.transfer payment_state.initiator_transfers[ new_transfer.lock.secrethash] = sub_iteration.new_state return TransitionResult(payment_state, events)