Example #1
0
def test_refund_transfer_matches_received():
    amount = 30
    expiration = 50

    transfer = factories.make_transfer(
        amount,
        UNIT_TRANSFER_INITIATOR,
        UNIT_TRANSFER_TARGET,
        expiration,
        UNIT_SECRET,
    )

    refund_lower_expiration = factories.make_signed_transfer(
        amount,
        UNIT_TRANSFER_INITIATOR,
        UNIT_TRANSFER_TARGET,
        expiration - 1,
        UNIT_SECRET,
    )

    assert channel.refund_transfer_matches_received(refund_lower_expiration, transfer) is True

    refund_same_expiration = factories.make_signed_transfer(
        amount,
        UNIT_TRANSFER_INITIATOR,
        UNIT_TRANSFER_TARGET,
        expiration,
        UNIT_SECRET,
    )
    assert channel.refund_transfer_matches_received(refund_same_expiration, transfer) is False
Example #2
0
def handle_transferrefundcancelroute(
    payment_state: InitiatorPaymentState,
    state_change: ReceiveTransferRefundCancelRoute,
    channelidentifiers_to_channels: typing.ChannelMap,
    pseudo_random_generator: random.Random,
    block_number: typing.BlockNumber,
) -> TransitionResult:

    channel_identifier = payment_state.initiator.channel_identifier
    channel_state = channelidentifiers_to_channels[channel_identifier]
    refund_transfer = state_change.transfer
    original_transfer = payment_state.initiator.transfer

    is_valid_lock = (
        refund_transfer.lock.secrethash == original_transfer.lock.secrethash
        and refund_transfer.lock.amount == original_transfer.lock.amount and
        refund_transfer.lock.expiration == original_transfer.lock.expiration)

    is_valid_refund = channel.refund_transfer_matches_received(
        refund_transfer,
        original_transfer,
    )

    events = list()
    if is_valid_lock and is_valid_refund:
        is_valid, channel_events, _ = channel.handle_receive_refundtransfercancelroute(
            channel_state,
            refund_transfer,
        )

        events.extend(channel_events)

        if is_valid:
            old_description = payment_state.initiator.transfer_description
            transfer_description = TransferDescriptionWithSecretState(
                old_description.payment_network_identifier,
                old_description.payment_identifier,
                old_description.amount,
                old_description.token_network_identifier,
                old_description.initiator,
                old_description.target,
                state_change.secret,
            )
            payment_state.initiator.transfer_description = transfer_description

            sub_iteration = handle_cancelroute(
                payment_state,
                state_change,
                channelidentifiers_to_channels,
                pseudo_random_generator,
                block_number,
            )

            events.extend(sub_iteration.events)
            if sub_iteration.new_state is None:
                payment_state = None

    iteration = TransitionResult(payment_state, events)

    return iteration
Example #3
0
def test_refund_transfer_does_not_match_received():
    amount = 30
    expiration = 50
    target = UNIT_TRANSFER_SENDER
    transfer = factories.make_transfer(
        amount,
        UNIT_TRANSFER_INITIATOR,
        target,
        expiration,
        UNIT_SECRET,
    )

    refund_from_target = factories.make_signed_transfer(
        amount,
        UNIT_TRANSFER_INITIATOR,
        UNIT_TRANSFER_TARGET,
        expiration - 1,
        UNIT_SECRET,
    )
    # target cannot refund
    assert not channel.refund_transfer_matches_received(refund_from_target, transfer)
Example #4
0
def handle_transferrefundcancelroute(
    payment_state: InitiatorPaymentState,
    state_change: ReceiveTransferRefundCancelRoute,
    channelidentifiers_to_channels: ChannelMap,
    pseudo_random_generator: random.Random,
    block_number: BlockNumber,
) -> TransitionResult[InitiatorPaymentState]:
    initiator_state = payment_state.initiator_transfers.get(
        state_change.transfer.lock.secrethash)
    if not initiator_state:
        return TransitionResult(payment_state, list())

    channel_identifier = initiator_state.channel_identifier
    channel_state = channelidentifiers_to_channels.get(channel_identifier)

    if not channel_state:
        return TransitionResult(payment_state, list())

    refund_transfer = state_change.transfer
    original_transfer = initiator_state.transfer

    is_valid_lock = (
        refund_transfer.lock.secrethash == original_transfer.lock.secrethash
        and refund_transfer.lock.amount == original_transfer.lock.amount and
        refund_transfer.lock.expiration == original_transfer.lock.expiration)

    is_valid_refund = channel.refund_transfer_matches_received(
        refund_transfer,
        original_transfer,
    )

    events = list()
    if not is_valid_lock or not is_valid_refund:
        return TransitionResult(payment_state, list())

    is_valid, channel_events, _ = channel.handle_receive_refundtransfercancelroute(
        channel_state,
        refund_transfer,
    )

    events.extend(channel_events)

    if not is_valid:
        return TransitionResult(payment_state, list())

    old_description = initiator_state.transfer_description
    transfer_description = TransferDescriptionWithSecretState(
        payment_network_identifier=old_description.payment_network_identifier,
        payment_identifier=old_description.payment_identifier,
        amount=old_description.amount,
        token_network_identifier=old_description.token_network_identifier,
        allocated_fee=old_description.allocated_fee,
        initiator=old_description.initiator,
        target=old_description.target,
        secret=state_change.secret,
    )

    sub_iteration = maybe_try_new_route(
        payment_state=payment_state,
        initiator_state=initiator_state,
        transfer_description=transfer_description,
        available_routes=state_change.routes,
        channelidentifiers_to_channels=channelidentifiers_to_channels,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_number,
    )

    events.extend(sub_iteration.events)

    iteration = TransitionResult(payment_state, events)

    return iteration
Example #5
0
def handle_transferrefundcancelroute(
    payment_state: InitiatorPaymentState,
    state_change: ReceiveTransferRefundCancelRoute,
    channelidentifiers_to_channels: initiator.ChannelMap,
    pseudo_random_generator: random.Random,
    block_number: typing.BlockNumber,
) -> TransitionResult:

    channel_identifier = payment_state.initiator.channel_identifier
    channel_state = channelidentifiers_to_channels[channel_identifier]
    refund_transfer = state_change.transfer
    original_transfer = payment_state.initiator.transfer

    if channel_state.close_transaction:
        closed_block_number = channel_state.close_transaction.finished_block_number
    else:
        closed_block_number = None

    # This is overcommiting, since the initiator knows the secret it doesn't
    # need to wait for reveal_timeout blocks.
    timeout_blocks = mediator.get_timeout_blocks(
        channel_state.settle_timeout,
        closed_block_number,
        original_transfer.lock.expiration,
        block_number,
    )
    lock_timeout = timeout_blocks - channel_state.reveal_timeout
    maximum_expiration = lock_timeout + block_number

    is_valid_lock = (
        refund_transfer.lock.secrethash == original_transfer.lock.secrethash
        and refund_transfer.lock.amount == original_transfer.lock.amount
        and refund_transfer.lock.expiration <= maximum_expiration)

    is_valid_refund = channel.refund_transfer_matches_received(
        refund_transfer,
        original_transfer,
    )

    events = list()
    if is_valid_lock and is_valid_refund:
        is_valid, channel_events, _ = channel.handle_receive_refundtransfercancelroute(
            channel_state,
            refund_transfer,
        )

        events.extend(channel_events)

        if is_valid:
            old_description = payment_state.initiator.transfer_description
            transfer_description = TransferDescriptionWithSecretState(
                old_description.payment_identifier,
                old_description.amount,
                old_description.token_network_identifier,
                old_description.initiator,
                old_description.target,
                state_change.secret,
            )
            payment_state.initiator.transfer_description = transfer_description

            sub_iteration = handle_cancelroute(
                payment_state,
                state_change,
                channelidentifiers_to_channels,
                pseudo_random_generator,
                block_number,
            )

            events.extend(sub_iteration.events)
            if sub_iteration.new_state is None:
                payment_state = None

    iteration = TransitionResult(payment_state, events)

    return iteration
Example #6
0
def handle_transferrefundcancelroute(
        payment_state: InitiatorPaymentState,
        state_change: ReceiveTransferRefundCancelRoute,
        channelidentifiers_to_channels: initiator.ChannelMap,
        pseudo_random_generator: random.Random,
        block_number: typing.BlockNumber,
) -> TransitionResult:

    channel_identifier = payment_state.initiator.channel_identifier
    channel_state = channelidentifiers_to_channels[channel_identifier]
    refund_transfer = state_change.transfer
    original_transfer = payment_state.initiator.transfer

    if channel_state.close_transaction:
        closed_block_number = channel_state.close_transaction.finished_block_number
    else:
        closed_block_number = None

    # This is overcommiting, since the initiator knows the secret it doesn't
    # need to wait for reveal_timeout blocks.
    timeout_blocks = mediator.get_timeout_blocks(
        channel_state.settle_timeout,
        closed_block_number,
        original_transfer.lock.expiration,
        block_number,
    )
    lock_timeout = timeout_blocks - channel_state.reveal_timeout
    maximum_expiration = lock_timeout + block_number

    is_valid_lock = (
        refund_transfer.lock.secrethash == original_transfer.lock.secrethash and
        refund_transfer.lock.amount == original_transfer.lock.amount and
        refund_transfer.lock.expiration <= maximum_expiration
    )

    is_valid_refund = channel.refund_transfer_matches_received(
        refund_transfer,
        original_transfer,
    )

    events = list()
    if is_valid_lock and is_valid_refund:
        is_valid, channel_events, _ = channel.handle_receive_refundtransfercancelroute(
            channel_state,
            refund_transfer,
        )

        events.extend(channel_events)

        if is_valid:
            old_description = payment_state.initiator.transfer_description
            transfer_description = TransferDescriptionWithSecretState(
                old_description.payment_identifier,
                old_description.amount,
                old_description.token_network_identifier,
                old_description.initiator,
                old_description.target,
                state_change.secret,
            )
            payment_state.initiator.transfer_description = transfer_description

            sub_iteration = handle_cancelroute(
                payment_state,
                state_change,
                channelidentifiers_to_channels,
                pseudo_random_generator,
                block_number,
            )

            events.extend(sub_iteration.events)
            if sub_iteration.new_state is None:
                payment_state = None

    iteration = TransitionResult(payment_state, events)

    return iteration
Example #7
0
def handle_transferrefundcancelroute(
        payment_state: InitiatorPaymentState,
        state_change: ReceiveTransferRefundCancelRoute,
        channelidentifiers_to_channels: ChannelMap,
        pseudo_random_generator: random.Random,
        block_number: BlockNumber,
) -> TransitionResult:

    channel_identifier = payment_state.initiator.channel_identifier
    channel_state = channelidentifiers_to_channels[channel_identifier]
    refund_transfer = state_change.transfer
    original_transfer = payment_state.initiator.transfer

    is_valid_lock = (
        refund_transfer.lock.secrethash == original_transfer.lock.secrethash and
        refund_transfer.lock.amount == original_transfer.lock.amount and
        refund_transfer.lock.expiration == original_transfer.lock.expiration
    )

    is_valid_refund = channel.refund_transfer_matches_received(
        refund_transfer,
        original_transfer,
    )

    events = list()
    if is_valid_lock and is_valid_refund:
        is_valid, channel_events, _ = channel.handle_receive_refundtransfercancelroute(
            channel_state,
            refund_transfer,
        )

        events.extend(channel_events)

        if is_valid:
            old_description = payment_state.initiator.transfer_description
            transfer_description = TransferDescriptionWithSecretState(
                old_description.payment_network_identifier,
                old_description.payment_identifier,
                old_description.amount,
                old_description.token_network_identifier,
                old_description.initiator,
                old_description.target,
                state_change.secret,
            )
            payment_state.initiator.transfer_description = transfer_description

            sub_iteration = handle_cancelroute(
                payment_state,
                state_change,
                channelidentifiers_to_channels,
                pseudo_random_generator,
                block_number,
            )

            events.extend(sub_iteration.events)
            if sub_iteration.new_state is None:
                payment_state = None

    iteration = TransitionResult(payment_state, events)

    return iteration