Example #1
0
def test_write_read_events(tmpdir, in_memory_database):
    log = init_database(tmpdir, in_memory_database)
    event = EventTransferFailed(1, 'whatever')
    with pytest.raises(sqlite3.IntegrityError):
        log.storage.write_state_events(
            1, [(None, 1, log.serializer.serialize(event))])
    assert (len(get_all_state_events(log)) == 0)

    log.storage.write_state_change('statechangedata')
    log.storage.write_state_events(
        1, [(None, 1, log.serializer.serialize(event))])
    logged_events = get_all_state_events(log)
    assert (len(logged_events) == 1)
    assert (logged_events[0][0] == 1)
    assert (logged_events[0][1] == 1)
    assert (isinstance(logged_events[0][2], EventTransferFailed))
Example #2
0
def user_cancel_transfer(state):
    """ Cancel the current in-transit message. """
    assert state.revealsecret is None, 'cannot cancel a transfer with a RevealSecret in flight'

    state.transfer.secret = None
    state.transfer.hashlock = None
    state.message = None
    state.route = None
    state.secretrequest = None
    state.revealsecret = None

    cancel = EventTransferFailed(
        identifier=state.transfer.identifier,
        reason='user canceled transfer',
    )
    iteration = TransitionResult(None, [cancel])

    return iteration
Example #3
0
def clear_if_finalized(iteration):
    """ Clear the state if the transfer was either completed or failed. """
    state = iteration.state

    if state.from_transfer.secret is None and state.block_number > state.from_transfer.expiration:
        failed = EventTransferFailed(
            identifier=state.transfer.identifier,
            reason='lock expired',
        )
        iteration = TransitionResult(None, [failed])

    elif state.state == 'balance_proof':
        completed = EventTransferCompleted(
            state.from_transfer.identifier,
            state.from_transfer.secret,
            state.from_transfer.hashlock,
        )
        iteration = TransitionResult(None, completed)

    return iteration
Example #4
0
def try_new_route(state):
    assert state.route is None, 'cannot try a new route while one is being used'

    # TODO:
    # - Route ranking. An upper layer should rate each route to optimize
    #   the fee price/quality of each route and add a rate from in the range
    #   [0.0,1.0].
    # - Add in a policy per route:
    #   - filtering, e.g. so the user may have a per route maximum transfer
    #     value based on fixed value or reputation.
    #   - reveal time computation
    #   - These policy details are better hidden from this implementation and
    #     changes should be applied through the use of Route state changes.

    # Find a single route that may fulfill the request, this uses a single
    # route intentionally
    try_route = None
    while state.routes.available_routes:
        route = state.routes.available_routes.pop(0)

        if route.available_balance < state.transfer.amount:
            state.routes.ignored_routes.append(route)
        else:
            try_route = route
            break

    if try_route is None:
        # No available route has sufficient balance for the current transfer,
        # cancel it.
        #
        # At this point we can just discard all the state data, this is only
        # valid because we are the initiator and we know that the secret was
        # not released.
        cancel = EventTransferFailed(
            identifier=state.transfer.identifier,
            reason='no route available',
        )
        iteration = TransitionResult(None, [cancel])

    else:
        state.route = try_route

        secret = state.random_generator.next()
        hashlock = sha3(secret)

        # The initiator doesn't need to learn the secret, so there is no need
        # to decrement reveal_timeout from the lock timeout.
        #
        # A value larger than settle_timeout could be used but wouldn't
        # improve, since the next hop will take settle_timeout as an upper
        # limit for expiration.
        lock_expiration = state.block_number + try_route.settle_timeout
        identifier = state.transfer.identifier

        transfer = LockedTransferState(
            identifier,
            state.transfer.amount,
            state.transfer.token,
            state.transfer.target,
            lock_expiration,
            hashlock,
            secret,
        )

        message = SendMediatedTransfer(
            transfer.identifier,
            transfer.token,
            transfer.amount,
            transfer.hashlock,
            transfer.target,
            lock_expiration,
            try_route.node_address,
        )

        state.transfer = transfer
        state.message = message

        iteration = TransitionResult(state, [message])

    return iteration