Skip to content
This repository was archived by the owner on Jul 1, 2025. It is now read-only.

Commit de178ac

Browse files
siladumacfarla
authored andcommitted
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 <[email protected]> Co-authored-by: Sally MacFarlane <[email protected]>
1 parent efa7f27 commit de178ac

File tree

29 files changed

+701
-106
lines changed

29 files changed

+701
-106
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
### Additions and Improvements
1818
- Add RPC HTTP options to specify custom truststore and its password [#7978](https://github.com/hyperledger/besu/pull/7978)
1919
- Retrieve all transaction receipts for a block in one request [#6646](https://github.com/hyperledger/besu/pull/6646)
20+
- Implement EIP-7840: Add blob schedule to config files [#8042](https://github.com/hyperledger/besu/pull/8042)
2021

2122

2223
### Bug fixes

acceptance-tests/tests/src/test/resources/dev/dev_prague.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@
1515
"terminalTotalDifficulty":0,
1616
"cancunTime":0,
1717
"pragueTime":0,
18+
"blobSchedule": {
19+
"cancun": {
20+
"target": 3,
21+
"max": 6
22+
},
23+
"prague": {
24+
"target": 6,
25+
"max": 9
26+
},
27+
"osaka": {
28+
"target": 9,
29+
"max": 12
30+
}
31+
},
1832
"clique": {
1933
"period": 5,
2034
"epoch": 30000
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright contributors to Hyperledger Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.config;
16+
17+
import java.util.Map;
18+
import java.util.Optional;
19+
20+
import com.fasterxml.jackson.databind.node.ObjectNode;
21+
import com.google.common.collect.ImmutableMap;
22+
23+
/** The Blob Schedule config options. */
24+
public class BlobScheduleOptions {
25+
26+
private final ObjectNode blobScheduleOptionsConfigRoot;
27+
28+
private static final String CANCUN_KEY = "cancun";
29+
private static final String PRAGUE_KEY = "prague";
30+
private static final String OSAKA_KEY = "osaka";
31+
32+
/**
33+
* Instantiates a new Blob Schedule config options.
34+
*
35+
* @param blobScheduleConfigRoot the blob schedule config root
36+
*/
37+
public BlobScheduleOptions(final ObjectNode blobScheduleConfigRoot) {
38+
this.blobScheduleOptionsConfigRoot = blobScheduleConfigRoot;
39+
}
40+
41+
/**
42+
* Gets cancun blob schedule.
43+
*
44+
* @return the cancun blob schedule
45+
*/
46+
public Optional<BlobSchedule> getCancun() {
47+
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, CANCUN_KEY).map(BlobSchedule::new);
48+
}
49+
50+
/**
51+
* Gets prague blob schedule.
52+
*
53+
* @return the prague blob schedule
54+
*/
55+
public Optional<BlobSchedule> getPrague() {
56+
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, PRAGUE_KEY).map(BlobSchedule::new);
57+
}
58+
59+
/**
60+
* Gets osaka blob schedule.
61+
*
62+
* @return the osaka blob schedule
63+
*/
64+
public Optional<BlobSchedule> getOsaka() {
65+
return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, OSAKA_KEY).map(BlobSchedule::new);
66+
}
67+
68+
/**
69+
* As map.
70+
*
71+
* @return the map
72+
*/
73+
public Map<String, Object> asMap() {
74+
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
75+
getCancun().ifPresent(bs -> builder.put(CANCUN_KEY, bs.asMap()));
76+
getPrague().ifPresent(bs -> builder.put(PRAGUE_KEY, bs.asMap()));
77+
getOsaka().ifPresent(bs -> builder.put(OSAKA_KEY, bs.asMap()));
78+
return builder.build();
79+
}
80+
81+
/** The Blob schedule for a particular fork. */
82+
public static class BlobSchedule {
83+
private final int target;
84+
private final int max;
85+
86+
/** The constant CANCUN_DEFAULT. */
87+
public static final BlobSchedule CANCUN_DEFAULT = new BlobSchedule(3, 6);
88+
89+
/** The constant PRAGUE_DEFAULT. */
90+
public static final BlobSchedule PRAGUE_DEFAULT = new BlobSchedule(6, 9);
91+
92+
/** The constant OSAKA_DEFAULT. */
93+
public static final BlobSchedule OSAKA_DEFAULT = new BlobSchedule(9, 12);
94+
95+
/**
96+
* Instantiates a new Blob schedule.
97+
*
98+
* @param blobScheduleConfigRoot the blob schedule config root
99+
*/
100+
public BlobSchedule(final ObjectNode blobScheduleConfigRoot) {
101+
this.target = JsonUtil.getInt(blobScheduleConfigRoot, "target").orElseThrow();
102+
this.max = JsonUtil.getInt(blobScheduleConfigRoot, "max").orElseThrow();
103+
}
104+
105+
private BlobSchedule(final int target, final int max) {
106+
this.target = target;
107+
this.max = max;
108+
}
109+
110+
/**
111+
* Gets target.
112+
*
113+
* @return the target
114+
*/
115+
public int getTarget() {
116+
return target;
117+
}
118+
119+
/**
120+
* Gets max.
121+
*
122+
* @return the max
123+
*/
124+
public int getMax() {
125+
return max;
126+
}
127+
128+
/**
129+
* As map.
130+
*
131+
* @return the map
132+
*/
133+
Map<String, Object> asMap() {
134+
return Map.of("target", target, "max", max);
135+
}
136+
}
137+
}

config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,4 +546,11 @@ default boolean isConsensusMigration() {
546546
* @return the consolidation request contract address
547547
*/
548548
Optional<Address> getConsolidationRequestContractAddress();
549+
550+
/**
551+
* The blob schedule is a list of hardfork names and their associated target and max blob values.
552+
*
553+
* @return the blob schedule
554+
*/
555+
Optional<BlobScheduleOptions> getBlobScheduleOptions();
549556
}

config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
4747
private static final String TRANSITIONS_CONFIG_KEY = "transitions";
4848
private static final String DISCOVERY_CONFIG_KEY = "discovery";
4949
private static final String CHECKPOINT_CONFIG_KEY = "checkpoint";
50+
private static final String BLOB_SCHEDULE_CONFIG_KEY = "blobschedule";
5051
private static final String ZERO_BASE_FEE_KEY = "zerobasefee";
5152
private static final String FIXED_BASE_FEE_KEY = "fixedbasefee";
5253
private static final String WITHDRAWAL_REQUEST_CONTRACT_ADDRESS_KEY =
@@ -199,6 +200,12 @@ public EthashConfigOptions getEthashConfigOptions() {
199200
.orElse(EthashConfigOptions.DEFAULT);
200201
}
201202

203+
@Override
204+
public Optional<BlobScheduleOptions> getBlobScheduleOptions() {
205+
return JsonUtil.getObjectNode(configRoot, BLOB_SCHEDULE_CONFIG_KEY)
206+
.map(BlobScheduleOptions::new);
207+
}
208+
202209
@Override
203210
public TransitionsConfigOptions getTransitions() {
204211
return transitions;
@@ -537,6 +544,10 @@ public Map<String, Object> asMap() {
537544
builder.put("fixedBaseFee", true);
538545
}
539546

547+
if (getBlobScheduleOptions().isPresent()) {
548+
builder.put("blobSchedule", getBlobScheduleOptions().get().asMap());
549+
}
550+
540551
return builder.build();
541552
}
542553

config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,11 @@ public Optional<Address> getConsolidationRequestContractAddress() {
472472
return Optional.empty();
473473
}
474474

475+
@Override
476+
public Optional<BlobScheduleOptions> getBlobScheduleOptions() {
477+
return Optional.empty();
478+
}
479+
475480
/**
476481
* Homestead block stub genesis config options.
477482
*

config/src/main/resources/mainnet.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
"terminalTotalDifficulty": 58750000000000000000000,
1717
"shanghaiTime": 1681338455,
1818
"cancunTime": 1710338135,
19+
"blobSchedule": {
20+
"cancun": {
21+
"target": 3,
22+
"max": 6
23+
},
24+
"prague": {
25+
"target": 6,
26+
"max": 9
27+
}
28+
},
1929
"ethash": {
2030
},
2131
"discovery": {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright contributors to Hyperledger Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.config;
16+
17+
import static org.assertj.core.api.Assertions.assertThat;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
public class BlobScheduleOptionsTest {
22+
23+
@Test
24+
public void blobScheduleIsParsed() {
25+
final GenesisConfig genesisConfigFile =
26+
GenesisConfig.fromResource("/mainnet_with_blob_schedule.json");
27+
final GenesisConfigOptions configOptions = genesisConfigFile.getConfigOptions();
28+
29+
assertThat(configOptions.getBlobScheduleOptions()).isNotEmpty();
30+
final BlobScheduleOptions blobScheduleOptions = configOptions.getBlobScheduleOptions().get();
31+
assertThat(blobScheduleOptions.getCancun()).isNotEmpty();
32+
assertThat(blobScheduleOptions.getCancun().get().getTarget()).isEqualTo(4);
33+
assertThat(blobScheduleOptions.getCancun().get().getMax()).isEqualTo(7);
34+
assertThat(blobScheduleOptions.getPrague()).isNotEmpty();
35+
assertThat(blobScheduleOptions.getPrague().get().getTarget()).isEqualTo(7);
36+
assertThat(blobScheduleOptions.getPrague().get().getMax()).isEqualTo(10);
37+
assertThat(blobScheduleOptions.getOsaka()).isNotEmpty();
38+
assertThat(blobScheduleOptions.getOsaka().get().getTarget()).isEqualTo(10);
39+
assertThat(blobScheduleOptions.getOsaka().get().getMax()).isEqualTo(13);
40+
}
41+
}

config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,46 @@ void asMapIncludesConsolidationRequestContractAddress() {
408408
.containsValue(Address.ZERO);
409409
}
410410

411+
@SuppressWarnings("unchecked")
412+
@Test
413+
void asMapIncludesBlobFeeSchedule() {
414+
final GenesisConfigOptions config =
415+
GenesisConfig.fromConfig(
416+
"{\n"
417+
+ " \"config\": {\n"
418+
+ " \"blobSchedule\": {\n"
419+
+ " \"cancun\": {\n"
420+
+ " \"target\": 1,\n"
421+
+ " \"max\": 2\n"
422+
+ " },\n"
423+
+ " \"prague\": {\n"
424+
+ " \"target\": 3,\n"
425+
+ " \"max\": 4\n"
426+
+ " },\n"
427+
+ " \"osaka\": {\n"
428+
+ " \"target\": 4,\n"
429+
+ " \"max\": 5\n"
430+
+ " }\n"
431+
+ " }\n"
432+
+ " }\n"
433+
+ "}")
434+
.getConfigOptions();
435+
436+
final Map<String, Object> map = config.asMap();
437+
assertThat(map).containsOnlyKeys("blobSchedule");
438+
final Map<String, Object> blobSchedule = (Map<String, Object>) map.get("blobSchedule");
439+
assertThat(blobSchedule).containsOnlyKeys("cancun", "prague", "osaka");
440+
assertThat((Map<String, Object>) blobSchedule.get("cancun"))
441+
.containsOnlyKeys("target", "max")
442+
.containsValues(1, 2);
443+
assertThat((Map<String, Object>) blobSchedule.get("prague"))
444+
.containsOnlyKeys("target", "max")
445+
.containsValues(3, 4);
446+
assertThat((Map<String, Object>) blobSchedule.get("osaka"))
447+
.containsOnlyKeys("target", "max")
448+
.containsValues(4, 5);
449+
}
450+
411451
private GenesisConfigOptions fromConfigOptions(final Map<String, Object> configOptions) {
412452
final ObjectNode rootNode = JsonUtil.createEmptyObjectNode();
413453
final ObjectNode options = JsonUtil.objectNodeFromMap(configOptions);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"config": {
3+
"chainId": 3151908,
4+
"homesteadBlock": 0,
5+
"eip150Block": 0,
6+
"eip155Block": 0,
7+
"eip158Block": 0,
8+
"byzantiumBlock": 0,
9+
"constantinopleBlock": 0,
10+
"petersburgBlock": 0,
11+
"istanbulBlock": 0,
12+
"berlinBlock": 0,
13+
"londonBlock": 0,
14+
"preMergeForkBlock": 0,
15+
"terminalTotalDifficulty": 0,
16+
"ethash": {},
17+
"shanghaiTime": 0,
18+
"cancunTime": 0,
19+
"blobSchedule": {
20+
"cancun": {
21+
"target": 4,
22+
"max": 7
23+
},
24+
"prague": {
25+
"target": 7,
26+
"max": 10
27+
},
28+
"osaka": {
29+
"target": 10,
30+
"max": 13
31+
}
32+
},
33+
"depositContractAddress": "0x4242424242424242424242424242424242424242",
34+
"pragueTime": 1734106711,
35+
"osakaTime": 1734107095
36+
}
37+
}

0 commit comments

Comments
 (0)