From 15bc6e243dc76e7979d23582e21e6422c8f747e5 Mon Sep 17 00:00:00 2001 From: Rob Dawson Date: Thu, 11 Jul 2019 15:24:29 +1000 Subject: [PATCH] Ensure multiple privacy marker transactions can appear in the same block. (#1646) Signed-off-by: Adrian Sutton --- .../methods/privacy/EeaSendRawTransaction.java | 9 ++++++++- .../privacy/EeaSendRawTransactionTest.java | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransaction.java b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransaction.java index abcd38f53c..997f05085e 100644 --- a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransaction.java +++ b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransaction.java @@ -17,6 +17,7 @@ import static tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcErrorConverter.conve import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Transaction; +import tech.pegasys.pantheon.ethereum.eth.transactions.PendingTransactions; import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPool; import tech.pegasys.pantheon.ethereum.jsonrpc.RpcMethod; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest; @@ -35,6 +36,8 @@ import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLPException; import tech.pegasys.pantheon.util.bytes.BytesValue; +import java.util.OptionalLong; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -46,6 +49,7 @@ public class EeaSendRawTransaction implements JsonRpcMethod { private final PrivateTransactionHandler privateTransactionHandler; private final TransactionPool transactionPool; private final JsonRpcParameter parameters; + private final PendingTransactions pendingTransactions; public EeaSendRawTransaction( final BlockchainQueries blockchain, @@ -56,6 +60,7 @@ public class EeaSendRawTransaction implements JsonRpcMethod { this.privateTransactionHandler = privateTransactionHandler; this.transactionPool = transactionPool; this.parameters = parameters; + this.pendingTransactions = transactionPool.getPendingTransactions(); } @Override @@ -136,6 +141,8 @@ public class EeaSendRawTransaction implements JsonRpcMethod { } protected long getNonce(final Address address) { - return blockchain.getTransactionCount(address, blockchain.headBlockNumber()); + final OptionalLong pendingNonce = pendingTransactions.getNextNonceForSender(address); + return pendingNonce.orElseGet( + () -> blockchain.getTransactionCount(address, blockchain.headBlockNumber())); } } diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransactionTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransactionTest.java index b91f59d6fe..542f9296ec 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransactionTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransactionTest.java @@ -22,6 +22,7 @@ import tech.pegasys.pantheon.crypto.SECP256K1; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.Wei; +import tech.pegasys.pantheon.ethereum.eth.transactions.PendingTransactions; import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPool; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter; @@ -39,6 +40,7 @@ import tech.pegasys.pantheon.util.bytes.BytesValue; import java.io.IOException; import java.math.BigInteger; import java.util.Optional; +import java.util.OptionalLong; import org.junit.Before; import org.junit.Test; @@ -108,8 +110,12 @@ public class EeaSendRawTransactionTest { @Mock private BlockchainQueries blockchainQueries; + @Mock private PendingTransactions pendingTransactions; + @Before public void before() { + when(transactionPool.getPendingTransactions()).thenReturn(pendingTransactions); + method = new EeaSendRawTransaction(blockchainQueries, privateTxHandler, transactionPool, parameter); } @@ -200,7 +206,6 @@ public class EeaSendRawTransactionTest { .thenReturn(PUBLIC_TRANSACTION); when(transactionPool.addLocalTransaction(any(Transaction.class))) .thenReturn(ValidationResult.valid()); - final JsonRpcRequest request = new JsonRpcRequest( "2.0", "eea_sendRawTransaction", new String[] {VALID_PRIVATE_TRANSACTION_RLP}); @@ -340,7 +345,6 @@ public class EeaSendRawTransactionTest { .thenReturn(PUBLIC_TRANSACTION); when(transactionPool.addLocalTransaction(any(Transaction.class))) .thenReturn(ValidationResult.invalid(transactionInvalidReason)); - final JsonRpcRequest request = new JsonRpcRequest( "2.0", "eea_sendRawTransaction", new String[] {VALID_PRIVATE_TRANSACTION_RLP}); @@ -361,6 +365,13 @@ public class EeaSendRawTransactionTest { verify(transactionPool).addLocalTransaction(any(Transaction.class)); } + @Test + public void nextNonceUsesTxPool() { + Address address = PUBLIC_TRANSACTION.getSender(); + when(pendingTransactions.getNextNonceForSender(address)).thenReturn(OptionalLong.of(123)); + assertThat(method.getNonce(address)).isEqualTo(123); + } + @Test public void getMethodReturnsExpectedName() { assertThat(method.getName()).matches("eea_sendRawTransaction");