GoQuorum private tx when mining (#1938)

* hand craft receipt for goquorum private tx when creating a block
* validate goquorum private transaction and handle nonce issues

Signed-off-by: Sally MacFarlane <sally.macfarlane@consensys.net>
pull/1940/head
Sally MacFarlane 4 years ago committed by GitHub
parent 1c86ecbc97
commit ef997825ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 107
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.blockcreation;
import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.EvmAccount;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
@ -30,18 +31,24 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult;
import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.plugin.data.TransactionType;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.function.Supplier;
import com.google.common.collect.Lists;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
/**
* Responsible for extracting transactions from PendingTransactions and determining if the
@ -64,6 +71,7 @@ import com.google.common.collect.Lists;
* not cleared between executions of buildTransactionListForBlock().
*/
public class BlockTransactionSelector {
private static final Logger LOG = LogManager.getLogger();
private final Wei minTransactionGasPrice;
private final Double minBlockOccupancyRatio;
@ -213,34 +221,79 @@ public class BlockTransactionSelector {
final WorldUpdater worldStateUpdater = worldState.updater();
final BlockHashLookup blockHashLookup = new BlockHashLookup(processableBlockHeader, blockchain);
final TransactionProcessingResult result =
transactionProcessor.processTransaction(
blockchain,
worldStateUpdater,
processableBlockHeader,
transaction,
miningBeneficiary,
blockHashLookup,
false,
TransactionValidationParams.mining());
if (!result.isInvalid()) {
TransactionProcessingResult effectiveResult;
if (transaction.isGoQuorumPrivateTransaction()) {
final ValidationResult<TransactionInvalidReason> validationResult =
validateTransaction(processableBlockHeader, transaction, worldStateUpdater);
if (!validationResult.isValid()) {
LOG.warn(
"Invalid transaction: {}. Block {} Transaction {}",
validationResult.getErrorMessage(),
processableBlockHeader.getParentHash().toHexString(),
transaction.getHash().toHexString());
return transactionSelectionResultForInvalidResult(validationResult);
} else {
// valid GoQuorum private tx, we need to hand craft the receipt and increment the nonce
effectiveResult = publicResultForWhenWeHaveAPrivateTransaction(transaction);
worldStateUpdater.getOrCreate(transaction.getSender()).getMutable().incrementNonce();
}
} else {
effectiveResult =
transactionProcessor.processTransaction(
blockchain,
worldStateUpdater,
processableBlockHeader,
transaction,
miningBeneficiary,
blockHashLookup,
false,
TransactionValidationParams.mining());
}
if (!effectiveResult.isInvalid()) {
worldStateUpdater.commit();
updateTransactionResultTracking(transaction, result);
updateTransactionResultTracking(transaction, effectiveResult);
} else {
// If the transaction has an incorrect nonce, leave it in the pool and continue
if (result
.getValidationResult()
.getInvalidReason()
.equals(TransactionInvalidReason.INCORRECT_NONCE)) {
return TransactionSelectionResult.CONTINUE;
}
// If the transaction was invalid for any other reason, delete it, and continue.
return TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE;
return transactionSelectionResultForInvalidResult(effectiveResult.getValidationResult());
}
return TransactionSelectionResult.CONTINUE;
}
private TransactionSelectionResult transactionSelectionResultForInvalidResult(
final ValidationResult<TransactionInvalidReason> invalidReasonValidationResult) {
// If the transaction has an incorrect nonce, leave it in the pool and continue
if (invalidReasonValidationResult
.getInvalidReason()
.equals(TransactionInvalidReason.INCORRECT_NONCE)) {
return TransactionSelectionResult.CONTINUE;
}
// If the transaction was invalid for any other reason, delete it, and continue.
return TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE;
}
private ValidationResult<TransactionInvalidReason> validateTransaction(
final ProcessableBlockHeader blockHeader,
final Transaction transaction,
final WorldUpdater publicWorldStateUpdater) {
final MainnetTransactionValidator transactionValidator =
transactionProcessor.getTransactionValidator();
ValidationResult<TransactionInvalidReason> validationResult =
transactionValidator.validate(transaction, blockHeader.getBaseFee());
if (!validationResult.isValid()) {
return validationResult;
}
final Address senderAddress = transaction.getSender();
final EvmAccount sender = publicWorldStateUpdater.getOrCreate(senderAddress);
validationResult =
transactionValidator.validateForSender(
transaction, sender, TransactionValidationParams.processingBlock());
return validationResult;
}
/*
Responsible for updating the state maintained between transaction validation (i.e. receipts,
cumulative gas, world state root hash.).
@ -268,6 +321,16 @@ public class BlockTransactionSelector {
gasUsedByTransaction);
}
private TransactionProcessingResult publicResultForWhenWeHaveAPrivateTransaction(
final Transaction transaction) {
return TransactionProcessingResult.successful(
Collections.emptyList(),
0,
transaction.getGasLimit(),
Bytes.EMPTY,
ValidationResult.valid());
}
private boolean transactionTooLargeForBlock(
final long blockNumber, final long gasLimit, final Transaction transaction) {

Loading…
Cancel
Save