Added validation for GoQuorum transactions with value. (#2400)

* Added validation for GoQuorum transactions with value.

Signed-off-by: Mark Terry <mark.terry@consensys.net>
pull/2405/head
mark-terry 3 years ago committed by GitHub
parent 7a125b3db9
commit 974f58848d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverter.java
  2. 1
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java
  3. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java
  4. 18
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java
  5. 40
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolTest.java

@ -57,6 +57,8 @@ public class JsonRpcErrorConverter {
return JsonRpcError.ETH_SEND_TX_REPLACEMENT_UNDERPRICED; return JsonRpcError.ETH_SEND_TX_REPLACEMENT_UNDERPRICED;
case GAS_PRICE_MUST_BE_ZERO: case GAS_PRICE_MUST_BE_ZERO:
return JsonRpcError.GAS_PRICE_MUST_BE_ZERO; return JsonRpcError.GAS_PRICE_MUST_BE_ZERO;
case ETHER_VALUE_NOT_SUPPORTED:
return JsonRpcError.ETHER_VALUE_NOT_SUPPORTED;
default: default:
return JsonRpcError.INVALID_PARAMS; return JsonRpcError.INVALID_PARAMS;
} }

@ -125,6 +125,7 @@ public enum JsonRpcError {
CREATE_PRIVACY_GROUP_ERROR(-50100, "Error creating privacy group"), CREATE_PRIVACY_GROUP_ERROR(-50100, "Error creating privacy group"),
DECODE_ERROR(-50100, "Unable to decode the private signed raw transaction"), DECODE_ERROR(-50100, "Unable to decode the private signed raw transaction"),
DELETE_PRIVACY_GROUP_ERROR(-50100, "Error deleting privacy group"), DELETE_PRIVACY_GROUP_ERROR(-50100, "Error deleting privacy group"),
ETHER_VALUE_NOT_SUPPORTED(-50100, "ether value is not supported for private transactions"),
FIND_PRIVACY_GROUP_ERROR(-50100, "Error finding privacy group"), FIND_PRIVACY_GROUP_ERROR(-50100, "Error finding privacy group"),
FIND_ONCHAIN_PRIVACY_GROUP_ERROR(-50100, "Error finding onchain privacy group"), FIND_ONCHAIN_PRIVACY_GROUP_ERROR(-50100, "Error finding onchain privacy group"),
GOQUORUM_NO_PRIVATE_FOR( GOQUORUM_NO_PRIVATE_FOR(

@ -44,5 +44,6 @@ public enum TransactionInvalidReason {
PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE, PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE,
INTERNAL_ERROR, INTERNAL_ERROR,
// Quroum Compatibility Invalid Reasons // Quroum Compatibility Invalid Reasons
GAS_PRICE_MUST_BE_ZERO GAS_PRICE_MUST_BE_ZERO,
ETHER_VALUE_NOT_SUPPORTED
} }

@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.eth.transactions; package org.hyperledger.besu.ethereum.eth.transactions;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.Optional.ofNullable;
import static org.apache.logging.log4j.LogManager.getLogger; import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE;
@ -46,6 +47,7 @@ import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter; import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric; import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
import java.math.BigInteger;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional; import java.util.Optional;
@ -232,6 +234,15 @@ public class TransactionPool implements BlockAddedObserver {
private ValidationResult<TransactionInvalidReason> validateTransaction( private ValidationResult<TransactionInvalidReason> validateTransaction(
final Transaction transaction) { final Transaction transaction) {
final BlockHeader chainHeadBlockHeader = getChainHeadBlockHeader(); final BlockHeader chainHeadBlockHeader = getChainHeadBlockHeader();
// Check whether it's a GoQuorum transaction
if (isGoQuorumPrivateTransaction(transaction)) {
final Optional<Wei> weiValue = ofNullable(transaction.getValue());
if (weiValue.isPresent() && !weiValue.get().isZero()) {
return ValidationResult.invalid(TransactionInvalidReason.ETHER_VALUE_NOT_SUPPORTED);
}
}
final ValidationResult<TransactionInvalidReason> basicValidationResult = final ValidationResult<TransactionInvalidReason> basicValidationResult =
getTransactionValidator().validate(transaction, Optional.empty()); getTransactionValidator().validate(transaction, Optional.empty());
if (!basicValidationResult.isValid()) { if (!basicValidationResult.isValid()) {
@ -251,7 +262,7 @@ public class TransactionPool implements BlockAddedObserver {
.orElse(false)) { .orElse(false)) {
return ValidationResult.invalid( return ValidationResult.invalid(
TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, TransactionInvalidReason.INVALID_TRANSACTION_FORMAT,
String.format("EIP-1559 transaction are not allowed yet")); "EIP-1559 transaction are not allowed yet");
} }
return protocolContext return protocolContext
@ -276,6 +287,11 @@ public class TransactionPool implements BlockAddedObserver {
return blockchain.getBlockHeader(blockchain.getChainHeadHash()).get(); return blockchain.getBlockHeader(blockchain.getChainHeadHash()).get();
} }
private boolean isGoQuorumPrivateTransaction(final Transaction transaction) {
return (transaction.getV().equals(BigInteger.valueOf(37))
|| (transaction.getV().equals(BigInteger.valueOf(38))));
}
public interface TransactionBatchAddedListener { public interface TransactionBatchAddedListener {
void onTransactionsAdded(Iterable<Transaction> transactions); void onTransactionsAdded(Iterable<Transaction> transactions);

@ -71,6 +71,7 @@ import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.testutil.TestClock; import org.hyperledger.besu.testutil.TestClock;
import java.math.BigInteger;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -831,6 +832,45 @@ public class TransactionPoolTest {
assertThat(result.getInvalidReason()).isEqualTo(TransactionInvalidReason.TX_FEECAP_EXCEEDED); assertThat(result.getInvalidReason()).isEqualTo(TransactionInvalidReason.TX_FEECAP_EXCEEDED);
} }
@Test
public void shouldRejectGoQuorumTransactionWithNonZeroValue() {
final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create();
final EthContext ethContext = ethProtocolManager.ethContext();
final PeerTransactionTracker peerTransactionTracker = new PeerTransactionTracker();
final Wei twoEthers = Wei.fromEth(2);
final TransactionPool transactionPool =
new TransactionPool(
transactions,
protocolSchedule,
protocolContext,
batchAddedListener,
pendingBatchAddedListener,
syncState,
ethContext,
peerTransactionTracker,
peerPendingTransactionTracker,
Wei.ZERO,
metricsSystem,
Optional.empty(),
ImmutableTransactionPoolConfiguration.builder().txFeeCap(twoEthers).build());
final Transaction transaction37 =
Transaction.builder().v(BigInteger.valueOf(37)).value(Wei.ONE).build();
final Transaction transaction38 =
Transaction.builder().v(BigInteger.valueOf(38)).value(Wei.ONE).build();
final ValidationResult<TransactionInvalidReason> result37 =
transactionPool.addLocalTransaction(transaction37);
final ValidationResult<TransactionInvalidReason> result38 =
transactionPool.addLocalTransaction(transaction38);
assertThat(result37.getInvalidReason())
.isEqualTo(TransactionInvalidReason.ETHER_VALUE_NOT_SUPPORTED);
assertThat(result38.getInvalidReason())
.isEqualTo(TransactionInvalidReason.ETHER_VALUE_NOT_SUPPORTED);
}
private void assertTransactionPending(final Transaction t) { private void assertTransactionPending(final Transaction t) {
assertThat(transactions.getTransactionByHash(t.getHash())).contains(t); assertThat(transactions.getTransactionByHash(t.getHash())).contains(t);
} }

Loading…
Cancel
Save