From cf773374f44d3ee712af70bd176e7547d0282c48 Mon Sep 17 00:00:00 2001 From: thinkAfCod Date: Thu, 19 Sep 2024 17:42:33 +0800 Subject: [PATCH] add granite precompile contract --- .../besu/controller/BesuController.java | 2 +- .../besu/config/GenesisConfigOptions.java | 15 + .../besu/config/JsonGenesisConfigOptions.java | 39 +- .../besu/config/StubGenesisConfigOptions.java | 22 + .../besu/datatypes/HardforkId.java | 38 ++ .../besu/datatypes/TransactionType.java | 2 +- .../engine/EnginePreparePayloadDebug.java | 8 +- .../txselection/BlockTransactionSelector.java | 5 +- .../core/encoding/TransactionDecoder.java | 2 +- .../mainnet/AbstractBlockProcessor.java | 8 +- .../MainnetPrecompiledContractRegistries.java | 8 + .../mainnet/MainnetProtocolSpecFactory.java | 39 +- .../mainnet/MainnetProtocolSpecs.java | 448 +++++++++++++----- .../mainnet/MainnetTransactionProcessor.java | 24 +- .../mainnet/ProtocolScheduleBuilder.java | 43 +- .../MainnetParallelBlockProcessor.java | 4 +- .../evmtool/benchmarks/BenchmarkExecutor.java | 2 +- .../hyperledger/besu/evm/EvmSpecVersion.java | 7 +- .../besu/evm/fluent/EVMExecutor.java | 16 + ...Caculator.java => FjordGasCalculator.java} | 6 +- .../AltBN128PairingPrecompiledContract.java | 30 ++ .../MainnetPrecompiledContracts.java | 25 + 22 files changed, 624 insertions(+), 169 deletions(-) rename evm/src/main/java/org/hyperledger/besu/evm/gascalculator/{FjordGasCaculator.java => FjordGasCalculator.java} (91%) diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java index b20045a9a1b..8c5e34e44cb 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java @@ -387,7 +387,7 @@ public BesuControllerBuilder fromGenesisFile( // https://github.com/hyperledger/besu/issues/2897 return new TransitionBesuControllerBuilder(builder, new MergeBesuControllerBuilder()) .genesisConfigFile(genesisConfigFile) - .genesisConfigOptions(genesisConfigFile.getConfigOptions(overrides)); + .genesisConfigOptions(genesisConfigFile.withOverrides(overrides).getConfigOptions()); } } else return builder.genesisConfigFile(genesisConfigFile); diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java index 9684f04acc3..26748b19c3c 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java @@ -367,6 +367,21 @@ default boolean isConsensusMigration() { */ boolean isFjord(long headTime); + /** + * Gets granite time. + * + * @return the granite time + */ + OptionalLong getGraniteTime(); + + /** + * Returns whether a fork scheduled at granite timestamp is active at the given head timestamp. + * + * @param headTime the current head time + * @return the boolean + */ + boolean isGranite(long headTime); + /** * Gets interop time. * diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index 39d7bd26ae6..6aa46e13cd9 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -415,6 +415,23 @@ public boolean isFjord(final long headTime) { return false; } + @Override + public OptionalLong getGraniteTime() { + return getOptionalLong("granitetime"); + } + + @Override + public boolean isGranite(final long headTime) { + if (!isOptimism()) { + return false; + } + var graniteTime = getGraniteTime(); + if (graniteTime.isPresent()) { + return graniteTime.getAsLong() <= headTime; + } + return false; + } + @Override public OptionalLong getInteropTime() { return getOptionalLong("interoptime"); @@ -740,19 +757,17 @@ public List getForkBlockNumbers() { public List getForkBlockTimestamps() { Stream forkBlockTimestamps; if (this.isOptimism()) { - forkBlockTimestamps = Stream.of( - getFjordTime(), - getCanyonTime(), - getEcotoneTime()); + forkBlockTimestamps = Stream.of(getFjordTime(), getCanyonTime(), getEcotoneTime()); } else { - forkBlockTimestamps = Stream.of( - getShanghaiTime(), - getCancunTime(), - getCancunEOFTime(), - getPragueTime(), - getPragueEOFTime(), - getFutureEipsTime(), - getExperimentalEipsTime()); + forkBlockTimestamps = + Stream.of( + getShanghaiTime(), + getCancunTime(), + getCancunEOFTime(), + getPragueTime(), + getPragueEOFTime(), + getFutureEipsTime(), + getExperimentalEipsTime()); } // when adding forks add an entry to ${REPO_ROOT}/config/src/test/resources/all_forks.json diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index 40e7f3b7ba4..8129d257db2 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -58,6 +58,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable private OptionalLong canyonTime = OptionalLong.empty(); private OptionalLong ecotoneTime = OptionalLong.empty(); private OptionalLong fjordTime = OptionalLong.empty(); + private OptionalLong graniteTime = OptionalLong.empty(); private OptionalLong interopTime = OptionalLong.empty(); private OptionalLong terminalBlockNumber = OptionalLong.empty(); private Optional terminalBlockHash = Optional.empty(); @@ -332,6 +333,16 @@ public boolean isFjord(final long headTime) { return false; } + @Override + public OptionalLong getGraniteTime() { + return graniteTime; + } + + @Override + public boolean isGranite(final long headTime) { + return false; + } + @Override public OptionalLong getInteropTime() { return interopTime; @@ -830,6 +841,17 @@ public StubGenesisConfigOptions fjordTime(final long timestamp) { return this; } + /** + * Granite time. + * + * @param timestamp the timestamp + * @return the stub genesis config options + */ + public StubGenesisConfigOptions graniteTime(final long timestamp) { + graniteTime = OptionalLong.of(timestamp); + return this; + } + /** * Interop time. * diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/HardforkId.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/HardforkId.java index 73eaddb7cad..576e12f6fd2 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/HardforkId.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/HardforkId.java @@ -161,4 +161,42 @@ public String description() { return description; } } + + /** List of all Optimism hard forks. */ + enum OptimismHardforkId implements HardforkId { + /** Bedrock fork. */ + BEDROCK(true, "Bedrock"), + /** Regolith fork. */ + REGOLITH(true, "Regolith"), + /** Bedrock fork. */ + CANYON(true, "Canyon"), + /** DELTA fork. */ + DELTA(true, "Delta"), + /** Ecotone fork. */ + ECOTONE(true, "Ecotone"), + /** Fjord fork. */ + FJORD(true, "Fjord"), + /** Granite fork. */ + GRANITE(true, "Granite"), + /** Interop fork. */ + INTEROP(false, "Interop"); + + final boolean finalized; + final String description; + + OptimismHardforkId(final boolean finalized, final String description) { + this.finalized = finalized; + this.description = description; + } + + @Override + public boolean finalized() { + return finalized; + } + + @Override + public String description() { + return description; + } + } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java index 03175a50d8a..b52ac76cfc9 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java @@ -89,7 +89,7 @@ public static TransactionType of(final int serializedTypeValue) { TransactionType.EIP1559, TransactionType.BLOB, TransactionType.OPTIMISM_DEPOSIT, - TransactionType.SET_CODE + TransactionType.SET_CODE }) .filter(transactionType -> transactionType.typeValue == serializedTypeValue) .findFirst() diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java index 9f1c9de782b..6a31d80ae4f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java @@ -18,7 +18,6 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.SYNCING; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.VALID; -import org.apache.tuweni.bytes.Bytes; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.ethereum.ProtocolContext; @@ -42,6 +41,7 @@ import graphql.VisibleForTesting; import io.vertx.core.Vertx; +import org.apache.tuweni.bytes.Bytes; public class EnginePreparePayloadDebug extends ExecutionEngineJsonRpcMethod { private final MergeMiningCoordinator mergeCoordinator; @@ -108,9 +108,9 @@ Optional generatePayload(final EnginePreparePayloadParameter param.getWithdrawals().stream().map(WithdrawalParameter::toWithdrawal).collect(toList()); final List transactions = - param.getTransactions().stream() - .map(s -> Transaction.readFrom(Bytes.fromHexString(s))) - .collect(toList()); + param.getTransactions().stream() + .map(s -> Transaction.readFrom(Bytes.fromHexString(s))) + .collect(toList()); return param .getParentHash() .map(header -> protocolContext.getBlockchain().getBlockHeader(header)) diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java index c2286c75e41..604d57a7134 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java @@ -418,13 +418,14 @@ private TransactionSelectionResult handleTransactionSelected( transaction.getType(), processingResult, worldState, cumulativeGasUsed); } else { GenesisConfigOptions options = genesisConfigOptions.orElseThrow(); + Optional depositNonce = - options.isRegolith(blockSelectionContext.processableBlockHeader().getTimestamp()) + options.isRegolith(blockSelectionContext.pendingBlockHeader().getTimestamp()) ? Optional.of(nonce) : Optional.empty(); Optional canyonDepositReceiptVer = - options.isCanyon(blockSelectionContext.processableBlockHeader().getTimestamp()) + options.isCanyon(blockSelectionContext.pendingBlockHeader().getTimestamp()) ? Optional.of(1L) : Optional.empty(); receipt = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java index 4c0b8801b96..5170ebe64c2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java @@ -42,7 +42,7 @@ interface Decoder { TransactionType.BLOB, BlobTransactionDecoder::decode, TransactionType.OPTIMISM_DEPOSIT, - OptimismDepositTransactionDecoder::decode), + OptimismDepositTransactionDecoder::decode, TransactionType.SET_CODE, SetCodeTransactionDecoder::decode); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java index 8050a72f398..cd767c0e487 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java @@ -69,10 +69,10 @@ TransactionReceipt create( @FunctionalInterface public interface OpTransactionReceiptFactory { TransactionReceipt create( - TransactionType transactionType, - TransactionProcessingResult result, - WorldState worldState, - long gasUsed); + TransactionType transactionType, + TransactionProcessingResult result, + WorldState worldState, + long gasUsed); } private static final Logger LOG = LoggerFactory.getLogger(AbstractBlockProcessor.class); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetPrecompiledContractRegistries.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetPrecompiledContractRegistries.java index 90bbd1a9134..8132c47e261 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetPrecompiledContractRegistries.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetPrecompiledContractRegistries.java @@ -22,6 +22,7 @@ import static org.hyperledger.besu.evm.precompile.MainnetPrecompiledContracts.populateForFjord; import static org.hyperledger.besu.evm.precompile.MainnetPrecompiledContracts.populateForFrontier; import static org.hyperledger.besu.evm.precompile.MainnetPrecompiledContracts.populateForFutureEIPs; +import static org.hyperledger.besu.evm.precompile.MainnetPrecompiledContracts.populateForGranite; import static org.hyperledger.besu.evm.precompile.MainnetPrecompiledContracts.populateForIstanbul; import static org.hyperledger.besu.evm.precompile.MainnetPrecompiledContracts.populateForPrague; @@ -68,6 +69,13 @@ static PrecompileContractRegistry fjord( return registry; } + static PrecompileContractRegistry granite( + final PrecompiledContractConfiguration precompiledContractConfiguration) { + final PrecompileContractRegistry registry = new PrecompileContractRegistry(); + populateForGranite(registry, precompiledContractConfiguration.getGasCalculator()); + return registry; + } + static PrecompileContractRegistry prague( final PrecompiledContractConfiguration precompiledContractConfiguration) { final PrecompileContractRegistry registry = new PrecompileContractRegistry(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java index f62959ff298..304310d370d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java @@ -213,15 +213,48 @@ public ProtocolSpecBuilder cancunEOFDefinition(final GenesisConfigOptions genesi metricsSystem); } + public ProtocolSpecBuilder regolithDefinition(final GenesisConfigOptions genesisConfigOptions) { + return MainnetProtocolSpecs.regolithDefinition( + chainId, + isRevertReasonEnabled, + genesisConfigOptions, + evmConfiguration, + miningParameters, + isParallelTxProcessingEnabled, + metricsSystem); + } + + public ProtocolSpecBuilder canyonDefinition(final GenesisConfigOptions genesisConfigOptions) { + return MainnetProtocolSpecs.canyonDefinition( + chainId, + isRevertReasonEnabled, + genesisConfigOptions, + evmConfiguration, + miningParameters, + isParallelTxProcessingEnabled, + metricsSystem); + } + public ProtocolSpecBuilder fjordDefinition(final GenesisConfigOptions genesisConfigOptions) { return MainnetProtocolSpecs.fjordDefinition( chainId, - contractSizeLimit, - evmStackSize, isRevertReasonEnabled, genesisConfigOptions, evmConfiguration, - miningParameters); + miningParameters, + isParallelTxProcessingEnabled, + metricsSystem); + } + + public ProtocolSpecBuilder graniteDefinition(final GenesisConfigOptions genesisConfigOptions) { + return MainnetProtocolSpecs.graniteDefinition( + chainId, + isRevertReasonEnabled, + genesisConfigOptions, + evmConfiguration, + miningParameters, + isParallelTxProcessingEnabled, + metricsSystem); } public ProtocolSpecBuilder pragueDefinition(final GenesisConfigOptions genesisConfigOptions) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index 111b7bf356e..021d5055ce5 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -41,8 +41,8 @@ import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; import org.hyperledger.besu.ethereum.mainnet.feemarket.CancunFeeMarket; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; -import org.hyperledger.besu.ethereum.mainnet.parallelization.MainnetParallelBlockProcessor; import org.hyperledger.besu.ethereum.mainnet.feemarket.LondonFeeMarket; +import org.hyperledger.besu.ethereum.mainnet.parallelization.MainnetParallelBlockProcessor; import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor; import org.hyperledger.besu.ethereum.privacy.PrivateTransactionValidator; import org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater; @@ -52,12 +52,11 @@ import org.hyperledger.besu.evm.contractvalidation.EOFValidationCodeRule; import org.hyperledger.besu.evm.contractvalidation.MaxCodeSizeRule; import org.hyperledger.besu.evm.contractvalidation.PrefixCodeRule; -import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.BerlinGasCalculator; import org.hyperledger.besu.evm.gascalculator.ByzantiumGasCalculator; import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; -import org.hyperledger.besu.evm.gascalculator.FjordGasCaculator; +import org.hyperledger.besu.evm.gascalculator.FjordGasCalculator; import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator; import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator; import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator; @@ -82,7 +81,6 @@ import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.OptionalInt; import java.util.Set; import java.util.stream.IntStream; @@ -463,11 +461,6 @@ static ProtocolSpecBuilder londonDefinition( final BaseFeeMarket londonFeeMarket; if (genesisConfigOptions.isZeroBaseFee()) { londonFeeMarket = FeeMarket.zeroBaseFee(londonForkBlockNumber); - } else if (genesisConfigOptions.isOptimism()) { - londonFeeMarket = new LondonFeeMarket( - londonForkBlockNumber, - genesisConfigOptions.getBaseFeePerGas(), - Optional.of(genesisConfigOptions)); } else if (genesisConfigOptions.isFixedBaseFee()) { londonFeeMarket = FeeMarket.fixedBaseFee( @@ -517,9 +510,7 @@ static ProtocolSpecBuilder londonDefinition( false, evmConfiguration.evmStackSize(), feeMarket, - CoinbaseFeePriceCalculator.eip1559(), - Optional.of(genesisConfigOptions), - Optional.of(new L1CostCalculator()))) + CoinbaseFeePriceCalculator.eip1559())) .contractCreationProcessorBuilder( evm -> new ContractCreationProcessor( @@ -541,7 +532,6 @@ static ProtocolSpecBuilder londonDefinition( MainnetBlockHeaderValidator.createBaseFeeMarketOmmerValidator( (BaseFeeMarket) feeMarket)) .blockBodyValidatorBuilder(BaseFeeBlockBodyValidator::new) - .genesisConfigOptions(Optional.of(genesisConfigOptions)) .name("London"); } @@ -652,10 +642,7 @@ static ProtocolSpecBuilder shanghaiDefinition( true, evmConfiguration.evmStackSize(), feeMarket, - CoinbaseFeePriceCalculator.eip1559(), - null, - Optional.of(genesisConfigOptions), - Optional.of(new L1CostCalculator()))) + CoinbaseFeePriceCalculator.eip1559())) // Contract creation rules for EIP-3860 Limit and meter intitcode .transactionValidatorFactoryBuilder( (evm, gasLimitCalculator, feeMarket) -> @@ -668,12 +655,10 @@ static ProtocolSpecBuilder shanghaiDefinition( Set.of( TransactionType.FRONTIER, TransactionType.ACCESS_LIST, - TransactionType.EIP1559, - TransactionType.OPTIMISM_DEPOSIT), + TransactionType.EIP1559), evm.getEvmVersion().getMaxInitcodeSize())) .withdrawalsProcessor(new WithdrawalsProcessor()) .withdrawalsValidator(new WithdrawalsValidator.AllowedWithdrawals()) - .genesisConfigOptions(Optional.of(genesisConfigOptions)) .name("Shanghai"); } @@ -689,9 +674,6 @@ static ProtocolSpecBuilder cancunDefinition( final BaseFeeMarket cancunFeeMarket; if (genesisConfigOptions.isZeroBaseFee()) { cancunFeeMarket = FeeMarket.zeroBaseFee(londonForkBlockNumber); - } else if (genesisConfigOptions.isOptimism()) { - cancunFeeMarket = - new CancunFeeMarket(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas(), Optional.of(genesisConfigOptions)); } else if (genesisConfigOptions.isFixedBaseFee()) { cancunFeeMarket = FeeMarket.fixedBaseFee( @@ -739,9 +721,7 @@ static ProtocolSpecBuilder cancunDefinition( evmConfiguration.evmStackSize(), feeMarket, CoinbaseFeePriceCalculator.eip1559(), - new AuthorityProcessor(chainId), - Optional.of(genesisConfigOptions), - Optional.of(new L1CostCalculator()))) + new AuthorityProcessor(chainId))) // change to check for max blob gas per block for EIP-4844 .transactionValidatorFactoryBuilder( (evm, gasLimitCalculator, feeMarket) -> @@ -755,7 +735,6 @@ static ProtocolSpecBuilder cancunDefinition( TransactionType.FRONTIER, TransactionType.ACCESS_LIST, TransactionType.EIP1559, - TransactionType.OPTIMISM_DEPOSIT, TransactionType.BLOB), evm.getEvmVersion().getMaxInitcodeSize())) .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::cancun) @@ -785,93 +764,6 @@ static ProtocolSpecBuilder cancunEOFDefinition( return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("CancunEOF"); } - static ProtocolSpecBuilder fjordDefinition( - final Optional chainId, - final boolean enableRevertReason, - final GenesisConfigOptions genesisConfigOptions, - final EvmConfiguration evmConfiguration, - final MiningParameters miningParameters, - final boolean isParallelTxProcessingEnabled, - final MetricsSystem metricsSystem) { - - final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L); - final BaseFeeMarket cancunFeeMarket; - if (genesisConfigOptions.isZeroBaseFee()) { - cancunFeeMarket = FeeMarket.zeroBaseFee(londonForkBlockNumber); - } else if (genesisConfigOptions.isOptimism()) { - cancunFeeMarket = - new CancunFeeMarket(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas(), Optional.of(genesisConfigOptions)); - } else if (genesisConfigOptions.isFixedBaseFee()) { - cancunFeeMarket = - FeeMarket.fixedBaseFee( - londonForkBlockNumber, miningParameters.getMinTransactionGasPrice()); - } else { - cancunFeeMarket = - FeeMarket.cancun(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas()); - } - - return shanghaiDefinition( - chainId, - enableRevertReason, - genesisConfigOptions, - evmConfiguration, - miningParameters, - isParallelTxProcessingEnabled, - metricsSystem) - .feeMarket(cancunFeeMarket) - // gas calculator for EIP-4844 blob gas - .gasCalculator(FjordGasCaculator::new) - // gas limit with EIP-4844 max blob gas per block - .gasLimitCalculatorBuilder( - feeMarket -> - new CancunTargetingGasLimitCalculator( - londonForkBlockNumber, (BaseFeeMarket) feeMarket)) - // EVM changes to support EIP-1153: TSTORE and EIP-5656: MCOPY - .evmBuilder( - (gasCalculator, jdCacheConfig) -> - MainnetEVMs.fjord( - gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) - // use Cancun fee market - .transactionProcessorBuilder( - (gasCalculator, - feeMarket, - transactionValidator, - contractCreationProcessor, - messageCallProcessor) -> - new MainnetTransactionProcessor( - gasCalculator, - transactionValidator, - contractCreationProcessor, - messageCallProcessor, - true, - true, - evmConfiguration.evmStackSize(), - feeMarket, - CoinbaseFeePriceCalculator.eip1559(), - new AuthorityProcessor(chainId), - Optional.of(genesisConfigOptions), - Optional.of(new L1CostCalculator()))) - // change to check for max blob gas per block for EIP-4844 - .transactionValidatorFactoryBuilder( - (evm, gasLimitCalculator, feeMarket) -> - new TransactionValidatorFactory( - evm.getGasCalculator(), - gasLimitCalculator, - feeMarket, - true, - chainId, - Set.of( - TransactionType.FRONTIER, - TransactionType.ACCESS_LIST, - TransactionType.EIP1559, - TransactionType.OPTIMISM_DEPOSIT), - evm.getEvmVersion().getMaxInitcodeSize())) - .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::fjord) - .blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::cancunBlockHeaderValidator) - .blockHashProcessor(new CancunBlockHashProcessor()) - .name("Fjord"); - } - static ProtocolSpecBuilder pragueDefinition( final Optional chainId, final boolean enableRevertReason, @@ -1038,6 +930,334 @@ static ProtocolSpecBuilder experimentalEipsDefinition( .name("ExperimentalEips"); } + static ProtocolSpecBuilder regolithDefinition( + final Optional chainId, + final boolean enableRevertReason, + final GenesisConfigOptions genesisConfigOptions, + final EvmConfiguration evmConfiguration, + final MiningParameters miningParameters, + final boolean isParallelTxProcessingEnabled, + final MetricsSystem metricsSystem) { + final long londonForkBlockNumber = + genesisConfigOptions.getLondonBlockNumber().orElse(Long.MAX_VALUE); + final BaseFeeMarket londonFeeMarket; + if (genesisConfigOptions.isZeroBaseFee()) { + londonFeeMarket = FeeMarket.zeroBaseFee(londonForkBlockNumber); + } else if (genesisConfigOptions.isOptimism()) { + londonFeeMarket = + new LondonFeeMarket( + londonForkBlockNumber, + genesisConfigOptions.getBaseFeePerGas(), + Optional.of(genesisConfigOptions)); + } else if (genesisConfigOptions.isFixedBaseFee()) { + londonFeeMarket = + FeeMarket.fixedBaseFee( + londonForkBlockNumber, miningParameters.getMinTransactionGasPrice()); + } else { + londonFeeMarket = + FeeMarket.london(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas()); + } + return berlinDefinition( + chainId, + enableRevertReason, + evmConfiguration, + isParallelTxProcessingEnabled, + metricsSystem) + .feeMarket(londonFeeMarket) + .gasCalculator(LondonGasCalculator::new) + .gasLimitCalculatorBuilder( + feeMarket -> + new LondonTargetingGasLimitCalculator( + londonForkBlockNumber, (BaseFeeMarket) feeMarket)) + .transactionValidatorFactoryBuilder( + (evm, gasLimitCalculator, feeMarket) -> + new TransactionValidatorFactory( + evm.getGasCalculator(), + gasLimitCalculator, + feeMarket, + true, + chainId, + Set.of( + TransactionType.FRONTIER, + TransactionType.ACCESS_LIST, + TransactionType.EIP1559, + TransactionType.OPTIMISM_DEPOSIT), + Integer.MAX_VALUE)) + .transactionProcessorBuilder( + (gasCalculator, + feeMarket, + transactionValidatorFactory, + contractCreationProcessor, + messageCallProcessor) -> + new MainnetTransactionProcessor( + gasCalculator, + transactionValidatorFactory, + contractCreationProcessor, + messageCallProcessor, + true, + false, + evmConfiguration.evmStackSize(), + feeMarket, + CoinbaseFeePriceCalculator.eip1559(), + null, + Optional.of(genesisConfigOptions), + Optional.of(new L1CostCalculator()))) + .contractCreationProcessorBuilder( + evm -> + new ContractCreationProcessor( + evm, + true, + List.of(MaxCodeSizeRule.from(evm), PrefixCodeRule.of()), + 1, + SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES)) + .evmBuilder( + (gasCalculator, jdCacheConfig) -> + MainnetEVMs.london( + gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) + .difficultyCalculator(MainnetDifficultyCalculators.LONDON) + .blockHeaderValidatorBuilder( + feeMarket -> + MainnetBlockHeaderValidator.createBaseFeeMarketValidator((BaseFeeMarket) feeMarket)) + .ommerHeaderValidatorBuilder( + feeMarket -> + MainnetBlockHeaderValidator.createBaseFeeMarketOmmerValidator( + (BaseFeeMarket) feeMarket)) + .blockBodyValidatorBuilder(BaseFeeBlockBodyValidator::new) + .genesisConfigOptions(Optional.of(genesisConfigOptions)) + .name("Regolith"); + } + + static ProtocolSpecBuilder canyonDefinition( + final Optional chainId, + final boolean enableRevertReason, + final GenesisConfigOptions genesisConfigOptions, + final EvmConfiguration evmConfiguration, + final MiningParameters miningParameters, + final boolean isParallelTxProcessingEnabled, + final MetricsSystem metricsSystem) { + final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L); + final BaseFeeMarket cancunFeeMarket = + new CancunFeeMarket( + londonForkBlockNumber, + genesisConfigOptions.getBaseFeePerGas(), + Optional.of(genesisConfigOptions)); + + return shanghaiDefinition( + chainId, + enableRevertReason, + genesisConfigOptions, + evmConfiguration, + miningParameters, + isParallelTxProcessingEnabled, + metricsSystem) + .feeMarket(cancunFeeMarket) + // gas calculator for EIP-4844 blob gas + .gasCalculator(CancunGasCalculator::new) + // gas limit with EIP-4844 max blob gas per block + .gasLimitCalculatorBuilder( + feeMarket -> + new CancunTargetingGasLimitCalculator( + londonForkBlockNumber, (BaseFeeMarket) feeMarket)) + // EVM changes to support EIP-1153: TSTORE and EIP-5656: MCOPY + .evmBuilder( + (gasCalculator, jdCacheConfig) -> + MainnetEVMs.cancun( + gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) + // use Cancun fee market + .transactionProcessorBuilder( + (gasCalculator, + feeMarket, + transactionValidator, + contractCreationProcessor, + messageCallProcessor) -> + new MainnetTransactionProcessor( + gasCalculator, + transactionValidator, + contractCreationProcessor, + messageCallProcessor, + true, + true, + evmConfiguration.evmStackSize(), + feeMarket, + CoinbaseFeePriceCalculator.eip1559(), + new AuthorityProcessor(chainId), + Optional.of(genesisConfigOptions), + Optional.of(new L1CostCalculator()))) + // change to check for max blob gas per block for EIP-4844 + .transactionValidatorFactoryBuilder( + (evm, gasLimitCalculator, feeMarket) -> + new TransactionValidatorFactory( + evm.getGasCalculator(), + gasLimitCalculator, + feeMarket, + true, + chainId, + Set.of( + TransactionType.FRONTIER, + TransactionType.ACCESS_LIST, + TransactionType.EIP1559, + TransactionType.OPTIMISM_DEPOSIT), + evm.getEvmVersion().getMaxInitcodeSize())) + .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::cancun) + .blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::cancunBlockHeaderValidator) + .blockHashProcessor(new CancunBlockHashProcessor()) + .name("Canyon"); + } + + static ProtocolSpecBuilder fjordDefinition( + final Optional chainId, + final boolean enableRevertReason, + final GenesisConfigOptions genesisConfigOptions, + final EvmConfiguration evmConfiguration, + final MiningParameters miningParameters, + final boolean isParallelTxProcessingEnabled, + final MetricsSystem metricsSystem) { + + final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L); + final BaseFeeMarket cancunFeeMarket = + new CancunFeeMarket( + londonForkBlockNumber, + genesisConfigOptions.getBaseFeePerGas(), + Optional.of(genesisConfigOptions)); + + return shanghaiDefinition( + chainId, + enableRevertReason, + genesisConfigOptions, + evmConfiguration, + miningParameters, + isParallelTxProcessingEnabled, + metricsSystem) + .feeMarket(cancunFeeMarket) + // gas calculator for EIP-4844 blob gas + .gasCalculator(FjordGasCalculator::new) + // gas limit with EIP-4844 max blob gas per block + .gasLimitCalculatorBuilder( + feeMarket -> + new CancunTargetingGasLimitCalculator( + londonForkBlockNumber, (BaseFeeMarket) feeMarket)) + // EVM changes to support EIP-1153: TSTORE and EIP-5656: MCOPY + .evmBuilder( + (gasCalculator, jdCacheConfig) -> + MainnetEVMs.fjord(gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) + // use Cancun fee market + .transactionProcessorBuilder( + (gasCalculator, + feeMarket, + transactionValidator, + contractCreationProcessor, + messageCallProcessor) -> + new MainnetTransactionProcessor( + gasCalculator, + transactionValidator, + contractCreationProcessor, + messageCallProcessor, + true, + true, + evmConfiguration.evmStackSize(), + feeMarket, + CoinbaseFeePriceCalculator.eip1559(), + new AuthorityProcessor(chainId), + Optional.of(genesisConfigOptions), + Optional.of(new L1CostCalculator()))) + // change to check for max blob gas per block for EIP-4844 + .transactionValidatorFactoryBuilder( + (evm, gasLimitCalculator, feeMarket) -> + new TransactionValidatorFactory( + evm.getGasCalculator(), + gasLimitCalculator, + feeMarket, + true, + chainId, + Set.of( + TransactionType.FRONTIER, + TransactionType.ACCESS_LIST, + TransactionType.EIP1559, + TransactionType.OPTIMISM_DEPOSIT), + evm.getEvmVersion().getMaxInitcodeSize())) + .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::fjord) + .blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::cancunBlockHeaderValidator) + .blockHashProcessor(new CancunBlockHashProcessor()) + .name("Fjord"); + } + + static ProtocolSpecBuilder graniteDefinition( + final Optional chainId, + final boolean enableRevertReason, + final GenesisConfigOptions genesisConfigOptions, + final EvmConfiguration evmConfiguration, + final MiningParameters miningParameters, + final boolean isParallelTxProcessingEnabled, + final MetricsSystem metricsSystem) { + + final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L); + final BaseFeeMarket cancunFeeMarket = + new CancunFeeMarket( + londonForkBlockNumber, + genesisConfigOptions.getBaseFeePerGas(), + Optional.of(genesisConfigOptions)); + + return shanghaiDefinition( + chainId, + enableRevertReason, + genesisConfigOptions, + evmConfiguration, + miningParameters, + isParallelTxProcessingEnabled, + metricsSystem) + .feeMarket(cancunFeeMarket) + // gas calculator for EIP-4844 blob gas + .gasCalculator(FjordGasCalculator::new) + // gas limit with EIP-4844 max blob gas per block + .gasLimitCalculatorBuilder( + feeMarket -> + new CancunTargetingGasLimitCalculator( + londonForkBlockNumber, (BaseFeeMarket) feeMarket)) + // EVM changes to support EIP-1153: TSTORE and EIP-5656: MCOPY + .evmBuilder( + (gasCalculator, jdCacheConfig) -> + MainnetEVMs.fjord(gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) + // use Cancun fee market + .transactionProcessorBuilder( + (gasCalculator, + feeMarket, + transactionValidator, + contractCreationProcessor, + messageCallProcessor) -> + new MainnetTransactionProcessor( + gasCalculator, + transactionValidator, + contractCreationProcessor, + messageCallProcessor, + true, + true, + evmConfiguration.evmStackSize(), + feeMarket, + CoinbaseFeePriceCalculator.eip1559(), + new AuthorityProcessor(chainId), + Optional.of(genesisConfigOptions), + Optional.of(new L1CostCalculator()))) + // change to check for max blob gas per block for EIP-4844 + .transactionValidatorFactoryBuilder( + (evm, gasLimitCalculator, feeMarket) -> + new TransactionValidatorFactory( + evm.getGasCalculator(), + gasLimitCalculator, + feeMarket, + true, + chainId, + Set.of( + TransactionType.FRONTIER, + TransactionType.ACCESS_LIST, + TransactionType.EIP1559, + TransactionType.OPTIMISM_DEPOSIT), + evm.getEvmVersion().getMaxInitcodeSize())) + .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::granite) + .blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::cancunBlockHeaderValidator) + .blockHashProcessor(new CancunBlockHashProcessor()) + .name("Granite"); + } + private static TransactionReceipt frontierTransactionReceiptFactory( // ignored because it's always FRONTIER final TransactionType __, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 638028ae913..23a6f5a9a18 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -392,15 +392,15 @@ public TransactionProcessingResult processTransaction( final long blobGas = gasCalculator.blobGasCost(transaction.getBlobCount()); - final Wei upfrontGasCost = - transaction.getUpfrontGasCost(transactionGasPrice, blobGasPrice, blobGas); - final Wei previousBalance = sender.decrementBalance(upfrontGasCost); - LOG.trace( - "Deducted sender {} upfront gas cost {} ({} -> {})", - senderAddress, - upfrontGasCost, - previousBalance, - sender.getBalance()); + final Wei upfrontGasCost = + transaction.getUpfrontGasCost(transactionGasPrice, blobGasPrice, blobGas); + final Wei previousBalance = sender.decrementBalance(upfrontGasCost); + LOG.trace( + "Deducted sender {} upfront gas cost {} ({} -> {})", + senderAddress, + upfrontGasCost, + previousBalance, + sender.getBalance()); } var l1CostGasFee = genesisConfigOptions @@ -690,9 +690,11 @@ public TransactionProcessingResult processTransaction( if (l1CostCalculator.isEmpty()) { return; } - var l1Cost = l1CostCalculator.get().l1Cost(options, blockHeader, transaction, worldState); + var l1Cost = + l1CostCalculator.get().l1Cost(options, blockHeader, transaction, worldState); MutableAccount opL1FeeRecipient = - evmWorldUpdater.getOrCreate(Address.fromHexString("0x420000000000000000000000000000000000001A")); + evmWorldUpdater.getOrCreate( + Address.fromHexString("0x420000000000000000000000000000000000001A")); opL1FeeRecipient.incrementBalance(l1Cost); }); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java index 9c6aca8a74b..1d653915f6b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java @@ -145,7 +145,12 @@ private void initSchedule( validateForkOrdering(); - final List mileStones = createMilestones(specFactory); + final List mileStones; + if (config.isOptimism()) { + mileStones = createOpMileStones(specFactory); + } else { + mileStones = createMilestones(specFactory); + } final Map completeMileStoneList = buildFullMilestoneMap(mileStones); protocolSchedule.setMilestones(completeMileStoneList); @@ -319,8 +324,8 @@ private long validateForkOrder( private NavigableMap buildFlattenedMilestoneMap( final List mileStones) { - //Stream> milestones = createMilestones(specFactory); - //milestones.close(); + // Stream> milestones = createMilestones(specFactory); + // milestones.close(); return mileStones.stream() .collect( Collectors.toMap( @@ -339,13 +344,33 @@ private Map buildFullMilestoneMap(final List (existing, replacement) -> existing)); } + private List createOpMileStones(final MainnetProtocolSpecFactory specFactory) { + return Stream.of( + blockNumberMilestone( + HardforkId.OptimismHardforkId.BEDROCK, + config.getBedrockBlock(), + specFactory.regolithDefinition(config)), + timestampMilestone( + HardforkId.OptimismHardforkId.REGOLITH, + config.getRegolithTime(), + specFactory.regolithDefinition(config)), + timestampMilestone( + HardforkId.OptimismHardforkId.CANYON, + config.getCanyonTime(), + specFactory.canyonDefinition(config)), + timestampMilestone( + HardforkId.OptimismHardforkId.FJORD, + config.getFjordTime(), + specFactory.fjordDefinition(config)), + timestampMilestone( + HardforkId.OptimismHardforkId.GRANITE, + config.getGraniteTime(), + specFactory.graniteDefinition(config))) + .flatMap(Optional::stream) + .toList(); + } + private List createMilestones(final MainnetProtocolSpecFactory specFactory) { -// if (config.isOptimism()) { -// return Stream.of( -// blockNumberMilestone(config.getBedrockBlock(), specFactory.londonDefinition(config)), -// timestampMilestone(config.getRegolithTime(), specFactory.londonDefinition(config)), -// timestampMilestone(config.getCanyonTime(), specFactory.shanghaiDefinition(config))); -// } return Stream.of( blockNumberMilestone( HardforkId.MainnetHardforkId.FRONTIER, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java index d1f0d9c5127..a5bcf029dfb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet.parallelization; +import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -185,7 +186,8 @@ public BlockProcessor apply( final Wei blockReward, final MiningBeneficiaryCalculator miningBeneficiaryCalculator, final boolean skipZeroBlockRewards, - final ProtocolSchedule protocolSchedule) { + final ProtocolSchedule protocolSchedule, + final Optional genesisConfigOptions) { return new MainnetParallelBlockProcessor( transactionProcessor, transactionReceiptFactory, diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java index e9fd4944d68..8f7de290cec 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java @@ -141,7 +141,7 @@ public static GasCalculator gasCalculatorForFork(final String fork) { case BERLIN -> new BerlinGasCalculator(); case LONDON, PARIS -> new LondonGasCalculator(); case SHANGHAI -> new ShanghaiGasCalculator(); - case CANCUN, FJORD -> new CancunGasCalculator(); + case CANCUN, FJORD, GRANITE -> new CancunGasCalculator(); case PRAGUE -> new PragueGasCalculator(); case CANCUN_EOF, PRAGUE_EOF, diff --git a/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java b/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java index 176d13b644d..bf610efa703 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java @@ -16,6 +16,7 @@ import org.hyperledger.besu.datatypes.HardforkId; import org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId; +import org.hyperledger.besu.datatypes.HardforkId.OptimismHardforkId; import java.util.Comparator; import java.util.stream.Stream; @@ -53,8 +54,10 @@ public enum EvmSpecVersion { CANCUN(MainnetHardforkId.CANCUN, 0x6000, 0xc000, 0), /** Cancun evm spec version. */ CANCUN_EOF(MainnetHardforkId.CANCUN_EOF, 0x6000, 0xc000, 1), -// /** Fjord evm spec version. */ -// FJORD(0, true, "Fjord", "Finalized"), + /** Fjord evm spec version. */ + FJORD(OptimismHardforkId.FJORD, 0x6000, 0xc000, 0), + /** Granite evm spec version. */ + GRANITE(OptimismHardforkId.GRANITE, 0x6000, 0xc000, 0), /** Prague evm spec version. */ PRAGUE(MainnetHardforkId.PRAGUE, 0x6000, 0xc000, 0), /** PragueEOF evm spec version. */ diff --git a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java index b68953b2c56..95f0a9bc068 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java @@ -162,6 +162,7 @@ public static EVMExecutor evm( case CANCUN -> cancun(chainId, evmConfiguration); case CANCUN_EOF -> cancunEOF(chainId, evmConfiguration); case FJORD -> fjord(chainId, evmConfiguration); + case GRANITE -> granite(chainId, evmConfiguration); case PRAGUE -> prague(chainId, evmConfiguration); case PRAGUE_EOF -> pragueEOF(chainId, evmConfiguration); case OSAKA -> osaka(chainId, evmConfiguration); @@ -525,6 +526,21 @@ public static EVMExecutor fjord( return executor; } + /** + * Instantiate Granite evm executor. + * + * @param chainId the chain ID + * @param evmConfiguration the evm configuration + * @return the evm executor + */ + private static EVMExecutor granite( + final BigInteger chainId, final EvmConfiguration evmConfiguration) { + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.cancun(chainId, evmConfiguration)); + executor.precompileContractRegistry = + MainnetPrecompiledContracts.granite(executor.evm.getGasCalculator()); + return executor; + } + /** * Instantiate Prague evm executor. * diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FjordGasCaculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FjordGasCalculator.java similarity index 91% rename from evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FjordGasCaculator.java rename to evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FjordGasCalculator.java index 74dba277be3..34bcee42223 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FjordGasCaculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FjordGasCalculator.java @@ -24,12 +24,12 @@ *
  • Blob gas for EIP-4844 * */ -public class FjordGasCaculator extends CancunGasCalculator { +public class FjordGasCalculator extends CancunGasCalculator { private int maxPrecompile; /** Instantiates a new Cancun Gas Calculator. */ - public FjordGasCaculator() { + public FjordGasCalculator() { this(256); this.maxPrecompile = 256; } @@ -39,7 +39,7 @@ public FjordGasCaculator() { * * @param maxPrecompile the max precompile */ - protected FjordGasCaculator(final int maxPrecompile) { + protected FjordGasCalculator(final int maxPrecompile) { super(maxPrecompile); this.maxPrecompile = maxPrecompile; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java index e6cd892233a..3fbde941598 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java @@ -82,6 +82,16 @@ public static AltBN128PairingPrecompiledContract istanbul(final GasCalculator ga return new AltBN128PairingPrecompiledContract(gasCalculator, 34_000L, 45_000L); } + /** + * Create Granite AltBN128Pairing precompiled contract. + * + * @param gasCalculator the gas calculator + * @return the AltBN128Pairing precompiled contract + */ + public static AltBN128PairingPrecompiledContract granite(final GasCalculator gasCalculator) { + return new AltBN128PairingGranitePrecompiledContract(gasCalculator, 34_000L, 45_000L); + } + @Override public long gasRequirement(final Bytes input) { final int parameters = input.size() / PARAMETER_LENGTH; @@ -155,4 +165,24 @@ private static BigInteger extractParameter( final byte[] raw = Arrays.copyOfRange(input.toArrayUnsafe(), offset, offset + length); return new BigInteger(1, raw); } + + private static class AltBN128PairingGranitePrecompiledContract + extends AltBN128PairingPrecompiledContract { + private static final int MAX_INPUT_SIZE_GRANITE = 112687; + + private AltBN128PairingGranitePrecompiledContract( + final GasCalculator gasCalculator, final long pairingGasCost, final long baseGasCost) { + super(gasCalculator, pairingGasCost, baseGasCost); + } + + @Override + public PrecompileContractResult computePrecompile( + final Bytes input, @Nonnull final MessageFrame messageFrame) { + if (input.size() > MAX_INPUT_SIZE_GRANITE) { + return PrecompileContractResult.halt( + null, Optional.of(ExceptionalHaltReason.PRECOMPILE_ERROR)); + } + return super.computePrecompile(input, messageFrame); + } + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/MainnetPrecompiledContracts.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/MainnetPrecompiledContracts.java index 9e430b200a7..1de26564769 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/MainnetPrecompiledContracts.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/MainnetPrecompiledContracts.java @@ -163,6 +163,31 @@ static void populateForFjord( registry.put(Address.P256_VERIFY, new P256VerifyPrecompiledContract()); } + /** + * Fjord precompile contract registry. + * + * @param gasCalculator the gas calculator + * @return the precompile contract registry + */ + static PrecompileContractRegistry granite(final GasCalculator gasCalculator) { + PrecompileContractRegistry precompileContractRegistry = new PrecompileContractRegistry(); + populateForGranite(precompileContractRegistry, gasCalculator); + return precompileContractRegistry; + } + + /** + * Populate registry for Fjord. + * + * @param registry the registry + * @param gasCalculator the gas calculator + */ + static void populateForGranite( + final PrecompileContractRegistry registry, final GasCalculator gasCalculator) { + populateForFjord(registry, gasCalculator); + registry.put( + Address.ALTBN128_PAIRING, AltBN128PairingPrecompiledContract.granite(gasCalculator)); + } + /** * Prague precompile contract registry. *