Ejemplo n.º 1
0
def test_funds_check_for_openchannel(raiden_network, token_addresses):
    """Reproduces issue 2923 -- two open channel racing through the gas reserve"""
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]

    gas = get_required_gas_estimate(raiden=app0.raiden, channels_to_open=1)
    gas = round(gas * GAS_RESERVE_ESTIMATE_SECURITY_FACTOR)
    api0 = RaidenAPI(app0.raiden)
    burn_eth(
        raiden_service=app0.raiden,
        amount_to_leave=gas,
    )

    partners = [app1.raiden.address, app2.raiden.address]

    greenlets = [
        gevent.spawn(
            api0.channel_open,
            app0.raiden.default_registry.address,
            token_address,
            partner,
        )
        for partner in partners
    ]

    # Opening two channels needs to fail, because the gas reserve is not big enough
    # This didn't fail prior to #2977, which serializes calls to channel open,
    # so that the gas reserve checks cannot pass in parallel
    with pytest.raises(InsufficientGasReserve):
        gevent.joinall(greenlets, raise_error=True)
Ejemplo n.º 2
0
def test_register_token_insufficient_eth(raiden_network, token_amount,
                                         contract_manager):
    app1 = raiden_network[0]

    registry_address = app1.raiden.default_registry.address

    token_address = deploy_contract_web3(
        contract_name=CONTRACT_HUMAN_STANDARD_TOKEN,
        deploy_client=app1.raiden.chain.client,
        contract_manager=contract_manager,
        constructor_arguments=(
            token_amount,
            2,
            'raiden',
            'Rd',
        ),
    )

    api1 = RaidenAPI(app1.raiden)
    assert token_address not in api1.get_tokens_list(registry_address)

    # app1.raiden loses all its ETH because it has been naughty
    burn_eth(app1.raiden)

    # At this point we should get an UnrecoverableError due to InsufficientFunds
    with pytest.raises(InsufficientFunds):
        api1.token_network_register(registry_address, token_address)
Ejemplo n.º 3
0
def test_funds_check_for_openchannel(raiden_network, token_addresses):
    """Reproduces issue 2923 -- two open channel racing through the gas reserve"""
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]

    gas = get_required_gas_estimate(raiden=app0.raiden, channels_to_open=1)
    gas = round(gas * GAS_RESERVE_ESTIMATE_SECURITY_FACTOR)
    api0 = RaidenAPI(app0.raiden)
    burn_eth(
        raiden_service=app0.raiden,
        amount_to_leave=gas,
    )

    partners = [app1.raiden.address, app2.raiden.address]

    greenlets = [
        gevent.spawn(
            api0.channel_open,
            app0.raiden.default_registry.address,
            token_address,
            partner,
        ) for partner in partners
    ]

    # Opening two channels needs to fail, because the gas reserve is not big enough
    # This didn't fail prior to #2977, which serializes calls to channel open,
    # so that the gas reserve checks cannot pass in parallel
    with pytest.raises(InsufficientGasReserve):
        gevent.joinall(greenlets, raise_error=True)
Ejemplo n.º 4
0
def test_api_testnet_token_mint(api_server_test_instance: APIServer,
                                token_addresses):
    user_address = factories.make_checksum_address()
    token_address = token_addresses[0]
    url = api_url_for(api_server_test_instance,
                      "tokensmintresource",
                      token_address=token_address)
    request = grequests.post(url, json=dict(to=user_address, value=1))
    response = request.send().response
    assert_response_with_code(response, HTTPStatus.OK)

    # mint method defaults to mintFor
    request = grequests.post(url, json=dict(to=user_address, value=10))
    response = request.send().response
    assert_response_with_code(response, HTTPStatus.OK)

    # invalid due to negative value
    request = grequests.post(url, json=dict(to=user_address, value=-1))
    response = request.send().response
    assert_response_with_error(response, HTTPStatus.BAD_REQUEST)

    # invalid due to invalid address
    request = grequests.post(url, json=dict(to=user_address[:-2], value=10))
    response = request.send().response
    assert_response_with_error(response, HTTPStatus.BAD_REQUEST)

    # trying to mint with no ETH
    burn_eth(api_server_test_instance.rest_api.raiden_api.raiden.rpc_client)
    request = grequests.post(url, json=dict(to=user_address, value=1))
    response = request.send().response
    assert_response_with_code(response, HTTPStatus.PAYMENT_REQUIRED)
Ejemplo n.º 5
0
def test_register_token_insufficient_eth(raiden_network, retry_timeout,
                                         unregistered_token):
    app1 = raiden_network[0]
    registry_address = app1.raiden.default_registry.address
    token_address = unregistered_token

    # Wait until Raiden can start using the token contract.
    # Here, the block at which the contract was deployed should be confirmed by Raiden.
    # Therefore, until that block is received.
    waiting.wait_for_block(
        raiden=app1.raiden,
        block_number=app1.raiden.get_block_number() +
        DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS + 1,
        retry_timeout=retry_timeout,
    )

    api1 = RaidenAPI(app1.raiden)
    assert token_address not in api1.get_tokens_list(registry_address)

    # app1.raiden loses all its ETH because it has been naughty
    burn_eth(app1.raiden.rpc_client)

    with pytest.raises(InsufficientEth):
        api1.token_network_register(
            registry_address=registry_address,
            token_address=token_address,
            channel_participant_deposit_limit=TokenAmount(UINT256_MAX),
            token_network_deposit_limit=TokenAmount(UINT256_MAX),
        )
def test_matrix_tx_error_handling(  # pylint: disable=unused-argument
    raiden_chain: List[App], token_addresses, request
):
    """Proxies exceptions must be forwarded by the transport."""
    if request.config.option.usepdb:
        pytest.skip("test fails with pdb")
    app0, app1 = raiden_chain
    token_address = token_addresses[0]

    channel_state = views.get_channelstate_for(
        chain_state=views.state_from_app(app0),
        token_network_registry_address=app0.raiden.default_registry.address,
        token_address=token_address,
        partner_address=app1.raiden.address,
    )
    burn_eth(app0.raiden.rpc_client)

    def make_tx(*args, **kwargs):  # pylint: disable=unused-argument
        close_channel = ActionChannelClose(canonical_identifier=channel_state.canonical_identifier)
        app0.raiden.handle_and_track_state_changes([close_channel])

    app0.raiden.transport._client.add_presence_listener(make_tx)

    exception = ValueError("Exception was not raised from the transport")
    with pytest.raises(InsufficientEth), gevent.Timeout(10, exception=exception):
        # Change presence in peer app to trigger callback in app0
        app1.raiden.transport._client.set_presence_state(UserPresence.UNAVAILABLE.value)
        app0.raiden.greenlet.get()
Ejemplo n.º 7
0
def test_register_token_insufficient_eth(raiden_network, token_amount, contract_manager):
    app1 = raiden_network[0]

    registry_address = app1.raiden.default_registry.address

    token_address = deploy_contract_web3(
        contract_name=CONTRACT_HUMAN_STANDARD_TOKEN,
        deploy_client=app1.raiden.chain.client,
        contract_manager=contract_manager,
        constructor_arguments=(
            token_amount,
            2,
            'raiden',
            'Rd',
        ),
    )

    api1 = RaidenAPI(app1.raiden)
    assert token_address not in api1.get_tokens_list(registry_address)

    # app1.raiden loses all its ETH because it has been naughty
    burn_eth(app1.raiden)

    # At this point we should get an UnrecoverableError due to InsufficientFunds
    with pytest.raises(InsufficientFunds):
        api1.token_network_register(registry_address, token_address)
Ejemplo n.º 8
0
def test_matrix_tx_error_handling(  # pylint: disable=unused-argument
        skip_if_not_matrix, raiden_chain, token_addresses):
    """Proxies exceptions must be forwarded by the transport."""
    app0, app1 = raiden_chain
    token_address = token_addresses[0]

    channel_state = views.get_channelstate_for(
        chain_state=views.state_from_app(app0),
        payment_network_id=app0.raiden.default_registry.address,
        token_address=token_address,
        partner_address=app1.raiden.address,
    )
    burn_eth(app0.raiden)

    def make_tx(*args, **kwargs):  # pylint: disable=unused-argument
        close_channel = ActionChannelClose(
            canonical_identifier=channel_state.canonical_identifier)
        app0.raiden.handle_and_track_state_change(close_channel)

    app0.raiden.transport._client.add_presence_listener(make_tx)

    exception = ValueError("exception was not raised from the transport")
    with pytest.raises(InsufficientFunds), gevent.Timeout(200,
                                                          exception=exception):
        app0.raiden.get()
Ejemplo n.º 9
0
def test_register_token_without_balance(
    api_server_test_instance,
    token_amount,
    raiden_network: List[RaidenService],
    contract_manager,
    retry_timeout,
):
    app0 = raiden_network[0]
    contract_proxy, _ = app0.rpc_client.deploy_single_contract(
        contract_name=CONTRACT_HUMAN_STANDARD_TOKEN,
        contract=contract_manager.get_contract(CONTRACT_HUMAN_STANDARD_TOKEN),
        constructor_parameters=(token_amount, 2, "raiden", "Rd2"),
    )
    new_token_address = Address(to_canonical_address(contract_proxy.address))

    # Wait until Raiden can start using the token contract.
    # Here, the block at which the contract was deployed should be confirmed by Raiden.
    # Therefore, until that block is received.
    wait_for_block(
        raiden=app0,
        block_number=BlockNumber(app0.get_block_number() +
                                 DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS + 1),
        retry_timeout=retry_timeout,
    )

    # Burn all the eth and then make sure we get the appropriate API error
    burn_eth(app0.rpc_client)
    poor_request = grequests.put(
        api_url_for(
            api_server_test_instance,
            "registertokenresource",
            token_address=to_checksum_address(new_token_address),
        ))
    poor_response = poor_request.send().response
    assert_response_with_error(poor_response, HTTPStatus.PAYMENT_REQUIRED)
Ejemplo n.º 10
0
def test_handle_insufficient_eth(raiden_network, token_addresses, caplog):
    app0, app1 = raiden_network
    token = token_addresses[0]
    registry_address = app0.raiden.default_registry.address

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

    transfer(
        initiator_app=app0,
        target_app=app1,
        amount=PaymentAmount(1),
        token_address=token,
        identifier=PaymentID(1),
        timeout=60,
    )

    app1.raiden.stop()
    burn_eth(app1.raiden.rpc_client)
    app1.raiden.start()

    settle_block_timeout = BlockTimeout(
        exception_to_throw=RuntimeError("Settle did not happen."),
        raiden=app0.raiden,
        block_number=app0.raiden.get_block_number() + channel_state.settle_timeout * 2,
        retry_timeout=DEFAULT_RETRY_TIMEOUT,
    )

    with settle_block_timeout:
        RaidenAPI(app0.raiden).channel_close(
            registry_address=registry_address,
            token_address=token,
            partner_address=app1.raiden.address,
        )

        waiting.wait_for_settle(
            raiden=app0.raiden,
            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
    )
def test_transact_fails_if_the_account_does_not_have_enough_eth_to_pay_for_the_gas(
    deploy_client: JSONRPCClient, ) -> None:
    """ The gas estimation does not fail if the transaction execution requires
    more gas then the account's eth balance. However sending the transaction
    will.
    """
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    estimated_transaction = deploy_client.estimate_gas(contract_proxy, "loop",
                                                       {}, 1000)
    assert estimated_transaction, "The gas estimation should not have failed."

    burn_eth(deploy_client,
             amount_to_leave=estimated_transaction.estimated_gas // 2)
    with pytest.raises(InsufficientEth):
        deploy_client.transact(estimated_transaction)
def test_transact_fails_if_the_account_does_not_have_enough_eth_to_pay_for_the_gas(
        deploy_client: JSONRPCClient) -> None:
    """ The gas estimation does not fail if the transaction execution requires
    more gas then the account's eth balance. However sending the transaction
    will.
    """
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    check_block = deploy_client.get_checking_block()

    startgas = contract_proxy.estimate_gas(check_block, "loop", 1000)
    assert startgas, "The gas estimation should not have failed."

    burn_eth(deploy_client, amount_to_leave=startgas // 2)
    with pytest.raises(InsufficientEth):
        contract_proxy.transact("loop", startgas, 1000)
Ejemplo n.º 13
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
    )
Ejemplo n.º 14
0
def test_api_channel_close_insufficient_eth(
        api_server_test_instance: APIServer, token_addresses, reveal_timeout):

    # let's create a new channel
    partner_address = "0x61C808D82A3Ac53231750daDc13c777b59310bD9"
    token_address = token_addresses[0]
    settle_timeout = 1650
    channel_data_obj = {
        "partner_address": partner_address,
        "token_address": to_checksum_address(token_address),
        "settle_timeout": str(settle_timeout),
    }
    request = grequests.put(api_url_for(api_server_test_instance,
                                        "channelsresource"),
                            json=channel_data_obj)
    response = request.send().response

    balance = 0
    assert_proper_response(response, status_code=HTTPStatus.CREATED)
    channel_identifier = 1
    json_response = get_json_response(response)
    expected_response = channel_data_obj.copy()
    expected_response.update({
        "balance": str(balance),
        "state": ChannelState.STATE_OPENED.value,
        "reveal_timeout": str(reveal_timeout),
        "channel_identifier": str(channel_identifier),
        "total_deposit": "0",
    })
    assert check_dict_nested_attrs(json_response, expected_response)

    # let's burn all eth and try to close the channel
    burn_eth(api_server_test_instance.rest_api.raiden_api.raiden.rpc_client)
    request = grequests.patch(
        api_url_for(
            api_server_test_instance,
            "channelsresourcebytokenandpartneraddress",
            token_address=token_address,
            partner_address=partner_address,
        ),
        json={"state": ChannelState.STATE_CLOSED.value},
    )
    response = request.send().response
    assert_proper_response(response, HTTPStatus.PAYMENT_REQUIRED)
    json_response = get_json_response(response)
    assert "insufficient ETH" in json_response["errors"]
Ejemplo n.º 15
0
def test_connect_insufficient_reserve(api_server_test_instance: APIServer,
                                      token_addresses):

    # Burn all eth and then try to connect to a token network
    burn_eth(api_server_test_instance.rest_api.raiden_api.raiden.rpc_client)
    funds = 100
    token_address1 = to_checksum_address(token_addresses[0])
    connect_data_obj = {"funds": funds}
    request = grequests.put(
        api_url_for(api_server_test_instance,
                    "connectionsresource",
                    token_address=token_address1),
        json=connect_data_obj,
    )
    response = request.send().response
    assert_proper_response(response, HTTPStatus.PAYMENT_REQUIRED)
    json_response = get_json_response(response)
    assert "The account balance is below the estimated amount" in json_response[
        "errors"]
Ejemplo n.º 16
0
def test_register_token_insufficient_eth(
    raiden_network, token_amount, contract_manager, retry_timeout
):
    app1 = raiden_network[0]

    registry_address = app1.raiden.default_registry.address

    token_address = deploy_contract_web3(
        contract_name=CONTRACT_HUMAN_STANDARD_TOKEN,
        deploy_client=app1.raiden.rpc_client,
        contract_manager=contract_manager,
        constructor_arguments=(token_amount, 2, "raiden", "Rd"),
    )

    # Wait until Raiden can start using the token contract.
    # Here, the block at which the contract was deployed should be confirmed by Raiden.
    # Therefore, until that block is received.
    waiting.wait_for_block(
        raiden=app1.raiden,
        block_number=app1.raiden.get_block_number() + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS + 1,
        retry_timeout=retry_timeout,
    )

    api1 = RaidenAPI(app1.raiden)
    assert token_address not in api1.get_tokens_list(registry_address)

    # app1.raiden loses all its ETH because it has been naughty
    burn_eth(app1.raiden.rpc_client)

    # At this point we should get an UnrecoverableError due to InsufficientFunds
    with pytest.raises(InsufficientFunds):
        api1.token_network_register(
            registry_address=registry_address,
            token_address=token_address,
            channel_participant_deposit_limit=UINT256_MAX,
            token_network_deposit_limit=UINT256_MAX,
        )
Ejemplo n.º 17
0
def test_api_channel_open_and_deposit(api_server_test_instance: APIServer,
                                      token_addresses, reveal_timeout):

    first_partner_address = "0x61C808D82A3Ac53231750daDc13c777b59310bD9"
    token_address = token_addresses[0]
    token_address_hex = to_checksum_address(token_address)
    settle_timeout = 1650
    channel_data_obj = {
        "partner_address": first_partner_address,
        "token_address": token_address_hex,
        "settle_timeout": str(settle_timeout),
        "reveal_timeout": str(reveal_timeout),
    }
    # First let's try to create channel with the null address and see error is handled
    channel_data_obj["partner_address"] = NULL_ADDRESS_HEX
    request = grequests.put(api_url_for(api_server_test_instance,
                                        "channelsresource"),
                            json=channel_data_obj)
    response = request.send().response
    assert_response_with_error(response, status_code=HTTPStatus.BAD_REQUEST)
    # now let's really create a new channel
    channel_data_obj["partner_address"] = first_partner_address
    request = grequests.put(api_url_for(api_server_test_instance,
                                        "channelsresource"),
                            json=channel_data_obj)
    response = request.send().response

    assert_proper_response(response, HTTPStatus.CREATED)
    first_channel_id = 1
    json_response = get_json_response(response)
    expected_response = channel_data_obj.copy()
    expected_response.update({
        "balance": "0",
        "state": ChannelState.STATE_OPENED.value,
        "channel_identifier": "1",
        "total_deposit": "0",
    })
    assert check_dict_nested_attrs(json_response, expected_response)
    token_network_address = json_response["token_network_address"]

    # Now let's try to open the same channel again, because it is possible for
    # the participants to race on the channel creation, this is not considered
    # an error.
    request = grequests.put(api_url_for(api_server_test_instance,
                                        "channelsresource"),
                            json=channel_data_obj)
    response = request.send().response
    assert_proper_response(response, HTTPStatus.OK)
    json_response = get_json_response(response)
    assert check_dict_nested_attrs(json_response, expected_response)

    # now let's open a channel and make a deposit too
    second_partner_address = "0x29FA6cf0Cce24582a9B20DB94Be4B6E017896038"
    total_deposit = 100
    channel_data_obj = {
        "partner_address": second_partner_address,
        "token_address": to_checksum_address(token_address),
        "settle_timeout": str(settle_timeout),
        "reveal_timeout": str(reveal_timeout),
        "total_deposit": str(total_deposit),
    }
    request = grequests.put(api_url_for(api_server_test_instance,
                                        "channelsresource"),
                            json=channel_data_obj)
    response = request.send().response

    assert_proper_response(response, HTTPStatus.CREATED)
    second_channel_id = 2
    json_response = get_json_response(response)
    expected_response = channel_data_obj.copy()
    expected_response.update({
        "balance": str(total_deposit),
        "state": ChannelState.STATE_OPENED.value,
        "channel_identifier": str(second_channel_id),
        "token_network_address": token_network_address,
        "total_deposit": str(total_deposit),
    })
    assert check_dict_nested_attrs(json_response, expected_response)

    # assert depositing again with less than the initial deposit returns 409
    request = grequests.patch(
        api_url_for(
            api_server_test_instance,
            "channelsresourcebytokenandpartneraddress",
            token_address=token_address,
            partner_address=second_partner_address,
        ),
        json={"total_deposit": "99"},
    )
    response = request.send().response
    assert_proper_response(response, HTTPStatus.CONFLICT)

    # assert depositing negative amount fails
    request = grequests.patch(
        api_url_for(
            api_server_test_instance,
            "channelsresourcebytokenandpartneraddress",
            token_address=token_address,
            partner_address=first_partner_address,
        ),
        json={"total_deposit": "-1000"},
    )
    response = request.send().response
    assert_proper_response(response, HTTPStatus.CONFLICT)

    # let's deposit on the first channel
    request = grequests.patch(
        api_url_for(
            api_server_test_instance,
            "channelsresourcebytokenandpartneraddress",
            token_address=token_address,
            partner_address=first_partner_address,
        ),
        json={"total_deposit": str(total_deposit)},
    )
    response = request.send().response
    assert_proper_response(response)
    json_response = get_json_response(response)
    expected_response = {
        "channel_identifier": str(first_channel_id),
        "partner_address": first_partner_address,
        "token_address": to_checksum_address(token_address),
        "settle_timeout": str(settle_timeout),
        "reveal_timeout": str(reveal_timeout),
        "state": ChannelState.STATE_OPENED.value,
        "balance": str(total_deposit),
        "total_deposit": str(total_deposit),
        "token_network_address": token_network_address,
    }
    assert check_dict_nested_attrs(json_response, expected_response)

    # let's try querying for the second channel
    request = grequests.get(
        api_url_for(
            api_server_test_instance,
            "channelsresourcebytokenandpartneraddress",
            token_address=token_address,
            partner_address=second_partner_address,
        ))

    response = request.send().response
    assert_proper_response(response)
    json_response = get_json_response(response)
    expected_response = {
        "channel_identifier": str(second_channel_id),
        "partner_address": second_partner_address,
        "token_address": to_checksum_address(token_address),
        "settle_timeout": str(settle_timeout),
        "reveal_timeout": str(reveal_timeout),
        "state": ChannelState.STATE_OPENED.value,
        "balance": str(total_deposit),
        "total_deposit": str(total_deposit),
        "token_network_address": token_network_address,
    }
    assert check_dict_nested_attrs(json_response, expected_response)

    # finally let's burn all eth and try to open another channel
    burn_eth(api_server_test_instance.rest_api.raiden_api.raiden.rpc_client)
    channel_data_obj = {
        "partner_address": "0xf3AF96F89b3d7CdcBE0C083690A28185Feb0b3CE",
        "token_address": to_checksum_address(token_address),
        "settle_timeout": str(settle_timeout),
        "reveal_timeout": str(reveal_timeout),
    }
    request = grequests.put(api_url_for(api_server_test_instance,
                                        "channelsresource"),
                            json=channel_data_obj)
    response = request.send().response
    assert_proper_response(response, HTTPStatus.PAYMENT_REQUIRED)
    json_response = get_json_response(response)
    assert "The account balance is below the estimated amount" in json_response[
        "errors"]