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

EIP-7623 #8093

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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 @@ -84,6 +84,6 @@ protected long getGasLimit(final PrivateTransaction privateTransaction, final St
// choose the highest of the two options
return Math.max(
privateTransaction.getGasLimit(),
gasCalculator.transactionIntrinsicGasCost(Bytes.fromBase64String(pmtPayload), false));
gasCalculator.transactionIntrinsicGasCost(Bytes.fromBase64String(pmtPayload), false, 0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER;
import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION;
import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH;
import static org.hyperledger.besu.evm.internal.Words.clampedAdd;

import org.hyperledger.besu.collections.trie.BytesTrieSet;
import org.hyperledger.besu.datatypes.AccessListEntry;
Expand Down Expand Up @@ -372,22 +373,22 @@ public TransactionProcessingResult processTransaction(
warmAddressList.add(miningBeneficiary);
}

final long intrinsicGas =
gasCalculator.transactionIntrinsicGasCost(
transaction.getPayload(), transaction.isContractCreation());
final long accessListGas =
gasCalculator.accessListGasCost(accessListEntries.size(), accessListStorageCount);
final long codeDelegationGas =
gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize());
final long gasAvailable =
transaction.getGasLimit() - intrinsicGas - accessListGas - codeDelegationGas;
final long intrinsicGas =
gasCalculator.transactionIntrinsicGasCost(
transaction.getPayload(),
transaction.isContractCreation(),
clampedAdd(accessListGas, codeDelegationGas));

final long gasAvailable = transaction.getGasLimit() - intrinsicGas;
LOG.trace(
"Gas available for execution {} = {} - {} - {} - {} (limit - intrinsic - accessList - codeDelegation)",
"Gas available for execution {} = {} - {} (limit - intrinsic)",
gasAvailable,
transaction.getGasLimit(),
intrinsicGas,
accessListGas,
codeDelegationGas);
intrinsicGas);

final WorldUpdater worldUpdater = evmWorldUpdater.updater();
final ImmutableMap.Builder<String, Object> contextVariablesBuilder =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.mainnet;

import static org.hyperledger.besu.evm.account.Account.MAX_NONCE;
import static org.hyperledger.besu.evm.internal.Words.clampedAdd;

import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
Expand Down Expand Up @@ -252,11 +253,13 @@ private ValidationResult<TransactionInvalidReason> validateCostAndFee(
}
}

final long baselineGas =
clampedAdd(
transaction.getAccessList().map(gasCalculator::accessListGasCost).orElse(0L),
gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize()));
final long intrinsicGasCost =
gasCalculator.transactionIntrinsicGasCost(
transaction.getPayload(), transaction.isContractCreation())
+ (transaction.getAccessList().map(gasCalculator::accessListGasCost).orElse(0L))
+ gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize());
transaction.getPayload(), transaction.isContractCreation(), baselineGas);
if (Long.compareUnsigned(intrinsicGasCost, transaction.getGasLimit()) > 0) {
return ValidationResult.invalid(
TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@

import static org.assertj.core.api.Assertions.assertThat;

import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;

import java.util.List;
import java.util.stream.Stream;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand All @@ -36,6 +42,8 @@ public class IntrinsicGasTest {
public static Stream<Arguments> data() {
final GasCalculator frontier = new FrontierGasCalculator();
final GasCalculator istanbul = new IstanbulGasCalculator();
final GasCalculator shanghai = new ShanghaiGasCalculator();
final GasCalculator prague = new PragueGasCalculator();
return Stream.of(
// EnoughGAS
Arguments.of(
Expand Down Expand Up @@ -81,16 +89,36 @@ public static Stream<Arguments> data() {
Arguments.of(
istanbul,
21116L,
"0xf87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"));
"0xf87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"),
// CallData Gas Increase
Arguments.of(
prague,
21290L,
"0xf87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"),
// AccessList
Arguments.of(
shanghai,
25300L,
"0x01f89a018001826a4094095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f794a95e7baea6a6c7c4c2dfeb977efac326af552d87e1a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a05cbd172231fc0735e0fb994dd5b1a4939170a260b36f0427a8a80866b063b948a07c230f7f578dd61785c93361b9871c0706ebfa6d06e3f4491dc9558c5202ed36"));
}

@ParameterizedTest
@MethodSource("data")
public void validateGasCost(
final GasCalculator gasCalculator, final long expectedGas, final String txRlp) {
Transaction t = Transaction.readFrom(RLP.input(Bytes.fromHexString(txRlp)));
Bytes rlp = Bytes.fromHexString(txRlp);

// non-frontier transactions need to be opaque for parsing to work
if (rlp.get(0) > 0) {
final BytesValueRLPOutput output = new BytesValueRLPOutput();
output.writeBytes(rlp);
rlp = output.encoded();
}

Transaction t = Transaction.readFrom(RLP.input(rlp));
Assertions.assertThat(
gasCalculator.transactionIntrinsicGasCost(t.getPayload(), t.isContractCreation()))
gasCalculator.transactionIntrinsicGasCost(
t.getPayload(), t.isContractCreation(), baselineGas(gasCalculator, t)))
.isEqualTo(expectedGas);
}

Expand All @@ -100,4 +128,21 @@ void dryRunDetector() {
.withFailMessage("This test is here so gradle --dry-run executes this class")
.isTrue();
}

long baselineGas(final GasCalculator gasCalculator, final Transaction transaction) {
final List<AccessListEntry> accessListEntries = transaction.getAccessList().orElse(List.of());

int accessListStorageCount = 0;
for (final var entry : accessListEntries) {
final List<Bytes32> storageKeys = entry.storageKeys();
accessListStorageCount += storageKeys.size();
}
final long accessListGas =
gasCalculator.accessListGasCost(accessListEntries.size(), accessListStorageCount);

final long codeDelegationGas =
gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize());

return accessListGas + codeDelegationGas;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void shouldRejectTransactionIfIntrinsicGasExceedsGasLimit() {
.gasLimit(10)
.chainId(Optional.empty())
.createTransaction(senderKeys);
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(50L);
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(50L);

assertThat(
validator.validate(
Expand Down Expand Up @@ -398,7 +398,7 @@ public void shouldAcceptOnlyTransactionsInAcceptedTransactionTypes() {
transaction, Optional.empty(), Optional.empty(), transactionValidationParams))
.isEqualTo(ValidationResult.invalid(INVALID_TRANSACTION_FORMAT));

when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(0L);
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(0L);

assertThat(
eip1559Validator.validate(
Expand Down Expand Up @@ -475,7 +475,7 @@ public void shouldAcceptValidEIP1559() {
.chainId(Optional.of(BigInteger.ONE))
.createTransaction(senderKeys);
final Optional<Wei> basefee = Optional.of(Wei.of(150000L));
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(50L);
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(50L);

assertThat(
validator.validate(transaction, basefee, Optional.empty(), transactionValidationParams))
Expand All @@ -500,7 +500,7 @@ public void shouldValidate1559TransactionWithPriceLowerThanBaseFeeForTransaction
.type(TransactionType.EIP1559)
.chainId(Optional.of(BigInteger.ONE))
.createTransaction(senderKeys);
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(50L);
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(50L);

assertThat(
validator.validate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,16 +402,20 @@ public void run() {

long txGas = gas;
if (chargeIntrinsicGas) {
final long intrinsicGasCost =
protocolSpec
.getGasCalculator()
.transactionIntrinsicGasCost(tx.getPayload(), tx.isContractCreation());
txGas -= intrinsicGasCost;
final long accessListCost =
tx.getAccessList()
.map(list -> protocolSpec.getGasCalculator().accessListGasCost(list))
.orElse(0L);
txGas -= accessListCost;

final long delegateCodeCost =
protocolSpec.getGasCalculator().delegateCodeGasCost(tx.codeDelegationListSize());

final long intrinsicGasCost =
protocolSpec
.getGasCalculator()
.transactionIntrinsicGasCost(
tx.getPayload(), tx.isContractCreation(), accessListCost + delegateCodeCost);
txGas -= intrinsicGasCost;
}

final EVM evm = protocolSpec.getEvm();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ static T8nResult runTest(
gasUsed += transactionGasUsed;
long intrinsicGas =
gasCalculator.transactionIntrinsicGasCost(
transaction.getPayload(), transaction.getTo().isEmpty());
transaction.getPayload(), transaction.getTo().isEmpty(), 0);
TransactionReceipt receipt =
protocolSpec
.getTransactionReceiptFactory()
Expand Down
Loading
Loading