Ejemplo n.º 1
0
def test_resending_mined_transaction_raises(
        deploy_client: JSONRPCClient) -> None:
    """ If a mined transaction is re-sent the exception `EthereumNonceTooLow` is raised. """
    # Use a _fixed_ gas price strategy so that both transactions are identical.
    deploy_client.web3.eth.setGasPriceStrategy(
        make_fixed_gas_price_strategy(GasPrice(2000000000)))
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    address = contract_proxy.contract_address
    assert len(deploy_client.web3.eth.getCode(
        to_checksum_address(address))) > 0

    # Create a new instance of the JSONRPCClient, this will store the current available nonce
    client_invalid_nonce = JSONRPCClient(deploy_client.web3,
                                         deploy_client.privkey)

    check_block = deploy_client.get_checking_block()
    gas_estimate = contract_proxy.estimate_gas(check_block, "ret")
    assert gas_estimate, "Gas estimation should not fail here"
    startgas = safe_gas_limit(gas_estimate)

    txhash = contract_proxy.transact("ret", startgas)
    deploy_client.poll(txhash)

    # At this point `client_invalid_nonce` has a nonce that is `1` too low,
    # since a transaction was sent using `deploy_client` above and these two
    # instances share the same underlying private key.
    #
    # Note that the same function is called in this test.
    with pytest.raises(EthereumNonceTooLow):
        client_invalid_nonce.new_contract_proxy(
            abi=contract_proxy.contract.abi,
            contract_address=contract_proxy.contract_address).transact(
                "ret", startgas)
def test_resending_pending_transaction_raises(deploy_client: JSONRPCClient) -> None:
    """ If a pending transaction is re-sent the exception `EthereumNonceTooLow` is raised.

    This tests is only sufficient because of the companion test
    `test_resending_mined_transaction_raises` which shows that if the
    transaction has been mined a different exception is raised.
    """
    # Use a _fixed_ gas price strategy so that both transactions are identical.
    deploy_client.web3.eth.setGasPriceStrategy(make_fixed_gas_price_strategy(GasPrice(2000000000)))
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    address = contract_proxy.contract_address
    assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0

    # Create a new instance of the JSONRPCClient, this will store the current available nonce
    client_invalid_nonce = JSONRPCClient(web3=deploy_client.web3, privkey=deploy_client.privkey)

    check_block = deploy_client.get_checking_block()
    gas_estimate = contract_proxy.estimate_gas(check_block, "ret")
    assert gas_estimate, "Gas estimation should not fail here"
    startgas = safe_gas_limit(gas_estimate)

    # At this point `client_invalid_nonce` has a nonce that is `1` too low,
    # since a transaction was sent using `deploy_client` above and these two
    # instances share the same underlying private key.
    #
    # Note that it is assumed this runs fast enough so that the first transaction is not
    # mined before second is sent.
    contract_proxy.transact("ret", startgas)
    with pytest.raises(EthereumNonceTooLow):
        client_invalid_nonce.new_contract_proxy(
            abi=contract_proxy.contract.abi, contract_address=contract_proxy.contract_address
        ).transact("ret", startgas)
Ejemplo n.º 3
0
def test_reusing_nonce_with_lower_gas_raises(
        deploy_client: JSONRPCClient) -> None:
    """ If a _new_ transaction is sent but with a lower gas the exception
    `ReplacementTransactionUnderpriced` is raised.
    """
    # Use a _decreasing_ gas price strategy so that the second transactions is
    # lower than the first.
    deploy_client.web3.eth.setGasPriceStrategy(
        make_decreasing_gas_price_strategy(GasPrice(2000000000)))
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    address = contract_proxy.contract_address
    assert len(deploy_client.web3.eth.getCode(
        to_checksum_address(address))) > 0

    client_invalid_nonce = JSONRPCClient(web3=deploy_client.web3,
                                         privkey=deploy_client.privkey)

    check_block = deploy_client.get_checking_block()
    gas_estimate = contract_proxy.estimate_gas(check_block, "ret")
    assert gas_estimate, "Gas estimation should not fail here"
    startgas = safe_gas_limit(gas_estimate)

    contract_proxy.transact("ret", startgas)

    # At this point `client_invalid_nonce` has a nonce that is `1` too low,
    # since a transaction was sent using `deploy_client` above and these two
    # instances share the same underlying private key.
    #
    # Note that the same function is called in this test but the gas is decreasing.
    with pytest.raises(ReplacementTransactionUnderpriced):
        client_invalid_nonce.new_contract_proxy(
            abi=contract_proxy.contract.abi,
            contract_address=contract_proxy.contract_address).transact(
                "ret_str", contract_proxy.estimate_gas(check_block, "ret_str"))
Ejemplo n.º 4
0
def test_local_transaction_with_zero_gasprice_is_mined(
        deploy_client: JSONRPCClient) -> None:
    """ If a transaction is sent through the eth_sendRawTransaction interface,
    directly to the miner, with a gas price of zero, it is considered local and
    mined anyways.
    """
    normal_gas_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    gas_price = GasPrice(0)
    gas_price_strategy = make_fixed_gas_price_strategy(gas_price)
    deploy_client.web3.eth.setGasPriceStrategy(gas_price_strategy)
    zero_gas_proxy = deploy_client.new_contract_proxy(
        abi=normal_gas_proxy.contract.abi,
        contract_address=normal_gas_proxy.contract_address)

    address = normal_gas_proxy.contract_address
    assert len(deploy_client.web3.eth.getCode(
        to_checksum_address(address))) > 0

    check_block = deploy_client.get_checking_block()
    gas_estimate = zero_gas_proxy.estimate_gas(check_block, "ret")
    assert gas_estimate, "Gas estimation should not fail here"

    zerogas_txhash = zero_gas_proxy.transact("ret", gas_estimate)
    zerogas_receipt = deploy_client.poll(zerogas_txhash)
    zerogas_tx = deploy_client.web3.eth.getTransaction(zerogas_txhash)

    msg = "Even thought the transaction had a zero gas price, it is not removed from the pool"
    assert zerogas_tx is not None, msg

    msg = "Even though the transaction had gas price of zero, it did get mined."
    assert zerogas_receipt["status"] != RECEIPT_FAILURE_CODE, msg
Ejemplo n.º 5
0
def test_resending_mined_transaction_raises(
        deploy_client: JSONRPCClient) -> None:
    """ If a mined transaction is re-sent the exception `EthereumNonceTooLow` is raised. """
    # Use a _fixed_ gas price strategy so that both transactions are identical.
    deploy_client.web3.eth.setGasPriceStrategy(
        make_fixed_gas_price_strategy(GasPrice(2000000000)))
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    address = contract_proxy.address
    assert len(deploy_client.web3.eth.getCode(address)) > 0

    # Create a new instance of the JSONRPCClient, this will store the current available nonce
    client_invalid_nonce = JSONRPCClient(deploy_client.web3,
                                         deploy_client.privkey)

    estimated_transaction = deploy_client.estimate_gas(contract_proxy, "ret",
                                                       {})
    assert estimated_transaction, "Gas estimation should not fail here"

    transaction_hash = deploy_client.transact(estimated_transaction)
    deploy_client.poll_transaction(transaction_hash)

    # At this point `client_invalid_nonce` has a nonce that is `1` too low,
    # since a transaction was sent using `deploy_client` above and these two
    # instances share the same underlying private key.
    #
    # Note that the same function is called in this test.
    with pytest.raises(EthereumNonceTooLow):
        proxy_invalid = client_invalid_nonce.new_contract_proxy(
            abi=contract_proxy.abi, contract_address=contract_proxy.address)
        estimated_transaction_invalid = deploy_client.estimate_gas(
            proxy_invalid, "ret", {})
        msg = "ret always succed, gas estimation should have succeed."
        assert estimated_transaction_invalid, msg
        client_invalid_nonce.transact(estimated_transaction_invalid)
Ejemplo n.º 6
0
def test_reusing_nonce_with_lower_gas_raises(
        deploy_client: JSONRPCClient) -> None:
    """ If a _new_ transaction is sent but with a lower gas the exception
    `ReplacementTransactionUnderpriced` is raised.
    """
    # Use a _decreasing_ gas price strategy so that the second transactions is
    # lower than the first.
    deploy_client.web3.eth.setGasPriceStrategy(
        make_decreasing_gas_price_strategy(GasPrice(2000000000)))
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    address = contract_proxy.address
    assert len(deploy_client.web3.eth.getCode(address)) > 0

    client_invalid_nonce = JSONRPCClient(web3=deploy_client.web3,
                                         privkey=deploy_client.privkey)

    estimated_transaction = deploy_client.estimate_gas(contract_proxy, "ret",
                                                       {})
    assert estimated_transaction, "Gas estimation should not fail here"
    deploy_client.transact(estimated_transaction)

    # At this point `client_invalid_nonce` has a nonce that is `1` too low,
    # since a transaction was sent using `deploy_client` above and these two
    # instances share the same underlying private key.
    #
    # Note that the same function is called in this test but the gas is decreasing.
    with pytest.raises(ReplacementTransactionUnderpriced):
        proxy_invalid = client_invalid_nonce.new_contract_proxy(
            abi=contract_proxy.abi, contract_address=contract_proxy.address)
        estimated_transaction = client_invalid_nonce.estimate_gas(
            proxy_invalid, "ret_str", {})
        assert estimated_transaction, "ret_str never fails, gas estimation must succeed."
        client_invalid_nonce.transact(estimated_transaction)
Ejemplo n.º 7
0
def test_duplicated_transaction_different_gas_price_raises(deploy_client: JSONRPCClient) -> None:
    """ If the same transaction is sent twice a JSON RPC error is raised. """
    gas_price = GasPrice(2000000000)
    deploy_client.web3.eth.setGasPriceStrategy(make_decreasing_gas_price_strategy(gas_price))
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    address = contract_proxy.contract_address
    assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0

    second_client = JSONRPCClient(web3=deploy_client.web3, privkey=deploy_client.privkey)

    second_proxy = second_client.new_contract_proxy(
        abi=contract_proxy.contract.abi, contract_address=contract_proxy.contract_address
    )

    check_block = deploy_client.get_checking_block()
    startgas = safe_gas_limit(contract_proxy.estimate_gas(check_block, "ret"))

    with pytest.raises(ReplacementTransactionUnderpriced):
        second_proxy.transact("ret", startgas)
        contract_proxy.transact("ret", startgas)
Ejemplo n.º 8
0
def test_duplicated_transaction_same_gas_price_raises(deploy_client: JSONRPCClient) -> None:
    """ If the same transaction is sent twice a JSON RPC error is raised. """
    gas_price = GasPrice(2000000000)
    gas_price_strategy = make_fixed_gas_price_strategy(gas_price)
    deploy_client.web3.eth.setGasPriceStrategy(gas_price_strategy)
    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest")

    address = contract_proxy.contract_address
    assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0

    second_client = JSONRPCClient(web3=deploy_client.web3, privkey=deploy_client.privkey)

    second_proxy = second_client.new_contract_proxy(
        abi=contract_proxy.contract.abi, contract_address=contract_proxy.contract_address
    )

    check_block = deploy_client.get_checking_block()
    gas_estimate = contract_proxy.estimate_gas(check_block, "ret")
    assert gas_estimate, "Gas estimation should not fail here"
    startgas = safe_gas_limit(gas_estimate)

    contract_proxy.transact("ret", startgas)
    with pytest.raises(TransactionAlreadyPending):
        second_proxy.transact("ret", startgas)
Ejemplo n.º 9
0
def test_remote_transaction_with_zero_gasprice_is_not_mined(
        web3: Web3, deploy_key: PrivateKey, blockchain_rpc_ports: List[Port],
        blockchain_type: str) -> None:
    """ If the non-local transaction is sent with a gas price set to zero it is
    not mined.
    """
    host = "127.0.0.1"
    miner_rpc_port, rpc_port = blockchain_rpc_ports

    miner_web3 = Web3(HTTPProvider(f"http://{host}:{miner_rpc_port}"))
    miner_client = JSONRPCClient(miner_web3, deploy_key)

    web3 = Web3(HTTPProvider(f"http://{host}:{rpc_port}"))
    client = JSONRPCClient(web3, deploy_key)

    before_deploy_block = client.block_number()
    normal_gas_proxy, _ = deploy_rpc_test_contract(client, "RpcTest")
    num_blocks_to_wait = client.block_number() - before_deploy_block

    gas_price = GasPrice(0)
    gas_price_strategy = make_fixed_gas_price_strategy(gas_price)
    client.web3.eth.setGasPriceStrategy(gas_price_strategy)
    zero_gas_proxy = client.new_contract_proxy(
        abi=normal_gas_proxy.contract.abi,
        contract_address=normal_gas_proxy.contract_address)

    address = normal_gas_proxy.contract_address
    assert len(client.web3.eth.getCode(to_checksum_address(address))) > 0

    check_block = client.get_checking_block()
    gas_estimate = zero_gas_proxy.estimate_gas(check_block, "ret")
    assert gas_estimate, "Gas estimation should not fail here"

    zerogas_txhash = zero_gas_proxy.transact("ret", gas_estimate)

    # wait for how many blocks it took to mine the deployment, since this is a
    # private chain, if the new transaction will be mined it should be roughly
    # in the same time frame (adding two blocks to cover race conditions)
    target_block_number = client.block_number() + num_blocks_to_wait + 2
    while client.block_number() < target_block_number:
        gevent.sleep(0.5)

    miner_zerogas_tx = miner_client.web3.eth.getTransaction(zerogas_txhash)
    miner_zerogas_receipt = miner_client.web3.eth.getTransactionReceipt(
        zerogas_txhash)

    msg = "The transaction was discarded by the miner, there is no transaction and no receipt"
    assert miner_zerogas_tx is None, msg
    assert miner_zerogas_receipt is None, msg

    zerogas_tx = client.web3.eth.getTransaction(zerogas_txhash)
    zerogas_receipt = client.web3.eth.getTransactionReceipt(zerogas_txhash)

    msg = (
        "The transaction was NOT discarded by the original node, because it is a local transaction"
    )
    assert zerogas_tx is not None, msg

    zerogas_receipt = client.web3.eth.getTransactionReceipt(zerogas_txhash)
    msg = "The transaction does NOT have a receipt because the miner rejected it"

    if blockchain_type == "geth":
        assert zerogas_receipt is None, msg
    elif blockchain_type == "parity":
        assert zerogas_receipt["blockNumber"] is None, msg
    else:
        raise RuntimeError(f"Unknown blockchain_type {blockchain_type}")
Ejemplo n.º 10
0
def test_remote_transaction_with_zero_gasprice_is_not_mined(
        web3: Web3, deploy_key: PrivateKey,
        eth_nodes_configuration: List[EthNodeDescription]) -> None:
    """ If the non-local transaction is sent with a gas price set to zero it is
    not mined.
    """
    host = "127.0.0.1"

    assert eth_nodes_configuration[0].miner
    miner_rpc_port = eth_nodes_configuration[0].rpc_port

    assert not eth_nodes_configuration[1].miner
    rpc_port = eth_nodes_configuration[1].rpc_port

    miner_web3 = Web3(HTTPProvider(f"http://{host}:{miner_rpc_port}"))
    miner_client = JSONRPCClient(miner_web3, deploy_key)

    web3 = Web3(HTTPProvider(f"http://{host}:{rpc_port}"))
    client = JSONRPCClient(web3, deploy_key)

    before_deploy_block = client.block_number()
    normal_gas_proxy, _ = deploy_rpc_test_contract(client, "RpcTest")
    num_blocks_to_wait = client.block_number() - before_deploy_block

    gas_price = GasPrice(0)
    gas_price_strategy = make_fixed_gas_price_strategy(gas_price)
    client.web3.eth.setGasPriceStrategy(gas_price_strategy)
    zero_gas_proxy = client.new_contract_proxy(
        abi=normal_gas_proxy.abi, contract_address=normal_gas_proxy.address)

    address = normal_gas_proxy.address
    assert len(client.web3.eth.getCode(address)) > 0

    estimated_transaction = client.estimate_gas(zero_gas_proxy, "ret", {})
    assert estimated_transaction, "Gas estimation should not fail here"

    zerogas_transaction_sent = client.transact(estimated_transaction)

    # wait for how many blocks it took to mine the deployment, since this is a
    # private chain, if the new transaction will be mined it should be roughly
    # in the same time frame (adding two blocks to cover race conditions)
    target_block_number = client.block_number() + num_blocks_to_wait + 2
    while client.block_number() < target_block_number:
        gevent.sleep(0.5)

    try:
        miner_zerogas_tx = miner_client.web3.eth.getTransaction(
            zerogas_transaction_sent.transaction_hash)
        miner_zerogas_receipt = miner_client.web3.eth.getTransactionReceipt(
            zerogas_transaction_sent.transaction_hash)
    except TransactionNotFound:
        miner_zerogas_tx = None
        miner_zerogas_receipt = None

    msg = "The transaction was discarded by the miner, there is no transaction and no receipt"
    assert miner_zerogas_tx is None, msg
    assert miner_zerogas_receipt is None, msg

    zerogas_tx = client.web3.eth.getTransaction(
        zerogas_transaction_sent.transaction_hash)
    msg = (
        "The transaction was NOT discarded by the original node, because it is a local transaction"
    )
    assert zerogas_tx is not None, msg

    try:
        zerogas_receipt = client.web3.eth.getTransactionReceipt(
            zerogas_transaction_sent.transaction_hash)
    except TransactionNotFound:
        zerogas_receipt = None

    msg = "The transaction does NOT have a receipt because the miner rejected it"
    assert zerogas_receipt is None, msg