Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split Transaction Gas Calculation from EVM Calculation #2659

Merged
merged 8 commits into from
Aug 19, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
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;
Expand All @@ -34,19 +34,19 @@
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,
final PrivacyIdProvider privacyIdProvider,
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
Expand Down Expand Up @@ -81,7 +81,7 @@ protected long getGasLimit(final PrivateTransaction privateTransaction, final St
// choose the highest of the two options
return Math.max(
privateTransaction.getGasLimit(),
gasCalculator
transactionGasCalculator
.transactionIntrinsicGasCostAndAccessedState(
new Transaction.Builder()
.to(Address.PLUGIN_PRIVACY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected Map<String, JsonRpcMethod> create(
privateMarkerTransactionFactory,
nonceProvider,
privacyController,
getGasCalculator()),
getTransactionGasCalculator()),
new PrivGetEeaTransactionCount(privacyController, privacyIdProvider));
} else if (getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) {
return mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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;
Expand Down Expand Up @@ -92,6 +93,12 @@ public GasCalculator getGasCalculator() {
.getGasCalculator();
}

public TransactionGasCalculator getTransactionGasCalculator() {
return protocolSchedule
.getByBlockNumber(blockchainQueries.headBlockNumber())
.getTransactionGasCalculator();
}

@Override
protected Map<String, JsonRpcMethod> create() {
final PrivateMarkerTransactionFactory markerTransactionFactory =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ public class EthGetTransactionReceiptTest {
null,
false,
null,
null,
GasLimitCalculator.constant(),
FeeMarket.legacy(),
Optional.empty(),
Expand All @@ -133,6 +134,7 @@ public class EthGetTransactionReceiptTest {
null,
false,
null,
null,
GasLimitCalculator.constant(),
FeeMarket.legacy(),
Optional.empty(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
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;

Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void before() {
privateMarkerTransactionFactory,
address -> 0,
privacyController,
gasCalculator);
transactionGasCalculator);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -72,35 +61,6 @@ public BerlinGasCalculator() {
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();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright ConsenSys AG.
*
* 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public static ProtocolSpecBuilder tangerineWhistleDefinition(
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(TangerineWhistleGasCalculator::new)
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
transactionGasCalculator, true, chainId, quorumCompatibilityMode))
.name("ClassicTangerineWhistle");
}

Expand Down Expand Up @@ -116,9 +116,9 @@ public static ProtocolSpecBuilder defuseDifficultyBombDefinition(
quorumCompatibilityMode)
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_REMOVED)
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
transactionGasCalculator, true, chainId, quorumCompatibilityMode))
.name("DefuseDifficultyBomb");
}

Expand Down Expand Up @@ -151,20 +151,22 @@ public static ProtocolSpecBuilder atlantisDefinition(
? 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,
Expand Down Expand Up @@ -302,9 +304,9 @@ public static ProtocolSpecBuilder magnetoDefinition(
quorumCompatibilityMode)
.gasCalculator(BerlinGasCalculator::new)
.transactionValidatorBuilder(
gasCalculator ->
transactionGasCalculator ->
new MainnetTransactionValidator(
gasCalculator,
transactionGasCalculator,
true,
chainId,
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST),
Expand Down
Loading