hyperledger-web3j/web3j

FastRawTransactionManager's resetNonce() will bring its nonce field out of sync

IvanovVenko opened this issue · 1 comments

FastRawTransactionManager's function resetNonce() will bring its nonce field out of sync

Steps To Reproduce

  1. Using FastRawTransactionManager to instantiate a web3j contract instance.
    MyContract myContractInstance = MyContract.load(myContractAddress, myWeb3jInstance, myFastRawTxManager, myGasProvider);

  2. Call resetNonce on the FastRawTransactionManager instance:
    myFastRawTxManager.resetNonce();

  3. Send a contract transaction:
    RemoteFunctionCall rfc = myContractInstance.myMethod().send();

  4. The result is that the transaction times out:
    "Transaction receipt was not generated after 40 seconds for transaction: 0x21d063bb9057abc172bb7b590a3ea03d3a76eabc5409675fed961269a9d3f1e7"

Expected behavior

The expectation is that the transaction will succeed.

Actual behavior

Originally:

  • the FastRawTransactionManager's nonce is "-1"
  • the network's TransactionCount for the current user is "n".

Calling resetNonce() will result in:

  • the FastRawTransactionManager's nonce is "n"
  • the network's TransactionCount for the current user is "n".

Creating the TX will perform a call to:

    protected synchronized BigInteger getNonce() throws IOException {
        if (nonce.signum() == -1) {
            // obtain lock
            nonce = super.getNonce();
        } else {
            nonce = nonce.add(BigInteger.ONE);
        }
        return nonce;
    }

that will return an incremented nonce (one with value "n+1"), so the transaction will remain in the node's Transaction Pool until another transaction with a nonce with value "n" is sent.
In the most scenario's this will occur only after:

  • restarting the application containing the web3j instance;
    or
  • calling FastRawTransactionManager's setNonce (-1); // of course with casting to BigInteger
    or
  • calling FastRawTransactionManager's setNonce (n-1); // of course with casting to BigInteger

Environment

Describe the environment in which the issue occurs

  • Web3j 4.10.3
  • Java 17
  • ubuntu 22.04

Additional context

Add any other context about the problem here.

  • Logs
  • Sample code and/or code snippets
  • Unit/integration tests to highlight the issue
  • etherscan references

I had the same problem. As a workaround I solved it by using the setNonce(BigInteger.valueOf(-1L)) instead of resetNonce().
This will trigger the super.getNonce() in the next call to getNonce(), which makes the call to the blockchain, when the next transaction is processed.