Split Transaction Gas Calculation from EVM Calculation (#2659)

In preparation for the EVM library pull out the transaction related gas
calculations and move them into their own `TransactionGasCalculator.`

This has 4 calls right now, none of which occur inside the EVM:
* Intrinsic gas cost
* Code Deposit gas cost
* Max refund quotient
* Max Privacy Marker Transaction intrinsic gas cost.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
pull/2661/head
Danno Ferrin 3 years ago committed by GitHub
parent 650b5a01b1
commit f9b17cf92b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java
  2. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java
  3. 7
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethods.java
  4. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java
  5. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/BaseEeaSendRawTransaction.java
  6. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransactionTest.java
  7. 40
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BerlinGasCalculator.java
  8. 67
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BerlinTransactionGasCalculator.java
  9. 18
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java
  10. 57
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/FrontierGasCalculator.java
  11. 79
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/FrontierTransactionGasCalculator.java
  12. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/HomesteadTransactionGasCalculator.java
  13. 37
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/IstanbulGasCalculator.java
  14. 58
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/IstanbulTransactionGasCalculator.java
  15. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/LondonGasCalculator.java
  16. 26
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/LondonTransactionGasCalculator.java
  17. 13
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetContractCreationProcessor.java
  18. 60
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java
  19. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
  20. 17
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java
  21. 14
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpec.java
  22. 35
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java
  23. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TangerineWhistleGasCalculator.java
  24. 67
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionGasCalculator.java
  25. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java
  26. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java
  27. 44
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/GasCalculator.java
  28. 16
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/IntrinsicGasTest.java
  29. 20
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetContractCreationProcessorTest.java
  30. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java
  31. 75
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java
  32. 2
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java
  33. 1
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java

@ -18,12 +18,12 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.Privac
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.TransactionGasCalculator;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.util.NonceProvider;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Optional;
@ -34,7 +34,7 @@ import org.apache.tuweni.bytes.Bytes;
public class PluginEeaSendRawTransaction extends AbstractEeaSendRawTransaction {
private final PrivacyController privacyController;
private final PrivacyIdProvider privacyIdProvider;
private final GasCalculator gasCalculator;
private final TransactionGasCalculator transactionGasCalculator;
public PluginEeaSendRawTransaction(
final TransactionPool transactionPool,
@ -42,11 +42,11 @@ public class PluginEeaSendRawTransaction extends AbstractEeaSendRawTransaction {
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final NonceProvider publicNonceProvider,
final PrivacyController privacyController,
final GasCalculator gasCalculator) {
final TransactionGasCalculator transactionGasCalculator) {
super(transactionPool, privacyIdProvider, privateMarkerTransactionFactory, publicNonceProvider);
this.privacyController = privacyController;
this.privacyIdProvider = privacyIdProvider;
this.gasCalculator = gasCalculator;
this.transactionGasCalculator = transactionGasCalculator;
}
@Override
@ -81,7 +81,7 @@ public class PluginEeaSendRawTransaction extends AbstractEeaSendRawTransaction {
// choose the highest of the two options
return Math.max(
privateTransaction.getGasLimit(),
gasCalculator
transactionGasCalculator
.transactionIntrinsicGasCostAndAccessedState(
new Transaction.Builder()
.to(Address.PLUGIN_PRIVACY)

@ -65,7 +65,7 @@ public class EeaJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
privateMarkerTransactionFactory,
nonceProvider,
privacyController,
getGasCalculator()),
getTransactionGasCalculator()),
new PrivGetEeaTransactionCount(privacyController, privacyIdProvider));
} else if (getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) {
return mapOf(

@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.api.query.PrivacyQueries;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.TransactionGasCalculator;
import org.hyperledger.besu.ethereum.privacy.ChainHeadPrivateNonceProvider;
import org.hyperledger.besu.ethereum.privacy.PluginPrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
@ -92,6 +93,12 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
.getGasCalculator();
}
public TransactionGasCalculator getTransactionGasCalculator() {
return protocolSchedule
.getByBlockNumber(blockchainQueries.headBlockNumber())
.getTransactionGasCalculator();
}
@Override
protected Map<String, JsonRpcMethod> create() {
final PrivateMarkerTransactionFactory markerTransactionFactory =

@ -107,6 +107,7 @@ public class EthGetTransactionReceiptTest {
null,
false,
null,
null,
GasLimitCalculator.constant(),
FeeMarket.legacy(),
null,
@ -132,6 +133,7 @@ public class EthGetTransactionReceiptTest {
null,
false,
null,
null,
GasLimitCalculator.constant(),
FeeMarket.legacy(),
null,

@ -23,12 +23,12 @@ import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.BerlinGasCalculator;
import org.hyperledger.besu.ethereum.mainnet.BerlinTransactionGasCalculator;
import org.hyperledger.besu.ethereum.mainnet.TransactionGasCalculator;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.markertransaction.FixedKeySigningPrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.plugin.data.Restriction;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
@ -61,7 +61,7 @@ public class BaseEeaSendRawTransaction {
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory =
new FixedKeySigningPrivateMarkerTransactionFactory(keyPair);
final GasCalculator gasCalculator = new BerlinGasCalculator();
final TransactionGasCalculator transactionGasCalculator = new BerlinTransactionGasCalculator();
final Transaction PUBLIC_ONCHAIN_TRANSACTION =
new Transaction(

@ -42,7 +42,7 @@ public class PluginEeaSendRawTransactionTest extends BaseEeaSendRawTransaction {
privateMarkerTransactionFactory,
address -> 0,
privacyController,
gasCalculator);
transactionGasCalculator);
}
@Test

@ -14,28 +14,18 @@
*/
package org.hyperledger.besu.ethereum.mainnet;
import static java.util.Collections.emptyList;
import static org.hyperledger.besu.ethereum.core.Address.BLAKE2B_F_COMPRESSION;
import org.hyperledger.besu.ethereum.core.AccessListEntry;
import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.precompiles.BigIntegerModularExponentiationPrecompiledContract;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
public class BerlinGasCalculator extends IstanbulGasCalculator {
@ -44,7 +34,6 @@ public class BerlinGasCalculator extends IstanbulGasCalculator {
private static final Gas COLD_SLOAD_COST = Gas.of(2100);
private static final Gas COLD_ACCOUNT_ACCESS_COST = Gas.of(2600);
private static final Gas WARM_STORAGE_READ_COST = Gas.of(100);
private static final Gas ACCESS_LIST_ADDRESS_COST = Gas.of(2400);
protected static final Gas ACCESS_LIST_STORAGE_COST = Gas.of(1900);
// redefinitions for EIP-2929
@ -72,35 +61,6 @@ public class BerlinGasCalculator extends IstanbulGasCalculator {
this(BLAKE2B_F_COMPRESSION.toArrayUnsafe()[19]);
}
@Override
public GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(
final Transaction transaction) {
// As per https://eips.ethereum.org/EIPS/eip-2930
final List<AccessListEntry> accessList = transaction.getAccessList().orElse(emptyList());
long accessedStorageCount = 0;
final Set<Address> accessedAddresses = new HashSet<>();
final Multimap<Address, Bytes32> accessedStorage = HashMultimap.create();
for (final AccessListEntry accessListEntry : accessList) {
final Address address = accessListEntry.getAddress();
accessedAddresses.add(address);
for (final Bytes32 storageKeyBytes : accessListEntry.getStorageKeys()) {
accessedStorage.put(address, storageKeyBytes);
++accessedStorageCount;
}
}
return new GasAndAccessedState(
super.transactionIntrinsicGasCostAndAccessedState(transaction)
.getGas()
.plus(ACCESS_LIST_ADDRESS_COST.times(accessList.size()))
.plus(ACCESS_LIST_STORAGE_COST.times(accessedStorageCount)),
accessedAddresses,
accessedStorage);
}
@Override
public boolean isPrecompile(final Address address) {
final byte[] addressBytes = address.toArrayUnsafe();

@ -0,0 +1,67 @@
/*
* Copyright contributors to Hyperledger Besu
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.mainnet;
import static java.util.Collections.emptyList;
import org.hyperledger.besu.ethereum.core.AccessListEntry;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.apache.tuweni.bytes.Bytes32;
public class BerlinTransactionGasCalculator extends IstanbulTransactionGasCalculator {
// new constants for EIP-2929
private static final Gas ACCESS_LIST_ADDRESS_COST = Gas.of(2400);
protected static final Gas ACCESS_LIST_STORAGE_COST = Gas.of(1900);
@Override
public GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(
final Transaction transaction) {
// As per https://eips.ethereum.org/EIPS/eip-2930
final List<AccessListEntry> accessList = transaction.getAccessList().orElse(emptyList());
long accessedStorageCount = 0;
final Set<Address> accessedAddresses = new HashSet<>();
final Multimap<Address, Bytes32> accessedStorage = HashMultimap.create();
for (final AccessListEntry accessListEntry : accessList) {
final Address address = accessListEntry.getAddress();
accessedAddresses.add(address);
for (final Bytes32 storageKeyBytes : accessListEntry.getStorageKeys()) {
accessedStorage.put(address, storageKeyBytes);
++accessedStorageCount;
}
}
return new GasAndAccessedState(
super.transactionIntrinsicGasCostAndAccessedState(transaction)
.getGas()
.plus(ACCESS_LIST_ADDRESS_COST.times(accessList.size()))
.plus(ACCESS_LIST_STORAGE_COST.times(accessedStorageCount)),
accessedAddresses,
accessedStorage);
}
}

@ -56,9 +56,9 @@ public class ClassicProtocolSpecs {
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(TangerineWhistleGasCalculator::new)
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
transactionGasCalculator, true, chainId, quorumCompatibilityMode))
.name("ClassicTangerineWhistle");
}
@ -115,9 +115,9 @@ public class ClassicProtocolSpecs {
quorumCompatibilityMode)
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_REMOVED)
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
transactionGasCalculator, true, chainId, quorumCompatibilityMode))
.name("DefuseDifficultyBomb");
}
@ -150,20 +150,22 @@ public class ClassicProtocolSpecs {
? ClassicProtocolSpecs::byzantiumTransactionReceiptFactoryWithReasonEnabled
: ClassicProtocolSpecs::byzantiumTransactionReceiptFactory)
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
(transactionGasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
true,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
1))
.transactionProcessorBuilder(
(gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
@ -300,9 +302,9 @@ public class ClassicProtocolSpecs {
quorumCompatibilityMode)
.gasCalculator(BerlinGasCalculator::new)
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
true,
chainId,
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST),

@ -17,8 +17,6 @@ package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
@ -31,16 +29,6 @@ import org.apache.tuweni.units.bigints.UInt256;
public class FrontierGasCalculator implements GasCalculator {
private static final Gas TX_DATA_ZERO_COST = Gas.of(4L);
private static final Gas TX_DATA_NON_ZERO_COST = Gas.of(68L);
private static final Gas TX_BASE_COST = Gas.of(21_000L);
private static final Gas TX_CREATE_EXTRA_COST = Gas.of(0L);
private static final Gas CODE_DEPOSIT_BYTE_COST = Gas.of(200L);
private static final Gas ID_PRECOMPILED_BASE_GAS_COST = Gas.of(15L);
private static final Gas ID_PRECOMPILED_WORD_GAS_COST = Gas.of(3L);
@ -113,44 +101,6 @@ public class FrontierGasCalculator implements GasCalculator {
private static final Gas SELF_DESTRUCT_REFUND_AMOUNT = Gas.of(24_000L);
@Override
public GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(
final Transaction transaction) {
final Bytes payload = transaction.getPayload();
int zeros = 0;
for (int i = 0; i < payload.size(); i++) {
if (payload.get(i) == 0) {
++zeros;
}
}
final int nonZeros = payload.size() - zeros;
Gas cost =
TX_BASE_COST
.plus(TX_DATA_ZERO_COST.times(zeros))
.plus(TX_DATA_NON_ZERO_COST.times(nonZeros));
if (transaction.isContractCreation()) {
cost = cost.plus(txCreateExtraGasCost());
}
return new GasAndAccessedState(cost);
}
/**
* Returns the additional gas cost for contract creation transactions
*
* @return the additional gas cost for contract creation transactions
*/
protected Gas txCreateExtraGasCost() {
return TX_CREATE_EXTRA_COST;
}
@Override
public Gas codeDepositGasCost(final int codeSize) {
return CODE_DEPOSIT_BYTE_COST.times(codeSize);
}
@Override
public Gas idPrecompiledContractGasCost(final Bytes input) {
return ID_PRECOMPILED_WORD_GAS_COST
@ -467,11 +417,4 @@ public class FrontierGasCalculator implements GasCalculator {
return MEMORY_WORD_GAS_COST.times(len).plus(base);
}
@Override
public Gas getMaximumPmtCost() {
// what would be the gas for PMT with hash of all non-zeros
int nonZeros = 64;
return TX_BASE_COST.plus(TX_DATA_NON_ZERO_COST.times(nonZeros));
}
}

@ -0,0 +1,79 @@
/*
* Copyright contributors to Hyperledger Besu
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.apache.tuweni.bytes.Bytes;
public class FrontierTransactionGasCalculator implements TransactionGasCalculator {
private static final Gas TX_DATA_ZERO_COST = Gas.of(4L);
private static final Gas TX_DATA_NON_ZERO_COST = Gas.of(68L);
private static final Gas TX_BASE_COST = Gas.of(21_000L);
private static final Gas TX_CREATE_EXTRA_COST = Gas.of(0L);
private static final Gas CODE_DEPOSIT_BYTE_COST = Gas.of(200L);
@Override
public GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(
final Transaction transaction) {
final Bytes payload = transaction.getPayload();
int zeros = 0;
for (int i = 0; i < payload.size(); i++) {
if (payload.get(i) == 0) {
++zeros;
}
}
final int nonZeros = payload.size() - zeros;
Gas cost =
TX_BASE_COST
.plus(TX_DATA_ZERO_COST.times(zeros))
.plus(TX_DATA_NON_ZERO_COST.times(nonZeros));
if (transaction.isContractCreation()) {
cost = cost.plus(txCreateExtraGasCost());
}
return new GasAndAccessedState(cost);
}
/**
* Returns the additional gas cost for contract creation transactions
*
* @return the additional gas cost for contract creation transactions
*/
protected Gas txCreateExtraGasCost() {
return TX_CREATE_EXTRA_COST;
}
@Override
public Gas codeDepositGasCost(final int codeSize) {
return CODE_DEPOSIT_BYTE_COST.times(codeSize);
}
@Override
public Gas getMaximumPmtCost() {
// what would be the gas for PMT with hash of all non-zeros
int nonZeros = 64;
return TX_BASE_COST.plus(TX_DATA_NON_ZERO_COST.times(nonZeros));
}
}

@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Hyperledger Besu
*
* 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
@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Gas;
public class HomesteadGasCalculator extends FrontierGasCalculator {
public class HomesteadTransactionGasCalculator extends FrontierTransactionGasCalculator {
private static final Gas TX_CREATE_EXTRA = Gas.of(32_000L);

@ -16,18 +16,11 @@ package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
public class IstanbulGasCalculator extends PetersburgGasCalculator {
private static final Gas TX_DATA_ZERO_COST = Gas.of(4L);
private static final Gas ISTANBUL_TX_DATA_NON_ZERO_COST = Gas.of(16L);
private static final Gas TX_BASE_COST = Gas.of(21_000L);
private static final Gas SLOAD_GAS = Gas.of(800);
private static final Gas BALANCE_OPERATION_GAS_COST = Gas.of(700);
private static final Gas EXTCODE_HASH_COST = Gas.of(700);
@ -40,30 +33,6 @@ public class IstanbulGasCalculator extends PetersburgGasCalculator {
private static final Gas SSTORE_RESET_GAS_LESS_SLOAD_GAS = SSTORE_RESET_GAS.minus(SLOAD_GAS);
private static final Gas NEGATIVE_SSTORE_CLEARS_SCHEDULE = Gas.ZERO.minus(SSTORE_CLEARS_SCHEDULE);
@Override
public GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(
final Transaction transaction) {
final Bytes payload = transaction.getPayload();
int zeros = 0;
for (int i = 0; i < payload.size(); i++) {
if (payload.get(i) == 0) {
++zeros;
}
}
final int nonZeros = payload.size() - zeros;
Gas cost =
TX_BASE_COST
.plus(TX_DATA_ZERO_COST.times(zeros))
.plus(ISTANBUL_TX_DATA_NON_ZERO_COST.times(nonZeros));
if (transaction.isContractCreation()) {
cost = cost.plus(txCreateExtraGasCost());
}
return new GasAndAccessedState(cost);
}
@Override
// As per https://eips.ethereum.org/EIPS/eip-2200
public Gas calculateStorageCost(
@ -139,10 +108,4 @@ public class IstanbulGasCalculator extends PetersburgGasCalculator {
public Gas extCodeHashOperationGasCost() {
return EXTCODE_HASH_COST;
}
@Override
public Gas getMaximumPmtCost() {
int nonZeros = 64;
return TX_BASE_COST.plus(ISTANBUL_TX_DATA_NON_ZERO_COST.times(nonZeros));
}
}

@ -0,0 +1,58 @@
/*
* Copyright contributors to Hyperledger Besu
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.apache.tuweni.bytes.Bytes;
public class IstanbulTransactionGasCalculator extends HomesteadTransactionGasCalculator {
private static final Gas TX_DATA_ZERO_COST = Gas.of(4L);
private static final Gas ISTANBUL_TX_DATA_NON_ZERO_COST = Gas.of(16L);
private static final Gas TX_BASE_COST = Gas.of(21_000L);
@Override
public GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(
final Transaction transaction) {
final Bytes payload = transaction.getPayload();
int zeros = 0;
for (int i = 0; i < payload.size(); i++) {
if (payload.get(i) == 0) {
++zeros;
}
}
final int nonZeros = payload.size() - zeros;
Gas cost =
TX_BASE_COST
.plus(TX_DATA_ZERO_COST.times(zeros))
.plus(ISTANBUL_TX_DATA_NON_ZERO_COST.times(nonZeros));
if (transaction.isContractCreation()) {
cost = cost.plus(txCreateExtraGasCost());
}
return new GasAndAccessedState(cost);
}
@Override
public Gas getMaximumPmtCost() {
int nonZeros = 64;
return TX_BASE_COST.plus(ISTANBUL_TX_DATA_NON_ZERO_COST.times(nonZeros));
}
}

@ -26,9 +26,6 @@ public class LondonGasCalculator extends BerlinGasCalculator {
private static final Gas NEGATIVE_SSTORE_CLEARS_SCHEDULE = Gas.ZERO.minus(SSTORE_CLEARS_SCHEDULE);
// redefinitions for EIP-3529
private static final int NEW_MAX_REFUND_QUOTIENT = 5;
protected LondonGasCalculator() {}
// Redefined refund amount from EIP-3529
@ -76,9 +73,4 @@ public class LondonGasCalculator extends BerlinGasCalculator {
}
}
}
@Override
public long getMaxRefundQuotient() {
return NEW_MAX_REFUND_QUOTIENT;
}
}

@ -0,0 +1,26 @@
/*
* Copyright contributors to Hyperledger Besu
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.mainnet;
public class LondonTransactionGasCalculator extends BerlinTransactionGasCalculator {
// redefinitions for EIP-3529
private static final int NEW_MAX_REFUND_QUOTIENT = 5;
@Override
public long getMaxRefundQuotient() {
return NEW_MAX_REFUND_QUOTIENT;
}
}

@ -21,7 +21,6 @@ import org.hyperledger.besu.ethereum.core.ModificationNotAllowedException;
import org.hyperledger.besu.ethereum.core.MutableAccount;
import org.hyperledger.besu.ethereum.vm.EVM;
import org.hyperledger.besu.ethereum.vm.ExceptionalHaltReason;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
import org.hyperledger.besu.ethereum.vm.OperationTracer;
@ -41,34 +40,34 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
private final boolean requireCodeDepositToSucceed;
private final GasCalculator gasCalculator;
private final TransactionGasCalculator transactionGasCalculator;
private final long initialContractNonce;
private final List<ContractValidationRule> contractValidationRules;
public MainnetContractCreationProcessor(
final GasCalculator gasCalculator,
final TransactionGasCalculator transactionGasCalculator,
final EVM evm,
final boolean requireCodeDepositToSucceed,
final List<ContractValidationRule> contractValidationRules,
final long initialContractNonce,
final Collection<Address> forceCommitAddresses) {
super(evm, forceCommitAddresses);
this.gasCalculator = gasCalculator;
this.transactionGasCalculator = transactionGasCalculator;
this.requireCodeDepositToSucceed = requireCodeDepositToSucceed;
this.contractValidationRules = contractValidationRules;
this.initialContractNonce = initialContractNonce;
}
public MainnetContractCreationProcessor(
final GasCalculator gasCalculator,
final TransactionGasCalculator transactionGasCalculator,
final EVM evm,
final boolean requireCodeDepositToSucceed,
final List<ContractValidationRule> contractValidationRules,
final long initialContractNonce) {
this(
gasCalculator,
transactionGasCalculator,
evm,
requireCodeDepositToSucceed,
contractValidationRules,
@ -117,7 +116,7 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
protected void codeSuccess(final MessageFrame frame, final OperationTracer operationTracer) {
final Bytes contractCode = frame.getOutputData();
final Gas depositFee = gasCalculator.codeDepositGasCost(contractCode.size());
final Gas depositFee = transactionGasCalculator.codeDepositGasCost(contractCode.size());
if (frame.getRemainingGas().compareTo(depositFee) < 0) {
LOG.trace(

@ -92,29 +92,32 @@ public abstract class MainnetProtocolSpecs {
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
return new ProtocolSpecBuilder()
.gasCalculator(FrontierGasCalculator::new)
.transactionGasCalculator(new FrontierTransactionGasCalculator())
.gasLimitCalculator(new FrontierTargetingGasLimitCalculator())
.evmBuilder(MainnetEvmRegistries::frontier)
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::frontier)
.messageCallProcessorBuilder(MainnetMessageCallProcessor::new)
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
(transactionGasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
false,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
0))
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), goQuorumMode))
transactionGasCalculator, false, Optional.empty(), goQuorumMode))
.transactionProcessorBuilder(
(gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
@ -123,13 +126,13 @@ public abstract class MainnetProtocolSpecs {
FeeMarket.legacy(),
CoinbaseFeePriceCalculator.frontier()))
.privateTransactionProcessorBuilder(
(gasCalculator,
(transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
privateTransactionValidator) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
@ -196,20 +199,20 @@ public abstract class MainnetProtocolSpecs {
final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT);
return frontierDefinition(
configContractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(HomesteadGasCalculator::new)
.transactionGasCalculator(new HomesteadTransactionGasCalculator())
.evmBuilder(MainnetEvmRegistries::homestead)
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
(transactionGasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
true,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
0))
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, Optional.empty(), quorumCompatibilityMode))
transactionGasCalculator, true, Optional.empty(), quorumCompatibilityMode))
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
.name("Homestead");
}
@ -277,25 +280,27 @@ public abstract class MainnetProtocolSpecs {
precompileContractRegistry,
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
(transactionGasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
true,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
1,
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
transactionGasCalculator, true, chainId, quorumCompatibilityMode))
.transactionProcessorBuilder(
(gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
@ -326,13 +331,13 @@ public abstract class MainnetProtocolSpecs {
.blockReward(BYZANTIUM_BLOCK_REWARD)
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(chainId))
.privateTransactionProcessorBuilder(
(gasCalculator,
(transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
privateTransactionValidator) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
@ -392,14 +397,15 @@ public abstract class MainnetProtocolSpecs {
enableRevertReason,
quorumCompatibilityMode)
.gasCalculator(IstanbulGasCalculator::new)
.transactionGasCalculator(new IstanbulTransactionGasCalculator())
.evmBuilder(
gasCalculator ->
MainnetEvmRegistries.istanbul(gasCalculator, chainId.orElse(BigInteger.ZERO)))
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::istanbul)
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
(transactionGasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
true,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
@ -437,10 +443,11 @@ public abstract class MainnetProtocolSpecs {
enableRevertReason,
quorumCompatibilityMode)
.gasCalculator(BerlinGasCalculator::new)
.transactionGasCalculator(new BerlinTransactionGasCalculator())
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
true,
chainId,
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST),
@ -472,12 +479,13 @@ public abstract class MainnetProtocolSpecs {
enableRevertReason,
quorumCompatibilityMode)
.gasCalculator(LondonGasCalculator::new)
.transactionGasCalculator(new LondonTransactionGasCalculator())
.gasLimitCalculator(
new LondonTargetingGasLimitCalculator(londonForkBlockNumber, londonFeeMarket))
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
londonFeeMarket,
true,
chainId,
@ -488,11 +496,13 @@ public abstract class MainnetProtocolSpecs {
quorumCompatibilityMode))
.transactionProcessorBuilder(
(gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
@ -501,9 +511,9 @@ public abstract class MainnetProtocolSpecs {
londonFeeMarket,
CoinbaseFeePriceCalculator.eip1559()))
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
(transactionGasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
true,
List.of(MaxCodeSizeRule.of(contractSizeLimit), PrefixCodeRule.of()),

@ -53,6 +53,8 @@ public class MainnetTransactionProcessor {
protected final GasCalculator gasCalculator;
protected final TransactionGasCalculator transactionGasCalculator;
protected final MainnetTransactionValidator transactionValidator;
private final AbstractMessageProcessor contractCreationProcessor;
@ -218,6 +220,7 @@ public class MainnetTransactionProcessor {
public MainnetTransactionProcessor(
final GasCalculator gasCalculator,
final TransactionGasCalculator transacitonGasCalculator,
final MainnetTransactionValidator transactionValidator,
final AbstractMessageProcessor contractCreationProcessor,
final AbstractMessageProcessor messageCallProcessor,
@ -226,6 +229,7 @@ public class MainnetTransactionProcessor {
final FeeMarket feeMarket,
final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator) {
this.gasCalculator = gasCalculator;
this.transactionGasCalculator = transacitonGasCalculator;
this.transactionValidator = transactionValidator;
this.contractCreationProcessor = contractCreationProcessor;
this.messageCallProcessor = messageCallProcessor;
@ -290,7 +294,7 @@ public class MainnetTransactionProcessor {
sender.getBalance());
final GasAndAccessedState gasAndAccessedState =
gasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction);
transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction);
final Gas intrinsicGas = gasAndAccessedState.getGas();
final Gas gasAvailable = Gas.of(transaction.getGasLimit()).minus(intrinsicGas);
LOG.trace(
@ -467,7 +471,7 @@ public class MainnetTransactionProcessor {
final Gas maxRefundAllowance =
Gas.of(transaction.getGasLimit())
.minus(gasRemaining)
.dividedBy(gasCalculator.getMaxRefundQuotient());
.dividedBy(transactionGasCalculator.getMaxRefundQuotient());
final Gas refundAllowance = maxRefundAllowance.min(gasRefund);
return gasRemaining.plus(refundAllowance);
}

@ -23,7 +23,6 @@ import org.hyperledger.besu.ethereum.core.TransactionFilter;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.plugin.data.TransactionType;
import java.math.BigInteger;
@ -38,7 +37,7 @@ import java.util.Set;
*/
public class MainnetTransactionValidator {
private final GasCalculator gasCalculator;
private final TransactionGasCalculator transactionGasCalculator;
private final FeeMarket feeMarket;
private final boolean disallowSignatureMalleability;
@ -50,12 +49,12 @@ public class MainnetTransactionValidator {
private final boolean goQuorumCompatibilityMode;
public MainnetTransactionValidator(
final GasCalculator gasCalculator,
final TransactionGasCalculator transactionGasCalculator,
final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId,
final boolean goQuorumCompatibilityMode) {
this(
gasCalculator,
transactionGasCalculator,
checkSignatureMalleability,
chainId,
Set.of(TransactionType.FRONTIER),
@ -63,13 +62,13 @@ public class MainnetTransactionValidator {
}
public MainnetTransactionValidator(
final GasCalculator gasCalculator,
final TransactionGasCalculator transactionGasCalculator,
final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId,
final Set<TransactionType> acceptedTransactionTypes,
final boolean quorumCompatibilityMode) {
this(
gasCalculator,
transactionGasCalculator,
FeeMarket.legacy(),
checkSignatureMalleability,
chainId,
@ -78,13 +77,13 @@ public class MainnetTransactionValidator {
}
public MainnetTransactionValidator(
final GasCalculator gasCalculator,
final TransactionGasCalculator transactionGasCalculator,
final FeeMarket feeMarket,
final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId,
final Set<TransactionType> acceptedTransactionTypes,
final boolean goQuorumCompatibilityMode) {
this.gasCalculator = gasCalculator;
this.transactionGasCalculator = transactionGasCalculator;
this.feeMarket = feeMarket;
this.disallowSignatureMalleability = checkSignatureMalleability;
this.chainId = chainId;
@ -151,7 +150,7 @@ public class MainnetTransactionValidator {
}
final Gas intrinsicGasCost =
gasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction).getGas();
transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction).getGas();
if (intrinsicGasCost.compareTo(Gas.of(transaction.getGasLimit())) > 0) {
return ValidationResult.invalid(
TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT,

@ -35,6 +35,8 @@ public class ProtocolSpec {
private final GasCalculator gasCalculator;
private final TransactionGasCalculator transactionGasCalculator;
private final GasLimitCalculator gasLimitCalculator;
private final MainnetTransactionValidator transactionValidator;
@ -97,6 +99,7 @@ public class ProtocolSpec {
* @param precompileContractRegistry all the pre-compiled contracts added
* @param skipZeroBlockRewards should rewards be skipped if it is zero
* @param gasCalculator the gas calculator to use.
* @param transactionGasCalculator the transaction gas calculator to use.
* @param gasLimitCalculator the gas limit calculator to use.
* @param feeMarket an {@link Optional} wrapping {@link FeeMarket} class if appropriate.
* @param badBlockManager the cache to use to keep invalid blocks
@ -122,6 +125,7 @@ public class ProtocolSpec {
final PrecompileContractRegistry precompileContractRegistry,
final boolean skipZeroBlockRewards,
final GasCalculator gasCalculator,
final TransactionGasCalculator transactionGasCalculator,
final GasLimitCalculator gasLimitCalculator,
final FeeMarket feeMarket,
final BadBlockManager badBlockManager,
@ -145,6 +149,7 @@ public class ProtocolSpec {
this.precompileContractRegistry = precompileContractRegistry;
this.skipZeroBlockRewards = skipZeroBlockRewards;
this.gasCalculator = gasCalculator;
this.transactionGasCalculator = transactionGasCalculator;
this.gasLimitCalculator = gasLimitCalculator;
this.feeMarket = feeMarket;
this.badBlockManager = badBlockManager;
@ -309,6 +314,15 @@ public class ProtocolSpec {
return gasCalculator;
}
/**
* Returns the transactionGasCalculator used in this specification.
*
* @return the transaction processing gas calculator
*/
public TransactionGasCalculator getTransactionGasCalculator() {
return transactionGasCalculator;
}
/**
* Returns the gasLimitCalculator used in this specification.
*

@ -41,6 +41,7 @@ import java.util.function.Supplier;
public class ProtocolSpecBuilder {
private Supplier<GasCalculator> gasCalculatorBuilder;
private TransactionGasCalculator transactionGasCalculator;
private GasLimitCalculator gasLimitCalculator;
private Wei blockReward;
private boolean skipZeroBlockRewards;
@ -48,11 +49,13 @@ public class ProtocolSpecBuilder {
private AbstractBlockProcessor.TransactionReceiptFactory transactionReceiptFactory;
private DifficultyCalculator difficultyCalculator;
private Function<GasCalculator, EVM> evmBuilder;
private Function<GasCalculator, MainnetTransactionValidator> transactionValidatorBuilder;
private Function<TransactionGasCalculator, MainnetTransactionValidator>
transactionValidatorBuilder;
private BlockHeaderValidator.Builder blockHeaderValidatorBuilder;
private BlockHeaderValidator.Builder ommerHeaderValidatorBuilder;
private Function<ProtocolSchedule, BlockBodyValidator> blockBodyValidatorBuilder;
private BiFunction<GasCalculator, EVM, AbstractMessageProcessor> contractCreationProcessorBuilder;
private BiFunction<TransactionGasCalculator, EVM, AbstractMessageProcessor>
contractCreationProcessorBuilder;
private Function<PrecompiledContractConfiguration, PrecompileContractRegistry>
precompileContractRegistryBuilder;
private BiFunction<EVM, PrecompileContractRegistry, AbstractMessageProcessor>
@ -75,6 +78,12 @@ public class ProtocolSpecBuilder {
return this;
}
public ProtocolSpecBuilder transactionGasCalculator(
final TransactionGasCalculator transactionGasCalculator) {
this.transactionGasCalculator = transactionGasCalculator;
return this;
}
public ProtocolSpecBuilder gasLimitCalculator(final GasLimitCalculator gasLimitCalculator) {
this.gasLimitCalculator = gasLimitCalculator;
return this;
@ -112,7 +121,8 @@ public class ProtocolSpecBuilder {
}
public ProtocolSpecBuilder transactionValidatorBuilder(
final Function<GasCalculator, MainnetTransactionValidator> transactionValidatorBuilder) {
final Function<TransactionGasCalculator, MainnetTransactionValidator>
transactionValidatorBuilder) {
this.transactionValidatorBuilder = transactionValidatorBuilder;
return this;
}
@ -136,7 +146,7 @@ public class ProtocolSpecBuilder {
}
public ProtocolSpecBuilder contractCreationProcessorBuilder(
final BiFunction<GasCalculator, EVM, AbstractMessageProcessor>
final BiFunction<TransactionGasCalculator, EVM, AbstractMessageProcessor>
contractCreationProcessorBuilder) {
this.contractCreationProcessorBuilder = contractCreationProcessorBuilder;
return this;
@ -233,6 +243,7 @@ public class ProtocolSpecBuilder {
public ProtocolSpec build(final ProtocolSchedule protocolSchedule) {
checkNotNull(gasCalculatorBuilder, "Missing gasCalculator");
checkNotNull(transactionGasCalculator, "Missing transactionGasCalculator");
checkNotNull(gasLimitCalculator, "Missing gasLimitCalculator");
checkNotNull(evmBuilder, "Missing operation registry");
checkNotNull(transactionValidatorBuilder, "Missing transaction validator");
@ -263,16 +274,20 @@ public class ProtocolSpecBuilder {
final PrecompiledContractConfiguration precompiledContractConfiguration =
new PrecompiledContractConfiguration(gasCalculator, privacyParameters);
final MainnetTransactionValidator transactionValidator =
transactionValidatorBuilder.apply(gasCalculator);
transactionValidatorBuilder.apply(transactionGasCalculator);
final AbstractMessageProcessor contractCreationProcessor =
contractCreationProcessorBuilder.apply(gasCalculator, evm);
contractCreationProcessorBuilder.apply(transactionGasCalculator, evm);
final PrecompileContractRegistry precompileContractRegistry =
precompileContractRegistryBuilder.apply(precompiledContractConfiguration);
final AbstractMessageProcessor messageCallProcessor =
messageCallProcessorBuilder.apply(evm, precompileContractRegistry);
final MainnetTransactionProcessor transactionProcessor =
transactionProcessorBuilder.apply(
gasCalculator, transactionValidator, contractCreationProcessor, messageCallProcessor);
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor);
final BlockHeaderValidator blockHeaderValidator =
blockHeaderValidatorBuilder.difficultyCalculator(difficultyCalculator).build();
@ -296,7 +311,7 @@ public class ProtocolSpecBuilder {
privateTransactionValidatorBuilder.apply();
privateTransactionProcessor =
privateTransactionProcessorBuilder.apply(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
@ -359,6 +374,7 @@ public class ProtocolSpecBuilder {
precompileContractRegistry,
skipZeroBlockRewards,
gasCalculator,
transactionGasCalculator,
gasLimitCalculator,
feeMarket,
badBlockManager,
@ -368,6 +384,7 @@ public class ProtocolSpecBuilder {
public interface TransactionProcessorBuilder {
MainnetTransactionProcessor apply(
GasCalculator gasCalculator,
TransactionGasCalculator transactionGasCalculator,
MainnetTransactionValidator transactionValidator,
AbstractMessageProcessor contractCreationProcessor,
AbstractMessageProcessor messageCallProcessor);
@ -375,7 +392,7 @@ public class ProtocolSpecBuilder {
public interface PrivateTransactionProcessorBuilder {
PrivateTransactionProcessor apply(
GasCalculator gasCalculator,
TransactionGasCalculator transactionGasCalculator,
MainnetTransactionValidator transactionValidator,
AbstractMessageProcessor contractCreationProcessor,
AbstractMessageProcessor messageCallProcessor,

@ -22,7 +22,7 @@ import org.hyperledger.besu.ethereum.vm.MessageFrame;
import org.apache.tuweni.units.bigints.UInt256;
public class TangerineWhistleGasCalculator extends HomesteadGasCalculator {
public class TangerineWhistleGasCalculator extends FrontierGasCalculator {
private static final Gas BALANCE_OPERATION_GAS_COST = Gas.of(400L);

@ -0,0 +1,67 @@
/*
* Copyright contributors to Hyperledger Besu
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
/**
* Provides various gas cost lookups and calculations used during transaction processing outside the
* EVM.
*
* <p>The {@code TransactionGasCalculator} is meant to encapsulate all {@link Gas}-related
* calculations not needed during EVM execution or caused by EVM execution. EVM Relevant or caused
* gas calculations live in the {@link org.hyperledger.besu.ethereum.vm.GasCalculator}. Current
* calculations revolve around block encoding of transactions, account creation, how much refund to
* apply, and private transaction gas reservations.
*/
public interface TransactionGasCalculator {
/**
* Returns a {@link Transaction}s intrinsic gas cost, i.e. the cost deriving from its encoded
* binary representation when stored on-chain.
*
* @param transaction The transaction
* @return the transaction's intrinsic gas cost
*/
GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(Transaction transaction);
/**
* Returns the cost for a {@link AbstractMessageProcessor} to deposit the code in storage
*
* @param codeSize The size of the code in bytes
* @return the code deposit cost
*/
Gas codeDepositGasCost(int codeSize);
/**
* A measure of the maximum amount of refunded gas a transaction will be credited with.
*
* @return the quotient of the equation `txGasCost / refundQuotient`.
*/
default long getMaxRefundQuotient() {
return 2;
}
/**
* Maximum Cost of a Privacy Marker Transaction (PMT). See {@link
* org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory}
*
* @return the maximum gas cost
*/
// what would be the gas for a PMT with hash of all non-zeros
Gas getMaximumPmtCost();
}

@ -28,12 +28,12 @@ import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.mainnet.AbstractMessageProcessor;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator;
import org.hyperledger.besu.ethereum.mainnet.TransactionGasCalculator;
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.ethereum.vm.Code;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
import org.hyperledger.besu.ethereum.vm.OperationTracer;
import org.hyperledger.besu.ethereum.worldstate.DefaultMutablePrivateWorldStateUpdater;
@ -50,8 +50,7 @@ public class PrivateTransactionProcessor {
private static final Logger LOG = LogManager.getLogger();
@SuppressWarnings("unused")
private final GasCalculator gasCalculator;
private final TransactionGasCalculator transactionGasCalculator;
@SuppressWarnings("unused")
private final MainnetTransactionValidator transactionValidator;
@ -68,14 +67,14 @@ public class PrivateTransactionProcessor {
private final boolean clearEmptyAccounts;
public PrivateTransactionProcessor(
final GasCalculator gasCalculator,
final TransactionGasCalculator transactionGasCalculator,
final MainnetTransactionValidator transactionValidator,
final AbstractMessageProcessor contractCreationProcessor,
final AbstractMessageProcessor messageCallProcessor,
final boolean clearEmptyAccounts,
final int maxStackSize,
final PrivateTransactionValidator privateTransactionValidator) {
this.gasCalculator = gasCalculator;
this.transactionGasCalculator = transactionGasCalculator;
this.transactionValidator = transactionValidator;
this.contractCreationProcessor = contractCreationProcessor;
this.messageCallProcessor = messageCallProcessor;
@ -233,7 +232,7 @@ public class PrivateTransactionProcessor {
final Gas maxRefundAllowance =
Gas.of(transaction.getGasLimit())
.minus(gasRemaining)
.dividedBy(gasCalculator.getMaxRefundQuotient());
.dividedBy(transactionGasCalculator.getMaxRefundQuotient());
final Gas refundAllowance = maxRefundAllowance.min(gasRefund);
return gasRemaining.plus(refundAllowance);
}

@ -233,7 +233,8 @@ public class TransactionSimulator {
// This means a potential over-estimate of gas, but the tx, if sent with this gas, will not
// fail.
if (GoQuorumOptions.goQuorumCompatibilityMode && value.isZero()) {
Gas privateGasEstimateAndState = protocolSpec.getGasCalculator().getMaximumPmtCost();
Gas privateGasEstimateAndState =
protocolSpec.getTransactionGasCalculator().getMaximumPmtCost();
if (privateGasEstimateAndState.toLong() > result.getEstimateGasUsedByTransaction()) {
// modify the result to have the larger estimate
TransactionProcessingResult resultPmt =

@ -17,10 +17,7 @@ package org.hyperledger.besu.ethereum.vm;
import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.GasAndAccessedState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.AbstractMessageProcessor;
import org.hyperledger.besu.ethereum.mainnet.precompiles.ECRECPrecompiledContract;
import org.hyperledger.besu.ethereum.mainnet.precompiles.IDPrecompiledContract;
import org.hyperledger.besu.ethereum.mainnet.precompiles.RIPEMD160PrecompiledContract;
@ -44,38 +41,16 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
/**
* Provides various gas cost lookups and calculations used during block processing.
* Provides various gas cost lookups and calculations used during EVM Execution.
*
* <p>The {@code GasCalculator} is meant to encapsulate all {@link Gas}-related calculations except
* for the following "safe" operations:
*
* <ul>
* <li><b>Operation Gas Deductions:</b> Deducting the operation's gas cost from the VM's current
* message frame because the
* </ul>
* <p>The {@code GasCalculator} is meant to encapsulate all {@link Gas}-related calculations needed
* during EVM execution or caused by EVM execution. Hence, refund calculation is part of this as the
* EVM should report the refund counter at the end of execution. However, the amount to apply to a
* transaction is out of scope and part of the {@link
* org.hyperledger.besu.ethereum.mainnet.TransactionGasCalculator}.
*/
public interface GasCalculator {
// Transaction Gas Calculations
/**
* Returns a {@link Transaction}s intrinsic gas cost
*
* @param transaction The transaction
* @return the transaction's intrinsic gas cost
*/
GasAndAccessedState transactionIntrinsicGasCostAndAccessedState(Transaction transaction);
// Contract Creation Gas Calculations
/**
* Returns the cost for a {@link AbstractMessageProcessor} to deposit the code in storage
*
* @param codeSize The size of the code in bytes
* @return the code deposit cost
*/
Gas codeDepositGasCost(int codeSize);
// Precompiled Contract Gas Calculations
/**
@ -434,11 +409,4 @@ public interface GasCalculator {
default Gas modExpGasCost(final Bytes input) {
return Gas.ZERO;
}
default long getMaxRefundQuotient() {
return 2;
}
// what would be the gas for a PMT with hash of all non-zeros
Gas getMaximumPmtCost();
}

@ -17,7 +17,6 @@ package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import java.util.Arrays;
import java.util.Collection;
@ -32,21 +31,23 @@ import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class IntrinsicGasTest {
private final GasCalculator gasCalculator;
private final TransactionGasCalculator transactionGasCalculator;
private final Gas expectedGas;
private final String txRlp;
public IntrinsicGasTest(
final GasCalculator gasCalculator, final Gas expectedGas, final String txRlp) {
this.gasCalculator = gasCalculator;
final TransactionGasCalculator transactionGasCalculator,
final Gas expectedGas,
final String txRlp) {
this.transactionGasCalculator = transactionGasCalculator;
this.expectedGas = expectedGas;
this.txRlp = txRlp;
}
@Parameters
public static Collection<Object[]> data() {
final GasCalculator frontier = new FrontierGasCalculator();
final GasCalculator istanbul = new IstanbulGasCalculator();
final TransactionGasCalculator frontier = new FrontierTransactionGasCalculator();
final TransactionGasCalculator istanbul = new IstanbulTransactionGasCalculator();
return Arrays.asList(
new Object[][] {
// EnoughGAS
@ -110,7 +111,8 @@ public class IntrinsicGasTest {
@Test
public void validateGasCost() {
Transaction t = Transaction.readFrom(RLP.input(Bytes.fromHexString(txRlp)));
Assertions.assertThat(gasCalculator.transactionIntrinsicGasCostAndAccessedState(t).getGas())
Assertions.assertThat(
transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(t).getGas())
.isEqualTo(expectedGas);
}
}

@ -23,7 +23,6 @@ import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.MessageFrameTestFixture;
import org.hyperledger.besu.ethereum.mainnet.contractvalidation.PrefixCodeRule;
import org.hyperledger.besu.ethereum.vm.EVM;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
import org.hyperledger.besu.ethereum.vm.OperationTracer;
@ -38,7 +37,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MainnetContractCreationProcessorTest {
@Mock GasCalculator gasCalculator;
@Mock TransactionGasCalculator transactionGasCalculator;
@Mock EVM evm;
private MainnetContractCreationProcessor processor;
@ -47,7 +46,7 @@ public class MainnetContractCreationProcessorTest {
public void shouldThrowAnExceptionWhenCodeContractFormatInvalid() {
processor =
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
true,
Collections.singletonList(PrefixCodeRule.of()),
@ -58,7 +57,7 @@ public class MainnetContractCreationProcessorTest {
messageFrame.setOutputData(contractCode);
messageFrame.setGasRemaining(Gas.of(100));
when(gasCalculator.codeDepositGasCost(contractCode.size())).thenReturn(Gas.of(10));
when(transactionGasCalculator.codeDepositGasCost(contractCode.size())).thenReturn(Gas.of(10));
processor.codeSuccess(messageFrame, OperationTracer.NO_TRACING);
assertThat(messageFrame.getState()).isEqualTo(EXCEPTIONAL_HALT);
}
@ -67,7 +66,7 @@ public class MainnetContractCreationProcessorTest {
public void shouldNotThrowAnExceptionWhenCodeContractIsValid() {
processor =
new MainnetContractCreationProcessor(
gasCalculator,
transactionGasCalculator,
evm,
true,
Collections.singletonList(PrefixCodeRule.of()),
@ -78,7 +77,7 @@ public class MainnetContractCreationProcessorTest {
messageFrame.setOutputData(contractCode);
messageFrame.setGasRemaining(Gas.of(100));
when(gasCalculator.codeDepositGasCost(contractCode.size())).thenReturn(Gas.of(10));
when(transactionGasCalculator.codeDepositGasCost(contractCode.size())).thenReturn(Gas.of(10));
processor.codeSuccess(messageFrame, OperationTracer.NO_TRACING);
assertThat(messageFrame.getState()).isEqualTo(COMPLETED_SUCCESS);
}
@ -87,13 +86,18 @@ public class MainnetContractCreationProcessorTest {
public void shouldNotThrowAnExceptionWhenPrefixCodeRuleNotAdded() {
processor =
new MainnetContractCreationProcessor(
gasCalculator, evm, true, Collections.emptyList(), 1, Collections.emptyList());
transactionGasCalculator,
evm,
true,
Collections.emptyList(),
1,
Collections.emptyList());
final Bytes contractCode = Bytes.fromHexString("0F01010101010101");
MessageFrame messageFrame = new MessageFrameTestFixture().build();
messageFrame.setOutputData(contractCode);
messageFrame.setGasRemaining(Gas.of(100));
when(gasCalculator.codeDepositGasCost(contractCode.size())).thenReturn(Gas.of(10));
when(transactionGasCalculator.codeDepositGasCost(contractCode.size())).thenReturn(Gas.of(10));
processor.codeSuccess(messageFrame, OperationTracer.NO_TRACING);
assertThat(messageFrame.getState()).isEqualTo(COMPLETED_SUCCESS);
}

@ -44,6 +44,7 @@ public class MainnetTransactionProcessorTest {
private MainnetTransactionProcessor transactionProcessor;
@Mock private GasCalculator gasCalculator;
@Mock private TransactionGasCalculator transactionGasCalculator;
@Mock private MainnetTransactionValidator transactionValidator;
@Mock private AbstractMessageProcessor contractCreationProcessor;
@Mock private AbstractMessageProcessor messageCallProcessor;
@ -59,6 +60,7 @@ public class MainnetTransactionProcessorTest {
transactionProcessor =
new MainnetTransactionProcessor(
gasCalculator,
transactionGasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,

@ -38,7 +38,6 @@ import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.plugin.data.TransactionType;
import java.math.BigInteger;
@ -64,7 +63,7 @@ public class MainnetTransactionValidatorTest {
private static final TransactionValidationParams transactionValidationParams =
TransactionValidationParams.processingBlockParams;
@Mock private GasCalculator gasCalculator;
@Mock private TransactionGasCalculator transactionGasCalculator;
private final Transaction basicTransaction =
new TransactionTestFixture()
@ -77,13 +76,13 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionIfIntrinsicGasExceedsGasLimit() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
transactionGasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture()
.gasLimit(10)
.chainId(Optional.empty())
.createTransaction(senderKeys);
when(gasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
when(transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
.thenReturn(new GasAndAccessedState(Gas.of(50)));
assertThat(validator.validate(transaction, Optional.empty(), transactionValidationParams))
@ -95,7 +94,7 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionWhenTransactionHasChainIdAndValidatorDoesNot() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
transactionGasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
assertThat(validator.validate(basicTransaction, Optional.empty(), transactionValidationParams))
.isEqualTo(
ValidationResult.invalid(
@ -106,7 +105,7 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionWhenTransactionHasIncorrectChainId() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
false,
Optional.of(BigInteger.valueOf(2)),
defaultGoQuorumCompatibilityMode);
@ -118,7 +117,10 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionWhenSenderAccountDoesNotExist() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
transactionGasCalculator,
false,
Optional.of(BigInteger.ONE),
defaultGoQuorumCompatibilityMode);
assertThat(validator.validateForSender(basicTransaction, null, false))
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE));
}
@ -127,7 +129,10 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionWhenTransactionNonceBelowAccountNonce() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
transactionGasCalculator,
false,
Optional.of(BigInteger.ONE),
defaultGoQuorumCompatibilityMode);
final Account account = accountWithNonce(basicTransaction.getNonce() + 1);
assertThat(validator.validateForSender(basicTransaction, account, false))
@ -139,7 +144,10 @@ public class MainnetTransactionValidatorTest {
shouldRejectTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsNotAllowed() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
transactionGasCalculator,
false,
Optional.of(BigInteger.ONE),
defaultGoQuorumCompatibilityMode);
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
assertThat(validator.validateForSender(basicTransaction, account, false))
@ -151,7 +159,10 @@ public class MainnetTransactionValidatorTest {
shouldAcceptTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsAllowed() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
transactionGasCalculator,
false,
Optional.of(BigInteger.ONE),
defaultGoQuorumCompatibilityMode);
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
assertThat(validator.validateForSender(basicTransaction, account, true))
@ -162,7 +173,10 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionWhenNonceExceedsMaximumAllowedNonce() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
transactionGasCalculator,
false,
Optional.of(BigInteger.ONE),
defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture().nonce(11).createTransaction(senderKeys);
@ -176,7 +190,10 @@ public class MainnetTransactionValidatorTest {
public void transactionWithNullSenderCanBeValidIfGasPriceAndValueIsZero() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
transactionGasCalculator,
false,
Optional.of(BigInteger.ONE),
defaultGoQuorumCompatibilityMode);
final TransactionTestFixture builder = new TransactionTestFixture();
final KeyPair senderKeyPair = SIGNATURE_ALGORITHM.get().generateKeyPair();
@ -191,7 +208,7 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionIfAccountIsNotPermitted() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
transactionGasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter(false));
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), true))
@ -202,7 +219,7 @@ public class MainnetTransactionValidatorTest {
public void shouldAcceptValidTransactionIfAccountIsPermitted() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
transactionGasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter(true));
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), true))
@ -213,7 +230,7 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionWithMaxFeeTimesGasLimitGreaterThanBalance() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
transactionGasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter(true));
assertThat(
@ -238,7 +255,7 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionWithMaxPriorityFeeGreaterThanMaxFee() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
FeeMarket.london(0L),
false,
Optional.of(BigInteger.ONE),
@ -282,7 +299,7 @@ public class MainnetTransactionValidatorTest {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
transactionGasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter);
final TransactionValidationParams validationParams =
@ -300,7 +317,7 @@ public class MainnetTransactionValidatorTest {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
transactionGasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter);
final TransactionValidationParams validationParams =
@ -321,7 +338,7 @@ public class MainnetTransactionValidatorTest {
public void shouldAcceptOnlyTransactionsInAcceptedTransactionTypes() {
final MainnetTransactionValidator frontierValidator =
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
FeeMarket.legacy(),
false,
Optional.of(BigInteger.ONE),
@ -330,7 +347,7 @@ public class MainnetTransactionValidatorTest {
final MainnetTransactionValidator eip1559Validator =
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
FeeMarket.london(0L),
false,
Optional.of(BigInteger.ONE),
@ -350,7 +367,7 @@ public class MainnetTransactionValidatorTest {
frontierValidator.validate(transaction, Optional.empty(), transactionValidationParams))
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.INVALID_TRANSACTION_FORMAT));
when(gasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
when(transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
.thenReturn(new GasAndAccessedState(Gas.of(0)));
assertThat(eip1559Validator.validate(transaction, Optional.of(1L), transactionValidationParams))
@ -361,7 +378,7 @@ public class MainnetTransactionValidatorTest {
public void shouldRejectTransactionIfEIP1559TransactionGasPriceLessBaseFee() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
FeeMarket.london(0L),
false,
Optional.of(BigInteger.ONE),
@ -383,7 +400,7 @@ public class MainnetTransactionValidatorTest {
public void shouldAcceptValidEIP1559() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
FeeMarket.london(0L),
false,
Optional.of(BigInteger.ONE),
@ -397,7 +414,7 @@ public class MainnetTransactionValidatorTest {
.chainId(Optional.of(BigInteger.ONE))
.createTransaction(senderKeys);
final Optional<Long> basefee = Optional.of(150000L);
when(gasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
when(transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
.thenReturn(new GasAndAccessedState(Gas.of(50)));
assertThat(validator.validate(transaction, basefee, transactionValidationParams))
@ -408,7 +425,7 @@ public class MainnetTransactionValidatorTest {
public void shouldValidate1559TransactionWithPriceLowerThanBaseFeeForTransactionPool() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
FeeMarket.london(0L),
false,
Optional.of(BigInteger.ONE),
@ -421,7 +438,7 @@ public class MainnetTransactionValidatorTest {
.type(TransactionType.EIP1559)
.chainId(Optional.of(BigInteger.ONE))
.createTransaction(senderKeys);
when(gasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
when(transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
.thenReturn(new GasAndAccessedState(Gas.of(50)));
assertThat(
@ -433,7 +450,7 @@ public class MainnetTransactionValidatorTest {
@Test
public void goQuorumCompatibilityModeRejectNonZeroGasPrice() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty(), true);
new MainnetTransactionValidator(transactionGasCalculator, false, Optional.empty(), true);
final Transaction transaction =
new TransactionTestFixture()
.gasPrice(Wei.ONE)
@ -455,14 +472,14 @@ public class MainnetTransactionValidatorTest {
@Test
public void goQuorumCompatibilityModeSuccessZeroGasPrice() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty(), true);
new MainnetTransactionValidator(transactionGasCalculator, false, Optional.empty(), true);
final Transaction transaction =
new TransactionTestFixture()
.gasPrice(Wei.ZERO)
.chainId(Optional.empty())
.createTransaction(senderKeys);
when(gasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
when(transactionGasCalculator.transactionIntrinsicGasCostAndAccessedState(transaction))
.thenReturn(new GasAndAccessedState(Gas.of(50)));
assertThat(

@ -284,7 +284,7 @@ public class EvmToolCommand implements Runnable {
final Gas intrinsicGasCost =
protocolSpec
.getGasCalculator()
.getTransactionGasCalculator()
.transactionIntrinsicGasCostAndAccessedState(tx)
.getGas();
final Gas evmGas = gas.minus(messageFrame.getRemainingGas());

@ -76,6 +76,7 @@ public class NoRewardProtocolScheduleWrapper implements ProtocolSchedule {
original.getPrecompileContractRegistry(),
original.isSkipZeroBlockRewards(),
original.getGasCalculator(),
original.getTransactionGasCalculator(),
original.getGasLimitCalculator(),
original.getFeeMarket(),
original.getBadBlocksManager(),

Loading…
Cancel
Save