예제 #1
0
def test_close_regression(raiden_network, deposit, token_addresses):
    """ The python api was using the wrong balance proof to close the channel,
    thus the close was failing if a transfer was made.
    """
    app0, app1 = raiden_network
    token_address = token_addresses[0]

    api1 = RaidenAPI(app0.raiden)
    api2 = RaidenAPI(app1.raiden)

    registry_address = app0.raiden.default_registry.address
    channel_list = api1.get_channel_list(registry_address, token_address,
                                         app1.raiden.address)
    channel12 = channel_list[0]

    token_proxy = app0.raiden.proxy_manager.token(token_address,
                                                  BLOCK_ID_LATEST)
    node1_balance_before = token_proxy.balance_of(api1.address)
    node2_balance_before = token_proxy.balance_of(api2.address)

    # Initialize app2 balance proof and close the channel
    amount = PaymentAmount(10)
    identifier = PaymentID(42)
    secret, secrethash = factories.make_secret_with_hash()
    timeout = block_offset_timeout(app1.raiden, "Transfer timed out.")
    with watch_for_unlock_failures(*raiden_network), timeout:
        assert api1.transfer_and_wait(
            registry_address=registry_address,
            token_address=token_address,
            amount=amount,
            target=TargetAddress(api2.address),
            identifier=identifier,
            secret=secret,
        )
        timeout.exception_to_throw = ValueError(
            "Waiting for transfer received success in the WAL timed out.")
        result = waiting.wait_for_received_transfer_result(
            raiden=app1.raiden,
            payment_identifier=identifier,
            amount=amount,
            retry_timeout=app1.raiden.alarm.sleep_time,
            secrethash=secrethash,
        )

    msg = f"Unexpected transfer result: {str(result)}"
    assert result == waiting.TransferWaitResult.UNLOCKED, msg

    api2.channel_close(registry_address, token_address, api1.address)

    waiting.wait_for_settle(
        app0.raiden,
        app0.raiden.default_registry.address,
        token_address,
        [channel12.identifier],
        app0.raiden.alarm.sleep_time,
    )
    node1_expected_balance = node1_balance_before + deposit - amount
    node2_expected_balance = node2_balance_before + deposit + amount
    assert token_proxy.balance_of(api1.address) == node1_expected_balance
    assert token_proxy.balance_of(api2.address) == node2_expected_balance
예제 #2
0
def test_channel_withdraw(
    raiden_network: List[App],
    token_addresses: List[TokenAddress],
    deposit: TokenAmount,
    retry_timeout: float,
) -> None:
    """ Withdraw funds after a mediated transfer."""
    alice_app, bob_app = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address
    )
    assert token_network_address

    token_proxy = bob_app.raiden.proxy_manager.token(token_address, BLOCK_ID_LATEST)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    message_handler = WaitForMessage()
    bob_app.raiden.message_handler = message_handler

    alice_to_bob_amount = PaymentAmount(10)
    identifier = PaymentID(1)
    target = TargetAddress(bob_app.raiden.address)
    secret = factories.make_secret()

    payment_status = alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=alice_to_bob_amount,
        target=target,
        identifier=identifier,
        secret=secret,
    )
    wait_for_unlock = bob_app.raiden.message_handler.wait_for_message(
        Unlock, {"payment_identifier": identifier}
    )
    with block_offset_timeout(alice_app.raiden):
        wait_for_unlock.get()
        msg = (
            f"transfer from {to_checksum_address(alice_app.raiden.address)} "
            f"to {to_checksum_address(bob_app.raiden.address)} failed."
        )
        assert payment_status.payment_done.get(), msg

    total_withdraw = WithdrawAmount(deposit + alice_to_bob_amount)

    bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address)
    bob_app.raiden.withdraw(
        canonical_identifier=bob_alice_channel_state.canonical_identifier,
        total_withdraw=total_withdraw,
    )

    waiting.wait_for_withdraw_complete(
        raiden=bob_app.raiden,
        canonical_identifier=bob_alice_channel_state.canonical_identifier,
        total_withdraw=total_withdraw,
        retry_timeout=retry_timeout,
    )

    bob_balance_after_withdraw = token_proxy.balance_of(bob_app.raiden.address)
    assert bob_initial_balance + total_withdraw == bob_balance_after_withdraw
예제 #3
0
def test_handle_insufficient_eth(
    raiden_network: List[RaidenService], restart_node, token_addresses, caplog
):
    app0, app1 = raiden_network
    token = token_addresses[0]
    registry_address = app0.default_registry.address

    channel_state = views.get_channelstate_for(
        chain_state=views.state_from_raiden(app0),
        token_network_registry_address=registry_address,
        token_address=token,
        partner_address=app1.address,
    )
    assert isinstance(channel_state, NettingChannelState)
    channel_identifier = channel_state.identifier

    with block_offset_timeout(app0):
        transfer(
            initiator_app=app0,
            target_app=app1,
            token_address=token,
            amount=PaymentAmount(1),
            identifier=PaymentID(1),
        )

    app1.stop()
    burn_eth(app1.rpc_client)
    restart_node(app1)

    block_offset = BlockOffset(channel_state.settle_timeout * 2)
    with block_offset_timeout(app0, "Settle did not happen", block_offset):
        RaidenAPI(app0).channel_close(
            registry_address=registry_address,
            token_address=token,
            partner_address=app1.address,
        )
        waiting.wait_for_settle(
            raiden=app0,
            token_network_registry_address=registry_address,
            token_address=token,
            channel_ids=[channel_identifier],
            retry_timeout=DEFAULT_RETRY_TIMEOUT,
        )

    assert any(
        "subtask died" in message and "insufficient ETH" in message for message in caplog.messages
    )
예제 #4
0
def test_leave_token_network(raiden_network: List[RaidenService],
                             token_addresses):
    registry_address = raiden_network[0].default_registry.address
    token_address = token_addresses[0]
    _, app1, _ = raiden_network

    channels = views.list_channelstate_for_tokennetwork(
        chain_state=views.state_from_raiden(app1),
        token_network_registry_address=registry_address,
        token_address=token_address,
    )

    timeout = block_offset_timeout(
        app1, "Channels not settled in time",
        BlockTimeout(channels[0].settle_timeout * 10))
    with timeout:
        RaidenAPI(app1).token_network_leave(registry_address, token_address)
        waiting.wait_for_settle(
            raiden=app1,
            token_network_registry_address=registry_address,
            token_address=token_address,
            channel_ids=[channel.identifier for channel in channels],
            retry_timeout=0.1,
        )
예제 #5
0
def test_payment_events_endpoints(api_server_test_instance: APIServer,
                                  raiden_network: List[RaidenService],
                                  token_addresses):
    app0, app1, app2 = raiden_network

    token_address0 = token_addresses[0]
    token_address1 = token_addresses[1]

    app0_server = api_server_test_instance
    app1_server = prepare_api_server(app1)
    app2_server = prepare_api_server(app2)

    # Payment 1: app0 is sending tokens of token0 to app1
    identifier1 = PaymentID(10)
    amount1 = PaymentAmount(10)
    secret1, secrethash1 = factories.make_secret_with_hash()
    request = grequests.post(
        api_url_for(
            app0_server,
            "token_target_paymentresource",
            token_address=to_checksum_address(token_address0),
            target_address=to_checksum_address(app1.address),
        ),
        json={
            "amount": str(amount1),
            "identifier": str(identifier1),
            "secret": to_hex(secret1)
        },
    )
    request.send()

    # Payment 2: app0 is sending some tokens of token1 to app2
    identifier2 = PaymentID(20)
    amount2 = PaymentAmount(10)
    secret2, secrethash2 = factories.make_secret_with_hash()
    request = grequests.post(
        api_url_for(
            app0_server,
            "token_target_paymentresource",
            token_address=to_checksum_address(token_address1),
            target_address=to_checksum_address(app2.address),
        ),
        json={
            "amount": str(amount2),
            "identifier": str(identifier2),
            "secret": to_hex(secret2)
        },
    )
    request.send()

    # Payment 3: app0 is sending some tokens of token0 to app2
    identifier3 = PaymentID(30)
    amount3 = PaymentAmount(17)
    secret3, secrethash3 = factories.make_secret_with_hash()
    request = grequests.post(
        api_url_for(
            app0_server,
            "token_target_paymentresource",
            token_address=to_checksum_address(token_address0),
            target_address=to_checksum_address(app1.address),
        ),
        json={
            "amount": str(amount3),
            "identifier": str(identifier3),
            "secret": to_hex(secret3)
        },
    )
    request.send()

    timeout = block_offset_timeout(
        app2, "Waiting for transfer received success in the WAL timed out")
    with watch_for_unlock_failures(*raiden_network), timeout:
        result = wait_for_received_transfer_result(app1, identifier1, amount1,
                                                   app1.alarm.sleep_time,
                                                   secrethash1)
        msg = f"Unexpected transfer result: {str(result)}"
        assert result == TransferWaitResult.UNLOCKED, msg
        result = wait_for_received_transfer_result(app2, identifier2, amount2,
                                                   app2.alarm.sleep_time,
                                                   secrethash2)
        msg = f"Unexpected transfer result: {str(result)}"
        assert result == TransferWaitResult.UNLOCKED, msg
        result = wait_for_received_transfer_result(app1, identifier3, amount3,
                                                   app1.alarm.sleep_time,
                                                   secrethash3)
        msg = f"Unexpected transfer result: {str(result)}"
        assert result == TransferWaitResult.UNLOCKED, msg

    # predefine events for later use in assertions
    event_sent_1 = {
        "event": "EventPaymentSentSuccess",
        "identifier": str(identifier1),
        "target": to_checksum_address(app1.address),
        "token_address": to_checksum_address(token_address0),
    }
    event_sent_2 = {
        "event": "EventPaymentSentSuccess",
        "identifier": str(identifier2),
        "target": to_checksum_address(app2.address),
        "token_address": to_checksum_address(token_address1),
    }
    event_sent_3 = {
        "event": "EventPaymentSentSuccess",
        "identifier": str(identifier3),
        "target": to_checksum_address(app1.address),
        "token_address": to_checksum_address(token_address0),
    }
    event_received_1 = {
        "event": "EventPaymentReceivedSuccess",
        "identifier": str(identifier1),
        "initiator": to_checksum_address(app0.address),
        "token_address": to_checksum_address(token_address0),
    }
    event_received_2 = {
        "event": "EventPaymentReceivedSuccess",
        "identifier": str(identifier2),
        "initiator": to_checksum_address(app0.address),
        "token_address": to_checksum_address(token_address1),
    }
    event_received_3 = {
        "event": "EventPaymentReceivedSuccess",
        "identifier": str(identifier3),
        "initiator": to_checksum_address(app0.address),
        "token_address": to_checksum_address(token_address0),
    }

    # test app0 endpoint without (partner and token) for sender
    request = grequests.get(api_url_for(app0_server, "paymentresource"))
    with watch_for_unlock_failures(*raiden_network):
        response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)

    assert must_have_event(json_response, event_sent_1)
    assert must_have_event(json_response, event_sent_2)
    assert must_have_event(json_response, event_sent_3)

    # test endpoint without (partner and token) for target1
    request = grequests.get(api_url_for(app1_server, "paymentresource"))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(json_response, event_received_1)
    assert must_have_event(json_response, event_received_3)

    # test endpoint without (partner and token) for target2
    request = grequests.get(api_url_for(app2_server, "paymentresource"))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(json_response, event_received_2)

    # test endpoint without partner for app0
    request = grequests.get(
        api_url_for(app0_server,
                    "token_paymentresource",
                    token_address=token_address0))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)

    assert must_have_event(json_response, event_sent_1)
    assert must_have_event(json_response, event_sent_3)

    # test endpoint without partner for app0 but with limit/offset to get only first
    request = grequests.get(
        api_url_for(
            app0_server,
            "token_paymentresource",
            token_address=token_address0,
            limit=1,
            offset=0,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)

    assert must_have_event(json_response, event_sent_1)
    assert len(json_response) == 1

    # test endpoint without partner for app0 but with limit/offset
    # to get only second transfer of token_address
    request = grequests.get(
        api_url_for(
            app0_server,
            "token_paymentresource",
            token_address=token_address0,
            limit=1,
            offset=1,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)

    # this should return only payment 3, since payment 1 is offset
    # and payment 2 is of another token address
    assert len(json_response) == 1
    assert must_have_event(json_response, event_sent_3)

    # test endpoint of app1 without partner for token_address
    request = grequests.get(
        api_url_for(app1_server,
                    "token_paymentresource",
                    token_address=token_address0))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_events(json_response, event_received_1)
    assert must_have_events(json_response, event_received_3)

    # test endpoint of app2 without partner for token_address
    request = grequests.get(
        api_url_for(app2_server,
                    "token_paymentresource",
                    token_address=token_address0))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 0

    # test endpoint of app2 without partner for token_address2
    request = grequests.get(
        api_url_for(app2_server,
                    "token_paymentresource",
                    token_address=token_address1))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_events(json_response, event_received_2)

    # test endpoint for token_address0 and partner for app0
    request = grequests.get(
        api_url_for(
            app0_server,
            "token_target_paymentresource",
            token_address=token_address0,
            target_address=app1.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 2
    assert must_have_event(json_response, event_sent_1)
    assert must_have_event(json_response, event_sent_3)

    request = grequests.get(
        api_url_for(
            app0_server,
            "token_target_paymentresource",
            token_address=token_address1,
            target_address=app2.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 1
    assert must_have_event(json_response, event_sent_2)

    # test endpoint for token_address0 and partner for app1. Check both partners
    # to see that filtering works correctly
    request = grequests.get(
        api_url_for(
            app1_server,
            "token_target_paymentresource",
            token_address=token_address0,
            target_address=app2.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 0

    request = grequests.get(
        api_url_for(
            app1_server,
            "token_target_paymentresource",
            token_address=token_address0,
            target_address=app0.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 2
    assert must_have_event(json_response, event_received_1)
    assert must_have_event(json_response, event_received_3)

    # test app1 checking payments to himself
    request = grequests.get(
        api_url_for(
            app1_server,
            "token_target_paymentresource",
            token_address=token_address0,
            target_address=app1.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 0

    # test endpoint for token and partner for app2
    request = grequests.get(
        api_url_for(
            app2_server,
            "token_target_paymentresource",
            token_address=token_address0,
            target_address=app0.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    # Since app2 has no payment with app0 in token_address
    assert len(json_response) == 0

    # test endpoint for token2 and partner for app2
    request = grequests.get(
        api_url_for(
            app2_server,
            "token_target_paymentresource",
            token_address=token_address1,
            target_address=app0.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)

    # app2 has one payment with app0 in token_address2
    assert len(json_response) == 1
    assert must_have_events(json_response, event_received_2)

    request = grequests.get(
        api_url_for(
            app2_server,
            "token_target_paymentresource",
            token_address=token_address0,
            target_address=app1.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert not must_have_event(json_response, event_received_2)

    # also add a test for filtering by wrong token address
    request = grequests.get(
        api_url_for(
            app2_server,
            "token_target_paymentresource",
            token_address=app1.address,
            target_address=app1.address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.BAD_REQUEST)

    app1_server.stop()
    app2_server.stop()
예제 #6
0
def test_clear_closed_queue(raiden_network: List[App], token_addresses,
                            network_wait):
    """ Closing a channel clears the respective message queue. """
    app0, app1 = raiden_network

    hold_event_handler = app1.raiden.raiden_event_handler
    assert isinstance(hold_event_handler, HoldRaidenEventHandler)

    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    chain_state0 = views.state_from_app(app0)
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state0, app0.raiden.default_registry.address, token_address)
    assert token_network_address
    token_network = views.get_token_network_by_address(chain_state0,
                                                       token_network_address)
    assert token_network

    channel_identifier = get_channelstate(app0, app1,
                                          token_network_address).identifier

    assert (channel_identifier
            in token_network.partneraddresses_to_channelidentifiers[
                app1.raiden.address])

    target = app1.raiden.address
    secret = Secret(keccak(target))
    secrethash = sha256_secrethash(secret)
    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    # make an unconfirmed transfer to ensure the nodes have communicated
    amount = PaymentAmount(10)
    payment_identifier = PaymentID(1337)
    app0.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=amount,
        target=TargetAddress(target),
        identifier=payment_identifier,
        secret=secret,
    )

    app1.raiden.transport.stop()
    app1.raiden.transport.greenlet.get()

    # make sure to wait until the queue is created
    def has_initiator_events():
        assert app0.raiden.wal, "raiden server must have been started"
        initiator_events = app0.raiden.wal.storage.get_events()
        return search_for_item(initiator_events, SendLockedTransfer, {})

    assert wait_until(has_initiator_events, network_wait)

    # assert the specific queue is present
    chain_state0 = views.state_from_app(app0)
    queues0 = views.get_all_messagequeues(chain_state=chain_state0)
    assert [
        (queue_id, queue) for queue_id, queue in queues0.items()
        if queue_id.recipient == app1.raiden.address and queue_id.
        canonical_identifier.channel_identifier == channel_identifier and queue
    ]

    # A ChannelClose event will be generated, this will be polled by both apps
    RaidenAPI(app0.raiden).channel_close(registry_address, token_address,
                                         app1.raiden.address)

    with block_offset_timeout(app0.raiden, "Could not get close event"):
        waiting.wait_for_close(
            app0.raiden,
            registry_address,
            token_address,
            [channel_identifier],
            app0.raiden.alarm.sleep_time,
        )

    # assert all queues with this partner are gone or empty
    chain_state0 = views.state_from_app(app0)
    queues0 = views.get_all_messagequeues(chain_state=chain_state0)
    assert not [(queue_id, queue) for queue_id, queue in queues0.items()
                if queue_id.recipient == app1.raiden.address and queue]

    chain_state1 = views.state_from_app(app1)
    queues1 = views.get_all_messagequeues(chain_state=chain_state1)
    assert not [(queue_id, queue) for queue_id, queue in queues1.items()
                if queue_id.recipient == app0.raiden.address and queue]
예제 #7
0
def test_secret_revealed_on_chain(raiden_chain, deposit, settle_timeout,
                                  token_addresses, retry_interval_initial):
    """ A node must reveal the secret on-chain if it's known and the channel is closed. """
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token_address)
    assert token_network_address

    amount = 10
    identifier = 1
    target = app2.raiden.address
    secret, secrethash = factories.make_secret_with_hash()

    # Reveal the secret, but do not unlock it off-chain
    app1_hold_event_handler = app1.raiden.raiden_event_handler
    app1_hold_event_handler.hold_unlock_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=amount,
        target=target,
        identifier=identifier,
        secret=secret,
    )

    with watch_for_unlock_failures(*raiden_chain), block_offset_timeout(
            app0.raiden):
        wait_for_state_change(app2.raiden, ReceiveSecretReveal,
                              {"secrethash": secrethash},
                              retry_interval_initial)

    channel_state2_1 = get_channelstate(app2, app1, token_network_address)
    pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get(
        secrethash)
    msg = "The lock must be registered in unlocked locks since the secret is known"
    assert pending_lock is not None, msg

    # The channels are out-of-sync. app1 has sent the unlock, however we are
    # intercepting it and app2 has not received the updated balance proof

    # Close the channel. This must register the secret on chain
    balance_proof = channel_state2_1.partner_state.balance_proof
    assert isinstance(balance_proof, BalanceProofSignedState)
    channel_close_event = ContractSendChannelClose(
        canonical_identifier=channel_state2_1.canonical_identifier,
        balance_proof=balance_proof,
        triggered_by_block_hash=app0.raiden.rpc_client.
        blockhash_from_blocknumber(BLOCK_ID_LATEST),
    )
    current_state = app2.raiden.wal.state_manager.current_state
    app2.raiden.raiden_event_handler.on_raiden_events(
        raiden=app2.raiden,
        chain_state=current_state,
        events=[channel_close_event])

    settle_expiration = (app0.raiden.rpc_client.block_number() +
                         settle_timeout +
                         DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS)
    app0.raiden.proxy_manager.client.wait_until_block(
        target_block_number=settle_expiration)

    # TODO:
    # - assert on the transferred amounts on-chain (for settle and unlock)

    # The channel app0-app1 should continue with the protocol off-chain, once
    # the secret is released on-chain by app2
    assert_synced_channel_state(token_network_address, app0, deposit - amount,
                                [], app1, deposit + amount, [])

    with watch_for_unlock_failures(*raiden_chain), gevent.Timeout(10):
        wait_for_state_change(
            app2.raiden,
            ContractReceiveSecretReveal,
            {"secrethash": secrethash},
            retry_interval_initial,
        )
예제 #8
0
def test_payment_events_endpoints(api_server_test_instance: APIServer,
                                  raiden_network, token_addresses):
    app0, app1, app2 = raiden_network
    amount1 = PaymentAmount(10)
    identifier1 = PaymentID(42)
    secret1, secrethash1 = factories.make_secret_with_hash()
    token_address = token_addresses[0]

    app0_address = app0.raiden.address
    target1_address = app1.raiden.address
    target2_address = app2.raiden.address

    app1_server = prepare_api_server(app1)
    app2_server = prepare_api_server(app2)

    # app0 is sending tokens to target 1
    request = grequests.post(
        api_url_for(
            api_server_test_instance,
            "token_target_paymentresource",
            token_address=to_checksum_address(token_address),
            target_address=to_checksum_address(target1_address),
        ),
        json={
            "amount": str(amount1),
            "identifier": str(identifier1),
            "secret": to_hex(secret1)
        },
    )
    request.send()
    # app0 is sending some tokens to target 2
    identifier2 = PaymentID(43)
    amount2 = PaymentAmount(10)
    secret2, secrethash2 = factories.make_secret_with_hash()
    request = grequests.post(
        api_url_for(
            api_server_test_instance,
            "token_target_paymentresource",
            token_address=to_checksum_address(token_address),
            target_address=to_checksum_address(target2_address),
        ),
        json={
            "amount": str(amount2),
            "identifier": str(identifier2),
            "secret": to_hex(secret2)
        },
    )
    request.send()

    # target1 also sends some tokens to target 2
    identifier3 = PaymentID(44)
    amount3 = PaymentAmount(5)
    secret3, secrethash3 = factories.make_secret_with_hash()
    request = grequests.post(
        api_url_for(
            app1_server,
            "token_target_paymentresource",
            token_address=to_checksum_address(token_address),
            target_address=to_checksum_address(target2_address),
        ),
        json={
            "amount": str(amount3),
            "identifier": str(identifier3),
            "secret": to_hex(secret3)
        },
    )
    request.send()

    timeout = block_offset_timeout(
        app2.raiden,
        "Waiting for transfer received success in the WAL timed out")
    with watch_for_unlock_failures(*raiden_network), timeout:
        result = wait_for_received_transfer_result(
            app1.raiden, identifier1, amount1, app1.raiden.alarm.sleep_time,
            secrethash1)
        msg = f"Unexpected transfer result: {str(result)}"
        assert result == TransferWaitResult.UNLOCKED, msg
        result = wait_for_received_transfer_result(
            app2.raiden, identifier2, amount2, app2.raiden.alarm.sleep_time,
            secrethash2)
        msg = f"Unexpected transfer result: {str(result)}"
        assert result == TransferWaitResult.UNLOCKED, msg
        result = wait_for_received_transfer_result(
            app2.raiden, identifier3, amount3, app2.raiden.alarm.sleep_time,
            secrethash3)
        msg = f"Unexpected transfer result: {str(result)}"
        assert result == TransferWaitResult.UNLOCKED, msg

    # test endpoint without (partner and token) for sender
    request = grequests.get(
        api_url_for(api_server_test_instance, "paymentresource"))
    with watch_for_unlock_failures(*raiden_network):
        response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier1),
            "target": to_checksum_address(target1_address),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier2),
            "target": to_checksum_address(target2_address),
            "token_address": to_checksum_address(token_address),
        },
    )

    # test endpoint without (partner and token) for target1
    request = grequests.get(api_url_for(app1_server, "paymentresource"))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier1),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier3),
            "token_address": to_checksum_address(token_address),
        },
    )
    # test endpoint without (partner and token) for target2
    request = grequests.get(api_url_for(app2_server, "paymentresource"))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier2),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier3),
            "token_address": to_checksum_address(token_address),
        },
    )

    # test endpoint without partner for app0
    request = grequests.get(
        api_url_for(api_server_test_instance,
                    "token_paymentresource",
                    token_address=token_address))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier1),
            "target": to_checksum_address(target1_address),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier2),
            "target": to_checksum_address(target2_address),
            "token_address": to_checksum_address(token_address),
        },
    )

    # test endpoint without partner for app0 but with limit/offset to get only first
    request = grequests.get(
        api_url_for(
            api_server_test_instance,
            "token_paymentresource",
            token_address=token_address,
            limit=1,
            offset=0,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)

    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier1),
            "target": to_checksum_address(target1_address),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert len(json_response) == 1
    # test endpoint without partner for app0 but with limit/offset to get only second
    request = grequests.get(
        api_url_for(
            api_server_test_instance,
            "token_paymentresource",
            token_address=token_address,
            limit=1,
            offset=1,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier2),
            "target": to_checksum_address(target2_address),
            "token_address": to_checksum_address(token_address),
        },
    )

    # test endpoint without partner for target1
    request = grequests.get(
        api_url_for(app1_server,
                    "token_paymentresource",
                    token_address=token_address))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_events(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier1),
            "token_address": to_checksum_address(token_address),
        },
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier3),
            "target": to_checksum_address(target2_address),
            "token_address": to_checksum_address(token_address),
        },
    )
    # test endpoint without partner for target2
    request = grequests.get(
        api_url_for(app2_server,
                    "token_paymentresource",
                    token_address=token_address))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_events(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier2),
            "token_address": to_checksum_address(token_address),
        },
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier3),
            "token_address": to_checksum_address(token_address),
        },
    )

    # test endpoint for token and partner for app0
    request = grequests.get(
        api_url_for(
            api_server_test_instance,
            "token_target_paymentresource",
            token_address=token_address,
            target_address=target1_address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier1),
            "target": to_checksum_address(target1_address),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert not must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier2),
            "target": to_checksum_address(target2_address),
            "token_address": to_checksum_address(token_address),
        },
    )
    # test endpoint for token and partner for target1. Check both partners
    # to see that filtering works correctly
    request = grequests.get(
        api_url_for(
            app1_server,
            "token_target_paymentresource",
            token_address=token_address,
            target_address=target2_address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_event(
        json_response,
        {
            "event": "EventPaymentSentSuccess",
            "identifier": str(identifier3),
            "target": to_checksum_address(target2_address),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert not must_have_event(
        response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier1),
            "token_address": to_checksum_address(token_address),
        },
    )
    request = grequests.get(
        api_url_for(
            app1_server,
            "token_target_paymentresource",
            token_address=token_address,
            target_address=target1_address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 0
    # test endpoint for token and partner for target2
    request = grequests.get(
        api_url_for(
            app2_server,
            "token_target_paymentresource",
            token_address=token_address,
            target_address=app0_address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_events(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier2),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert not must_have_event(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier1),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert not must_have_event(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier3),
            "token_address": to_checksum_address(token_address),
        },
    )
    request = grequests.get(
        api_url_for(
            app2_server,
            "token_target_paymentresource",
            token_address=token_address,
            target_address=target1_address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert must_have_events(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier3),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert not must_have_event(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier2),
            "token_address": to_checksum_address(token_address),
        },
    )
    assert not must_have_event(
        json_response,
        {
            "event": "EventPaymentReceivedSuccess",
            "identifier": str(identifier1),
            "token_address": to_checksum_address(token_address),
        },
    )

    # also add a test for filtering by wrong token address
    request = grequests.get(
        api_url_for(
            app2_server,
            "token_target_paymentresource",
            token_address=target1_address,
            target_address=target1_address,
        ))
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert len(json_response) == 0

    app1_server.stop()
    app2_server.stop()
예제 #9
0
def test_send_queued_messages_after_restart(  # pylint: disable=unused-argument
    raiden_network: List[App],
    restart_node: RestartNode,
    deposit: TokenAmount,
    token_addresses: List[TokenAddress],
    network_wait: float,
):
    """Test re-sending of undelivered messages on node restart"""
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state, token_network_registry_address, token_address)
    assert token_network_address

    number_of_transfers = 7
    amount_per_transfer = PaymentAmount(1)
    total_transferred_amount = TokenAmount(amount_per_transfer *
                                           number_of_transfers)

    # Make sure none of the transfers will be sent before the restart
    transfers = []
    for secret_seed in range(number_of_transfers):
        secret = make_secret(secret_seed)
        secrethash = sha256_secrethash(secret)
        transfers.append((create_default_identifier(), amount_per_transfer,
                          secret, secrethash))

        assert isinstance(app0.raiden.raiden_event_handler,
                          HoldRaidenEventHandler)  # for mypy
        app0.raiden.raiden_event_handler.hold(
            SendLockedTransfer,
            {"transfer": {
                "lock": {
                    "secrethash": secrethash
                }
            }})

    for identifier, amount, secret, _ in transfers:
        app0.raiden.mediated_transfer_async(
            token_network_address=token_network_address,
            amount=amount,
            target=TargetAddress(app1.raiden.address),
            identifier=identifier,
            secret=secret,
        )

    app0.stop()

    # Restart the app. The pending transfers must be processed.
    new_transport = MatrixTransport(
        config=app0.raiden.config.transport,
        environment=app0.raiden.config.environment_type)
    raiden_event_handler = RaidenEventHandler()
    message_handler = MessageHandler()
    app0_restart = App(
        config=app0.config,
        rpc_client=app0.raiden.rpc_client,
        proxy_manager=app0.raiden.proxy_manager,
        query_start_block=BlockNumber(0),
        default_registry=app0.raiden.default_registry,
        default_secret_registry=app0.raiden.default_secret_registry,
        default_service_registry=app0.raiden.default_service_registry,
        default_user_deposit=app0.raiden.default_user_deposit,
        default_one_to_n_address=app0.raiden.default_one_to_n_address,
        default_msc_address=app0.raiden.default_msc_address,
        transport=new_transport,
        raiden_event_handler=raiden_event_handler,
        message_handler=message_handler,
        routing_mode=RoutingMode.PRIVATE,
    )

    del app0
    restart_node(app0_restart)

    # XXX: There is no synchronization among the app and the test, so it is
    # possible between `start` and the check below that some of the transfers
    # have completed, making it flaky.
    #
    # Make sure the transfers are in the queue and fail otherwise.
    chain_state = views.state_from_raiden(app0_restart.raiden)
    for _, _, _, secrethash in transfers:
        msg = "The secrethashes of the pending transfers must be in the queue after a restart."
        assert secrethash in chain_state.payment_mapping.secrethashes_to_task, msg

    timeout = block_offset_timeout(
        app1.raiden, "Timeout waiting for balance update of app0")
    with watch_for_unlock_failures(*raiden_network), timeout:
        waiting.wait_for_payment_balance(
            raiden=app0_restart.raiden,
            token_network_registry_address=token_network_registry_address,
            token_address=token_address,
            partner_address=app1.raiden.address,
            target_address=app1.raiden.address,
            target_balance=total_transferred_amount,
            retry_timeout=network_wait,
        )
        timeout.exception_to_throw = ValueError(
            "Timeout waiting for balance update of app1")
        waiting.wait_for_payment_balance(
            raiden=app1.raiden,
            token_network_registry_address=token_network_registry_address,
            token_address=token_address,
            partner_address=app0_restart.raiden.address,
            target_address=app1.raiden.address,
            target_balance=total_transferred_amount,
            retry_timeout=network_wait,
        )

    assert_synced_channel_state(
        token_network_address,
        app0_restart,
        Balance(deposit - total_transferred_amount),
        [],
        app1,
        Balance(deposit + total_transferred_amount),
        [],
    )
    new_transport.stop()
예제 #10
0
def test_refund_transfer_after_2nd_hop(raiden_chain, number_of_nodes,
                                       token_addresses, deposit, network_wait):
    """Test the refund transfer sent due to failure after 2nd hop"""
    # Topology:
    #
    #  0 -> 1 -> 2 -> 3
    #
    app0, app1, app2, app3 = 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)

    # make a transfer to test the path app0 -> app1 -> app2 -> app3
    identifier_path = PaymentID(1)
    amount_path = PaymentAmount(1)
    with block_offset_timeout(app0.raiden):
        transfer(
            initiator_app=app0,
            target_app=app3,
            token_address=token_address,
            amount=amount_path,
            identifier=identifier_path,
            timeout=network_wait * number_of_nodes,
        )

    # drain the channel app2 -> app3
    identifier_drain = PaymentID(2)
    amount_drain = PaymentAmount(deposit * 8 // 10)
    with block_offset_timeout(app2.raiden):
        transfer(
            initiator_app=app2,
            target_app=app3,
            token_address=token_address,
            amount=amount_drain,
            identifier=identifier_drain,
            timeout=network_wait,
        )
        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,
            [],
            app2,
            deposit + amount_path,
            [],
        )
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app2,
            deposit - amount_path - amount_drain,
            [],
            app3,
            deposit + amount_path + amount_drain,
            [],
        )

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

    # Lock structures with the correct amount

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

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

    lock1 = send_locked1.transfer.lock
    refund_lock1 = send_refund1.transfer.lock
    assert lock1.amount == refund_lock1.amount
    assert lock1.secrethash == refund_lock1.secrethash

    send_locked2 = raiden_events_search_for_item(
        app1.raiden,
        SendLockedTransfer,
        {"transfer": {
            "lock": {
                "amount": amount_refund_with_fees
            }
        }},
    )
    assert send_locked2

    send_refund2 = raiden_events_search_for_item(app2.raiden,
                                                 SendRefundTransfer, {})
    assert send_refund2

    lock2 = send_locked2.transfer.lock
    refund_lock2 = send_refund2.transfer.lock
    assert lock2.amount == refund_lock2.amount
    assert lock2.secrethash
    assert lock2.expiration

    # channels have the amount locked because of the refund message

    with block_offset_timeout(app0.raiden):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount_path,
            [lock1],
            app1,
            deposit + amount_path,
            [refund_lock1],
        )
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app1,
            deposit - amount_path,
            [lock2],
            app2,
            deposit + amount_path,
            [refund_lock2],
        )
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app2,
            deposit - amount_path - amount_drain,
            [],
            app3,
            deposit + amount_path + amount_drain,
            [],
        )
예제 #11
0
def test_refund_messages(raiden_chain, token_addresses, deposit):
    # The network has the following topology:
    #
    #   App0 <---> App1 <---> App2
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    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)

    # Exhaust the channel App1 <-> App2 (to force the refund transfer)
    # Here we make a single-hop transfer, no fees are charged so we should
    # send the whole deposit amount to drain the channel.
    transfer(
        initiator_app=app1,
        target_app=app2,
        token_address=token_address,
        amount=deposit,
        identifier=PaymentID(1),
    )

    refund_amount = deposit // 2
    refund_fees = calculate_fee_for_amount(refund_amount)
    fee_margin = calculate_fee_margin(refund_amount, refund_fees)
    refund_amount_with_fees = refund_amount + refund_fees + fee_margin
    identifier = 1
    payment_status = app0.raiden.mediated_transfer_async(
        token_network_address, refund_amount, app2.raiden.address, identifier)
    msg = "Must fail, there are no routes available"
    assert isinstance(payment_status.payment_done.wait(),
                      EventPaymentSentFailed), msg

    # The transfer from app0 to app2 failed, so the balances did change.
    # Since the refund is not unlocked both channels have the corresponding
    # amount locked (issue #1091)
    send_lockedtransfer = raiden_events_search_for_item(
        app0.raiden,
        SendLockedTransfer,
        {"transfer": {
            "lock": {
                "amount": refund_amount_with_fees
            }
        }},
    )
    assert send_lockedtransfer

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

    with block_offset_timeout(app1.raiden):
        wait_assert(
            func=assert_synced_channel_state,
            token_network_address=token_network_address,
            app0=app0,
            balance0=deposit,
            pending_locks0=[send_lockedtransfer.transfer.lock],
            app1=app1,
            balance1=deposit,
            pending_locks1=[send_refundtransfer.transfer.lock],
        )
        # This channel was exhausted to force the refund transfer except for the fees
        wait_assert(
            func=assert_succeeding_transfer_invariants,
            token_network_address=token_network_address,
            app0=app1,
            balance0=0,
            pending_locks0=[],
            app1=app2,
            balance1=deposit * 2,
            pending_locks1=[],
        )
예제 #12
0
def test_different_view_of_last_bp_during_unlock(raiden_chain: List[App],
                                                 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.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)
    assert token_network_address
    token_proxy = app0.raiden.proxy_manager.token(token_address,
                                                  BLOCK_ID_LATEST)
    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 = PaymentID(1)
    amount_path = PaymentAmount(1)
    with block_offset_timeout(app0.raiden):
        transfer(
            initiator_app=app0,
            target_app=app2,
            token_address=token_address,
            amount=amount_path,
            identifier=identifier_path,
        )

    # drain the channel app1 -> app2
    identifier_drain = PaymentID(2)
    amount_drain = PaymentAmount(deposit * 8 // 10)
    with block_offset_timeout(app1.raiden):
        transfer(
            initiator_app=app1,
            target_app=app2,
            token_address=token_address,
            amount=amount_drain,
            identifier=identifier_drain,
        )
        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.raiden.mediated_transfer_async(
        token_network_address, amount_refund,
        TargetAddress(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 block_offset_timeout(app0.raiden):
        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.raiden).payment_mapping.secrethashes_to_task

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

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0.raiden,
            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.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_events_original = app1.raiden.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.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.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
    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
    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
예제 #13
0
def test_refund_transfer(raiden_chain, token_addresses, deposit,
                         retry_timeout):
    """A failed transfer must send a refund back.

    TODO:
        - Unlock the token on refund #1091
        - Clear the pending locks and update the locked amount #193
        - Remove the refund message type #490"""
    # 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)

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

    # drain the channel app1 -> app2
    identifier_drain = PaymentID(2)
    amount_drain = PaymentAmount(deposit * 8 // 10)

    transfer_timeout = block_offset_timeout(app1.raiden)
    with transfer_timeout:
        transfer(
            initiator_app=app1,
            target_app=app2,
            token_address=token_address,
            amount=amount_drain,
            identifier=identifier_drain,
        )
        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.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 transfer_timeout:
        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.raiden).payment_mapping.secrethashes_to_task

    # Wait for lock lock expiration but make sure app0 never processes LockExpired
    with dont_handle_lock_expired_mock(app0):
        wait_for_block(
            raiden=app0.raiden,
            block_number=BlockNumber(
                channel.get_sender_expiration_threshold(lock.expiration) + 1),
            retry_timeout=retry_timeout,
        )
        # make sure that app0 still has the payment task for the secrethash
        # https://github.com/raiden-network/raiden/issues/3183
        assert secrethash in state_from_raiden(
            app0.raiden).payment_mapping.secrethashes_to_task

        # make sure that app1 sent a lock expired message for the secrethash
        send_lock_expired = raiden_events_search_for_item(
            app1.raiden, SendLockExpired, {"secrethash": secrethash})
        assert send_lock_expired
        # make sure that app0 never got it
        state_changes = app0.raiden.wal.storage.get_statechanges_by_range(
            RANGE_ALL_STATE_CHANGES)
        assert not search_for_item(state_changes, ReceiveLockExpired,
                                   {"secrethash": secrethash})

    # Out of the handicapped app0 transport.
    # Now wait till app0 receives and processes LockExpired
    receive_lock_expired = wait_for_state_change(app0.raiden,
                                                 ReceiveLockExpired,
                                                 {"secrethash": secrethash},
                                                 retry_timeout)
    # And also till app1 received the processed
    wait_for_state_change(
        app1.raiden,
        ReceiveProcessed,
        {"message_identifier": receive_lock_expired.message_identifier},
        retry_timeout,
    )

    # make sure app1 queue has cleared the SendLockExpired
    chain_state1 = views.state_from_app(app1)
    queues1 = views.get_all_messagequeues(chain_state=chain_state1)
    result = [(queue_id, queue) for queue_id, queue in queues1.items()
              if queue_id.recipient == app0.raiden.address and queue]
    assert not result

    # and now wait for 1 more block so that the payment task can be deleted
    wait_for_block(
        raiden=app0.raiden,
        block_number=app0.raiden.get_block_number() + 1,
        retry_timeout=retry_timeout,
    )

    # and since the lock expired message has been sent and processed then the
    # payment task should have been deleted from both nodes
    # https://github.com/raiden-network/raiden/issues/3183
    assert secrethash not in state_from_raiden(
        app0.raiden).payment_mapping.secrethashes_to_task
    assert secrethash not in state_from_raiden(
        app1.raiden).payment_mapping.secrethashes_to_task
예제 #14
0
def test_participant_selection(raiden_network, token_addresses):
    # pylint: disable=too-many-locals
    registry_address = raiden_network[0].raiden.default_registry.address
    one_to_n_address = raiden_network[0].raiden.default_one_to_n_address
    token_address = token_addresses[0]
    # connect the first node - this will register the token and open the first channel
    # Since there is no other nodes available to connect to this call will do nothing more
    RaidenAPI(raiden_network[0].raiden).token_network_connect(
        registry_address=registry_address,
        token_address=token_address,
        funds=TokenAmount(100))

    # Test invalid argument values
    with pytest.raises(InvalidAmount):
        RaidenAPI(raiden_network[0].raiden).token_network_connect(
            registry_address=registry_address,
            token_address=token_address,
            funds=TokenAmount(-1))
    with pytest.raises(InvalidAmount):
        RaidenAPI(raiden_network[0].raiden).token_network_connect(
            registry_address=registry_address,
            token_address=token_address,
            funds=TokenAmount(100),
            joinable_funds_target=2,
        )
    with pytest.raises(InvalidAmount):
        RaidenAPI(raiden_network[0].raiden).token_network_connect(
            registry_address=registry_address,
            token_address=token_address,
            funds=TokenAmount(100),
            joinable_funds_target=-1,
        )

    # Call the connect endpoint for all but the first node
    connect_greenlets = set(
        gevent.spawn(
            RaidenAPI(app.raiden).token_network_connect, registry_address,
            token_address, 100) for app in raiden_network[1:])
    gevent.joinall(connect_greenlets, raise_error=True)

    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_raiden(raiden_network[0].raiden),
        token_network_registry_address=registry_address,
        token_address=token_address,
    )
    connection_managers = [
        app.raiden.connection_manager_for_token_network(token_network_address)
        for app in raiden_network
    ]

    unsaturated_connection_managers = connection_managers[:]
    exception = AssertionError("Unsaturated connection managers",
                               unsaturated_connection_managers)
    with gevent.Timeout(120, exception):
        while unsaturated_connection_managers:
            for manager in unsaturated_connection_managers:
                if is_manager_saturated(manager, registry_address,
                                        token_address):
                    unsaturated_connection_managers.remove(manager)
            gevent.sleep(1)

    assert saturated_count(connection_managers, registry_address,
                           token_address) == len(connection_managers)

    # ensure unpartitioned network
    for app in raiden_network:
        node_state = views.state_from_raiden(app.raiden)
        network_state = views.get_token_network_by_token_address(
            node_state, registry_address, token_address)
        assert network_state is not None
        for target in raiden_network:
            if target.raiden.address == app.raiden.address:
                continue
            _, routes, _ = routing.get_best_routes(
                chain_state=node_state,
                token_network_address=network_state.address,
                one_to_n_address=one_to_n_address,
                from_address=app.raiden.address,
                to_address=target.raiden.address,
                amount=PaymentAmount(1),
                previous_address=None,
                pfs_config=None,
                privkey=PrivateKey(b""),  # not used if pfs is not configured
            )
            assert routes is not None

    # create a transfer to the leaving node, so we have a channel to settle
    for app in raiden_network:
        sender = app.raiden
        sender_channel = next(
            (channel_state for channel_state in RaidenAPI(
                sender).get_channel_list(registry_address=registry_address,
                                         token_address=token_address)
             if channel_state.our_state.contract_balance > 0
             and channel_state.partner_state.contract_balance > 0),
            None,
        )  # choose a fully funded channel from sender
        if sender_channel:
            break
    assert sender_channel
    registry_address = sender.default_registry.address

    receiver = next(
        app.raiden for app in raiden_network
        if app.raiden.address == sender_channel.partner_state.address)

    # assert there is a direct channel receiver -> sender (vv)
    receiver_channel = RaidenAPI(receiver).get_channel_list(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=sender.address,
    )
    assert len(receiver_channel) == 1

    with gevent.Timeout(30, exception=ValueError("partner not reachable")):
        waiting.wait_for_healthy(sender, receiver.address, PaymentAmount(1))

    with watch_for_unlock_failures(*raiden_network):
        amount = PaymentAmount(1)
        RaidenAPI(sender).transfer_and_wait(registry_address,
                                            token_address,
                                            amount,
                                            receiver.address,
                                            transfer_timeout=10)

        with gevent.Timeout(
                30,
                exception=ValueError(
                    "timeout while waiting for incoming transaction")):
            wait_for_transaction(receiver, registry_address, token_address,
                                 sender.address)

    # test `leave()` method
    connection_manager = connection_managers[0]
    raiden = connection_manager.raiden
    blocks = BlockOffset(sender_channel.settle_timeout * 10)

    channels = views.list_channelstate_for_tokennetwork(
        chain_state=views.state_from_raiden(connection_manager.raiden),
        token_network_registry_address=registry_address,
        token_address=token_address,
    )
    channel_identifiers = [channel.identifier for channel in channels]

    timeout = block_offset_timeout(raiden, "Timeout while waiting for leave",
                                   blocks)
    with timeout:
        RaidenAPI(sender).token_network_leave(registry_address, token_address)

        timeout.exception_to_throw = ValueError("Channels not settled in time")
        waiting.wait_for_settle(
            raiden=connection_manager.raiden,
            token_network_registry_address=registry_address,
            token_address=token_address,
            channel_ids=channel_identifiers,
            retry_timeout=0.1,
        )
예제 #15
0
def test_batch_unlock_after_restart(raiden_network, restart_node, token_addresses, deposit):
    """Simulate the case where:
    - A sends B a transfer
    - B sends A a transfer
    - Secrets were never revealed
    - B closes channel
    - A crashes
    - Wait for settle
    - Wait for unlock from B
    - Restart A
    At this point, the current unlock logic will try to unlock
    iff the node gains from unlocking. Which means that the node will try to unlock
    either side. In the above scenario, each node will unlock its side.
    This test makes sure that we do NOT invalidate A's unlock transaction based
    on the ContractReceiveChannelBatchUnlock caused by B's unlock.
    """
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state=views.state_from_app(alice_app),
        token_network_registry_address=alice_app.raiden.default_registry.address,
        token_address=token_address,
    )
    assert token_network_address
    timeout = 10

    token_network = views.get_token_network_by_address(
        chain_state=views.state_from_app(alice_app), token_network_address=token_network_address
    )
    assert token_network

    channel_identifier = get_channelstate(alice_app, bob_app, token_network_address).identifier

    assert (
        channel_identifier
        in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address]
    )

    alice_to_bob_amount = 10
    identifier = 1

    alice_transfer_secret = Secret(keccak(alice_app.raiden.address))
    alice_transfer_secrethash = sha256_secrethash(alice_transfer_secret)

    bob_transfer_secret = Secret(keccak(bob_app.raiden.address))
    bob_transfer_secrethash = sha256_secrethash(bob_transfer_secret)

    alice_transfer_hold = bob_app.raiden.raiden_event_handler.hold_secretrequest_for(
        secrethash=alice_transfer_secrethash
    )
    bob_transfer_hold = alice_app.raiden.raiden_event_handler.hold_secretrequest_for(
        secrethash=bob_transfer_secrethash
    )

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=alice_to_bob_amount,
        target=bob_app.raiden.address,
        identifier=identifier,
        secret=alice_transfer_secret,
    )

    bob_app.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=alice_to_bob_amount,
        target=alice_app.raiden.address,
        identifier=identifier + 1,
        secret=bob_transfer_secret,
    )

    alice_transfer_hold.wait(timeout=timeout)
    bob_transfer_hold.wait(timeout=timeout)

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_address)
    alice_lock = channel.get_lock(alice_bob_channel_state.our_state, alice_transfer_secrethash)
    bob_lock = channel.get_lock(alice_bob_channel_state.partner_state, bob_transfer_secrethash)
    assert alice_lock
    assert bob_lock

    # This is the current state of protocol:
    #
    #    A -> B LockedTransfer
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_address=token_network_address,
        app0=alice_app,
        balance0=deposit,
        pending_locks0=[alice_lock],
        app1=bob_app,
        balance1=deposit,
        pending_locks1=[bob_lock],
    )

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=alice_app.raiden.address,
    )

    # wait for the close transaction to be mined, this is necessary to compute
    # the timeout for the settle
    with block_offset_timeout(alice_app.raiden):
        waiting.wait_for_close(
            raiden=alice_app.raiden,
            token_network_registry_address=registry_address,
            token_address=token_address,
            channel_ids=[alice_bob_channel_state.identifier],
            retry_timeout=alice_app.raiden.alarm.sleep_time,
        )

    channel_closed = raiden_state_changes_search_for_item(
        bob_app.raiden,
        ContractReceiveChannelClosed,
        {
            "canonical_identifier": {
                "token_network_address": token_network_address,
                "channel_identifier": alice_bob_channel_state.identifier,
            }
        },
    )
    assert isinstance(channel_closed, ContractReceiveChannelClosed)

    offset = BlockOffset(alice_bob_channel_state.settle_timeout * 2)
    with block_offset_timeout(bob_app.raiden, "Settle did not happen", offset):
        waiting.wait_for_settle(
            raiden=alice_app.raiden,
            token_network_registry_address=registry_address,
            token_address=token_address,
            channel_ids=[alice_bob_channel_state.identifier],
            retry_timeout=alice_app.raiden.alarm.sleep_time,
        )

    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            app=bob_app,
            token_network_address=token_network_address,
            receiver=alice_bob_channel_state.partner_state.address,
            sender=alice_bob_channel_state.our_state.address,
        )

    restart_node(alice_app)

    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            app=alice_app,
            token_network_address=token_network_address,
            receiver=alice_bob_channel_state.partner_state.address,
            sender=alice_bob_channel_state.our_state.address,
        )
예제 #16
0
def test_channel_withdraw_expired(
    raiden_network: List[App],
    network_wait: float,
    number_of_nodes: int,
    token_addresses: List[TokenAddress],
    deposit: TokenAmount,
    retry_timeout: float,
) -> None:
    """ Tests withdraw expiration. """
    alice_app, bob_app = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address
    )
    assert token_network_address

    msg = "hold event handler necessary to control messages"
    assert isinstance(alice_app.raiden.raiden_event_handler, HoldRaidenEventHandler), msg
    assert isinstance(alice_app.raiden.message_handler, WaitForMessage), msg

    msg = "hold event handler necessary to control messages"
    assert isinstance(bob_app.raiden.raiden_event_handler, HoldRaidenEventHandler), msg
    assert isinstance(bob_app.raiden.message_handler, WaitForMessage), msg

    # Prevent withdraw confirmation from being sent
    send_withdraw_confirmation_event = alice_app.raiden.raiden_event_handler.hold(
        SendWithdrawConfirmation, {}
    )

    alice_to_bob_amount = PaymentAmount(10)
    total_withdraw = WithdrawAmount(deposit + alice_to_bob_amount)
    wait_for_withdraw_expired_message = alice_app.raiden.message_handler.wait_for_message(
        WithdrawExpired, {"total_withdraw": total_withdraw}
    )

    identifier = PaymentID(1)
    target = TargetAddress(bob_app.raiden.address)
    secret = factories.make_secret()

    payment_status = alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=alice_to_bob_amount,
        target=target,
        identifier=identifier,
        secret=secret,
    )
    wait_for_unlock = bob_app.raiden.message_handler.wait_for_message(
        Unlock, {"payment_identifier": identifier}
    )
    with block_offset_timeout(alice_app.raiden):
        wait_for_unlock.get()
        msg = (
            f"transfer from {to_checksum_address(alice_app.raiden.address)} "
            f"to {to_checksum_address(bob_app.raiden.address)} failed."
        )
        assert payment_status.payment_done.get(), msg

    bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address)

    bob_app.raiden.withdraw(
        canonical_identifier=bob_alice_channel_state.canonical_identifier,
        total_withdraw=total_withdraw,
    )

    with block_offset_timeout(bob_app.raiden):
        send_withdraw_confirmation_event.wait()

    # Make sure proper withdraw state is set in both channel states
    bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address)
    assert bob_alice_channel_state.our_total_withdraw == total_withdraw
    assert bob_alice_channel_state.our_state.withdraws_pending.get(total_withdraw) is not None

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_address)
    assert alice_bob_channel_state.partner_total_withdraw == total_withdraw
    assert alice_bob_channel_state.partner_state.withdraws_pending.get(total_withdraw) is not None

    withdraw_expiration = bob_alice_channel_state.our_state.withdraws_pending[
        total_withdraw
    ].expiration
    expiration_threshold = channel.get_sender_expiration_threshold(withdraw_expiration)

    waiting.wait_for_block(
        raiden=bob_app.raiden,
        block_number=BlockNumber(expiration_threshold + 1),
        retry_timeout=retry_timeout,
    )

    bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address)
    assert bob_alice_channel_state.our_total_withdraw == 0
    assert bob_alice_channel_state.our_state.withdraws_pending.get(total_withdraw) is None

    with gevent.Timeout(network_wait * number_of_nodes):
        wait_for_withdraw_expired_message.wait()

        alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_address)
        assert alice_bob_channel_state.partner_total_withdraw == 0
        assert alice_bob_channel_state.partner_state.withdraws_pending.get(total_withdraw) is None