Пример #1
0
def test_mediator_task_view():
    """Same as above for mediator tasks."""
    secret1 = factories.make_secret(1)
    locked_amount1 = 11
    payee_transfer = factories.create(
        factories.LockedTransferUnsignedStateProperties(secret=secret1))
    payer_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            secret=secret1, payment_identifier=1,
            locked_amount=locked_amount1))
    secrethash1 = payee_transfer.lock.secrethash
    initiator = payee_transfer.initiator
    initiator_channel = factories.create(
        factories.NettingChannelStateProperties(
            partner_state=factories.NettingChannelEndStateProperties(
                address=initiator, balance=100)))
    routes = [factories.make_route_from_channel(initiator_channel)]
    transfer_state1 = MediatorTransferState(secrethash=secrethash1,
                                            routes=routes)
    transfer_state1.transfers_pair.append(
        MediationPairState(
            payer_transfer=payer_transfer,
            payee_transfer=payee_transfer,
            payee_address=payee_transfer.target,
        ))
    task1 = MediatorTask(
        token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS,
        mediator_state=transfer_state1,
    )

    secret2 = factories.make_secret(2)
    locked_amount2 = 13
    transfer2 = factories.create(
        factories.LockedTransferSignedStateProperties(
            secret=secret2, payment_identifier=2,
            locked_amount=locked_amount2))
    secrethash2 = transfer2.lock.secrethash
    transfer_state2 = MediatorTransferState(secrethash=secrethash2,
                                            routes=routes)
    transfer_state2.waiting_transfer = WaitingTransferState(transfer=transfer2)
    task2 = MediatorTask(
        token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS,
        mediator_state=transfer_state2,
    )

    payment_mapping = {secrethash1: task1, secrethash2: task2}
    view = transfer_tasks_view(payment_mapping)

    assert len(view) == 2
    if view[0].get("payment_identifier") == "1":
        pending_transfer, waiting_transfer = view
    else:
        waiting_transfer, pending_transfer = view

    assert pending_transfer.get("role") == waiting_transfer.get(
        "role") == "mediator"
    assert pending_transfer.get("payment_identifier") == "1"
    assert waiting_transfer.get("payment_identifier") == "2"
    assert pending_transfer.get("locked_amount") == str(locked_amount1)
    assert waiting_transfer.get("locked_amount") == str(locked_amount2)
Пример #2
0
def test_mediator_task_view():
    """Same as above for mediator tasks."""
    secret1 = factories.make_secret(1)
    locked_amount1 = TokenAmount(11)
    payee_transfer = factories.create(
        factories.LockedTransferUnsignedStateProperties(secret=secret1))
    payer_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            secret=secret1,
            payment_identifier=PaymentID(1),
            locked_amount=locked_amount1))
    secrethash1 = payee_transfer.lock.secrethash
    route_state = RouteState(route=[payee_transfer.target])

    transfer_state1 = MediatorTransferState(secrethash=secrethash1,
                                            routes=[route_state])
    # pylint: disable=E1101
    transfer_state1.transfers_pair.append(
        MediationPairState(
            payer_transfer=payer_transfer,
            payee_transfer=payee_transfer,
            payee_address=payee_transfer.target,
        ))
    task1 = MediatorTask(
        token_network_address=factories.UNIT_TOKEN_NETWORK_ADDRESS,
        mediator_state=transfer_state1)

    secret2 = factories.make_secret(2)
    locked_amount2 = TokenAmount(13)
    transfer2 = factories.create(
        factories.LockedTransferSignedStateProperties(
            secret=secret2,
            payment_identifier=PaymentID(2),
            locked_amount=locked_amount2))
    secrethash2 = transfer2.lock.secrethash
    transfer_state2 = MediatorTransferState(secrethash=secrethash2,
                                            routes=[route_state])
    transfer_state2.waiting_transfer = WaitingTransferState(transfer=transfer2)
    task2 = MediatorTask(
        token_network_address=factories.UNIT_TOKEN_NETWORK_ADDRESS,
        mediator_state=transfer_state2)

    payment_mapping = {
        secrethash1: cast(TransferTask, task1),
        secrethash2: cast(TransferTask, task2),
    }
    view = transfer_tasks_view(payment_mapping)

    assert len(view) == 2
    if view[0].get("payment_identifier") == "1":
        pending_transfer, waiting_transfer = view
    else:
        waiting_transfer, pending_transfer = view

    assert pending_transfer.get("role") == waiting_transfer.get(
        "role") == "mediator"
    assert pending_transfer.get("payment_identifier") == "1"
    assert waiting_transfer.get("payment_identifier") == "2"
    assert pending_transfer.get("locked_amount") == str(locked_amount1)
    assert waiting_transfer.get("locked_amount") == str(locked_amount2)
Пример #3
0
def mediate_transfer(
        state,
        possible_routes,
        payer_channel,
        channelidentifiers_to_channels,
        pseudo_random_generator,
        payer_transfer,
        block_number,
):
    """ Try a new route or fail back to a refund.

    The mediator can safely try a new route knowing that the tokens from
    payer_transfer will cover the expenses of the mediation. If there is no
    route available that may be used at the moment of the call the mediator may
    send a refund back to the payer, allowing the payer to try a different
    route.
    """
    available_routes = filter_used_routes(
        state.transfers_pair,
        possible_routes,
    )

    assert payer_channel.partner_state.address == payer_transfer.balance_proof.sender

    transfer_pair, mediated_events = forward_transfer_pair(
        payer_transfer,
        available_routes,
        channelidentifiers_to_channels,
        pseudo_random_generator,
        block_number,
    )

    if transfer_pair is None:
        assert not mediated_events

        if state.transfers_pair:
            original_pair = state.transfers_pair[0]
            original_channel = get_payer_channel(
                channelidentifiers_to_channels,
                original_pair,
            )
        else:
            original_channel = payer_channel

        transfer_pair, mediated_events = backward_transfer_pair(
            original_channel,
            payer_transfer,
            pseudo_random_generator,
            block_number,
        )

    if transfer_pair is None:
        assert not mediated_events
        mediated_events = list()
        state.waiting_transfer = WaitingTransferState(payer_transfer)

    else:
        # the list must be ordered from high to low expiration, expiration
        # handling depends on it
        state.transfers_pair.append(transfer_pair)

    return TransitionResult(state, mediated_events)
Пример #4
0
def events_for_expired_pairs(
        channelidentifiers_to_channels: typing.ChannelMap,
        transfers_pair: typing.List[MediationPairState],
        waiting_transfer: WaitingTransferState,
        block_number: typing.BlockNumber,
) -> typing.List[Event]:
    """ Informational events for expired locks. """
    pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair)

    events = list()
    for pair in pending_transfers_pairs:
        payer_balance_proof = pair.payer_transfer.balance_proof
        payer_channel = channelidentifiers_to_channels.get(payer_balance_proof.channel_identifier)
        payer_lock_expiration_threshold = (
            pair.payer_transfer.lock.expiration +
            DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2
        )
        has_payer_lock_expired, _ = channel.is_lock_expired(
            end_state=payer_channel.our_state,
            lock=pair.payer_transfer.lock,
            block_number=block_number,
            lock_expiration_threshold=payer_lock_expiration_threshold,
        )
        has_payer_transfer_expired = (
            has_payer_lock_expired and
            pair.payer_state != 'payer_expired'
        )

        if has_payer_transfer_expired:
            # For safety, the correct behavior is:
            #
            # - If the payee has been paid, then the payer must pay too.
            #
            #   And the corollary:
            #
            # - If the payer transfer has expired, then the payee transfer must
            #   have expired too.
            #
            # The problem is that this corollary cannot be asserted. If a user
            # is running Raiden without a monitoring service, then it may go
            # offline after having paid a transfer to a payee, but without
            # getting a balance proof of the payer, and once it comes back
            # online the transfer may have expired.
            #
            # assert pair.payee_state == 'payee_expired'

            pair.payer_state = 'payer_expired'
            unlock_claim_failed = EventUnlockClaimFailed(
                pair.payer_transfer.payment_identifier,
                pair.payer_transfer.lock.secrethash,
                'lock expired',
            )
            events.append(unlock_claim_failed)

    if waiting_transfer and waiting_transfer.state != 'expired':
        waiting_transfer.state = 'expired'
        unlock_claim_failed = EventUnlockClaimFailed(
            waiting_transfer.transfer.payment_identifier,
            waiting_transfer.transfer.lock.secrethash,
            'lock expired',
        )
        events.append(unlock_claim_failed)

    return events