Ejemplo n.º 1
0
def create_sendmediatedtransfer(channel_state, initiator, target, amount,
                                identifier, expiration, secrethash):

    our_state = channel_state.our_state
    partner_state = channel_state.partner_state
    our_balance_proof = our_state.balance_proof

    msg = 'caller must make sure there is enough balance'
    assert amount <= get_distributable(our_state, partner_state), msg

    msg = 'caller must make sure the channel is open'
    assert get_status(channel_state) == CHANNEL_STATE_OPENED, msg

    lock = HashTimeLockState(
        amount,
        expiration,
        secrethash,
    )

    merkletree = compute_merkletree_with(
        channel_state.our_state.merkletree,
        lock.lockhash,
    )
    # The caller must ensure the same lock is not being used twice
    assert merkletree, 'lock is already registered'

    locksroot = merkleroot(merkletree)

    if our_balance_proof:
        transferred_amount = our_balance_proof.transferred_amount
    else:
        transferred_amount = 0

    token = channel_state.token_address
    nonce = get_next_nonce(channel_state.our_state)
    recipient = channel_state.partner_state.address

    balance_proof = BalanceProofUnsignedState(
        nonce,
        transferred_amount,
        locksroot,
        channel_state.identifier,
    )

    locked_transfer = LockedTransferUnsignedState(
        identifier,
        token,
        balance_proof,
        lock,
        initiator,
        target,
    )

    mediatedtransfer = SendMediatedTransfer(
        locked_transfer,
        recipient,
    )

    return mediatedtransfer, merkletree
Ejemplo n.º 2
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