Skip to content

Commit e21fe0e

Browse files
authored
Merge branch 'main' into mod-exp-more-bnch
2 parents 173dfe0 + b692d48 commit e21fe0e

File tree

12 files changed

+259
-104
lines changed

12 files changed

+259
-104
lines changed

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/GasLimitCalculator.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ default long currentBlobGasLimit() {
5757
*
5858
* @param parentExcessBlobGas excess blob gas from the parent
5959
* @param blobGasUsed blob gas used
60+
* @param parentBaseFeePerGas base fee per gas from the parent
6061
* @return the new excess blob gas value
6162
*/
62-
default long computeExcessBlobGas(final long parentExcessBlobGas, final long blobGasUsed) {
63+
default long computeExcessBlobGas(
64+
final long parentExcessBlobGas, final long blobGasUsed, final long parentBaseFeePerGas) {
6365
return 0L;
6466
}
6567

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculator.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public class CancunTargetingGasLimitCalculator extends LondonTargetingGasLimitCa
3030
private final long targetBlobGasPerBlock;
3131

3232
private final long blobGasPerBlob;
33+
protected final int maxBlobsPerBlock;
34+
protected final int targetBlobsPerBlock;
3335

3436
public CancunTargetingGasLimitCalculator(
3537
final long londonForkBlock,
@@ -57,15 +59,20 @@ public CancunTargetingGasLimitCalculator(
5759
this.blobGasPerBlob = gasCalculator.getBlobGasPerBlob();
5860
this.targetBlobGasPerBlock = blobGasPerBlob * targetBlobsPerBlock;
5961
this.maxBlobGasPerBlock = blobGasPerBlob * maxBlobsPerBlock;
62+
this.maxBlobsPerBlock = maxBlobsPerBlock;
63+
this.targetBlobsPerBlock = targetBlobsPerBlock;
6064
}
6165

6266
@Override
6367
public long currentBlobGasLimit() {
64-
return maxBlobGasPerBlock;
68+
return getMaxBlobGasPerBlock();
6569
}
6670

6771
@Override
68-
public long computeExcessBlobGas(final long parentExcessBlobGas, final long parentBlobGasUsed) {
72+
public long computeExcessBlobGas(
73+
final long parentExcessBlobGas,
74+
final long parentBlobGasUsed,
75+
final long parentBaseFeePerGas) {
6976
final long currentExcessBlobGas = parentExcessBlobGas + parentBlobGasUsed;
7077
if (currentExcessBlobGas < targetBlobGasPerBlock) {
7178
return 0L;
@@ -85,4 +92,8 @@ public long getBlobGasPerBlob() {
8592
public long getTargetBlobGasPerBlock() {
8693
return targetBlobGasPerBlock;
8794
}
95+
96+
public long getMaxBlobGasPerBlock() {
97+
return maxBlobGasPerBlock;
98+
}
8899
}

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/LondonTargetingGasLimitCalculator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class LondonTargetingGasLimitCalculator extends FrontierTargetingGasLimit
2323
private static final Logger LOG =
2424
LoggerFactory.getLogger(LondonTargetingGasLimitCalculator.class);
2525
private final long londonForkBlock;
26-
private final BaseFeeMarket feeMarket;
26+
protected final BaseFeeMarket feeMarket;
2727

2828
public LondonTargetingGasLimitCalculator(
2929
final long londonForkBlock, final BaseFeeMarket feeMarket) {

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/OsakaTargetingGasLimitCalculator.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@
1414
*/
1515
package org.hyperledger.besu.ethereum.mainnet;
1616

17+
import org.hyperledger.besu.datatypes.BlobGas;
18+
import org.hyperledger.besu.datatypes.Wei;
1719
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
1820
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
1921

2022
public class OsakaTargetingGasLimitCalculator extends CancunTargetingGasLimitCalculator {
23+
/** The blob base cost constant for Osaka */
24+
private static final long BLOB_BASE_COST = 1 << 14; // 2^14
25+
2126
/** The mainnet transaction gas limit cap for Osaka */
2227
private static final long DEFAULT_TRANSACTION_GAS_LIMIT_CAP_OSAKA = 30_000_000L;
2328

@@ -53,4 +58,28 @@ public OsakaTargetingGasLimitCalculator(
5358
public long transactionGasLimitCap() {
5459
return transactionGasLimitCap;
5560
}
61+
62+
@Override
63+
public long computeExcessBlobGas(
64+
final long parentExcessBlobGas,
65+
final long parentBlobGasUsed,
66+
final long parentBaseFeePerGas) {
67+
final long currentExcessBlobGas = parentExcessBlobGas + parentBlobGasUsed;
68+
69+
// First check if we're below the target
70+
if (currentExcessBlobGas < getTargetBlobGasPerBlock()) {
71+
return 0L;
72+
}
73+
74+
// EIP-7918 https://eips.ethereum.org/EIPS/eip-7918
75+
Wei baseFeeBlobGas = feeMarket.blobGasPricePerGas(BlobGas.of(parentExcessBlobGas));
76+
long baseFeeBlobGasLong = baseFeeBlobGas.toLong();
77+
if (BLOB_BASE_COST * parentBaseFeePerGas > getBlobGasPerBlob() * baseFeeBlobGasLong) {
78+
return parentExcessBlobGas
79+
+ parentBlobGasUsed * (maxBlobsPerBlock - targetBlobsPerBlock) / maxBlobsPerBlock;
80+
} else {
81+
// same as Cancun
82+
return currentExcessBlobGas - getTargetBlobGasPerBlock();
83+
}
84+
}
5685
}

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ExcessBlobGasCalculator.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package org.hyperledger.besu.ethereum.mainnet.feemarket;
1616

1717
import org.hyperledger.besu.datatypes.BlobGas;
18+
import org.hyperledger.besu.datatypes.Wei;
1819
import org.hyperledger.besu.ethereum.core.BlockHeader;
1920
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
2021

@@ -35,7 +36,8 @@ public static BlobGas calculateExcessBlobGasForParent(
3536
.getGasLimitCalculator()
3637
.computeExcessBlobGas(
3738
parentHeader.getExcessBlobGas().map(BlobGas::toLong).orElse(0L),
38-
parentHeader.getBlobGasUsed().orElse(0L));
39+
parentHeader.getBlobGasUsed().orElse(0L),
40+
parentHeader.getBaseFee().orElse(Wei.ZERO).toLong());
3941
return BlobGas.of(headerExcess);
4042
}
4143
}

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package org.hyperledger.besu.ethereum.mainnet.headervalidationrules;
1616

1717
import org.hyperledger.besu.datatypes.BlobGas;
18+
import org.hyperledger.besu.datatypes.Wei;
1819
import org.hyperledger.besu.ethereum.GasLimitCalculator;
1920
import org.hyperledger.besu.ethereum.core.BlockHeader;
2021
import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule;
@@ -48,7 +49,8 @@ public boolean validate(final BlockHeader header, final BlockHeader parent) {
4849
long parentBlobGasUsed = parent.getBlobGasUsed().orElse(0L);
4950

5051
long calculatedExcessBlobGas =
51-
gasLimitCalculator.computeExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed);
52+
gasLimitCalculator.computeExcessBlobGas(
53+
parentExcessBlobGas, parentBlobGasUsed, parent.getBaseFee().orElse(Wei.ZERO).toLong());
5254

5355
if (headerExcessBlobGas != calculatedExcessBlobGas) {
5456
LOG.info(

ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculatorTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class CancunTargetingGasLimitCalculatorTest {
4444
public void shouldCalculateCancunExcessBlobGasCorrectly(
4545
final long parentExcess, final long used, final long expected) {
4646
final long usedBlobGas = new CancunGasCalculator().blobGasCost(used);
47-
assertThat(cancunTargetingGasLimitCalculator.computeExcessBlobGas(parentExcess, usedBlobGas))
47+
assertThat(
48+
cancunTargetingGasLimitCalculator.computeExcessBlobGas(parentExcess, usedBlobGas, 0L))
4849
.isEqualTo(expected);
4950
}
5051

@@ -126,7 +127,7 @@ void shouldUseFutureForkCalculatorBlobGasPerBlob() {
126127
public void shouldCalculatePragueExcessBlobGasCorrectly(
127128
final long parentExcess, final long used, final long expected) {
128129
final long usedBlobGas = pragueGasCalculator.blobGasCost(used);
129-
assertThat(pragueGasLimitCalculator.computeExcessBlobGas(parentExcess, usedBlobGas))
130+
assertThat(pragueGasLimitCalculator.computeExcessBlobGas(parentExcess, usedBlobGas, 0L))
130131
.isEqualTo(expected);
131132
}
132133

@@ -172,8 +173,8 @@ void shouldCalculateCorrectlyPragueBlobGasPerBlob() {
172173
int newTargetCount = 9;
173174
public static final OsakaGasCalculator osakaGasCalculator = new OsakaGasCalculator();
174175
// CancunTargetingGasLimitCalculator with Osaka numbers
175-
private final CancunTargetingGasLimitCalculator osakaGasLimitCalculator =
176-
new CancunTargetingGasLimitCalculator(
176+
private final OsakaTargetingGasLimitCalculator osakaGasLimitCalculator =
177+
new OsakaTargetingGasLimitCalculator(
177178
0L,
178179
FeeMarket.cancunDefault(0L, Optional.empty()),
179180
osakaGasCalculator,
@@ -187,7 +188,7 @@ void shouldCalculateCorrectlyPragueBlobGasPerBlob() {
187188
public void shouldCalculateOsakaExcessBlobGasCorrectly(
188189
final long parentExcess, final long used, final long expected) {
189190
final long usedBlobGas = osakaGasCalculator.blobGasCost(used);
190-
assertThat(osakaGasLimitCalculator.computeExcessBlobGas(parentExcess, usedBlobGas))
191+
assertThat(osakaGasLimitCalculator.computeExcessBlobGas(parentExcess, usedBlobGas, 0L))
191192
.isEqualTo(expected);
192193
}
193194

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright contributors to 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.ethereum.mainnet;
16+
17+
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
18+
19+
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
20+
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
21+
import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator;
22+
23+
import java.util.List;
24+
import java.util.Optional;
25+
26+
import org.assertj.core.api.Assertions;
27+
import org.junit.jupiter.api.Test;
28+
import org.junit.jupiter.api.TestInstance;
29+
import org.junit.jupiter.params.ParameterizedTest;
30+
import org.junit.jupiter.params.provider.Arguments;
31+
import org.junit.jupiter.params.provider.MethodSource;
32+
33+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
34+
class OsakaTargetingGasLimitCalculatorTest {
35+
private static final long TARGET_BLOB_GAS_PER_BLOCK_OSAKA = 0x120000;
36+
37+
private final OsakaGasCalculator osakaGasCalculator = new OsakaGasCalculator();
38+
private final BaseFeeMarket feeMarket = FeeMarket.cancunDefault(0L, Optional.empty());
39+
40+
@ParameterizedTest(
41+
name = "{index} - parent gas {0}, used gas {1}, parent base fee per gas {2}, new excess {3}")
42+
@MethodSource("osakaExcessBlobGasTestCases")
43+
public void shouldCalculateOsakaExcessBlobGasCorrectly(
44+
final long parentExcess,
45+
final long used,
46+
final long parentBaseFeePerGas,
47+
final long expected) {
48+
int maxBlobs = 10;
49+
int targetBlobs = 9;
50+
final OsakaTargetingGasLimitCalculator osakaTargetingGasLimitCalculator =
51+
new OsakaTargetingGasLimitCalculator(
52+
0L, feeMarket, osakaGasCalculator, maxBlobs, targetBlobs);
53+
54+
final long usedBlobGas = osakaGasCalculator.blobGasCost(used);
55+
assertThat(
56+
osakaTargetingGasLimitCalculator.computeExcessBlobGas(
57+
parentExcess, usedBlobGas, parentBaseFeePerGas))
58+
.isEqualTo(expected);
59+
}
60+
61+
Iterable<Arguments> osakaExcessBlobGasTestCases() {
62+
long targetGasPerBlock = TARGET_BLOB_GAS_PER_BLOCK_OSAKA;
63+
return List.of(
64+
// Case 1: Below target, should return 0
65+
Arguments.of(0L, 0L, 0L, 0L),
66+
Arguments.of(targetGasPerBlock - 1, 0L, 0L, 0L),
67+
Arguments.of(0L, 8, 0L, 0L), // 8 blobs is below target (9)
68+
69+
// Case 2: Above target, BLOB_BASE_COST * baseFee <= GAS_PER_BLOB * blobFee
70+
// This should use the formula: parentExcess + parentBlobGasUsed - target
71+
Arguments.of(targetGasPerBlock * 2, 10, 17L, 2490368L),
72+
73+
// Case 3: Above target, BLOB_BASE_COST * baseFee > GAS_PER_BLOB * blobFee
74+
// This should use the formula: parentExcess + parentBlobGasUsed * (max - target) / max
75+
Arguments.of(targetGasPerBlock, 1, 0L, osakaGasCalculator.getBlobGasPerBlob()),
76+
Arguments.of(targetGasPerBlock, 10, 1L, 1310720L),
77+
Arguments.of(targetGasPerBlock, 10, 16L, 1310720L));
78+
}
79+
80+
@Test
81+
void shouldUseCorrectBlobGasPerBlob() {
82+
// should use OsakaGasCalculator's blob gas per blob to calculate the gas limit
83+
final long blobGasPerBlob = osakaGasCalculator.getBlobGasPerBlob();
84+
assertThat(blobGasPerBlob).isEqualTo(131072); // same as Cancun
85+
86+
int maxBlobs = 10;
87+
int targetBlobs = 9;
88+
var osakaTargetingGasLimitCalculator =
89+
new OsakaTargetingGasLimitCalculator(
90+
0L, feeMarket, osakaGasCalculator, maxBlobs, targetBlobs);
91+
92+
// if maxBlobs = 10, then the gas limit would be 131072 * 10 = 1310720
93+
assertThat(osakaTargetingGasLimitCalculator.currentBlobGasLimit())
94+
.isEqualTo(blobGasPerBlob * maxBlobs);
95+
assertThat(osakaTargetingGasLimitCalculator.currentBlobGasLimit()).isEqualTo(1310720);
96+
assertThat(osakaTargetingGasLimitCalculator.getTargetBlobGasPerBlock())
97+
.isEqualTo(blobGasPerBlob * targetBlobs);
98+
}
99+
100+
@Test
101+
void testComputeExcessBlobGasWithDifferentConditions() {
102+
// Create a test instance with specific parameters
103+
int maxBlobs = 10;
104+
int targetBlobs = 9;
105+
var calculator =
106+
new OsakaTargetingGasLimitCalculator(
107+
0L, feeMarket, osakaGasCalculator, maxBlobs, targetBlobs);
108+
assertThat(calculator.maxBlobsPerBlock).isEqualTo(maxBlobs);
109+
assertThat(calculator.targetBlobsPerBlock).isEqualTo(targetBlobs);
110+
111+
long parentExcessBlobGas = calculator.getTargetBlobGasPerBlock();
112+
long parentBlobGasUsed = osakaGasCalculator.getBlobGasPerBlob() * 2;
113+
114+
// Test the condition where BLOB_BASE_COST * baseFee > GAS_PER_BLOB * blobFee
115+
// This should use the first formula
116+
long result1 = calculator.computeExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed, 0L);
117+
// Expected value based on the test case
118+
assertThat(result1).isEqualTo(262144L);
119+
120+
// Test with very high excess blob gas to trigger the second formula
121+
// When excess is high, blob fee will be high, potentially making BLOB_BASE_COST * baseFee <=
122+
// GAS_PER_BLOB * blobFee
123+
long highExcess = calculator.getTargetBlobGasPerBlock() * 10;
124+
long result2 = calculator.computeExcessBlobGas(highExcess, parentBlobGasUsed, 0L);
125+
// Expected value based on the test case
126+
assertThat(result2).isEqualTo(10878976L);
127+
}
128+
129+
@Test
130+
void dryRunDetector() {
131+
Assertions.assertThat(true)
132+
.withFailMessage("This test is here so gradle --dry-run executes this class")
133+
.isTrue();
134+
}
135+
}

ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeer.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242

4343
import java.time.Clock;
4444
import java.util.Collections;
45-
import java.util.Comparator;
4645
import java.util.HashMap;
4746
import java.util.LinkedHashMap;
4847
import java.util.List;
@@ -632,12 +631,6 @@ public boolean hasSupportForMessage(final int messageCode) {
632631
.anyMatch(cap -> EthProtocol.get().isValidMessageCode(cap.getVersion(), messageCode));
633632
}
634633

635-
public Capability getMaxAgreedCapability() {
636-
return getAgreedCapabilities().stream()
637-
.max(Comparator.comparingInt(Capability::getVersion))
638-
.orElseThrow(() -> new IllegalStateException("No capabilities available"));
639-
}
640-
641634
@Override
642635
public String toString() {
643636
return String.format(

0 commit comments

Comments
 (0)