mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-08 21:38:15 -05:00
EIP-7840 Implementation (#8042)
Drive Cancun, Prague and Osaka target and max blobs per block from genesis config. If blobSchedule is missing, use the mainnet default values. Target is wired into appropriate *GasCalculator implementations. Max is wired into appropriate *TargetingGasLimitCalculator implementations. --------- Signed-off-by: Simon Dudley <simon.dudley@consensys.net> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
### Additions and Improvements
|
||||
- Add RPC HTTP options to specify custom truststore and its password [#7978](https://github.com/hyperledger/besu/pull/7978)
|
||||
- Retrieve all transaction receipts for a block in one request [#6646](https://github.com/hyperledger/besu/pull/6646)
|
||||
- Implement EIP-7840: Add blob schedule to config files [#8042](https://github.com/hyperledger/besu/pull/8042)
|
||||
|
||||
|
||||
### Bug fixes
|
||||
|
||||
@@ -15,6 +15,20 @@
|
||||
"terminalTotalDifficulty":0,
|
||||
"cancunTime":0,
|
||||
"pragueTime":0,
|
||||
"blobSchedule": {
|
||||
"cancun": {
|
||||
"target": 3,
|
||||
"max": 6
|
||||
},
|
||||
"prague": {
|
||||
"target": 6,
|
||||
"max": 9
|
||||
},
|
||||
"osaka": {
|
||||
"target": 9,
|
||||
"max": 12
|
||||
}
|
||||
},
|
||||
"clique": {
|
||||
"period": 5,
|
||||
"epoch": 30000
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/** The Blob Schedule config options. */
|
||||
public class BlobScheduleOptions {
|
||||
|
||||
private final ObjectNode blobScheduleOptionsConfigRoot;
|
||||
|
||||
private static final String CANCUN_KEY = "cancun";
|
||||
private static final String PRAGUE_KEY = "prague";
|
||||
private static final String OSAKA_KEY = "osaka";
|
||||
|
||||
/**
|
||||
* Instantiates a new Blob Schedule config options.
|
||||
*
|
||||
* @param blobScheduleConfigRoot the blob schedule config root
|
||||
*/
|
||||
public BlobScheduleOptions(final ObjectNode blobScheduleConfigRoot) {
|
||||
this.blobScheduleOptionsConfigRoot = blobScheduleConfigRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets cancun blob schedule.
|
||||
*
|
||||
* @return the cancun blob schedule
|
||||
*/
|
||||
public Optional<BlobSchedule> getCancun() {
|
||||
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, CANCUN_KEY).map(BlobSchedule::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets prague blob schedule.
|
||||
*
|
||||
* @return the prague blob schedule
|
||||
*/
|
||||
public Optional<BlobSchedule> getPrague() {
|
||||
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, PRAGUE_KEY).map(BlobSchedule::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets osaka blob schedule.
|
||||
*
|
||||
* @return the osaka blob schedule
|
||||
*/
|
||||
public Optional<BlobSchedule> getOsaka() {
|
||||
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, OSAKA_KEY).map(BlobSchedule::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* As map.
|
||||
*
|
||||
* @return the map
|
||||
*/
|
||||
public Map<String, Object> asMap() {
|
||||
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
|
||||
getCancun().ifPresent(bs -> builder.put(CANCUN_KEY, bs.asMap()));
|
||||
getPrague().ifPresent(bs -> builder.put(PRAGUE_KEY, bs.asMap()));
|
||||
getOsaka().ifPresent(bs -> builder.put(OSAKA_KEY, bs.asMap()));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/** The Blob schedule for a particular fork. */
|
||||
public static class BlobSchedule {
|
||||
private final int target;
|
||||
private final int max;
|
||||
|
||||
/** The constant CANCUN_DEFAULT. */
|
||||
public static final BlobSchedule CANCUN_DEFAULT = new BlobSchedule(3, 6);
|
||||
|
||||
/** The constant PRAGUE_DEFAULT. */
|
||||
public static final BlobSchedule PRAGUE_DEFAULT = new BlobSchedule(6, 9);
|
||||
|
||||
/** The constant OSAKA_DEFAULT. */
|
||||
public static final BlobSchedule OSAKA_DEFAULT = new BlobSchedule(9, 12);
|
||||
|
||||
/**
|
||||
* Instantiates a new Blob schedule.
|
||||
*
|
||||
* @param blobScheduleConfigRoot the blob schedule config root
|
||||
*/
|
||||
public BlobSchedule(final ObjectNode blobScheduleConfigRoot) {
|
||||
this.target = JsonUtil.getInt(blobScheduleConfigRoot, "target").orElseThrow();
|
||||
this.max = JsonUtil.getInt(blobScheduleConfigRoot, "max").orElseThrow();
|
||||
}
|
||||
|
||||
private BlobSchedule(final int target, final int max) {
|
||||
this.target = target;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets target.
|
||||
*
|
||||
* @return the target
|
||||
*/
|
||||
public int getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets max.
|
||||
*
|
||||
* @return the max
|
||||
*/
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* As map.
|
||||
*
|
||||
* @return the map
|
||||
*/
|
||||
Map<String, Object> asMap() {
|
||||
return Map.of("target", target, "max", max);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,4 +546,11 @@ public interface GenesisConfigOptions {
|
||||
* @return the consolidation request contract address
|
||||
*/
|
||||
Optional<Address> getConsolidationRequestContractAddress();
|
||||
|
||||
/**
|
||||
* The blob schedule is a list of hardfork names and their associated target and max blob values.
|
||||
*
|
||||
* @return the blob schedule
|
||||
*/
|
||||
Optional<BlobScheduleOptions> getBlobScheduleOptions();
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
|
||||
private static final String TRANSITIONS_CONFIG_KEY = "transitions";
|
||||
private static final String DISCOVERY_CONFIG_KEY = "discovery";
|
||||
private static final String CHECKPOINT_CONFIG_KEY = "checkpoint";
|
||||
private static final String BLOB_SCHEDULE_CONFIG_KEY = "blobschedule";
|
||||
private static final String ZERO_BASE_FEE_KEY = "zerobasefee";
|
||||
private static final String FIXED_BASE_FEE_KEY = "fixedbasefee";
|
||||
private static final String WITHDRAWAL_REQUEST_CONTRACT_ADDRESS_KEY =
|
||||
@@ -199,6 +200,12 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
|
||||
.orElse(EthashConfigOptions.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BlobScheduleOptions> getBlobScheduleOptions() {
|
||||
return JsonUtil.getObjectNode(configRoot, BLOB_SCHEDULE_CONFIG_KEY)
|
||||
.map(BlobScheduleOptions::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransitionsConfigOptions getTransitions() {
|
||||
return transitions;
|
||||
@@ -537,6 +544,10 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
|
||||
builder.put("fixedBaseFee", true);
|
||||
}
|
||||
|
||||
if (getBlobScheduleOptions().isPresent()) {
|
||||
builder.put("blobSchedule", getBlobScheduleOptions().get().asMap());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -472,6 +472,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BlobScheduleOptions> getBlobScheduleOptions() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Homestead block stub genesis config options.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
"terminalTotalDifficulty": 58750000000000000000000,
|
||||
"shanghaiTime": 1681338455,
|
||||
"cancunTime": 1710338135,
|
||||
"blobSchedule": {
|
||||
"cancun": {
|
||||
"target": 3,
|
||||
"max": 6
|
||||
},
|
||||
"prague": {
|
||||
"target": 6,
|
||||
"max": 9
|
||||
}
|
||||
},
|
||||
"ethash": {
|
||||
},
|
||||
"discovery": {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class BlobScheduleOptionsTest {
|
||||
|
||||
@Test
|
||||
public void blobScheduleIsParsed() {
|
||||
final GenesisConfig genesisConfigFile =
|
||||
GenesisConfig.fromResource("/mainnet_with_blob_schedule.json");
|
||||
final GenesisConfigOptions configOptions = genesisConfigFile.getConfigOptions();
|
||||
|
||||
assertThat(configOptions.getBlobScheduleOptions()).isNotEmpty();
|
||||
final BlobScheduleOptions blobScheduleOptions = configOptions.getBlobScheduleOptions().get();
|
||||
assertThat(blobScheduleOptions.getCancun()).isNotEmpty();
|
||||
assertThat(blobScheduleOptions.getCancun().get().getTarget()).isEqualTo(4);
|
||||
assertThat(blobScheduleOptions.getCancun().get().getMax()).isEqualTo(7);
|
||||
assertThat(blobScheduleOptions.getPrague()).isNotEmpty();
|
||||
assertThat(blobScheduleOptions.getPrague().get().getTarget()).isEqualTo(7);
|
||||
assertThat(blobScheduleOptions.getPrague().get().getMax()).isEqualTo(10);
|
||||
assertThat(blobScheduleOptions.getOsaka()).isNotEmpty();
|
||||
assertThat(blobScheduleOptions.getOsaka().get().getTarget()).isEqualTo(10);
|
||||
assertThat(blobScheduleOptions.getOsaka().get().getMax()).isEqualTo(13);
|
||||
}
|
||||
}
|
||||
@@ -408,6 +408,46 @@ class GenesisConfigOptionsTest {
|
||||
.containsValue(Address.ZERO);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void asMapIncludesBlobFeeSchedule() {
|
||||
final GenesisConfigOptions config =
|
||||
GenesisConfig.fromConfig(
|
||||
"{\n"
|
||||
+ " \"config\": {\n"
|
||||
+ " \"blobSchedule\": {\n"
|
||||
+ " \"cancun\": {\n"
|
||||
+ " \"target\": 1,\n"
|
||||
+ " \"max\": 2\n"
|
||||
+ " },\n"
|
||||
+ " \"prague\": {\n"
|
||||
+ " \"target\": 3,\n"
|
||||
+ " \"max\": 4\n"
|
||||
+ " },\n"
|
||||
+ " \"osaka\": {\n"
|
||||
+ " \"target\": 4,\n"
|
||||
+ " \"max\": 5\n"
|
||||
+ " }\n"
|
||||
+ " }\n"
|
||||
+ " }\n"
|
||||
+ "}")
|
||||
.getConfigOptions();
|
||||
|
||||
final Map<String, Object> map = config.asMap();
|
||||
assertThat(map).containsOnlyKeys("blobSchedule");
|
||||
final Map<String, Object> blobSchedule = (Map<String, Object>) map.get("blobSchedule");
|
||||
assertThat(blobSchedule).containsOnlyKeys("cancun", "prague", "osaka");
|
||||
assertThat((Map<String, Object>) blobSchedule.get("cancun"))
|
||||
.containsOnlyKeys("target", "max")
|
||||
.containsValues(1, 2);
|
||||
assertThat((Map<String, Object>) blobSchedule.get("prague"))
|
||||
.containsOnlyKeys("target", "max")
|
||||
.containsValues(3, 4);
|
||||
assertThat((Map<String, Object>) blobSchedule.get("osaka"))
|
||||
.containsOnlyKeys("target", "max")
|
||||
.containsValues(4, 5);
|
||||
}
|
||||
|
||||
private GenesisConfigOptions fromConfigOptions(final Map<String, Object> configOptions) {
|
||||
final ObjectNode rootNode = JsonUtil.createEmptyObjectNode();
|
||||
final ObjectNode options = JsonUtil.objectNodeFromMap(configOptions);
|
||||
|
||||
37
config/src/test/resources/mainnet_with_blob_schedule.json
Normal file
37
config/src/test/resources/mainnet_with_blob_schedule.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"config": {
|
||||
"chainId": 3151908,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"berlinBlock": 0,
|
||||
"londonBlock": 0,
|
||||
"preMergeForkBlock": 0,
|
||||
"terminalTotalDifficulty": 0,
|
||||
"ethash": {},
|
||||
"shanghaiTime": 0,
|
||||
"cancunTime": 0,
|
||||
"blobSchedule": {
|
||||
"cancun": {
|
||||
"target": 4,
|
||||
"max": 7
|
||||
},
|
||||
"prague": {
|
||||
"target": 7,
|
||||
"max": 10
|
||||
},
|
||||
"osaka": {
|
||||
"target": 10,
|
||||
"max": 13
|
||||
}
|
||||
},
|
||||
"depositContractAddress": "0x4242424242424242424242424242424242424242",
|
||||
"pragueTime": 1734106711,
|
||||
"osakaTime": 1734107095
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,8 @@ public class BlobSizeTransactionSelector extends AbstractTransactionSelector {
|
||||
|
||||
if (remainingBlobGas == 0) {
|
||||
LOG.atTrace()
|
||||
.setMessage("The block already contains the max number of allowed blobs")
|
||||
.setMessage(
|
||||
"The block already contains the max number of allowed blobs, pending tx: {}")
|
||||
.addArgument(evaluationContext.getPendingTransaction()::toTraceLog)
|
||||
.log();
|
||||
return TransactionSelectionResult.BLOBS_FULL;
|
||||
|
||||
@@ -17,8 +17,11 @@ package org.hyperledger.besu.ethereum;
|
||||
/** The GasLimitCalculator interface defines methods for calculating the gas limit. */
|
||||
public interface GasLimitCalculator {
|
||||
|
||||
/** The constant BLOB_GAS_LIMIT represents the gas limit for blob data. */
|
||||
long BLOB_GAS_LIMIT = 786432;
|
||||
/**
|
||||
* The constant BLOB_GAS_LIMIT represents the gas limit for blob data. Defaults to the Cancun
|
||||
* value where it was first introduced as part of EIP-4844
|
||||
*/
|
||||
long BLOB_GAS_LIMIT = 0xC0000;
|
||||
|
||||
/**
|
||||
* Calculates the next gas limit based on the current gas limit, target gas limit, and new block
|
||||
|
||||
@@ -15,17 +15,33 @@
|
||||
package org.hyperledger.besu.ethereum.mainnet;
|
||||
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
|
||||
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
||||
|
||||
public class CancunTargetingGasLimitCalculator extends LondonTargetingGasLimitCalculator {
|
||||
private static final long MAX_BLOB_GAS_PER_BLOCK = 786432L;
|
||||
|
||||
/** The mainnet default maximum number of blobs per block for Cancun */
|
||||
private static final int DEFAULT_MAX_BLOBS_PER_BLOCK_CANCUN = 6;
|
||||
|
||||
private final long maxBlobGasPerBlock;
|
||||
|
||||
public CancunTargetingGasLimitCalculator(
|
||||
final long londonForkBlock, final BaseFeeMarket feeMarket) {
|
||||
this(londonForkBlock, feeMarket, DEFAULT_MAX_BLOBS_PER_BLOCK_CANCUN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using Cancun mainnet default of 6 blobs for maxBlobsPerBlock: getBlobGasPerBlob() * 6 blobs =
|
||||
* 131072 * 6 = 786432 = 0xC0000
|
||||
*/
|
||||
public CancunTargetingGasLimitCalculator(
|
||||
final long londonForkBlock, final BaseFeeMarket feeMarket, final int maxBlobsPerBlock) {
|
||||
super(londonForkBlock, feeMarket);
|
||||
final CancunGasCalculator cancunGasCalculator = new CancunGasCalculator();
|
||||
this.maxBlobGasPerBlock = cancunGasCalculator.getBlobGasPerBlob() * maxBlobsPerBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long currentBlobGasLimit() {
|
||||
return MAX_BLOB_GAS_PER_BLOCK;
|
||||
return maxBlobGasPerBlock;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,10 @@ import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.NoNonceRule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ProofOfWorkValidationRule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampBoundedByFutureParameter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent;
|
||||
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
@@ -197,8 +198,9 @@ public final class MainnetBlockHeaderValidator {
|
||||
.addRule(new IncrementalTimestampRule());
|
||||
}
|
||||
|
||||
public static BlockHeaderValidator.Builder cancunBlockHeaderValidator(final FeeMarket feeMarket) {
|
||||
public static BlockHeaderValidator.Builder blobAwareBlockHeaderValidator(
|
||||
final FeeMarket feeMarket, final Supplier<GasCalculator> gasCalculator) {
|
||||
return mergeBlockHeaderValidator(feeMarket)
|
||||
.addRule(new BlobGasValidationRule(new CancunGasCalculator()));
|
||||
.addRule(new BlobGasValidationRule(gasCalculator.get()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.mainnet;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.MainnetRequestsProcessor.pragueRequestsProcessors;
|
||||
|
||||
import org.hyperledger.besu.config.BlobScheduleOptions;
|
||||
import org.hyperledger.besu.config.GenesisConfigOptions;
|
||||
import org.hyperledger.besu.config.PowAlgorithm;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm;
|
||||
@@ -56,6 +57,7 @@ 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.FrontierGasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
||||
@@ -683,6 +685,15 @@ public abstract class MainnetProtocolSpecs {
|
||||
FeeMarket.cancun(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas());
|
||||
}
|
||||
|
||||
final var cancunBlobSchedule =
|
||||
genesisConfigOptions
|
||||
.getBlobScheduleOptions()
|
||||
.flatMap(BlobScheduleOptions::getCancun)
|
||||
.orElse(BlobScheduleOptions.BlobSchedule.CANCUN_DEFAULT);
|
||||
|
||||
final java.util.function.Supplier<GasCalculator> cancunGasCalcSupplier =
|
||||
() -> new CancunGasCalculator(cancunBlobSchedule.getTarget());
|
||||
|
||||
return shanghaiDefinition(
|
||||
chainId,
|
||||
enableRevertReason,
|
||||
@@ -693,12 +704,12 @@ public abstract class MainnetProtocolSpecs {
|
||||
metricsSystem)
|
||||
.feeMarket(cancunFeeMarket)
|
||||
// gas calculator for EIP-4844 blob gas
|
||||
.gasCalculator(CancunGasCalculator::new)
|
||||
.gasCalculator(cancunGasCalcSupplier)
|
||||
// gas limit with EIP-4844 max blob gas per block
|
||||
.gasLimitCalculatorBuilder(
|
||||
feeMarket ->
|
||||
new CancunTargetingGasLimitCalculator(
|
||||
londonForkBlockNumber, (BaseFeeMarket) feeMarket))
|
||||
londonForkBlockNumber, (BaseFeeMarket) feeMarket, cancunBlobSchedule.getMax()))
|
||||
// EVM changes to support EIP-1153: TSTORE and EIP-5656: MCOPY
|
||||
.evmBuilder(
|
||||
(gasCalculator, jdCacheConfig) ->
|
||||
@@ -739,7 +750,10 @@ public abstract class MainnetProtocolSpecs {
|
||||
TransactionType.BLOB),
|
||||
evm.getMaxInitcodeSize()))
|
||||
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::cancun)
|
||||
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::cancunBlockHeaderValidator)
|
||||
.blockHeaderValidatorBuilder(
|
||||
fm ->
|
||||
MainnetBlockHeaderValidator.blobAwareBlockHeaderValidator(
|
||||
fm, cancunGasCalcSupplier))
|
||||
.blockHashProcessor(new CancunBlockHashProcessor())
|
||||
.name("Cancun");
|
||||
}
|
||||
@@ -753,6 +767,12 @@ public abstract class MainnetProtocolSpecs {
|
||||
final boolean isParallelTxProcessingEnabled,
|
||||
final MetricsSystem metricsSystem) {
|
||||
|
||||
final var cancunBlobSchedule =
|
||||
genesisConfigOptions
|
||||
.getBlobScheduleOptions()
|
||||
.flatMap(BlobScheduleOptions::getCancun)
|
||||
.orElse(BlobScheduleOptions.BlobSchedule.CANCUN_DEFAULT);
|
||||
|
||||
ProtocolSpecBuilder protocolSpecBuilder =
|
||||
cancunDefinition(
|
||||
chainId,
|
||||
@@ -762,7 +782,14 @@ public abstract class MainnetProtocolSpecs {
|
||||
miningConfiguration,
|
||||
isParallelTxProcessingEnabled,
|
||||
metricsSystem);
|
||||
return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("CancunEOF");
|
||||
return addEOF(
|
||||
genesisConfigOptions,
|
||||
chainId,
|
||||
evmConfiguration,
|
||||
protocolSpecBuilder,
|
||||
cancunBlobSchedule.getTarget(),
|
||||
cancunBlobSchedule.getMax())
|
||||
.name("CancunEOF");
|
||||
}
|
||||
|
||||
static ProtocolSpecBuilder pragueDefinition(
|
||||
@@ -777,6 +804,17 @@ public abstract class MainnetProtocolSpecs {
|
||||
RequestContractAddresses requestContractAddresses =
|
||||
RequestContractAddresses.fromGenesis(genesisConfigOptions);
|
||||
|
||||
final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L);
|
||||
final var pragueBlobSchedule =
|
||||
genesisConfigOptions
|
||||
.getBlobScheduleOptions()
|
||||
.flatMap(BlobScheduleOptions::getPrague)
|
||||
.orElse(BlobScheduleOptions.BlobSchedule.PRAGUE_DEFAULT);
|
||||
|
||||
// EIP-3074 AUTH and AUTHCALL gas | EIP-7840 Blob schedule | EIP-7691 6/9 blob increase
|
||||
final java.util.function.Supplier<GasCalculator> pragueGasCalcSupplier =
|
||||
() -> new PragueGasCalculator(pragueBlobSchedule.getTarget());
|
||||
|
||||
return cancunDefinition(
|
||||
chainId,
|
||||
enableRevertReason,
|
||||
@@ -785,8 +823,12 @@ public abstract class MainnetProtocolSpecs {
|
||||
miningConfiguration,
|
||||
isParallelTxProcessingEnabled,
|
||||
metricsSystem)
|
||||
// EIP-3074 AUTH and AUTCALL gas
|
||||
.gasCalculator(PragueGasCalculator::new)
|
||||
.gasCalculator(pragueGasCalcSupplier)
|
||||
// EIP-7840 Blob schedule | EIP-7691 6/9 blob increase
|
||||
.gasLimitCalculatorBuilder(
|
||||
feeMarket ->
|
||||
new PragueTargetingGasLimitCalculator(
|
||||
londonForkBlockNumber, (BaseFeeMarket) feeMarket, pragueBlobSchedule.getMax()))
|
||||
// EIP-3074 AUTH and AUTHCALL
|
||||
.evmBuilder(
|
||||
(gasCalculator, jdCacheConfig) ->
|
||||
@@ -818,6 +860,14 @@ public abstract class MainnetProtocolSpecs {
|
||||
TransactionType.DELEGATE_CODE),
|
||||
evm.getMaxInitcodeSize()))
|
||||
|
||||
// TODO SLD EIP-7840 Can we dynamically wire in the appropriate GasCalculator instead of
|
||||
// overriding
|
||||
// blockHeaderValidatorBuilder every time the GasCalculator changes?
|
||||
// EIP-7840 blob schedule | EIP-7691 6/9 blob increase
|
||||
.blockHeaderValidatorBuilder(
|
||||
fm ->
|
||||
MainnetBlockHeaderValidator.blobAwareBlockHeaderValidator(
|
||||
fm, pragueGasCalcSupplier))
|
||||
// EIP-2935 Blockhash processor
|
||||
.blockHashProcessor(new PragueBlockHashProcessor())
|
||||
.name("Prague");
|
||||
@@ -832,6 +882,12 @@ public abstract class MainnetProtocolSpecs {
|
||||
final boolean isParallelTxProcessingEnabled,
|
||||
final MetricsSystem metricsSystem) {
|
||||
|
||||
final var osakaBlobSchedule =
|
||||
genesisConfigOptions
|
||||
.getBlobScheduleOptions()
|
||||
.flatMap(BlobScheduleOptions::getOsaka)
|
||||
.orElse(BlobScheduleOptions.BlobSchedule.OSAKA_DEFAULT);
|
||||
|
||||
ProtocolSpecBuilder protocolSpecBuilder =
|
||||
pragueDefinition(
|
||||
chainId,
|
||||
@@ -841,16 +897,34 @@ public abstract class MainnetProtocolSpecs {
|
||||
miningConfiguration,
|
||||
isParallelTxProcessingEnabled,
|
||||
metricsSystem);
|
||||
return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("Osaka");
|
||||
return addEOF(
|
||||
genesisConfigOptions,
|
||||
chainId,
|
||||
evmConfiguration,
|
||||
protocolSpecBuilder,
|
||||
osakaBlobSchedule.getTarget(),
|
||||
osakaBlobSchedule.getMax())
|
||||
.name("Osaka");
|
||||
}
|
||||
|
||||
private static ProtocolSpecBuilder addEOF(
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final Optional<BigInteger> chainId,
|
||||
final EvmConfiguration evmConfiguration,
|
||||
final ProtocolSpecBuilder protocolSpecBuilder) {
|
||||
final ProtocolSpecBuilder protocolSpecBuilder,
|
||||
final int targetBlobsPerBlock,
|
||||
final int maxBlobsPerBlock) {
|
||||
|
||||
final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L);
|
||||
final java.util.function.Supplier<GasCalculator> osakaGasCalcSupplier =
|
||||
() -> new OsakaGasCalculator(targetBlobsPerBlock);
|
||||
return protocolSpecBuilder
|
||||
// EIP-7692 EOF v1 Gas calculator
|
||||
.gasCalculator(OsakaGasCalculator::new)
|
||||
.gasCalculator(osakaGasCalcSupplier)
|
||||
.gasLimitCalculatorBuilder(
|
||||
feeMarket ->
|
||||
new OsakaTargetingGasLimitCalculator(
|
||||
londonForkBlockNumber, (BaseFeeMarket) feeMarket, maxBlobsPerBlock))
|
||||
// EIP-7692 EOF v1 EVM and opcodes
|
||||
.evmBuilder(
|
||||
(gasCalculator, jdCacheConfig) ->
|
||||
@@ -863,7 +937,11 @@ public abstract class MainnetProtocolSpecs {
|
||||
true,
|
||||
List.of(MaxCodeSizeRule.from(evm), EOFValidationCodeRule.from(evm)),
|
||||
1,
|
||||
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES));
|
||||
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
|
||||
.blockHeaderValidatorBuilder(
|
||||
fm ->
|
||||
MainnetBlockHeaderValidator.blobAwareBlockHeaderValidator(
|
||||
fm, osakaGasCalcSupplier));
|
||||
}
|
||||
|
||||
static ProtocolSpecBuilder futureEipsDefinition(
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.mainnet.feemarket.BaseFeeMarket;
|
||||
|
||||
public class OsakaTargetingGasLimitCalculator extends PragueTargetingGasLimitCalculator {
|
||||
|
||||
/** The mainnet default maximum number of blobs per block for Osaka */
|
||||
private static final int DEFAULT_MAX_BLOBS_PER_BLOCK_OSAKA = 12;
|
||||
|
||||
public OsakaTargetingGasLimitCalculator(
|
||||
final long londonForkBlock, final BaseFeeMarket feeMarket) {
|
||||
super(londonForkBlock, feeMarket, DEFAULT_MAX_BLOBS_PER_BLOCK_OSAKA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using Osaka mainnet default of 12 blobs for maxBlobsPerBlock:
|
||||
* CancunGasCalculator.BLOB_GAS_PER_BLOB * 12 blobs = 131072 * 12 = 1572864 = 0x180000
|
||||
*/
|
||||
public OsakaTargetingGasLimitCalculator(
|
||||
final long londonForkBlock, final BaseFeeMarket feeMarket, final int maxBlobsPerBlock) {
|
||||
super(londonForkBlock, feeMarket, maxBlobsPerBlock);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.mainnet.feemarket.BaseFeeMarket;
|
||||
|
||||
public class PragueTargetingGasLimitCalculator extends CancunTargetingGasLimitCalculator {
|
||||
|
||||
/** The mainnet default maximum number of blobs per block for Prague */
|
||||
private static final int DEFAULT_MAX_BLOBS_PER_BLOCK_PRAGUE = 9;
|
||||
|
||||
public PragueTargetingGasLimitCalculator(
|
||||
final long londonForkBlock, final BaseFeeMarket feeMarket) {
|
||||
super(londonForkBlock, feeMarket, DEFAULT_MAX_BLOBS_PER_BLOCK_PRAGUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using Prague mainnet default of 9 blobs for maxBlobsPerBlock:
|
||||
* CancunGasCalculator.BLOB_GAS_PER_BLOB * 9 blobs = 131072 * 9 = 1179648 = 0x120000
|
||||
*/
|
||||
public PragueTargetingGasLimitCalculator(
|
||||
final long londonForkBlock, final BaseFeeMarket feeMarket, final int maxBlobsPerBlock) {
|
||||
super(londonForkBlock, feeMarket, maxBlobsPerBlock);
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,7 @@ public class ExcessBlobGasCalculator {
|
||||
.getGasCalculator()
|
||||
.computeExcessBlobGas(
|
||||
parentHeader.getExcessBlobGas().map(BlobGas::toLong).orElse(0L),
|
||||
parentHeader.getBlobGasUsed().orElse(0L),
|
||||
parentHeader.getTargetBlobsPerBlock());
|
||||
parentHeader.getBlobGasUsed().orElse(0L));
|
||||
return BlobGas.of(headerExcess);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,7 @@ public class BlobGasValidationRule implements DetachedBlockHeaderValidationRule
|
||||
long parentBlobGasUsed = parent.getBlobGasUsed().orElse(0L);
|
||||
|
||||
long calculatedExcessBlobGas =
|
||||
gasCalculator.computeExcessBlobGas(
|
||||
parentExcessBlobGas, parentBlobGasUsed, parent.getTargetBlobsPerBlock());
|
||||
gasCalculator.computeExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed);
|
||||
|
||||
if (headerExcessBlobGas != calculatedExcessBlobGas) {
|
||||
LOG.info(
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright contributors to 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 org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CancunTargetingGasLimitCalculatorTest {
|
||||
|
||||
@Test
|
||||
void currentBlobGasLimitIs6Blobs() {
|
||||
var cancunTargetingGasLimitCalculator =
|
||||
new CancunTargetingGasLimitCalculator(0L, FeeMarket.cancun(0L, Optional.empty()));
|
||||
assertThat(cancunTargetingGasLimitCalculator.currentBlobGasLimit()).isEqualTo(0xC0000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright contributors to 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 org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PragueTargetingGasLimitCalculatorTest {
|
||||
|
||||
@Test
|
||||
void currentBlobGasLimitIs9BlobsByDefault() {
|
||||
var pragueTargetingGasLimitCalculator =
|
||||
new PragueTargetingGasLimitCalculator(0L, FeeMarket.cancun(0L, Optional.empty()));
|
||||
assertThat(pragueTargetingGasLimitCalculator.currentBlobGasLimit()).isEqualTo(0x120000);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
||||
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -88,16 +87,17 @@ public class BlobGasValidationRuleTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prague EIP-7742 - Tests that the header blob gas matches the calculated blob gas and passes
|
||||
* Prague EIP-7840 - Tests that the header blob gas matches the calculated blob gas and passes
|
||||
* validation.
|
||||
*/
|
||||
@Test
|
||||
public void validateHeader_BlobGasMatchesCalculated_SuccessValidation_Prague_Target3() {
|
||||
public void validateHeader_BlobGasMatchesCalculated_SuccessValidation_Prague() {
|
||||
long target = pragueGasCalculator.getTargetBlobGasPerBlock();
|
||||
|
||||
// Create parent header
|
||||
final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture();
|
||||
parentBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
parentBuilder.blobGasUsed(pragueGasCalculator.blobGasCost(3));
|
||||
parentBuilder.targetBlobsPerBlock(UInt64.valueOf(3));
|
||||
parentBuilder.blobGasUsed(target);
|
||||
final BlockHeader parentHeader = parentBuilder.buildHeader();
|
||||
|
||||
// Create block header with matching excessBlobGas
|
||||
@@ -109,23 +109,23 @@ public class BlobGasValidationRuleTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prague EIP-7742 - Tests that the header blob gas matches the calculated blob gas and passes
|
||||
* validation.
|
||||
* Prague EIP-7840 - Tests that the header blob gas is different from the calculated blob gas and
|
||||
* fails validation.
|
||||
*/
|
||||
@Test
|
||||
public void validateHeader_BlobGasMatchesCalculated_SuccessValidation_Prague_Target4() {
|
||||
public void validateHeader_BlobGasDifferentFromCalculated_FailsValidation_Prague() {
|
||||
long target = pragueGasCalculator.getTargetBlobGasPerBlock();
|
||||
|
||||
// Create parent header
|
||||
final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture();
|
||||
parentBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
parentBuilder.blobGasUsed(pragueGasCalculator.blobGasCost(4));
|
||||
parentBuilder.targetBlobsPerBlock(UInt64.valueOf(4));
|
||||
parentBuilder.blobGasUsed(target);
|
||||
final BlockHeader parentHeader = parentBuilder.buildHeader();
|
||||
|
||||
// Create block header with matching excessBlobGas
|
||||
// Create block header with different excessBlobGas
|
||||
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
|
||||
headerBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
final BlockHeader header = headerBuilder.buildHeader();
|
||||
|
||||
assertThat(pragueBlobGasValidationRule.validate(header, parentHeader)).isTrue();
|
||||
assertThat(pragueBlobGasValidationRule.validate(header, parentHeader)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,18 +26,35 @@ import static org.hyperledger.besu.datatypes.Address.KZG_POINT_EVAL;
|
||||
*/
|
||||
public class CancunGasCalculator extends ShanghaiGasCalculator {
|
||||
|
||||
/** The default mainnet target blobs per block for Cancun */
|
||||
private static final int DEFAULT_TARGET_BLOBS_PER_BLOCK_CANCUN = 3;
|
||||
|
||||
/** this.getBlobGasPerBlob() * 3 blobs = 131072 * 6 = 393216 = 0x60000 */
|
||||
private final long targetBlobGasPerBlock;
|
||||
|
||||
/** Instantiates a new Cancun Gas Calculator. */
|
||||
public CancunGasCalculator() {
|
||||
this(KZG_POINT_EVAL.toArrayUnsafe()[19]);
|
||||
this(KZG_POINT_EVAL.toArrayUnsafe()[19], DEFAULT_TARGET_BLOBS_PER_BLOCK_CANCUN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Cancun Gas Calculator
|
||||
*
|
||||
* @param targetBlobsPerBlock the target blobs per block
|
||||
*/
|
||||
public CancunGasCalculator(final int targetBlobsPerBlock) {
|
||||
this(KZG_POINT_EVAL.toArrayUnsafe()[19], targetBlobsPerBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Cancun Gas Calculator
|
||||
*
|
||||
* @param maxPrecompile the max precompile
|
||||
* @param targetBlobsPerBlock the target blobs per block
|
||||
*/
|
||||
protected CancunGasCalculator(final int maxPrecompile) {
|
||||
protected CancunGasCalculator(final int maxPrecompile, final int targetBlobsPerBlock) {
|
||||
super(maxPrecompile);
|
||||
this.targetBlobGasPerBlock = getBlobGasPerBlob() * targetBlobsPerBlock;
|
||||
}
|
||||
|
||||
private static final long TLOAD_GAS = WARM_STORAGE_READ_COST;
|
||||
@@ -49,9 +66,6 @@ public class CancunGasCalculator extends ShanghaiGasCalculator {
|
||||
*/
|
||||
private static final long BLOB_GAS_PER_BLOB = 1 << 17;
|
||||
|
||||
/** The target blob gas per block. */
|
||||
static final long TARGET_BLOB_GAS_PER_BLOCK = 0x60000;
|
||||
|
||||
// EIP-1153
|
||||
@Override
|
||||
public long getTransientLoadOperationGasCost() {
|
||||
@@ -79,6 +93,15 @@ public class CancunGasCalculator extends ShanghaiGasCalculator {
|
||||
* @return The target blob gas per block.
|
||||
*/
|
||||
public long getTargetBlobGasPerBlock() {
|
||||
return TARGET_BLOB_GAS_PER_BLOCK;
|
||||
return targetBlobGasPerBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long computeExcessBlobGas(final long parentExcessBlobGas, final long parentBlobGasUsed) {
|
||||
final long currentExcessBlobGas = parentExcessBlobGas + parentBlobGasUsed;
|
||||
if (currentExcessBlobGas < targetBlobGasPerBlock) {
|
||||
return 0L;
|
||||
}
|
||||
return currentExcessBlobGas - targetBlobGasPerBlock;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +40,10 @@ import org.hyperledger.besu.evm.precompile.SHA256PrecompiledContract;
|
||||
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
|
||||
/**
|
||||
* Provides various gas cost lookups and calculations used during block processing.
|
||||
@@ -636,30 +634,14 @@ public interface GasCalculator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the new value for the excess blob gas, given the parent value, the parent blob gas used
|
||||
* and the parent target blobs per block, if present. Used from Cancun onwards. Presence of
|
||||
* parentTargetBlobsPerBlock implies EIP-7442/Prague enabled. Default to Cancun constant target
|
||||
* gas value if parentTargetBlobsPerBlock is not present.
|
||||
* Compute the new value for the excess blob gas, given the parent value and the blob gas used
|
||||
*
|
||||
* @param parentExcessBlobGas excess blob gas from the parent
|
||||
* @param parentBlobGasUsed blob gas used from the parent
|
||||
* @param parentTargetBlobsPerBlock the optional target blobs per block from the parent
|
||||
* @param blobGasUsed blob gas used
|
||||
* @return the new excess blob gas value
|
||||
*/
|
||||
default long computeExcessBlobGas(
|
||||
final long parentExcessBlobGas,
|
||||
final long parentBlobGasUsed,
|
||||
final Optional<UInt64> parentTargetBlobsPerBlock) {
|
||||
final long parentTargetBlobGas =
|
||||
parentTargetBlobsPerBlock
|
||||
.map(blobCount -> blobGasCost(blobCount.toLong()))
|
||||
.orElse(CancunGasCalculator.TARGET_BLOB_GAS_PER_BLOCK);
|
||||
final long currentExcessBlobGas = parentExcessBlobGas + parentBlobGasUsed;
|
||||
|
||||
if (currentExcessBlobGas < parentTargetBlobGas) {
|
||||
return 0L;
|
||||
}
|
||||
return currentExcessBlobGas - parentTargetBlobGas;
|
||||
default long computeExcessBlobGas(final long parentExcessBlobGas, final long blobGasUsed) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,10 +17,9 @@ package org.hyperledger.besu.evm.gascalculator;
|
||||
import static org.hyperledger.besu.datatypes.Address.BLS12_MAP_FP2_TO_G2;
|
||||
|
||||
/**
|
||||
* Gas Calculator for Prague
|
||||
* Gas Calculator for Osaka
|
||||
*
|
||||
* <p>Placeholder for new gas schedule items. If Prague finalzies without changes this can be
|
||||
* removed
|
||||
* <p>Placeholder for new gas schedule items. If Osaka finalzies without changes this can be removed
|
||||
*
|
||||
* <UL>
|
||||
* <LI>TBD
|
||||
@@ -28,21 +27,34 @@ import static org.hyperledger.besu.datatypes.Address.BLS12_MAP_FP2_TO_G2;
|
||||
*/
|
||||
public class OsakaGasCalculator extends PragueGasCalculator {
|
||||
|
||||
/** The default mainnet target blobs per block for Osaka */
|
||||
private static final int DEFAULT_TARGET_BLOBS_PER_BLOCK_OSAKA = 9;
|
||||
|
||||
static final long MIN_RETAINED_GAS = 5_000;
|
||||
static final long MIN_CALLEE_GAS = 2300;
|
||||
|
||||
/** Instantiates a new Prague Gas Calculator. */
|
||||
/** Instantiates a new Osaka Gas Calculator. */
|
||||
public OsakaGasCalculator() {
|
||||
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19]);
|
||||
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19], DEFAULT_TARGET_BLOBS_PER_BLOCK_OSAKA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Prague Gas Calculator
|
||||
* Instantiates a new Osaka Gas Calculator
|
||||
*
|
||||
* @param targetBlobsPerBlock the target blobs per block
|
||||
*/
|
||||
public OsakaGasCalculator(final int targetBlobsPerBlock) {
|
||||
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19], targetBlobsPerBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Osaka Gas Calculator
|
||||
*
|
||||
* @param maxPrecompile the max precompile
|
||||
* @param targetBlobsPerBlock the target blobs per block
|
||||
*/
|
||||
protected OsakaGasCalculator(final int maxPrecompile) {
|
||||
super(maxPrecompile);
|
||||
protected OsakaGasCalculator(final int maxPrecompile, final int targetBlobsPerBlock) {
|
||||
super(maxPrecompile, targetBlobsPerBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,18 +28,34 @@ import org.hyperledger.besu.datatypes.CodeDelegation;
|
||||
public class PragueGasCalculator extends CancunGasCalculator {
|
||||
final long existingAccountGasRefund;
|
||||
|
||||
/**
|
||||
* The default mainnet target blobs per block for Prague getBlobGasPerBlob() * 6 blobs = 131072 *
|
||||
* 6 = 786432 = 0xC0000
|
||||
*/
|
||||
private static final int DEFAULT_TARGET_BLOBS_PER_BLOCK_PRAGUE = 6;
|
||||
|
||||
/** Instantiates a new Prague Gas Calculator. */
|
||||
public PragueGasCalculator() {
|
||||
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19]);
|
||||
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19], DEFAULT_TARGET_BLOBS_PER_BLOCK_PRAGUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Prague Gas Calculator
|
||||
*
|
||||
* @param targetBlobsPerBlock the target blobs per block
|
||||
*/
|
||||
public PragueGasCalculator(final int targetBlobsPerBlock) {
|
||||
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19], targetBlobsPerBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Prague Gas Calculator
|
||||
*
|
||||
* @param maxPrecompile the max precompile
|
||||
* @param targetBlobsPerBlock the target blobs per block
|
||||
*/
|
||||
protected PragueGasCalculator(final int maxPrecompile) {
|
||||
super(maxPrecompile);
|
||||
protected PragueGasCalculator(final int maxPrecompile, final int targetBlobsPerBlock) {
|
||||
super(maxPrecompile, targetBlobsPerBlock);
|
||||
this.existingAccountGasRefund = newAccountGasCost() - CodeDelegation.PER_AUTH_BASE_COST;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.hyperledger.besu.evm.gascalculator;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
@@ -28,6 +27,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class CancunGasCalculatorTest {
|
||||
|
||||
private static final long TARGET_BLOB_GAS_PER_BLOCK_CANCUN = 0x60000;
|
||||
private final CancunGasCalculator cancunGasCalculator = new CancunGasCalculator();
|
||||
|
||||
@ParameterizedTest(name = "{index} - parent gas {0}, used gas {1}, new excess {2}")
|
||||
@@ -35,13 +35,12 @@ public class CancunGasCalculatorTest {
|
||||
public void shouldCalculateExcessBlobGasCorrectly(
|
||||
final long parentExcess, final long used, final long expected) {
|
||||
final long usedBlobGas = cancunGasCalculator.blobGasCost(used);
|
||||
assertThat(
|
||||
cancunGasCalculator.computeExcessBlobGas(parentExcess, usedBlobGas, Optional.empty()))
|
||||
assertThat(cancunGasCalculator.computeExcessBlobGas(parentExcess, usedBlobGas))
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
Iterable<Arguments> blobGasses() {
|
||||
long targetGasPerBlock = CancunGasCalculator.TARGET_BLOB_GAS_PER_BLOCK;
|
||||
long targetGasPerBlock = TARGET_BLOB_GAS_PER_BLOCK_CANCUN;
|
||||
return List.of(
|
||||
Arguments.of(0L, 0L, 0L),
|
||||
Arguments.of(targetGasPerBlock, 0L, 0L),
|
||||
|
||||
@@ -18,10 +18,20 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class OsakaGasCalculatorTest {
|
||||
|
||||
private static final long TARGET_BLOB_GAS_PER_BLOCK_OSAKA = 0x120000;
|
||||
private final OsakaGasCalculator osakaGasCalculator = new OsakaGasCalculator();
|
||||
|
||||
@Test
|
||||
void testPrecompileSize() {
|
||||
OsakaGasCalculator subject = new OsakaGasCalculator();
|
||||
@@ -32,10 +42,35 @@ class OsakaGasCalculatorTest {
|
||||
@Test
|
||||
void testNewConstants() {
|
||||
CancunGasCalculator cancunGas = new CancunGasCalculator();
|
||||
OsakaGasCalculator praugeGasCalculator = new OsakaGasCalculator();
|
||||
assertThat(osakaGasCalculator.getMinCalleeGas()).isGreaterThan(cancunGas.getMinCalleeGas());
|
||||
assertThat(osakaGasCalculator.getMinRetainedGas()).isGreaterThan(cancunGas.getMinRetainedGas());
|
||||
}
|
||||
|
||||
assertThat(praugeGasCalculator.getMinCalleeGas()).isGreaterThan(cancunGas.getMinCalleeGas());
|
||||
assertThat(praugeGasCalculator.getMinRetainedGas())
|
||||
.isGreaterThan(cancunGas.getMinRetainedGas());
|
||||
@ParameterizedTest(
|
||||
name = "{index} - parent gas {0}, used gas {1}, blob target {2} new excess {3}")
|
||||
@MethodSource("blobGasses")
|
||||
public void shouldCalculateExcessBlobGasCorrectly(
|
||||
final long parentExcess, final long used, final long expected) {
|
||||
final long usedBlobGas = osakaGasCalculator.blobGasCost(used);
|
||||
assertThat(osakaGasCalculator.computeExcessBlobGas(parentExcess, usedBlobGas))
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
Iterable<Arguments> blobGasses() {
|
||||
long nineBlobTargetGas = TARGET_BLOB_GAS_PER_BLOCK_OSAKA;
|
||||
long newTargetCount = 9;
|
||||
|
||||
return List.of(
|
||||
// New target count
|
||||
Arguments.of(0L, 0L, 0L),
|
||||
Arguments.of(nineBlobTargetGas, 0L, 0L),
|
||||
Arguments.of(newTargetCount, 0L, 0L),
|
||||
Arguments.of(0L, newTargetCount, 0L),
|
||||
Arguments.of(1L, newTargetCount, 1L),
|
||||
Arguments.of(
|
||||
osakaGasCalculator.blobGasCost(newTargetCount),
|
||||
1L,
|
||||
osakaGasCalculator.getBlobGasPerBlob()),
|
||||
Arguments.of(nineBlobTargetGas, newTargetCount, nineBlobTargetGas));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
@@ -31,6 +29,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class PragueGasCalculatorTest {
|
||||
|
||||
private static final long TARGET_BLOB_GAS_PER_BLOCK_PRAGUE = 0xC0000;
|
||||
private final PragueGasCalculator pragueGasCalculator = new PragueGasCalculator();
|
||||
|
||||
@Test
|
||||
@@ -44,39 +43,27 @@ class PragueGasCalculatorTest {
|
||||
name = "{index} - parent gas {0}, used gas {1}, blob target {2} new excess {3}")
|
||||
@MethodSource("blobGasses")
|
||||
public void shouldCalculateExcessBlobGasCorrectly(
|
||||
final long parentExcess, final long used, final long target, final long expected) {
|
||||
final long parentExcess, final long used, final long expected) {
|
||||
final long usedBlobGas = pragueGasCalculator.blobGasCost(used);
|
||||
assertThat(
|
||||
pragueGasCalculator.computeExcessBlobGas(
|
||||
parentExcess, usedBlobGas, Optional.of(UInt64.valueOf(target))))
|
||||
assertThat(pragueGasCalculator.computeExcessBlobGas(parentExcess, usedBlobGas))
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
Iterable<Arguments> blobGasses() {
|
||||
long threeBlobTargetGas = CancunGasCalculator.TARGET_BLOB_GAS_PER_BLOCK;
|
||||
long cancunTargetCount = 3;
|
||||
long newTargetCount = 4;
|
||||
long sixBlobTargetGas = TARGET_BLOB_GAS_PER_BLOCK_PRAGUE;
|
||||
long newTargetCount = 6;
|
||||
|
||||
return List.of(
|
||||
// If blob target count remains at 3
|
||||
Arguments.of(0L, 0L, cancunTargetCount, 0L),
|
||||
Arguments.of(threeBlobTargetGas, 0L, cancunTargetCount, 0L),
|
||||
Arguments.of(0L, cancunTargetCount, cancunTargetCount, 0L),
|
||||
Arguments.of(1L, cancunTargetCount, cancunTargetCount, 1L),
|
||||
Arguments.of(
|
||||
threeBlobTargetGas, 1L, cancunTargetCount, pragueGasCalculator.getBlobGasPerBlob()),
|
||||
Arguments.of(threeBlobTargetGas, 3L, cancunTargetCount, threeBlobTargetGas),
|
||||
// New target count
|
||||
Arguments.of(0L, 0L, newTargetCount, 0L),
|
||||
Arguments.of(threeBlobTargetGas, 0L, newTargetCount, 0L),
|
||||
Arguments.of(newTargetCount, 0L, newTargetCount, 0L),
|
||||
Arguments.of(0L, newTargetCount, newTargetCount, 0L),
|
||||
Arguments.of(1L, newTargetCount, newTargetCount, 1L),
|
||||
Arguments.of(0L, 0L, 0L),
|
||||
Arguments.of(sixBlobTargetGas, 0L, 0L),
|
||||
Arguments.of(newTargetCount, 0L, 0L),
|
||||
Arguments.of(0L, newTargetCount, 0L),
|
||||
Arguments.of(1L, newTargetCount, 1L),
|
||||
Arguments.of(
|
||||
pragueGasCalculator.blobGasCost(newTargetCount),
|
||||
1L,
|
||||
newTargetCount,
|
||||
pragueGasCalculator.getBlobGasPerBlob()),
|
||||
Arguments.of(threeBlobTargetGas, newTargetCount, newTargetCount, threeBlobTargetGas));
|
||||
Arguments.of(sixBlobTargetGas, newTargetCount, sixBlobTargetGas));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user