Beispiel #1
0
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
Beispiel #2
0
def test_cancelpayment():
    """ A payment can be cancelled as long as the secret has not been revealed. """
    channel_state = factories.make_channel(
        our_balance=2 * MAXIMUM_PENDING_TRANSFERS * UNIT_TRANSFER_AMOUNT,
        token_address=UNIT_TOKEN_ADDRESS,
        token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS,
    )
    channel_map = {channel_state.identifier: channel_state}
    available_routes = [factories.route_from_channel(channel_state)]

    init_state_change = ActionInitInitiator(
        transfer_description=factories.UNIT_TRANSFER_DESCRIPTION,
        routes=available_routes,
    )

    transition = initiator_manager.state_transition(
        payment_state=None,
        state_change=init_state_change,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=random.Random(),
        block_number=1,
    )
    payment_state = transition.new_state
    assert isinstance(payment_state, InitiatorPaymentState)

    iteration = initiator_manager.handle_cancelpayment(
        payment_state=payment_state,
        channel_state=channel_state,
    )
    msg = 'The secret has not been revealed yet, the payment can be cancelled'
    assert iteration.new_state is None, msg
 def _action_init_initiator(self,
                            transfer: TransferDescriptionWithSecretState):
     channel = self.address_to_channel[transfer.target]
     if transfer.secrethash not in self.expected_expiry:
         self.expected_expiry[transfer.secrethash] = self.block_number + 10
     return ActionInitInitiator(
         transfer, [factories.make_route_from_channel(channel)])
Beispiel #4
0
def make_initiator_state(
    routes,
    transfer_description,
    channelmap,
    pseudo_random_generator,
    block_number,
    payment_network_identifier=None,
):

    if payment_network_identifier is None:
        payment_network_identifier = factories.make_address()

    init_state_change = ActionInitInitiator(
        transfer_description,
        routes,
    )

    inital_state = None
    iteration = initiator_manager.state_transition(
        inital_state,
        init_state_change,
        channelmap,
        pseudo_random_generator,
        block_number,
    )

    return iteration.new_state
Beispiel #5
0
def test_init_without_routes():
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    our_address, target_address = factories.HOP1, factories.HOP3
    routes = []

    transfer = factories.make_transfer(
        amount,
        initiator=our_address,
        target=target_address,
        secret=None,
        hashlock=None,
        expiration=None,
    )
    init_state_change = ActionInitInitiator(
        our_address,
        transfer,
        RoutesState(routes),
        SequenceGenerator(),
        block_number,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        None,
    )

    assert initiator_state_machine.current_state is None

    events = initiator_state_machine.dispatch(init_state_change, )

    assert len(events) == 1
    assert any(isinstance(e, EventTransferSentFailed) for e in events)
    assert initiator_state_machine.current_state is None
Beispiel #6
0
def make_init_statechange(routes,
                          target,
                          amount=factories.UNIT_TRANSFER_AMOUNT,
                          block_number=1,
                          our_address=factories.ADDR,
                          secret_generator=None,
                          identifier=0,
                          token=factories.UNIT_TOKEN_ADDRESS):

    if secret_generator is None:
        secret_generator = SequenceGenerator()

    transfer = factories.make_transfer(
        amount,
        initiator=our_address,
        target=target,
        identifier=identifier,
        token=token,
        secret=None,
        hashlock=None,
        expiration=None,
    )

    init_state_change = ActionInitInitiator(
        our_address,
        transfer,
        RoutesState(routes),
        secret_generator,
        block_number,
    )

    return init_state_change
Beispiel #7
0
def test_init_with_maximum_pending_transfers_exceeded():
    channel1 = factories.make_channel(
        our_balance=2 * MAXIMUM_PENDING_TRANSFERS * UNIT_TRANSFER_AMOUNT,
        token_address=UNIT_TOKEN_ADDRESS,
        token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS,
    )
    channel_map = {channel1.identifier: channel1}
    available_routes = [factories.route_from_channel(channel1)]
    pseudo_random_generator = random.Random()

    transitions = list()
    block_number = 1
    for _ in range(MAXIMUM_PENDING_TRANSFERS + 1):
        init_state_change = ActionInitInitiator(make_transfer_description(), available_routes)
        transitions.append(initiator_manager.state_transition(
            None,
            init_state_change,
            channel_map,
            pseudo_random_generator,
            block_number,
        ))

    failed_transition = transitions.pop()
    assert all(
        isinstance(transition.new_state, InitiatorPaymentState)
        for transition in transitions
    )

    assert failed_transition.new_state is None
    assert len(failed_transition.events) == 1
    assert isinstance(failed_transition.events[0], EventPaymentSentFailed)
Beispiel #8
0
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
Beispiel #9
0
def test_init_without_routes():
    block_number = 1
    routes = []
    payment_network_identifier = factories.make_address()
    pseudo_random_generator = random.Random()

    init_state_change = ActionInitInitiator(
        payment_network_identifier,
        factories.UNIT_TRANSFER_DESCRIPTION,
        routes,
    )

    channelmap = dict()
    iteration = initiator_manager.state_transition(
        None,
        init_state_change,
        channelmap,
        pseudo_random_generator,
        block_number,
    )

    assert iteration.new_state is None

    assert len(iteration.events) == 1
    assert isinstance(iteration.events[0], EventTransferSentFailed)
    assert iteration.new_state is None
Beispiel #10
0
def test_invalid_cancelpayment():
    """ A payment can *NOT* be cancelled if a secret for any transfer has been
    revealed.
    """
    channel_state = factories.make_channel(
        our_balance=2 * MAXIMUM_PENDING_TRANSFERS * UNIT_TRANSFER_AMOUNT,
        token_address=UNIT_TOKEN_ADDRESS,
        token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS,
    )
    channel_map = {channel_state.identifier: channel_state}
    available_routes = [factories.route_from_channel(channel_state)]

    init_state_change = ActionInitInitiator(
        transfer_description=factories.UNIT_TRANSFER_DESCRIPTION,
        routes=available_routes,
    )
    pseudo_random_generator = random.Random()

    init_iteration = initiator_manager.state_transition(
        payment_state=None,
        state_change=init_state_change,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=1,
    )

    lock = channel.get_lock(
        channel_state.our_state,
        init_iteration.new_state.initiator.transfer_description.secrethash,
    )
    receive_secret_request = ReceiveSecretRequest(
        UNIT_TRANSFER_IDENTIFIER,
        lock.amount,
        lock.expiration,
        lock.secrethash,
        UNIT_TRANSFER_TARGET,
    )
    secret_transition = initiator_manager.state_transition(
        payment_state=init_iteration.new_state,
        state_change=receive_secret_request,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=1,
    )

    iteration = initiator_manager.handle_cancelpayment(
        payment_state=secret_transition.new_state,
        channel_state=channel_state,
    )
    msg = 'The secret *has* been revealed, the payment must not be cancelled'
    assert iteration.new_state is not None, msg
    assert not iteration.events, msg
Beispiel #11
0
def test_init_with_usable_routes():
    channel1 = factories.make_channel(
        our_balance=UNIT_TRANSFER_AMOUNT,
        token_address=UNIT_TOKEN_ADDRESS,
        token_network_identifier=UNIT_TOKEN_NETWORK_ADDRESS,
    )
    channel_map = {channel1.identifier: channel1}
    available_routes = [factories.route_from_channel(channel1)]
    pseudo_random_generator = random.Random()

    init_state_change = ActionInitInitiator(
        factories.UNIT_TRANSFER_DESCRIPTION,
        available_routes,
    )

    block_number = 1
    transition = initiator_manager.state_transition(
        None,
        init_state_change,
        channel_map,
        pseudo_random_generator,
        block_number,
    )

    assert isinstance(transition.new_state, InitiatorPaymentState)
    assert transition.events, 'we have a valid route, the mediated transfer event must be emitted'

    payment_state = transition.new_state
    assert payment_state.initiator.transfer_description == factories.UNIT_TRANSFER_DESCRIPTION

    mediated_transfers = [
        e for e in transition.events if isinstance(e, SendLockedTransfer)
    ]
    assert len(mediated_transfers
               ) == 1, 'mediated_transfer should /not/ split the transfer'

    send_mediated_transfer = mediated_transfers[0]
    transfer = send_mediated_transfer.transfer
    expiration = initiator.get_initial_lock_expiration(block_number,
                                                       channel1.reveal_timeout)

    assert transfer.balance_proof.token_network_identifier == channel1.token_network_identifier
    assert transfer.lock.amount == factories.UNIT_TRANSFER_DESCRIPTION.amount
    assert transfer.lock.expiration == expiration
    assert transfer.lock.secrethash == factories.UNIT_TRANSFER_DESCRIPTION.secrethash
    assert send_mediated_transfer.recipient == channel1.partner_state.address
Beispiel #12
0
def make_init_statechange(routes,
                          target,
                          amount=factories.UNIT_TRANSFER_AMOUNT,
                          block_number=1,
                          our_address=factories.ADDR,
                          secret_generator=None,
                          identifier=0):

    if secret_generator is None:
        secret_generator = SequenceGenerator()

    init_state_change = ActionInitInitiator(
        our_address,
        make_hashlock_transfer(amount, target=target, identifier=identifier),
        RoutesState(routes),
        secret_generator,
        block_number,
    )

    return init_state_change
Beispiel #13
0
def make_initiator_manager_state(
        routes,
        transfer_description,
        channel_map,
        pseudo_random_generator,
        block_number,
):

    init_state_change = ActionInitInitiator(
        transfer_description,
        routes,
    )

    inital_state = None
    iteration = initiator_manager.state_transition(
        inital_state,
        init_state_change,
        channel_map,
        pseudo_random_generator,
        block_number,
    )

    return iteration.new_state
Beispiel #14
0
def initiator_init(
    raiden: 'RaidenService',
    transfer_identifier: PaymentID,
    transfer_amount: PaymentAmount,
    transfer_secret: Secret,
    transfer_fee: FeeAmount,
    token_network_identifier: TokenNetworkID,
    target_address: TargetAddress,
):
    assert transfer_secret != constants.EMPTY_HASH, f'Empty secret node:{raiden!r}'

    transfer_state = TransferDescriptionWithSecretState(
        payment_network_identifier=raiden.default_registry.address,
        payment_identifier=transfer_identifier,
        amount=transfer_amount,
        allocated_fee=transfer_fee,
        token_network_identifier=token_network_identifier,
        initiator=InitiatorAddress(raiden.address),
        target=target_address,
        secret=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,
        privkey=raiden.privkey,
    )
    init_initiator_statechange = ActionInitInitiator(
        transfer_state,
        routes,
    )
    return init_initiator_statechange
Beispiel #15
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
Beispiel #16
0
    def start_mediated_transfer(self, token_address, amount, identifier,
                                target):
        # pylint: disable=too-many-locals
        graph = self.channelgraphs[token_address]
        routes = graph.get_best_routes(
            self.address,
            target,
            amount,
            lock_timeout=None,
        )

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

        # send ping to target to make sure we can receive something back from target
        async_result = self.protocol.send_ping(target)
        async_result.wait(timeout=0.5)  # allow the ping to succeed
        if async_result.ready():
            log.debug("transfer target received invitation ping")
        else:
            log.debug(
                "transfer target did not receive invitation ping, probably behing NAT"
            )

        identifier = create_default_identifier(self.address, token_address,
                                               target)
        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)
        async_result = AsyncResult()

        # 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
Beispiel #17
0
 def _action_init_initiator(self,
                            transfer: TransferDescriptionWithSecretState):
     return ActionInitInitiator(
         transfer,
         [factories.route_from_channel(self.channel)],
     )
def test_invalid_instantiation_action_init_initiator():
    wrong_type_transfer = factories.create(factories.LockedTransferSignedStateProperties())
    with pytest.raises(ValueError):
        ActionInitInitiator(transfer=wrong_type_transfer, routes=list())