diff --git a/CHANGELOG.md b/CHANGELOG.md index a526e3316..ff707a791 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline * Bug fix for Int256 decode range [#2070](https://github.com/hyperledger/web3j/pull/2070) * Bug fix for BytesType.bytes32PaddedLength [#2089](https://github.com/hyperledger/web3j/pull/2089) +* Bug fix for FastRawTransactionManager.resetNonce [#2084](https://github.com/hyperledger/web3j/pull/2084) ### Features diff --git a/core/src/main/java/org/web3j/tx/FastRawTransactionManager.java b/core/src/main/java/org/web3j/tx/FastRawTransactionManager.java index 3ccd2b876..0cbf1ea6b 100644 --- a/core/src/main/java/org/web3j/tx/FastRawTransactionManager.java +++ b/core/src/main/java/org/web3j/tx/FastRawTransactionManager.java @@ -73,7 +73,11 @@ public BigInteger getCurrentNonce() { } public synchronized void resetNonce() throws IOException { - nonce = super.getNonce(); + nonce = super.getNonce().subtract(BigInteger.ONE); + } + + public synchronized void clearNonce() { + nonce = BigInteger.valueOf(-1); } public synchronized void setNonce(BigInteger value) { diff --git a/core/src/test/java/org/web3j/tx/FastRawTransactionManagerTest.java b/core/src/test/java/org/web3j/tx/FastRawTransactionManagerTest.java new file mode 100644 index 000000000..37f30a1f3 --- /dev/null +++ b/core/src/test/java/org/web3j/tx/FastRawTransactionManagerTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2024 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.web3j.tx; + +import java.io.IOException; +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.web3j.crypto.SampleKeys; +import org.web3j.protocol.Web3j; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +public class FastRawTransactionManagerTest { + private Web3j web3j; + private FastRawTransactionManager fastRawTransactionManager; + + @BeforeEach + public void setUp() throws Exception { + web3j = mock(Web3j.class); + fastRawTransactionManager = new FastRawTransactionManager(web3j, SampleKeys.CREDENTIALS); + } + + @Test + void clearNonce() throws IOException { + fastRawTransactionManager.setNonce(BigInteger.valueOf(42)); + + fastRawTransactionManager.clearNonce(); + + BigInteger currentNonce = fastRawTransactionManager.getCurrentNonce(); + assertEquals(currentNonce, BigInteger.valueOf(-1)); + } +} diff --git a/integration-tests/src/test/java/org/web3j/protocol/scenarios/FastRawTransactionManagerIT.java b/integration-tests/src/test/java/org/web3j/protocol/scenarios/FastRawTransactionManagerIT.java index c84c6e92e..08b3a4575 100644 --- a/integration-tests/src/test/java/org/web3j/protocol/scenarios/FastRawTransactionManagerIT.java +++ b/integration-tests/src/test/java/org/web3j/protocol/scenarios/FastRawTransactionManagerIT.java @@ -12,20 +12,9 @@ */ package org.web3j.protocol.scenarios; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Future; - import com.carrotsearch.junitbenchmarks.BenchmarkOptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import org.web3j.EVMTest; import org.web3j.NodeType; import org.web3j.protocol.Web3j; @@ -38,8 +27,17 @@ import org.web3j.tx.response.QueuingTransactionReceiptProcessor; import org.web3j.utils.Convert; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Future; + +import static org.junit.jupiter.api.Assertions.*; import static org.web3j.tx.TransactionManager.DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH; @EVMTest(type = NodeType.BESU) @@ -76,11 +74,11 @@ public void testTransactionPolling() throws Exception { } for (int i = 0; - i < DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH && !transactionReceipts.isEmpty(); - i++) { + i < DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH && !transactionReceipts.isEmpty(); + i++) { for (Iterator> iterator = transactionReceipts.iterator(); - iterator.hasNext(); ) { + iterator.hasNext(); ) { Future transactionReceiptFuture = iterator.next(); if (transactionReceiptFuture.isDone()) { @@ -96,6 +94,32 @@ public void testTransactionPolling() throws Exception { assertTrue(transactionReceipts.isEmpty()); } + @Test + public void testTransactionResetNonce() throws Exception { + FastRawTransactionManager transactionManager = + new FastRawTransactionManager( + web3j, + ALICE, + new PollingTransactionReceiptProcessor( + web3j, POLLING_FREQUENCY, DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH)); + + Transfer transfer = new Transfer(web3j, transactionManager); + BigInteger gasPrice = transfer.requestCurrentGasPrice(); + + createTransaction(transfer, gasPrice).send(); + createTransaction(transfer, gasPrice).send(); + + BigInteger expected = transactionManager.getCurrentNonce(); + + transactionManager.resetNonce(); + + BigInteger actual = transactionManager.getCurrentNonce(); + + createTransaction(transfer, gasPrice).send(); + + assertEquals(expected, actual); + } + @Test public void testTransactionQueuing() throws Exception { @@ -116,7 +140,8 @@ public void accept(TransactionReceipt transactionReceipt) { } @Override - public void exception(Exception exception) {} + public void exception(Exception exception) { + } }, DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH, POLLING_FREQUENCY)); @@ -131,8 +156,8 @@ public void exception(Exception exception) {} } for (int i = 0; - i < DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH && !pendingTransactions.isEmpty(); - i++) { + i < DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH && !pendingTransactions.isEmpty(); + i++) { for (TransactionReceipt transactionReceipt : transactionReceipts) { assertFalse(transactionReceipt.getBlockHash().isEmpty()); pendingTransactions.remove(transactionReceipt.getTransactionHash());