Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

EIP-7840 Implementation #8042

Merged
merged 17 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions acceptance-tests/tests/src/test/resources/dev/dev_prague.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -546,4 +546,11 @@ default boolean isConsensusMigration() {
* @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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -199,6 +200,12 @@ public EthashConfigOptions getEthashConfigOptions() {
.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;
Expand Down Expand Up @@ -537,6 +544,10 @@ public Map<String, Object> asMap() {
builder.put("fixedBaseFee", true);
}

if (getBlobScheduleOptions().isPresent()) {
builder.put("blobSchedule", getBlobScheduleOptions().get().asMap());
}

return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,11 @@ public Optional<Address> getConsolidationRequestContractAddress() {
return Optional.empty();
}

@Override
public Optional<BlobScheduleOptions> getBlobScheduleOptions() {
return Optional.empty();
}

/**
* Homestead block stub genesis config options.
*
Expand Down
10 changes: 10 additions & 0 deletions config/src/main/resources/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@
"terminalTotalDifficulty": 58750000000000000000000,
"shanghaiTime": 1681338455,
"cancunTime": 1710338135,
"blobSchedule": {
"cancun": {
"target": 3,
"max": 6
},
"prague": {
"target": 6,
"max": 9
}
},
"ethash": {
},
"discovery": {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,46 @@ void asMapIncludesConsolidationRequestContractAddress() {
.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);
Expand Down
37 changes: 37 additions & 0 deletions config/src/test/resources/mainnet_with_blob_schedule.json
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public TransactionSelectionResult evaluateTransactionPreProcessing(

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
/** 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
Expand Down
Loading
Loading