Ejemplo n.º 1
0
def restore_from_latest_snapshot(transition_function, storage):
    snapshot = storage.get_latest_state_snapshot()

    if snapshot:
        log.debug('Restoring from snapshot')
        last_applied_state_change_id, state = snapshot
        unapplied_state_changes = storage.get_statechanges_by_identifier(
            from_identifier=last_applied_state_change_id,
            to_identifier='latest',
        )
    else:
        log.debug('No snapshot found, replaying all state changes')
        state = None
        unapplied_state_changes = storage.get_statechanges_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )

    state_manager = StateManager(transition_function, state)
    wal = WriteAheadLog(state_manager, storage)

    log.debug('Replaying state changes',
              num_state_changes=len(unapplied_state_changes))
    for state_change in unapplied_state_changes:
        state_manager.dispatch(state_change)

    return wal
Ejemplo n.º 2
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
Ejemplo n.º 3
0
def test_state_wait_secretrequest_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    hashlock = current_state.transfer.hashlock

    state_change = ReceiveSecretRequest(
        identifier=identifier,
        amount=amount,
        hashlock=hashlock,
        sender=target_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    events = initiator_state_machine.dispatch(state_change)
    assert all(isinstance(event, SendRevealSecret) for event in events)
    assert len(events) == 1
def test_no_valid_routes():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT - 1),
        factories.make_route(factories.HOP3, available_balance=1),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(
        init_state_change,
    )

    assert mediator_state_machine.current_state is None

    assert len(events) == 1
    assert isinstance(events[0], SendRefundTransfer)
Ejemplo n.º 5
0
def test_no_valid_routes():
    from_route, from_transfer = make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT - 1),
        factories.make_route(factories.HOP3, available_balance=1),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(
        init_state_change,
    )

    assert mediator_state_machine.current_state is None

    assert len(events) == 1
    assert isinstance(events[0], SendRefundTransfer)
def test_cancel_transfer():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]

    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    state_change = ActionCancelTransfer(
        identifier=identifier
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert isinstance(events[0], EventTransferSentFailed)
    assert initiator_state_machine.current_state is None
def test_state_wait_secretrequest_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    hashlock = current_state.transfer.hashlock

    state_change = ReceiveSecretRequest(
        identifier=identifier,
        amount=amount,
        hashlock=hashlock,
        sender=target_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    events = initiator_state_machine.dispatch(state_change)
    assert all(isinstance(event, SendRevealSecret) for event in events)
    assert len(events) == 1
Ejemplo n.º 8
0
def test_cancel_transfer():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]

    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    state_change = ActionCancelTransfer(identifier=identifier)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert isinstance(events[0], EventTransferSentFailed)
    assert initiator_state_machine.current_state is None
Ejemplo n.º 9
0
def test_state_wait_unlock_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        identifier=identifier,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    # setup the state for the wait unlock
    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=mediator_address,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 3

    assert any(isinstance(e, SendBalanceProof) for e in events)
    assert any(isinstance(e, EventTransferSentSuccess) for e in events)
    assert any(isinstance(e, EventUnlockSuccess) for e in events)

    balance_proof = next(e for e in events if isinstance(e, SendBalanceProof))
    complete = next(e for e in events
                    if isinstance(e, EventTransferSentSuccess))

    assert balance_proof.receiver == mediator_address
    assert complete.identifier == identifier
    assert initiator_state_machine.current_state is None, 'state must be cleaned'
def test_state_wait_unlock_valid():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        identifier=identifier,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    # setup the state for the wait unlock
    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=mediator_address,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 3

    assert any(isinstance(e, SendBalanceProof) for e in events)
    assert any(isinstance(e, EventTransferSentSuccess) for e in events)
    assert any(isinstance(e, EventUnlockSuccess) for e in events)

    balance_proof = next(e for e in events if isinstance(e, SendBalanceProof))
    complete = next(e for e in events if isinstance(e, EventTransferSentSuccess))

    assert balance_proof.receiver == mediator_address
    assert complete.identifier == identifier
    assert initiator_state_machine.current_state is None, 'state must be cleaned'
Ejemplo n.º 11
0
def test_refund_transfer_next_route():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
        factories.make_route(factories.HOP2, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=mediator_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert any(
        isinstance(e, SendMediatedTransfer) for e in events
    ), 'No mediated transfer event emitted, should have tried a new route'

    assert initiator_state_machine.current_state is not None
    assert initiator_state_machine.current_state.routes.canceled_routes[
        0] == prior_state.route
Ejemplo n.º 12
0
def test_init_mediator():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2,
                             available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(init_state_change, )

    mediator_state = mediator_state_machine.current_state
    assert isinstance(mediator_state, MediatorState)
    assert mediator_state.our_address == factories.ADDR
    assert mediator_state.block_number == init_state_change.block_number
    assert mediator_state.transfers_pair[0].payer_transfer == from_transfer
    assert mediator_state.transfers_pair[0].payer_route == from_route

    assert len(
        events
    ), 'we have a valid route, the mediated transfer event must be emited'

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

    assert mediated_transfer.token == from_transfer.token, 'transfer token address mismatch'
    assert mediated_transfer.amount == from_transfer.amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration < from_transfer.expiration, 'transfer expiration mismatch'
    assert mediated_transfer.hashlock == from_transfer.hashlock, 'wrong hashlock'
def test_refund_transfer_next_route():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
        factories.make_route(factories.HOP2, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=mediator_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert any(
        isinstance(e, SendMediatedTransfer) for e in events
    ), 'No mediated transfer event emitted, should have tried a new route'

    assert initiator_state_machine.current_state is not None
    assert initiator_state_machine.current_state.routes.canceled_routes[0] == prior_state.route
def test_init_mediator():
    from_route, from_transfer = factories.make_from(
        amount=factories.UNIT_TRANSFER_AMOUNT,
        target=factories.HOP2,
        from_expiration=factories.HOP1_TIMEOUT,
    )

    routes = [
        factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT),
    ]

    init_state_change = make_init_statechange(
        from_transfer,
        from_route,
        routes,
    )

    mediator_state_machine = StateManager(
        mediator.state_transition,
        None,
    )

    assert mediator_state_machine.current_state is None

    events = mediator_state_machine.dispatch(
        init_state_change,
    )

    mediator_state = mediator_state_machine.current_state
    assert isinstance(mediator_state, MediatorState)
    assert mediator_state.our_address == factories.ADDR
    assert mediator_state.block_number == init_state_change.block_number
    assert mediator_state.transfers_pair[0].payer_transfer == from_transfer
    assert mediator_state.transfers_pair[0].payer_route == from_route

    assert len(events), 'we have a valid route, the mediated transfer event must be emited'

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

    assert mediated_transfer.token == from_transfer.token, 'transfer token address mismatch'
    assert mediated_transfer.amount == from_transfer.amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration < from_transfer.expiration, 'transfer expiration mismatch'
    assert mediated_transfer.hashlock == from_transfer.hashlock, 'wrong hashlock'
Ejemplo n.º 15
0
def test_state_wait_unlock_invalid():
    identifier = identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    before_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=factories.ADDR,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state.revealsecret is not None
    assert_state_equal(initiator_state_machine.current_state, current_state)
    assert_state_equal(current_state, before_state)
def test_state_wait_unlock_invalid():
    identifier = identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()
    token = factories.UNIT_TOKEN_ADDRESS

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
        token=token,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        token,
        target_address,
        our_address,
    )

    before_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        secret=secret,
        sender=factories.ADDR,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state.revealsecret is not None
    assert_state_equal(initiator_state_machine.current_state, current_state)
    assert_state_equal(current_state, before_state)
Ejemplo n.º 17
0
def test_state_wait_unlock_valid():
    identifier = identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
    )

    secret = secret_generator.secrets[0]
    assert secret is not None

    # setup the state for the wait unlock
    current_state.revealsecret = SendRevealSecret(
        identifier,
        secret,
        target_address,
        our_address,
    )

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )

    state_change = ReceiveSecretReveal(
        identifier=identifier,
        secret=secret,
        target=our_address,
        sender=mediator_address,
    )
    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 1
    assert isinstance(events[0], SendRevealSecret)
    assert events[0].target == mediator_address
    assert initiator_state_machine.current_state is None, 'state must be cleaned'
Ejemplo n.º 18
0
def test_refund_transfer_invalid_sender():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=our_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state is not None
    assert_state_equal(initiator_state_machine.current_state, prior_state)
def test_refund_transfer_invalid_sender():
    identifier = 1
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR

    routes = [
        factories.make_route(mediator_address, available_balance=amount),
    ]
    current_state = make_initiator_state(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=SequenceGenerator(),
        identifier=identifier,
    )

    transfer = factories.make_transfer(
        amount,
        our_address,
        target_address,
        block_number + factories.UNIT_SETTLE_TIMEOUT,
    )

    state_change = ReceiveTransferRefund(
        sender=our_address,
        transfer=transfer,
    )

    prior_state = deepcopy(current_state)

    initiator_state_machine = StateManager(
        initiator.state_transition,
        current_state,
    )
    assert initiator_state_machine.current_state is not None

    events = initiator_state_machine.dispatch(state_change)
    assert len(events) == 0
    assert initiator_state_machine.current_state is not None
    assert_state_equal(initiator_state_machine.current_state, prior_state)
Ejemplo n.º 20
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 = 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
        ]

        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)
        all_events = state_manager.dispatch(init_mediator)

        for event in all_events:
            self.state_machine_event_handler.on_event(event)

        self.identifier_statemanager[identifier].append(state_manager)
Ejemplo n.º 21
0
def restore_from_latest_snapshot(transition_function, storage):
    events = list()
    snapshot = storage.get_state_snapshot()

    if snapshot:
        last_applied_state_change_id, state = snapshot
        unapplied_state_changes = storage.get_statechanges_by_identifier(
            from_identifier=last_applied_state_change_id,
            to_identifier='latest',
        )
    else:
        state = None
        unapplied_state_changes = list()

    state_manager = StateManager(transition_function, state)
    wal = WriteAheadLog(state_manager, storage)

    for state_change in unapplied_state_changes:
        events.extend(state_manager.dispatch(state_change))

    return wal, events
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
Ejemplo n.º 23
0
    def target_mediated_transfer(self, message):
        graph = self.channelgraphs[message.token]
        from_channel = graph.partneraddress_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

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

        init_target = ActionInitTarget(
            our_address,
            from_route,
            from_transfer,
            block_number,
        )

        state_manager = StateManager(target_task.state_transition, None)
        all_events = state_manager.dispatch(init_target)

        for event in all_events:
            self.state_machine_event_handler.on_event(event)

        identifier = message.identifier
        self.identifier_statemanager[identifier].append(state_manager)
def test_init_with_usable_routes():
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    init_state_change = make_init_statechange(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
    )

    expiration = block_number + factories.HOP1_TIMEOUT

    initiator_state_machine = StateManager(
        initiator.state_transition,
        None,
    )

    assert initiator_state_machine.current_state is None

    events = initiator_state_machine.dispatch(
        init_state_change,
    )

    initiator_state = initiator_state_machine.current_state
    assert isinstance(initiator_state, InitiatorState)
    assert initiator_state.our_address == our_address

    transfer = initiator_state.transfer
    assert isinstance(transfer, LockedTransferState)
    assert transfer.amount == amount
    assert transfer.target == target_address
    assert transfer.secret == secret_generator.secrets[0]
    assert transfer.hashlock == sha3(transfer.secret)

    assert len(events), 'we have a valid route, the mediated transfer event must be emited'

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

    assert mediated_transfer.token == factories.UNIT_TOKEN_ADDRESS
    assert mediated_transfer.amount == amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration == expiration, 'transfer expiration mismatch'

    secret_hash = sha3(secret_generator.secrets[0])
    assert mediated_transfer.hashlock == secret_hash, 'wrong hashlock'
    assert mediated_transfer.receiver == mediator_address, 'wrong mediator address'

    assert initiator_state.route == routes[0]
    assert len(initiator_state.routes.available_routes) == 0
    assert len(initiator_state.routes.ignored_routes) == 0
    assert len(initiator_state.routes.refunded_routes) == 0
    assert len(initiator_state.routes.canceled_routes) == 0
Ejemplo n.º 25
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
        ]

        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)
        all_events = state_manager.dispatch(init_initiator)

        for event in all_events:
            self.state_machine_event_handler.on_event(event)

        async_result = AsyncResult()

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

        return async_result
Ejemplo n.º 26
0
def test_init_with_usable_routes():
    amount = factories.UNIT_TRANSFER_AMOUNT
    block_number = 1
    mediator_address = factories.HOP1
    target_address = factories.HOP2
    our_address = factories.ADDR
    secret_generator = SequenceGenerator()

    routes = [factories.make_route(mediator_address, available_balance=amount)]
    init_state_change = make_init_statechange(
        routes,
        target_address,
        block_number=block_number,
        our_address=our_address,
        secret_generator=secret_generator,
    )

    expiration = block_number + factories.HOP1_TIMEOUT

    initiator_state_machine = StateManager(
        initiator.state_transition,
        None,
    )

    assert initiator_state_machine.current_state is None

    events = initiator_state_machine.dispatch(init_state_change, )

    initiator_state = initiator_state_machine.current_state
    assert isinstance(initiator_state, InitiatorState)
    assert initiator_state.our_address == our_address

    transfer = initiator_state.transfer
    assert isinstance(transfer, LockedTransferState)
    assert transfer.amount == amount
    assert transfer.target == target_address
    assert transfer.secret == secret_generator.secrets[0]
    assert transfer.hashlock == sha3(transfer.secret)

    assert len(
        events
    ), 'we have a valid route, the mediated transfer event must be emited'

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

    assert mediated_transfer.token == factories.UNIT_TOKEN_ADDRESS
    assert mediated_transfer.amount == amount, 'transfer amount mismatch'
    assert mediated_transfer.expiration == expiration, 'transfer expiration mismatch'
    assert mediated_transfer.hashlock == sha3(
        secret_generator.secrets[0]), 'wrong hashlock'
    assert mediated_transfer.receiver == mediator_address, 'wrong mediator address'

    assert initiator_state.route == routes[0]
    assert len(initiator_state.routes.available_routes) == 0
    assert len(initiator_state.routes.ignored_routes) == 0
    assert len(initiator_state.routes.refunded_routes) == 0
    assert len(initiator_state.routes.canceled_routes) == 0