Exemple #1
0
def test_different_view_of_last_bp_during_unlock(
    raiden_chain,
    number_of_nodes,
    token_addresses,
    deposit,
    network_wait,
    retry_timeout,
    # UDP does not seem to retry messages until processed
    # https://github.com/raiden-network/raiden/issues/3185
    skip_if_not_matrix,
):
    """Test for https://github.com/raiden-network/raiden/issues/3196#issuecomment-449163888"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )
    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [],
        app1,
        deposit + amount_path,
        [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait(
    ) is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_search_for_item(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {
            'lock': {
                'amount': amount_refund
            }
        }},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_search_for_item(app1.raiden,
                                                SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [lockstate_from_lock(lock)],
        app1,
        deposit + amount_path,
        [lockstate_from_lock(refund_lock)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(
        app0.raiden).payment_mapping.secrethashes_to_task

    with dont_handle_node_change_network_state():
        # now app1 goes offline
        app1.raiden.stop()
        app1.raiden.get()
        assert not app1.raiden

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(lock) + 1,
            retry_timeout=retry_timeout,
        )

        # make sure that app0 sent a lock expired message for the secrethash
        wait_for_raiden_event(
            app0.raiden,
            SendLockExpired,
            {'secrethash': secrethash},
            retry_timeout,
        )

        # now app0 closes the channel
        RaidenAPI(app0.raiden).channel_close(
            registry_address=payment_network_identifier,
            token_address=token_address,
            partner_address=app1.raiden.address,
        )

    count = 0
    original_update = app1.raiden.raiden_event_handler.handle_contract_send_channelupdate

    def patched_update(raiden, event):
        nonlocal count
        count += 1
        original_update(raiden, event)

    app1.raiden.raiden_event_handler.handle_contract_send_channelupdate = patched_update
    # and now app1 comes back online
    app1.raiden.start()
    # test for https://github.com/raiden-network/raiden/issues/3216
    assert count == 1, 'Update transfer should have only been called once during restart'
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    # and we wait for settlement
    wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=payment_network_identifier,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    with gevent.Timeout(10):
        unlock_app0 = wait_for_state_change(
            app0.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app0.raiden.address},
            retry_timeout,
        )
    assert unlock_app0.returned_tokens == 50
    with gevent.Timeout(10):
        unlock_app1 = wait_for_state_change(
            app1.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app1.raiden.address},
            retry_timeout,
        )
    assert unlock_app1.returned_tokens == 50
    final_balance0 = token_proxy.balance_of(app0.raiden.address)
    final_balance1 = token_proxy.balance_of(app1.raiden.address)

    assert final_balance0 - deposit - initial_balance0 == -1
    assert final_balance1 - deposit - initial_balance1 == 1
def test_different_view_of_last_bp_during_unlock(
        raiden_chain,
        number_of_nodes,
        token_addresses,
        deposit,
        network_wait,
        retry_timeout,
        # UDP does not seem to retry messages until processed
        # https://github.com/raiden-network/raiden/issues/3185
        skip_if_not_matrix,
):
    """Test for https://github.com/raiden-network/raiden/issues/3196#issuecomment-449163888"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )
    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [],
        app1, deposit + amount_path, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': amount_refund}}},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [lockstate_from_lock(lock)],
        app1, deposit + amount_path, [lockstate_from_lock(refund_lock)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(app0.raiden).payment_mapping.secrethashes_to_task

    with dont_handle_node_change_network_state():
        # now app1 goes offline
        app1.raiden.stop()
        app1.raiden.get()
        assert not app1.raiden

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(lock) + 1,
            retry_timeout=retry_timeout,
        )

        # make sure that app0 sent a lock expired message for the secrethash
        wait_for_raiden_event(
            app0.raiden,
            SendLockExpired,
            {'secrethash': secrethash},
            retry_timeout,
        )

        # now app0 closes the channel
        RaidenAPI(app0.raiden).channel_close(
            registry_address=payment_network_identifier,
            token_address=token_address,
            partner_address=app1.raiden.address,
        )

    count = 0
    original_update = app1.raiden.raiden_event_handler.handle_contract_send_channelupdate

    def patched_update(raiden, event):
        nonlocal count
        count += 1
        original_update(raiden, event)

    app1.raiden.raiden_event_handler.handle_contract_send_channelupdate = patched_update
    # and now app1 comes back online
    app1.raiden.start()
    # test for https://github.com/raiden-network/raiden/issues/3216
    assert count == 1, 'Update transfer should have only been called once during restart'
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # and we wait for settlement
    wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=payment_network_identifier,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    with gevent.Timeout(10):
        unlock_app0 = wait_for_state_change(
            app0.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app0.raiden.address},
            retry_timeout,
        )
    assert unlock_app0.returned_tokens == 50
    with gevent.Timeout(10):
        unlock_app1 = wait_for_state_change(
            app1.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app1.raiden.address},
            retry_timeout,
        )
    assert unlock_app1.returned_tokens == 50
    final_balance0 = token_proxy.balance_of(app0.raiden.address)
    final_balance1 = token_proxy.balance_of(app1.raiden.address)

    assert final_balance0 - deposit - initial_balance0 == -1
    assert final_balance1 - deposit - initial_balance1 == 1
def test_different_view_of_last_bp_during_unlock(
    raiden_chain,
    number_of_nodes,
    token_addresses,
    deposit,
    network_wait,
    retry_timeout,
    blockchain_type,
):
    """Test for https://github.com/raiden-network/raiden/issues/3196#issuecomment-449163888"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), token_network_registry_address,
        token_address)
    token_proxy = app0.raiden.proxy_manager.token(token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=amount_path,
        identifier=identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    transfer(
        initiator_app=app1,
        target_app=app2,
        token_address=token_address,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount_path,
            [],
            app1,
            deposit + amount_path,
            [],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app1,
            deposit - amount_path - amount_drain,
            [],
            app2,
            deposit + amount_path + amount_drain,
            [],
        )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    amount_refund_with_fees = amount_refund + calculate_fee_for_amount(50)
    payment_status = app0.raiden.mediated_transfer_async(
        token_network_address, amount_refund, app2.raiden.address,
        identifier_refund)
    msg = "there is no path with capacity, the transfer must fail"
    assert isinstance(payment_status.payment_done.wait(),
                      EventPaymentSentFailed), msg

    # A lock structure with the correct amount

    send_locked = raiden_events_search_for_item(
        app0.raiden,
        SendLockedTransfer,
        {"transfer": {
            "lock": {
                "amount": amount_refund_with_fees
            }
        }},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_search_for_item(app1.raiden,
                                                SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount_path,
            [lock],
            app1,
            deposit + amount_path,
            [refund_lock],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app1,
            deposit - amount_path - amount_drain,
            [],
            app2,
            deposit + amount_path + amount_drain,
            [],
        )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(
        app0.raiden).payment_mapping.secrethashes_to_task

    with dont_handle_node_change_network_state():
        # now app1 goes offline
        app1.raiden.stop()
        app1.raiden.get()
        assert not app1.raiden

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(
                lock.expiration) + 1,
            retry_timeout=retry_timeout,
        )

        # make sure that app0 sent a lock expired message for the secrethash
        wait_for_raiden_event(app0.raiden, SendLockExpired,
                              {"secrethash": secrethash}, retry_timeout)

        # now app0 closes the channel
        RaidenAPI(app0.raiden).channel_close(
            registry_address=token_network_registry_address,
            token_address=token_address,
            partner_address=app1.raiden.address,
        )

    count = 0
    on_raiden_event_original = app1.raiden.raiden_event_handler.on_raiden_event

    def patched_on_raiden_event(raiden, chain_state, event):
        if type(event) == ContractSendChannelUpdateTransfer:
            nonlocal count
            count += 1

        on_raiden_event_original(raiden, chain_state, event)

    app1.raiden.raiden_event_handler.on_raiden_event = patched_on_raiden_event
    # and now app1 comes back online
    app1.raiden.start()
    # test for https://github.com/raiden-network/raiden/issues/3216
    assert count == 1, "Update transfer should have only been called once during restart"
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_address).identifier

    # and we wait for settlement
    wait_for_settle(
        raiden=app0.raiden,
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    timeout = 30 if blockchain_type == "parity" else 10
    with gevent.Timeout(timeout):
        unlock_app0 = wait_for_state_change(
            app0.raiden,
            ContractReceiveChannelBatchUnlock,
            {"receiver": app0.raiden.address},
            retry_timeout,
        )
    assert unlock_app0.returned_tokens == amount_refund_with_fees
    with gevent.Timeout(timeout):
        unlock_app1 = wait_for_state_change(
            app1.raiden,
            ContractReceiveChannelBatchUnlock,
            {"receiver": app1.raiden.address},
            retry_timeout,
        )
    assert unlock_app1.returned_tokens == amount_refund_with_fees
    final_balance0 = token_proxy.balance_of(app0.raiden.address)
    final_balance1 = token_proxy.balance_of(app1.raiden.address)

    assert final_balance0 - deposit - initial_balance0 == -1
    assert final_balance1 - deposit - initial_balance1 == 1
Exemple #4
0
def test_different_view_of_last_bp_during_unlock(
    raiden_chain: List[RaidenService],
    restart_node,
    token_addresses,
    deposit,
    retry_timeout,
    blockchain_type,
):
    """Test for https://github.com/raiden-network/raiden/issues/3196#issuecomment-449163888"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    token_network_registry_address = app0.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_raiden(app0), token_network_registry_address,
        token_address)
    assert token_network_address
    token_proxy = app0.proxy_manager.token(token_address, BLOCK_ID_LATEST)
    initial_balance0 = token_proxy.balance_of(app0.address)
    initial_balance1 = token_proxy.balance_of(app1.address)

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = PaymentID(1)
    amount_path = PaymentAmount(1)
    with block_offset_timeout(app0):
        transfer(
            initiator_app=app0,
            target_app=app2,
            token_address=token_address,
            amount=amount_path,
            identifier=identifier_path,
            routes=[[app0.address, app1.address, app2.address]],
        )

    # drain the channel app1 -> app2
    identifier_drain = PaymentID(2)
    amount_drain = PaymentAmount(deposit * 8 // 10)
    with block_offset_timeout(app1):
        transfer(
            initiator_app=app1,
            target_app=app2,
            token_address=token_address,
            amount=amount_drain,
            identifier=identifier_drain,
            routes=[[app1.address, app2.address]],
        )
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount_path,
            [],
            app1,
            deposit + amount_path,
            [],
        )
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app1,
            deposit - amount_path - amount_drain,
            [],
            app2,
            deposit + amount_path + amount_drain,
            [],
        )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = PaymentID(3)
    amount_refund = PaymentAmount(50)
    fee = calculate_fee_for_amount(amount_refund)
    fee_margin = calculate_fee_margin(amount_refund, fee)
    amount_refund_with_fees = amount_refund + fee + fee_margin

    payment_status = app0.mediated_transfer_async(
        token_network_address=token_network_address,
        amount=amount_refund,
        target=TargetAddress(app2.address),
        identifier=identifier_refund,
        route_states=[
            create_route_state_for_route(
                apps=raiden_chain,
                token_address=token_address,
                fee_estimate=FeeAmount(
                    round(INTERNAL_ROUTING_DEFAULT_FEE_PERC * amount_refund)),
            )
        ],
    )
    msg = "there is no path with capacity, the transfer must fail"
    assert isinstance(payment_status.payment_done.wait(),
                      EventPaymentSentFailed), msg

    # A lock structure with the correct amount

    send_locked = raiden_events_search_for_item(
        app0,
        SendLockedTransfer,
        {"transfer": {
            "lock": {
                "amount": amount_refund_with_fees
            }
        }},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_search_for_item(app1, SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    with block_offset_timeout(app0):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount_path,
            [lock],
            app1,
            deposit + amount_path,
            [refund_lock],
        )
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app1,
            deposit - amount_path - amount_drain,
            [],
            app2,
            deposit + amount_path + amount_drain,
            [],
        )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(
        app0).payment_mapping.secrethashes_to_task

    with dont_handle_node_change_network_state():
        # now app1 goes offline
        app1.stop()
        app1.greenlet.get()
        assert not app1

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0,
            block_number=BlockNumber(
                channel.get_sender_expiration_threshold(lock.expiration) + 1),
            retry_timeout=retry_timeout,
        )

        # make sure that app0 sent a lock expired message for the secrethash
        wait_for_raiden_event(app0, SendLockExpired,
                              {"secrethash": secrethash}, retry_timeout)

        # now app0 closes the channel
        RaidenAPI(app0).channel_close(
            registry_address=token_network_registry_address,
            token_address=token_address,
            partner_address=app1.address,
        )

    count = 0
    on_raiden_events_original = app1.raiden_event_handler.on_raiden_events

    def patched_on_raiden_events(raiden, chain_state, events):
        nonlocal count

        count += sum(1 for event in events
                     if type(event) == ContractSendChannelUpdateTransfer)

        on_raiden_events_original(raiden, chain_state, events)

    setattr(app1.raiden_event_handler, "on_raiden_events",
            patched_on_raiden_events)  # NOQA

    # and now app1 comes back online
    restart_node(app1)
    # test for https://github.com/raiden-network/raiden/issues/3216
    assert count == 1, "Update transfer should have only been called once during restart"
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_address).identifier

    # and we wait for settlement
    wait_for_settle(
        raiden=app0,
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.alarm.sleep_time,
    )

    timeout = 30 if blockchain_type == "parity" else 10
    with gevent.Timeout(timeout):
        unlock_app0 = wait_for_state_change(
            app0,
            ContractReceiveChannelBatchUnlock,
            {"receiver": app0.address},
            retry_timeout,
        )
    assert unlock_app0
    assert unlock_app0.returned_tokens == amount_refund_with_fees
    with gevent.Timeout(timeout):
        unlock_app1 = wait_for_state_change(
            app1,
            ContractReceiveChannelBatchUnlock,
            {"receiver": app1.address},
            retry_timeout,
        )
    assert unlock_app1
    assert unlock_app1.returned_tokens == amount_refund_with_fees
    final_balance0 = token_proxy.balance_of(app0.address)
    final_balance1 = token_proxy.balance_of(app1.address)

    assert final_balance0 - deposit - initial_balance0 == -1
    assert final_balance1 - deposit - initial_balance1 == 1