Skip to content

Commit

Permalink
Remove a couple of TODOs:
Browse files Browse the repository at this point in the history
- Add asMap for blobSchedule so it appears in admin_nodeInfo
- Prememptively add OsakaTargetingGasLimitCalculator and wire in the max blob count

Add blobschedule to mainnet.json to be explicit, since the code will default to the same values anyway

Signed-off-by: Simon Dudley <[email protected]>
  • Loading branch information
siladu committed Dec 19, 2024
1 parent ea7dd6b commit 5cdc356
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
*/
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 Checkpoint config options. */
public class BlobScheduleOptions {
Expand All @@ -39,42 +43,46 @@ public BlobScheduleOptions(final ObjectNode blobScheduleConfigRoot) {
*
* @return the cancun blob schedule
*/
public BlobSchedule getCancun() {
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, CANCUN_KEY)
.map(BlobSchedule::new)
.orElse(BlobSchedule.DEFAULT);
public Optional<BlobSchedule> getCancun() {
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, CANCUN_KEY).map(BlobSchedule::new);
}

/**
* Gets prague blob schedule.
*
* @return the prague blob schedule
*/
public BlobSchedule getPrague() {
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, PRAGUE_KEY)
.map(BlobSchedule::new)
.orElse(BlobSchedule.DEFAULT);
public Optional<BlobSchedule> getPrague() {
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, PRAGUE_KEY).map(BlobSchedule::new);
}

/**
* Gets osaka blob schedule.
*
* @return the osaka blob schedule
*/
public BlobSchedule getOsaka() {
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, OSAKA_KEY)
.map(BlobSchedule::new)
.orElse(BlobSchedule.DEFAULT);
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 DEFAULT. */
public static final BlobSchedule DEFAULT = new BlobSchedule(JsonUtil.createEmptyObjectNode());

/** The constant CANCUN_DEFAULT. */
public static final BlobSchedule CANCUN_DEFAULT = new BlobSchedule(3, 6);

Expand All @@ -90,9 +98,8 @@ public static class BlobSchedule {
* @param blobScheduleConfigRoot the blob schedule config root
*/
public BlobSchedule(final ObjectNode blobScheduleConfigRoot) {
// TODO SLD EIP-7840 - reasonable defaults?
this.target = JsonUtil.getInt(blobScheduleConfigRoot, "target").orElse(3);
this.max = JsonUtil.getInt(blobScheduleConfigRoot, "max").orElse(6);
this.target = JsonUtil.getInt(blobScheduleConfigRoot, "target").orElseThrow();
this.max = JsonUtil.getInt(blobScheduleConfigRoot, "max").orElseThrow();
}

private BlobSchedule(final int target, final int max) {
Expand All @@ -117,5 +124,14 @@ public int getTarget() {
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 @@ -469,7 +469,6 @@ public Optional<Address> getConsolidationRequestContractAddress() {
return inputAddress.map(Address::fromHexString);
}

// TODO SLD - EIP-7840
@Override
public Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
Expand Down Expand Up @@ -545,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
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
Expand Up @@ -28,11 +28,14 @@ public void blobScheduleIsParsed() {

assertThat(configOptions.getBlobScheduleOptions()).isNotEmpty();
final BlobScheduleOptions blobScheduleOptions = configOptions.getBlobScheduleOptions().get();
assertThat(blobScheduleOptions.getCancun().getTarget()).isEqualTo(4);
assertThat(blobScheduleOptions.getCancun().getMax()).isEqualTo(7);
assertThat(blobScheduleOptions.getPrague().getTarget()).isEqualTo(7);
assertThat(blobScheduleOptions.getPrague().getMax()).isEqualTo(10);
assertThat(blobScheduleOptions.getOsaka().getTarget()).isEqualTo(10);
assertThat(blobScheduleOptions.getOsaka().getMax()).isEqualTo(13);
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 =
GenesisConfigFile.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
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ static ProtocolSpecBuilder cancunDefinition(
final var cancunBlobSchedule =
genesisConfigOptions
.getBlobScheduleOptions()
.map(BlobScheduleOptions::getCancun)
.flatMap(BlobScheduleOptions::getCancun)
.orElse(BlobScheduleOptions.BlobSchedule.CANCUN_DEFAULT);

final java.util.function.Supplier<GasCalculator> cancunGasCalcSupplier =
Expand Down Expand Up @@ -767,10 +767,10 @@ static ProtocolSpecBuilder cancunEOFDefinition(
final boolean isParallelTxProcessingEnabled,
final MetricsSystem metricsSystem) {

final var blobSchedule =
final var cancunBlobSchedule =
genesisConfigOptions
.getBlobScheduleOptions()
.map(BlobScheduleOptions::getCancun)
.flatMap(BlobScheduleOptions::getCancun)
.orElse(BlobScheduleOptions.BlobSchedule.CANCUN_DEFAULT);

ProtocolSpecBuilder protocolSpecBuilder =
Expand All @@ -782,7 +782,13 @@ static ProtocolSpecBuilder cancunEOFDefinition(
miningConfiguration,
isParallelTxProcessingEnabled,
metricsSystem);
return addEOF(chainId, evmConfiguration, protocolSpecBuilder, blobSchedule.getTarget())
return addEOF(
genesisConfigOptions,
chainId,
evmConfiguration,
protocolSpecBuilder,
cancunBlobSchedule.getTarget(),
cancunBlobSchedule.getMax())
.name("CancunEOF");
}

Expand All @@ -802,7 +808,7 @@ static ProtocolSpecBuilder pragueDefinition(
final var pragueBlobSchedule =
genesisConfigOptions
.getBlobScheduleOptions()
.map(BlobScheduleOptions::getPrague)
.flatMap(BlobScheduleOptions::getPrague)
.orElse(BlobScheduleOptions.BlobSchedule.PRAGUE_DEFAULT);

// EIP-3074 AUTH and AUTHCALL gas | EIP-7840 Blob schedule | EIP-7691 6/9 blob increase
Expand Down Expand Up @@ -879,7 +885,7 @@ static ProtocolSpecBuilder osakaDefinition(
final var osakaBlobSchedule =
genesisConfigOptions
.getBlobScheduleOptions()
.map(BlobScheduleOptions::getOsaka)
.flatMap(BlobScheduleOptions::getOsaka)
.orElse(BlobScheduleOptions.BlobSchedule.OSAKA_DEFAULT);

ProtocolSpecBuilder protocolSpecBuilder =
Expand All @@ -891,20 +897,34 @@ static ProtocolSpecBuilder osakaDefinition(
miningConfiguration,
isParallelTxProcessingEnabled,
metricsSystem);
return addEOF(chainId, evmConfiguration, protocolSpecBuilder, osakaBlobSchedule.getTarget())
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 int targetBlobsPerBlock) {
final int targetBlobsPerBlock,
final int maxBlobsPerBlock) {

// TODO SLD EIP-7840 Add OsakaTargetingGasLimitCalculator with 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(() -> new OsakaGasCalculator(targetBlobsPerBlock))
.gasCalculator(osakaGasCalcSupplier)
.gasLimitCalculatorBuilder(
feeMarket ->
new OsakaTargetingGasLimitCalculator(
londonForkBlockNumber, (BaseFeeMarket) feeMarket, maxBlobsPerBlock))
// EIP-7692 EOF v1 EVM and opcodes
.evmBuilder(
(gasCalculator, jdCacheConfig) ->
Expand All @@ -917,7 +937,11 @@ private static ProtocolSpecBuilder addEOF(
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(
Expand Down
Original file line number Diff line number Diff line change
@@ -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 * 9 blobs = 131072 * 12 = 1572864 = 0x180000
*/
public OsakaTargetingGasLimitCalculator(
final long londonForkBlock, final BaseFeeMarket feeMarket, final int maxBlobsPerBlock) {
super(londonForkBlock, feeMarket, maxBlobsPerBlock);
}
}

0 comments on commit 5cdc356

Please sign in to comment.