Modify Gas estimation logic for GoQuorum mode (#2282)

* modify tx simulator for possibly private tx

Signed-off-by: Sally MacFarlane <sally.macfarlane@consensys.net>
pull/2293/head
Sally MacFarlane 4 years ago committed by GitHub
parent fff119b43b
commit 3627662f82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java
  2. 42
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java

@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.transaction;
import static org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStateUtil.getPrivateWorldStateAtBlock;
import org.hyperledger.besu.config.GoQuorumOptions;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
@ -71,6 +72,11 @@ public class TransactionSimulator {
private static final Address DEFAULT_FROM =
Address.fromHexString("0x0000000000000000000000000000000000000000");
// Hex-encoded 64 byte array of "17" values
private static final Bytes MAX_PRIVATE_INTRINSIC_DATA_HEX =
Bytes.fromHexString(
"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
private final Blockchain blockchain;
private final WorldStateArchive worldStateArchive;
private final ProtocolSchedule protocolSchedule;
@ -157,12 +163,25 @@ public class TransactionSimulator {
callParams.getGasLimit() >= 0 ? callParams.getGasLimit() : header.getGasLimit();
final Wei gasPrice = callParams.getGasPrice() != null ? callParams.getGasPrice() : Wei.ZERO;
final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO;
final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY;
// If GoQuorum privacy enabled, and value = zero, do simulation with max non-zero bytes.
// It is possible to have a data field that has a lower intrinsic value than the PTM hash
// so this checks the tx as if we were to place a PTM hash (with all non-zero values).
// This means a potential over-estimate of gas, rather than the exact cost to run right now.
final Bytes payload =
GoQuorumOptions.goQuorumCompatibilityMode && value.isZero()
? MAX_PRIVATE_INTRINSIC_DATA_HEX
: (callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY);
if (transactionValidationParams.isAllowExceedingBalance()) {
updater.getOrCreate(senderAddress).getMutable().setBalance(Wei.of(UInt256.MAX_VALUE));
}
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(header.getNumber());
final MainnetTransactionProcessor transactionProcessor =
protocolSchedule.getByBlockNumber(header.getNumber()).getTransactionProcessor();
final Transaction.Builder transactionBuilder =
Transaction.builder()
.type(TransactionType.FRONTIER)
@ -179,10 +198,6 @@ public class TransactionSimulator {
final Transaction transaction = transactionBuilder.build();
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(header.getNumber());
final MainnetTransactionProcessor transactionProcessor =
protocolSchedule.getByBlockNumber(header.getNumber()).getTransactionProcessor();
final TransactionProcessingResult result =
transactionProcessor.processTransaction(
blockchain,

@ -23,6 +23,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.config.GoQuorumOptions;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
@ -53,6 +54,7 @@ import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -75,6 +77,11 @@ public class TransactionSimulatorTest {
private static final Hash DEFAULT_BLOCK_HEADER_HASH =
Hash.fromHexString("0x0000000000000000000000000000000000000000000000000000000000000001");
// Hex-encoded 64 byte array of "17" values
private static final Bytes MAX_PRIVATE_INTRINSIC_DATA_HEX =
Bytes.fromHexString(
"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
private TransactionSimulator transactionSimulator;
@Mock private Blockchain blockchain;
@ -91,6 +98,12 @@ public class TransactionSimulatorTest {
new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule);
}
@After
public void tearDown() {
GoQuorumOptions.goQuorumCompatibilityMode =
GoQuorumOptions.GOQUORUM_COMPATIBILITY_MODE_DEFAULT_VALUE;
}
@Test
public void shouldReturnEmptyWhenBlockDoesNotExist() {
when(blockchain.getBlockHeader(eq(1L))).thenReturn(Optional.empty());
@ -128,6 +141,35 @@ public class TransactionSimulatorTest {
verifyTransactionWasProcessed(expectedTransaction);
}
@Test
public void shouldReturnSuccessfulResultWhenProcessingPotentiallyPrivateTxIsSuccessful() {
final CallParameter callParameter = legacyTransactionCallParameter();
GoQuorumOptions.goQuorumCompatibilityMode = true;
mockBlockchainForBlockHeader(Hash.ZERO, 1L);
mockWorldStateForAccount(Hash.ZERO, callParameter.getFrom(), 1L);
final Transaction expectedTransaction =
Transaction.builder()
.nonce(1L)
.gasPrice(callParameter.getGasPrice())
.gasLimit(callParameter.getGasLimit())
.to(callParameter.getTo())
.sender(callParameter.getFrom())
.value(callParameter.getValue())
.payload(MAX_PRIVATE_INTRINSIC_DATA_HEX)
.signature(FAKE_SIGNATURE)
.build();
mockProcessorStatusForTransaction(1L, expectedTransaction, Status.SUCCESSFUL);
final Optional<TransactionSimulatorResult> result =
transactionSimulator.process(callParameter, 1L);
assertThat(result.get().isSuccessful()).isTrue();
verifyTransactionWasProcessed(expectedTransaction);
}
@Test
public void shouldIncreaseBalanceAccountWhenExceedingBalanceAllowed() {
final CallParameter callParameter = legacyTransactionCallParameter();

Loading…
Cancel
Save