Ejemplo n.º 1
0
    def mediate_mediated_transfer(self, message):
        # pylint: disable=too-many-locals
        identifier = message.identifier
        amount = message.lock.amount
        target = message.target
        token = message.token
        graph = self.channelgraphs[token]
        routes = get_best_routes(
            graph,
            self.protocol.nodeaddresses_networkstatuses,
            self.address,
            target,
            amount,
            lock_timeout=None,
        )

        available_routes = [
            route
            for route in map(route_to_routestate, routes)
            if route.state == CHANNEL_STATE_OPENED
        ]

        from_channel = graph.partneraddress_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

        our_address = self.address
        from_transfer = lockedtransfer_from_message(message)
        route_state = RoutesState(available_routes)
        block_number = self.get_block_number()

        init_mediator = ActionInitMediator(
            our_address,
            from_transfer,
            route_state,
            from_route,
            block_number,
        )

        state_manager = StateManager(mediator.state_transition, None)

        self.state_machine_event_handler.log_and_dispatch(state_manager, init_mediator)

        self.identifier_to_statemanagers[identifier].append(state_manager)
    def mediate_mediated_transfer(self, message):
        # pylint: disable=too-many-locals
        identifier = message.identifier
        amount = message.lock.amount
        target = message.target
        token = message.token
        graph = self.token_to_channelgraph[token]

        available_routes = get_best_routes(
            graph,
            self.protocol.nodeaddresses_networkstatuses,
            self.address,
            target,
            amount,
            message.sender,
        )

        from_channel = graph.partneraddress_to_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

        our_address = self.address
        from_transfer = lockedtransfer_from_message(message)
        route_state = RoutesState(available_routes)
        block_number = self.get_block_number()

        init_mediator = ActionInitMediator(
            our_address,
            from_transfer,
            route_state,
            from_route,
            block_number,
        )

        state_manager = StateManager(mediator.state_transition, None)

        self.state_machine_event_handler.log_and_dispatch(state_manager, init_mediator)

        self.identifier_to_statemanagers[identifier].append(state_manager)
Ejemplo n.º 3
0
    def start_mediated_transfer(self, token_address, amount, identifier,
                                target):
        # pylint: disable=too-many-locals

        async_result = AsyncResult()
        graph = self.token_to_channelgraph[token_address]

        available_routes = get_best_routes(
            graph,
            self.protocol.nodeaddresses_networkstatuses,
            self.address,
            target,
            amount,
            None,
        )

        if not available_routes:
            async_result.set(False)
            return async_result

        self.protocol.start_health_check(target)

        if identifier is None:
            identifier = create_default_identifier()

        route_state = RoutesState(available_routes)
        our_address = self.address
        block_number = self.get_block_number()

        transfer_state = LockedTransferState(
            identifier=identifier,
            amount=amount,
            token=token_address,
            initiator=self.address,
            target=target,
            expiration=None,
            hashlock=None,
            secret=None,
        )

        # Issue #489
        #
        # Raiden may fail after a state change using the random generator is
        # handled but right before the snapshot is taken. If that happens on
        # the next initialization when raiden is recovering and applying the
        # pending state changes a new secret will be generated and the
        # resulting events won't match, this breaks the architecture model,
        # since it's assumed the re-execution of a state change will always
        # produce the same events.
        #
        # TODO: Removed the secret generator from the InitiatorState and add
        # the secret into all state changes that require one, this way the
        # secret will be serialized with the state change and the recovery will
        # use the same /random/ secret.
        random_generator = RandomSecretGenerator()

        init_initiator = ActionInitInitiator(
            our_address=our_address,
            transfer=transfer_state,
            routes=route_state,
            random_generator=random_generator,
            block_number=block_number,
        )

        state_manager = StateManager(initiator.state_transition, None)
        self.state_machine_event_handler.log_and_dispatch(
            state_manager, init_initiator)

        # TODO: implement the network timeout raiden.config['msg_timeout'] and
        # cancel the current transfer if it hapens (issue #374)
        self.identifier_to_statemanagers[identifier].append(state_manager)
        self.identifier_to_results[identifier].append(async_result)

        return async_result
    def _run(self):  # pylint: disable=method-hidden,too-many-locals
        fee = 0
        raiden = self.raiden
        tokenswap = self.tokenswap

        # this is the MediatedTransfer that wil pay the maker's half of the
        # swap, not necessarily from him
        maker_paying_transfer = self.from_mediated_transfer

        # this is the address of the node that the taker actually has a channel
        # with (might or might not be the maker)
        maker_payer_hop = maker_paying_transfer.sender

        assert tokenswap.identifier == maker_paying_transfer.identifier
        assert tokenswap.from_token == maker_paying_transfer.token
        assert tokenswap.from_amount == maker_paying_transfer.lock.amount
        assert tokenswap.from_nodeaddress == maker_paying_transfer.initiator

        maker_receiving_token = tokenswap.to_token
        to_amount = tokenswap.to_amount

        identifier = maker_paying_transfer.identifier
        hashlock = maker_paying_transfer.lock.hashlock
        maker_address = maker_paying_transfer.initiator

        taker_receiving_token = maker_paying_transfer.token
        taker_paying_token = maker_receiving_token

        from_graph = raiden.token_to_channelgraph[taker_receiving_token]
        from_channel = from_graph.partneraddress_to_channel[maker_payer_hop]

        to_graph = raiden.token_to_channelgraph[maker_receiving_token]

        # update the channel's distributable and merkle tree
        from_channel.register_transfer(
            raiden.get_block_number(),
            maker_paying_transfer,
        )

        # register the task to receive Refund/Secrect/RevealSecret messages
        raiden.greenlet_task_dispatcher.register_task(self, hashlock)
        raiden.register_channel_for_hashlock(taker_receiving_token, from_channel, hashlock)

        # send to the maker a secret request informing how much the taker will
        # be _paid_, this is used to inform the maker that his part of the
        # mediated transfer is okay
        secret_request = SecretRequest(
            identifier,
            maker_paying_transfer.lock.hashlock,
            maker_paying_transfer.lock.amount,
        )
        raiden.sign(secret_request)
        raiden.send_async(maker_address, secret_request)

        lock_expiration = maker_paying_transfer.lock.expiration - raiden.config['reveal_timeout']

        # Note: taker may only try different routes if a RefundTransfer is
        # received, because the maker is the node controlling the secret
        available_routes = get_best_routes(
            to_graph,
            raiden.protocol.nodeaddresses_networkstatuses,
            raiden.address,
            maker_address,
            maker_paying_transfer.lock.amount,
            previous_address=None,
        )

        if not available_routes:
            if log.isEnabledFor(logging.DEBUG):
                node_address = raiden.address
                log.debug(
                    'TAKER TOKEN SWAP FAILED, NO ROUTES',
                    from_=pex(node_address),
                    to=pex(maker_address),
                )

            return

        first_transfer = None
        for route in available_routes:
            taker_paying_channel = to_graph.get_channel_by_contract_address(
                route.channel_address,
            )
            taker_paying_hop = route.node_address

            if log.isEnabledFor(logging.DEBUG):
                log.debug(
                    'TAKER TOKEN SWAP',
                    from_=pex(maker_paying_transfer.target),
                    to=pex(maker_address),
                    msghash=pex(maker_paying_transfer.hash),
                    hashlock=pex(hashlock),
                )

            # make a paying MediatedTransfer with same hashlock/identifier and the
            # taker's paying token/amount
            taker_paying_transfer = taker_paying_channel.create_mediatedtransfer(
                raiden.address,
                maker_address,
                fee,
                to_amount,
                identifier,
                lock_expiration,
                hashlock,
            )
            raiden.sign(taker_paying_transfer)
            taker_paying_channel.register_transfer(
                raiden.get_block_number(),
                taker_paying_transfer,
            )

            if not first_transfer:
                first_transfer = taker_paying_transfer

            if log.isEnabledFor(logging.DEBUG):
                log.debug(
                    'EXCHANGE TRANSFER NEW PATH',
                    path=lpex(taker_paying_hop),
                    hashlock=pex(hashlock),
                )

            # register the task to receive Refund/Secrect/RevealSecret messages
            raiden.register_channel_for_hashlock(
                maker_receiving_token,
                taker_paying_channel,
                hashlock,
            )

            response, secret = self.send_and_wait_valid(
                raiden,
                taker_paying_transfer,
                maker_payer_hop,
            )

            # only refunds for `maker_receiving_token` must be considered
            # (check send_and_wait_valid)
            if isinstance(response, RefundTransfer):
                if response.lock.amount != taker_paying_transfer.amount:
                    log.info(
                        'Partner %s sent an invalid refund message with an invalid amount',
                        pex(taker_paying_hop),
                    )
                    raiden.greenlet_task_dispatcher.unregister_task(self, hashlock, False)
                    return
                else:
                    taker_paying_channel.register_transfer(
                        raiden.get_block_number(),
                        response,
                    )

            elif isinstance(response, RevealSecret):
                # the secret was registered by the message handler

                # wait for the taker_paying_hop to reveal the secret prior to
                # unlocking locally
                if response.sender != taker_paying_hop:
                    response = self.wait_reveal_secret(
                        raiden,
                        taker_paying_hop,
                        taker_paying_transfer.lock.expiration,
                    )

                # unlock and send the Secret message
                raiden.handle_secret(
                    identifier,
                    taker_paying_token,
                    response.secret,
                    None,
                    hashlock,
                )

                # if the secret arrived early, withdraw it, otherwise send the
                # RevealSecret forward in the maker-path
                if secret:
                    raiden.handle_secret(
                        identifier,
                        taker_receiving_token,
                        response.secret,
                        secret,
                        hashlock,
                    )

                # wait for the withdraw in case it did not happen yet
                self._wait_for_unlock_or_close(
                    raiden,
                    from_graph,
                    from_channel,
                    maker_paying_transfer,
                )

                return

            # the lock expired
            else:
                if log.isEnabledFor(logging.DEBUG):
                    node_address = raiden.address
                    log.debug(
                        'TAKER TOKEN SWAP FAILED',
                        from_=pex(node_address),
                        to=pex(maker_address),
                    )

                self.async_result.set(False)
                return

        # no route is available, wait for the sent mediated transfer to expire
        self._wait_expiration(raiden, first_transfer)

        if log.isEnabledFor(logging.DEBUG):
            node_address = raiden.address
            log.debug(
                'TAKER TOKEN SWAP FAILED',
                from_=pex(node_address),
                to=pex(maker_address),
            )

        self.async_result.set(False)
    def _run(self):  # pylint: disable=method-hidden,too-many-locals
        tokenswap = self.tokenswap
        raiden = self.raiden

        identifier = tokenswap.identifier
        from_token = tokenswap.from_token
        from_amount = tokenswap.from_amount
        to_token = tokenswap.to_token
        to_amount = tokenswap.to_amount
        to_nodeaddress = tokenswap.to_nodeaddress

        from_graph = raiden.token_to_channelgraph[from_token]
        to_graph = raiden.token_to_channelgraph[to_token]

        from_routes = get_best_routes(
            from_graph,
            raiden.protocol.nodeaddresses_networkstatuses,
            raiden.address,
            to_nodeaddress,
            from_amount,
            previous_address=None,
        )
        fee = 0

        for route in from_routes:
            # for each new path a new secret must be used
            secret = sha3(hex(random.getrandbits(256)))
            hashlock = sha3(secret)

            from_channel = from_graph.get_channel_by_contract_address(route.channel_address)

            raiden.greenlet_task_dispatcher.register_task(self, hashlock)
            raiden.register_channel_for_hashlock(from_token, from_channel, hashlock)

            block_number = raiden.get_block_number()
            lock_expiration = block_number + from_channel.settle_timeout

            from_mediated_transfer = from_channel.create_mediatedtransfer(
                raiden.address,
                to_nodeaddress,
                fee,
                from_amount,
                identifier,
                lock_expiration,
                hashlock,
            )
            raiden.sign(from_mediated_transfer)
            from_channel.register_transfer(
                # must be the same block number used to compute lock_expiration
                block_number,
                from_mediated_transfer,
            )

            # wait for the SecretRequest and MediatedTransfer
            to_mediated_transfer = self.send_and_wait_valid_state(
                raiden,
                route.node_address,
                to_nodeaddress,
                from_mediated_transfer,
                to_token,
                to_amount,
            )

            if to_mediated_transfer is None:
                # the initiator can unregister right away since it knows the
                # secret wont be revealed
                raiden.greenlet_task_dispatcher.unregister_task(self, hashlock, False)

            elif isinstance(to_mediated_transfer, MediatedTransfer):
                to_hop = to_mediated_transfer.sender
                to_channel = to_graph.partneraddress_to_channel[to_hop]

                to_channel.register_transfer(
                    raiden.get_block_number(),
                    to_mediated_transfer,
                )
                raiden.register_channel_for_hashlock(to_token, to_channel, hashlock)

                # A swap is composed of two mediated transfers, we need to
                # reveal the secret to both, since the maker is one of the ends
                # we just need to send the reveal secret directly to the taker.
                reveal_secret = RevealSecret(secret)
                raiden.sign(reveal_secret)
                raiden.send_async(to_nodeaddress, reveal_secret)

                from_channel.register_secret(secret)

                # Register the secret with the to_channel and send the
                # RevealSecret message to the node that is paying the to_token
                # (this node might, or might not be the same as the taker),
                # then wait for the withdraw.
                raiden.handle_secret(
                    identifier,
                    to_token,
                    secret,
                    None,
                    hashlock,
                )

                to_channel = to_graph.partneraddress_to_channel[to_mediated_transfer.sender]
                self._wait_for_unlock_or_close(
                    raiden,
                    to_graph,
                    to_channel,
                    to_mediated_transfer,
                )

                # unlock the from_token and optimistically reveal the secret
                # forward
                raiden.handle_secret(
                    identifier,
                    from_token,
                    secret,
                    None,
                    hashlock,
                )

                raiden.greenlet_task_dispatcher.unregister_task(self, hashlock, True)
                self.async_result.set(True)
                return

        if log.isEnabledFor(logging.DEBUG):
            node_address = raiden.address
            log.debug(
                'MAKER TOKEN SWAP FAILED',
                node=pex(node_address),
                to=pex(to_nodeaddress),
            )

        # all routes failed
        self.async_result.set(False)
    def start_mediated_transfer(self, token_address, amount, identifier, target):
        # pylint: disable=too-many-locals

        async_result = AsyncResult()
        graph = self.token_to_channelgraph[token_address]

        available_routes = get_best_routes(
            graph,
            self.protocol.nodeaddresses_networkstatuses,
            self.address,
            target,
            amount,
            None,
        )

        if not available_routes:
            async_result.set(False)
            return async_result

        self.protocol.start_health_check(target)

        if identifier is None:
            identifier = create_default_identifier()

        route_state = RoutesState(available_routes)
        our_address = self.address
        block_number = self.get_block_number()

        transfer_state = LockedTransferState(
            identifier=identifier,
            amount=amount,
            token=token_address,
            initiator=self.address,
            target=target,
            expiration=None,
            hashlock=None,
            secret=None,
        )

        # Issue #489
        #
        # Raiden may fail after a state change using the random generator is
        # handled but right before the snapshot is taken. If that happens on
        # the next initialization when raiden is recovering and applying the
        # pending state changes a new secret will be generated and the
        # resulting events won't match, this breaks the architecture model,
        # since it's assumed the re-execution of a state change will always
        # produce the same events.
        #
        # TODO: Removed the secret generator from the InitiatorState and add
        # the secret into all state changes that require one, this way the
        # secret will be serialized with the state change and the recovery will
        # use the same /random/ secret.
        random_generator = RandomSecretGenerator()

        init_initiator = ActionInitInitiator(
            our_address=our_address,
            transfer=transfer_state,
            routes=route_state,
            random_generator=random_generator,
            block_number=block_number,
        )

        state_manager = StateManager(initiator.state_transition, None)
        self.state_machine_event_handler.log_and_dispatch(state_manager, init_initiator)

        # TODO: implement the network timeout raiden.config['msg_timeout'] and
        # cancel the current transfer if it hapens (issue #374)
        self.identifier_to_statemanagers[identifier].append(state_manager)
        self.identifier_to_results[identifier].append(async_result)

        return async_result
Ejemplo n.º 7
0
    def _run(self):  # pylint: disable=method-hidden,too-many-locals
        fee = 0
        raiden = self.raiden
        tokenswap = self.tokenswap

        # this is the MediatedTransfer that wil pay the maker's half of the
        # swap, not necessarily from him
        maker_paying_transfer = self.from_mediated_transfer

        # this is the address of the node that the taker actually has a channel
        # with (might or might not be the maker)
        maker_payer_hop = maker_paying_transfer.sender

        assert tokenswap.identifier == maker_paying_transfer.identifier
        assert tokenswap.from_token == maker_paying_transfer.token
        assert tokenswap.from_amount == maker_paying_transfer.lock.amount
        assert tokenswap.from_nodeaddress == maker_paying_transfer.initiator

        maker_receiving_token = tokenswap.to_token
        to_amount = tokenswap.to_amount

        identifier = maker_paying_transfer.identifier
        hashlock = maker_paying_transfer.lock.hashlock
        maker_address = maker_paying_transfer.initiator

        taker_receiving_token = maker_paying_transfer.token
        taker_paying_token = maker_receiving_token

        from_graph = raiden.token_to_channelgraph[taker_receiving_token]
        from_channel = from_graph.partneraddress_to_channel[maker_payer_hop]

        to_graph = raiden.token_to_channelgraph[maker_receiving_token]

        # update the channel's distributable and merkle tree
        from_channel.register_transfer(
            raiden.get_block_number(),
            maker_paying_transfer,
        )

        # register the task to receive Refund/Secrect/RevealSecret messages
        raiden.greenlet_task_dispatcher.register_task(self, hashlock)
        raiden.register_channel_for_hashlock(taker_receiving_token, from_channel, hashlock)

        # send to the maker a secret request informing how much the taker will
        # be _paid_, this is used to inform the maker that his part of the
        # mediated transfer is okay
        secret_request = SecretRequest(
            identifier,
            maker_paying_transfer.lock.hashlock,
            maker_paying_transfer.lock.amount,
        )
        raiden.sign(secret_request)
        raiden.send_async(maker_address, secret_request)

        lock_expiration = maker_paying_transfer.lock.expiration - raiden.config['reveal_timeout']

        # Note: taker may only try different routes if a RefundTransfer is
        # received, because the maker is the node controlling the secret
        available_routes = get_best_routes(
            to_graph,
            raiden.protocol.nodeaddresses_networkstatuses,
            raiden.address,
            maker_address,
            maker_paying_transfer.lock.amount,
            previous_address=None,
        )

        if not available_routes:
            if log.isEnabledFor(logging.DEBUG):
                node_address = raiden.address
                log.debug(
                    'TAKER TOKEN SWAP FAILED, NO ROUTES',
                    from_=pex(node_address),
                    to=pex(maker_address),
                )

            return

        first_transfer = None
        for route in available_routes:
            taker_paying_channel = to_graph.get_channel_by_contract_address(
                route.channel_address,
            )
            taker_paying_hop = route.node_address

            if log.isEnabledFor(logging.DEBUG):
                log.debug(
                    'TAKER TOKEN SWAP',
                    from_=pex(maker_paying_transfer.target),
                    to=pex(maker_address),
                    msghash=pex(maker_paying_transfer.hash),
                    hashlock=pex(hashlock),
                )

            # make a paying MediatedTransfer with same hashlock/identifier and the
            # taker's paying token/amount
            taker_paying_transfer = taker_paying_channel.create_mediatedtransfer(
                raiden.address,
                maker_address,
                fee,
                to_amount,
                identifier,
                lock_expiration,
                hashlock,
            )
            raiden.sign(taker_paying_transfer)
            taker_paying_channel.register_transfer(
                raiden.get_block_number(),
                taker_paying_transfer,
            )

            if not first_transfer:
                first_transfer = taker_paying_transfer

            if log.isEnabledFor(logging.DEBUG):
                log.debug(
                    'EXCHANGE TRANSFER NEW PATH',
                    path=lpex(str(t).encode() for t in taker_paying_hop),
                    hashlock=pex(hashlock),
                )

            # register the task to receive Refund/Secrect/RevealSecret messages
            raiden.register_channel_for_hashlock(
                maker_receiving_token,
                taker_paying_channel,
                hashlock,
            )

            response, secret = self.send_and_wait_valid(
                raiden,
                taker_paying_transfer,
                maker_payer_hop,
            )

            # only refunds for `maker_receiving_token` must be considered
            # (check send_and_wait_valid)
            if isinstance(response, RefundTransfer):
                if response.lock.amount != taker_paying_transfer.amount:
                    log.info(
                        'Partner %s sent an invalid refund message with an invalid amount',
                        pex(taker_paying_hop),
                    )
                    raiden.greenlet_task_dispatcher.unregister_task(self, hashlock, False)
                    return
                else:
                    taker_paying_channel.register_transfer(
                        raiden.get_block_number(),
                        response,
                    )

            elif isinstance(response, RevealSecret):
                # the secret was registered by the message handler

                # wait for the taker_paying_hop to reveal the secret prior to
                # unlocking locally
                if response.sender != taker_paying_hop:
                    response = self.wait_reveal_secret(
                        raiden,
                        taker_paying_hop,
                        taker_paying_transfer.lock.expiration,
                    )

                # unlock and send the Secret message
                raiden.handle_secret(
                    identifier,
                    taker_paying_token,
                    response.secret,
                    None,
                    hashlock,
                )

                # if the secret arrived early, withdraw it, otherwise send the
                # RevealSecret forward in the maker-path
                if secret:
                    raiden.handle_secret(
                        identifier,
                        taker_receiving_token,
                        response.secret,
                        secret,
                        hashlock,
                    )

                # wait for the withdraw in case it did not happen yet
                self._wait_for_unlock_or_close(
                    raiden,
                    from_graph,
                    from_channel,
                    maker_paying_transfer,
                )

                return

            # the lock expired
            else:
                if log.isEnabledFor(logging.DEBUG):
                    node_address = raiden.address
                    log.debug(
                        'TAKER TOKEN SWAP FAILED',
                        from_=pex(node_address),
                        to=pex(maker_address),
                    )

                return

        # no route is available, wait for the sent mediated transfer to expire
        self._wait_expiration(raiden, first_transfer)

        if log.isEnabledFor(logging.DEBUG):
            node_address = raiden.address
            log.debug(
                'TAKER TOKEN SWAP FAILED',
                from_=pex(node_address),
                to=pex(maker_address),
            )
Ejemplo n.º 8
0
    def _run(self):  # pylint: disable=method-hidden,too-many-locals
        tokenswap = self.tokenswap
        raiden = self.raiden

        identifier = tokenswap.identifier
        from_token = tokenswap.from_token
        from_amount = tokenswap.from_amount
        to_token = tokenswap.to_token
        to_amount = tokenswap.to_amount
        to_nodeaddress = tokenswap.to_nodeaddress

        from_graph = raiden.token_to_channelgraph[from_token]
        to_graph = raiden.token_to_channelgraph[to_token]

        from_routes = get_best_routes(
            from_graph,
            raiden.protocol.nodeaddresses_networkstatuses,
            raiden.address,
            to_nodeaddress,
            from_amount,
            previous_address=None,
        )
        fee = 0

        for route in from_routes:
            # for each new path a new secret must be used
            secret = sha3(hex(random.getrandbits(256)).encode())
            hashlock = sha3(secret)

            from_channel = from_graph.get_channel_by_contract_address(route.channel_address)

            raiden.greenlet_task_dispatcher.register_task(self, hashlock)
            raiden.register_channel_for_hashlock(from_token, from_channel, hashlock)

            block_number = raiden.get_block_number()
            lock_expiration = block_number + from_channel.settle_timeout

            from_mediated_transfer = from_channel.create_mediatedtransfer(
                raiden.address,
                to_nodeaddress,
                fee,
                from_amount,
                identifier,
                lock_expiration,
                hashlock,
            )
            raiden.sign(from_mediated_transfer)
            from_channel.register_transfer(
                # must be the same block number used to compute lock_expiration
                block_number,
                from_mediated_transfer,
            )

            # wait for the SecretRequest and MediatedTransfer
            to_mediated_transfer = self.send_and_wait_valid_state(
                raiden,
                route.node_address,
                to_nodeaddress,
                from_mediated_transfer,
                to_token,
                to_amount,
            )

            if to_mediated_transfer is None:
                # the initiator can unregister right away since it knows the
                # secret wont be revealed
                raiden.greenlet_task_dispatcher.unregister_task(self, hashlock, False)

            elif isinstance(to_mediated_transfer, MediatedTransfer):
                to_hop = to_mediated_transfer.sender
                to_channel = to_graph.partneraddress_to_channel[to_hop]

                to_channel.register_transfer(
                    raiden.get_block_number(),
                    to_mediated_transfer,
                )
                raiden.register_channel_for_hashlock(to_token, to_channel, hashlock)

                # A swap is composed of two mediated transfers, we need to
                # reveal the secret to both. Since the maker is one of the ends
                # we just need to send the reveal secret directly to the taker.
                reveal_secret = RevealSecret(secret)
                raiden.sign(reveal_secret)
                raiden.send_async(to_nodeaddress, reveal_secret)

                from_channel.register_secret(secret)

                # Register the secret with the to_channel and send the
                # RevealSecret message to the node that is paying the to_token
                # (this node might, or might not be the same as the taker),
                # then wait for the withdraw.
                raiden.handle_secret(
                    identifier,
                    to_token,
                    secret,
                    None,
                    hashlock,
                )

                to_channel = to_graph.partneraddress_to_channel[to_mediated_transfer.sender]
                self._wait_for_unlock_or_close(
                    raiden,
                    to_graph,
                    to_channel,
                    to_mediated_transfer,
                )

                # unlock the from_token and optimistically reveal the secret
                # forward
                raiden.handle_secret(
                    identifier,
                    from_token,
                    secret,
                    None,
                    hashlock,
                )

                raiden.greenlet_task_dispatcher.unregister_task(self, hashlock, True)
                self.async_result.set(True)
                return

        if log.isEnabledFor(logging.DEBUG):
            node_address = raiden.address
            log.debug(
                'MAKER TOKEN SWAP FAILED',
                node=pex(node_address),
                to=pex(to_nodeaddress),
            )

        # all routes failed
        self.async_result.set(False)