Skip to content

Commit a962023

Browse files
committed
Track max data gas per block using GasLimitCalculator
Signed-off-by: Fabio Di Fabio <[email protected]>
1 parent 72c6988 commit a962023

File tree

14 files changed

+221
-82
lines changed

14 files changed

+221
-82
lines changed

ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.hyperledger.besu.datatypes.DataGas;
1919
import org.hyperledger.besu.datatypes.Hash;
2020
import org.hyperledger.besu.datatypes.Wei;
21+
import org.hyperledger.besu.ethereum.GasLimitCalculator;
2122
import org.hyperledger.besu.ethereum.ProtocolContext;
2223
import org.hyperledger.besu.ethereum.core.Block;
2324
import org.hyperledger.besu.ethereum.core.BlockBody;
@@ -294,7 +295,8 @@ private BlockTransactionSelector.TransactionSelectionResults selectTransactions(
294295
isCancelled::get,
295296
miningBeneficiary,
296297
protocolSpec.getFeeMarket(),
297-
protocolSpec.getGasCalculator());
298+
protocolSpec.getGasCalculator(),
299+
protocolSpec.getGasLimitCalculator());
298300

299301
if (transactions.isPresent()) {
300302
return selector.evaluateTransactions(transactions.get());
@@ -337,13 +339,13 @@ private ProcessableBlockHeader createPendingBlockHeader(
337339
final Optional<Bytes32> maybePrevRandao,
338340
final ProtocolSpec protocolSpec) {
339341
final long newBlockNumber = parentHeader.getNumber() + 1;
340-
long gasLimit =
341-
protocolSpec
342-
.getGasLimitCalculator()
343-
.nextGasLimit(
344-
parentHeader.getGasLimit(),
345-
targetGasLimitSupplier.get().orElse(parentHeader.getGasLimit()),
346-
newBlockNumber);
342+
final GasLimitCalculator gasLimitCalculator = protocolSpec.getGasLimitCalculator();
343+
344+
final long gasLimit =
345+
gasLimitCalculator.nextGasLimit(
346+
parentHeader.getGasLimit(),
347+
targetGasLimitSupplier.get().orElse(parentHeader.getGasLimit()),
348+
newBlockNumber);
347349

348350
final DifficultyCalculator difficultyCalculator = protocolSpec.getDifficultyCalculator();
349351
final BigInteger difficulty =

ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.hyperledger.besu.datatypes.Address;
2020
import org.hyperledger.besu.datatypes.Wei;
21+
import org.hyperledger.besu.ethereum.GasLimitCalculator;
2122
import org.hyperledger.besu.ethereum.chain.Blockchain;
2223
import org.hyperledger.besu.ethereum.core.MutableWorldState;
2324
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
@@ -90,6 +91,7 @@ public class BlockTransactionSelector {
9091
private final Address miningBeneficiary;
9192
private final FeeMarket feeMarket;
9293
private final GasCalculator gasCalculator;
94+
private final GasLimitCalculator gasLimitCalculator;
9395

9496
private final TransactionSelectionResults transactionSelectionResult =
9597
new TransactionSelectionResults();
@@ -106,7 +108,8 @@ public BlockTransactionSelector(
106108
final Supplier<Boolean> isCancelled,
107109
final Address miningBeneficiary,
108110
final FeeMarket feeMarket,
109-
final GasCalculator gasCalculator) {
111+
final GasCalculator gasCalculator,
112+
final GasLimitCalculator gasLimitCalculator) {
110113
this.transactionProcessor = transactionProcessor;
111114
this.blockchain = blockchain;
112115
this.worldState = worldState;
@@ -119,6 +122,7 @@ public BlockTransactionSelector(
119122
this.miningBeneficiary = miningBeneficiary;
120123
this.feeMarket = feeMarket;
121124
this.gasCalculator = gasCalculator;
125+
this.gasLimitCalculator = gasLimitCalculator;
122126
}
123127

124128
/*
@@ -338,7 +342,7 @@ private void updateTransactionResultTracking(
338342
transaction.isGoQuorumPrivateTransaction(
339343
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());
340344

341-
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
345+
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount()).toLong();
342346

343347
final long gasUsedByTransaction =
344348
isGoQuorumPrivateTransaction
@@ -373,12 +377,14 @@ private TransactionProcessingResult publicResultForWhenWeHaveAPrivateTransaction
373377
private boolean transactionTooLargeForBlock(final Transaction transaction) {
374378
final var dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
375379

376-
if (dataGasUsed
377-
> gasCalculator.getDataGasLimit() - transactionSelectionResult.getCumulativeDataGasUsed()) {
380+
if (dataGasUsed.greaterThan(
381+
gasLimitCalculator
382+
.nextDataGasLimit()
383+
.subtract(transactionSelectionResult.getCumulativeDataGasUsed()))) {
378384
return true;
379385
}
380386

381-
return transaction.getGasLimit() + dataGasUsed
387+
return transaction.getGasLimit() + dataGasUsed.toLong()
382388
> processableBlockHeader.getGasLimit() - transactionSelectionResult.getCumulativeGasUsed();
383389
}
384390

ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.hyperledger.besu.datatypes.Address;
2828
import org.hyperledger.besu.datatypes.Hash;
2929
import org.hyperledger.besu.datatypes.Wei;
30+
import org.hyperledger.besu.ethereum.GasLimitCalculator;
3031
import org.hyperledger.besu.ethereum.chain.Blockchain;
3132
import org.hyperledger.besu.ethereum.core.AddressHelpers;
3233
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -257,7 +258,8 @@ public void useSingleGasSpaceForAllTransactions() {
257258
this::isCancelled,
258259
miningBeneficiary,
259260
FeeMarket.london(0L),
260-
new LondonGasCalculator());
261+
new LondonGasCalculator(),
262+
GasLimitCalculator.constant());
261263

262264
// this should fill up all the block space
263265
final Transaction fillingLegacyTx =
@@ -455,7 +457,8 @@ protected BlockTransactionSelector createBlockSelector(
455457
this::isCancelled,
456458
miningBeneficiary,
457459
getFeeMarket(),
458-
new LondonGasCalculator());
460+
new LondonGasCalculator(),
461+
GasLimitCalculator.constant());
459462
return selector;
460463
}
461464

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

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

17+
import org.hyperledger.besu.datatypes.DataGas;
18+
1719
public interface GasLimitCalculator {
1820

1921
long nextGasLimit(long currentGasLimit, long targetGasLimit, long newBlockNumber);
2022

2123
static GasLimitCalculator constant() {
2224
return (currentGasLimit, targetGasLimit, newBlockNumber) -> currentGasLimit;
2325
}
26+
27+
default DataGas nextDataGasLimit() {
28+
return DataGas.ZERO;
29+
}
2430
}

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.hyperledger.besu.crypto.SignatureAlgorithm;
2525
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
2626
import org.hyperledger.besu.datatypes.Address;
27+
import org.hyperledger.besu.datatypes.DataGas;
2728
import org.hyperledger.besu.datatypes.Hash;
2829
import org.hyperledger.besu.datatypes.Wei;
2930
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
@@ -704,7 +705,7 @@ public boolean isContractCreation() {
704705
*
705706
* @return the max up-front cost for the gas the transaction can use.
706707
*/
707-
private Wei getMaxUpfrontGasCost(final int dataGasPerBlock) {
708+
private Wei getMaxUpfrontGasCost(final DataGas dataGasPerBlock) {
708709
return getUpfrontGasCost(
709710
getMaxGasPrice(), getMaxFeePerDataGas().orElse(Wei.ZERO), dataGasPerBlock);
710711
}
@@ -715,7 +716,7 @@ private Wei getMaxUpfrontGasCost(final int dataGasPerBlock) {
715716
* @return true is upfront data cost overflow uint256 max value
716717
*/
717718
private boolean isUpfrontGasCostTooHigh() {
718-
return calculateUpfrontGasCost(getMaxGasPrice(), Wei.ZERO, 0).bitLength() > 256;
719+
return calculateUpfrontGasCost(getMaxGasPrice(), Wei.ZERO, DataGas.ZERO).bitLength() > 256;
719720
}
720721

721722
/**
@@ -725,7 +726,8 @@ private boolean isUpfrontGasCostTooHigh() {
725726
* @param dataGasPrice the data gas price to use
726727
* @return the up-front cost for the gas the transaction can use.
727728
*/
728-
public Wei getUpfrontGasCost(final Wei gasPrice, final Wei dataGasPrice, final int totalDataGas) {
729+
public Wei getUpfrontGasCost(
730+
final Wei gasPrice, final Wei dataGasPrice, final DataGas totalDataGas) {
729731
if (gasPrice == null || gasPrice.isZero()) {
730732
return Wei.ZERO;
731733
}
@@ -740,12 +742,12 @@ public Wei getUpfrontGasCost(final Wei gasPrice, final Wei dataGasPrice, final i
740742
}
741743

742744
private BigInteger calculateUpfrontGasCost(
743-
final Wei gasPrice, final Wei dataGasPrice, final int totalDataGas) {
745+
final Wei gasPrice, final Wei dataGasPrice, final DataGas totalDataGas) {
744746
var cost =
745747
new BigInteger(1, Longs.toByteArray(getGasLimit())).multiply(gasPrice.getAsBigInteger());
746748

747749
if (transactionType.supportsBlob()) {
748-
cost = cost.add(dataGasPrice.getAsBigInteger().multiply(BigInteger.valueOf(totalDataGas)));
750+
cost = cost.add(dataGasPrice.getAsBigInteger().multiply(totalDataGas.getAsBigInteger()));
749751
}
750752

751753
return cost;
@@ -760,7 +762,7 @@ private BigInteger calculateUpfrontGasCost(
760762
*
761763
* @return the up-front gas cost for the transaction
762764
*/
763-
public Wei getUpfrontCost(final int totalDataGas) {
765+
public Wei getUpfrontCost(final DataGas totalDataGas) {
764766
return getMaxUpfrontGasCost(totalDataGas).addExact(getValue());
765767
}
766768

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2019 ConsenSys AG.
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 org.hyperledger.besu.datatypes.DataGas;
18+
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
19+
20+
public class CancunTargetingGasLimitCalculator extends LondonTargetingGasLimitCalculator {
21+
public static final DataGas MAX_DATA_GAS_PER_BLOCK = DataGas.of(524288); // 2^19
22+
23+
public CancunTargetingGasLimitCalculator(
24+
final long londonForkBlock, final BaseFeeMarket feeMarket) {
25+
super(londonForkBlock, feeMarket);
26+
}
27+
28+
@Override
29+
public DataGas nextDataGasLimit() {
30+
return MAX_DATA_GAS_PER_BLOCK;
31+
}
32+
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ public static ProtocolSpecBuilder tangerineWhistleDefinition(
7676
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode, evmConfiguration)
7777
.gasCalculator(TangerineWhistleGasCalculator::new)
7878
.transactionValidatorBuilder(
79-
gasCalculator ->
79+
(gasCalculator, gasLimitCalculator) ->
8080
new MainnetTransactionValidator(
81-
gasCalculator, true, chainId, quorumCompatibilityMode))
81+
gasCalculator, gasLimitCalculator, true, chainId, quorumCompatibilityMode))
8282
.name("ClassicTangerineWhistle");
8383
}
8484

@@ -149,9 +149,9 @@ public static ProtocolSpecBuilder defuseDifficultyBombDefinition(
149149
evmConfiguration)
150150
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_REMOVED)
151151
.transactionValidatorBuilder(
152-
gasCalculator ->
152+
(gasCalculator, gasLimitCalculator) ->
153153
new MainnetTransactionValidator(
154-
gasCalculator, true, chainId, quorumCompatibilityMode))
154+
gasCalculator, gasLimitCalculator, true, chainId, quorumCompatibilityMode))
155155
.name("DefuseDifficultyBomb");
156156
}
157157

@@ -353,9 +353,10 @@ public static ProtocolSpecBuilder magnetoDefinition(
353353
evmConfiguration)
354354
.gasCalculator(BerlinGasCalculator::new)
355355
.transactionValidatorBuilder(
356-
gasCalculator ->
356+
(gasCalculator, gasLimitCalculator) ->
357357
new MainnetTransactionValidator(
358358
gasCalculator,
359+
gasLimitCalculator,
359360
true,
360361
chainId,
361362
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST),

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

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.hyperledger.besu.datatypes.Address;
2020
import org.hyperledger.besu.datatypes.Wei;
2121
import org.hyperledger.besu.ethereum.BlockProcessingResult;
22+
import org.hyperledger.besu.ethereum.GasLimitCalculator;
2223
import org.hyperledger.besu.ethereum.MainnetBlockValidator;
2324
import org.hyperledger.besu.ethereum.chain.Blockchain;
2425
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -123,9 +124,9 @@ public static ProtocolSpecBuilder frontierDefinition(
123124
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
124125
0))
125126
.transactionValidatorBuilder(
126-
gasCalculator ->
127+
(gasCalculator, gasLimitCalculator) ->
127128
new MainnetTransactionValidator(
128-
gasCalculator, false, Optional.empty(), goQuorumMode))
129+
gasCalculator, gasLimitCalculator, false, Optional.empty(), goQuorumMode))
129130
.transactionProcessorBuilder(
130131
(gasCalculator,
131132
transactionValidator,
@@ -229,9 +230,13 @@ public static ProtocolSpecBuilder homesteadDefinition(
229230
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
230231
0))
231232
.transactionValidatorBuilder(
232-
gasCalculator ->
233+
(gasCalculator, gasLimitCalculator) ->
233234
new MainnetTransactionValidator(
234-
gasCalculator, true, Optional.empty(), quorumCompatibilityMode))
235+
gasCalculator,
236+
gasLimitCalculator,
237+
true,
238+
Optional.empty(),
239+
quorumCompatibilityMode))
235240
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
236241
.name("Homestead");
237242
}
@@ -316,9 +321,9 @@ public static ProtocolSpecBuilder spuriousDragonDefinition(
316321
1,
317322
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
318323
.transactionValidatorBuilder(
319-
gasCalculator ->
324+
(gasCalculator, gasLimitCalculator) ->
320325
new MainnetTransactionValidator(
321-
gasCalculator, true, chainId, quorumCompatibilityMode))
326+
gasCalculator, gasLimitCalculator, true, chainId, quorumCompatibilityMode))
322327
.transactionProcessorBuilder(
323328
(gasCalculator,
324329
transactionValidator,
@@ -483,9 +488,10 @@ static ProtocolSpecBuilder berlinDefinition(
483488
evmConfiguration)
484489
.gasCalculator(BerlinGasCalculator::new)
485490
.transactionValidatorBuilder(
486-
gasCalculator ->
491+
(gasCalculator, gasLimitCalculator) ->
487492
new MainnetTransactionValidator(
488493
gasCalculator,
494+
gasLimitCalculator,
489495
true,
490496
chainId,
491497
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST),
@@ -525,9 +531,10 @@ static ProtocolSpecBuilder londonDefinition(
525531
.gasLimitCalculator(
526532
new LondonTargetingGasLimitCalculator(londonForkBlockNumber, londonFeeMarket))
527533
.transactionValidatorBuilder(
528-
gasCalculator ->
534+
(gasCalculator, gasLimitCalculator) ->
529535
new MainnetTransactionValidator(
530536
gasCalculator,
537+
gasLimitCalculator,
531538
londonFeeMarket,
532539
true,
533540
chainId,
@@ -692,9 +699,10 @@ static ProtocolSpecBuilder shanghaiDefinition(
692699
CoinbaseFeePriceCalculator.eip1559()))
693700
// Contract creation rules for EIP-3860 Limit and meter intitcode
694701
.transactionValidatorBuilder(
695-
gasCalculator ->
702+
(gasCalculator, gasLimitCalculator) ->
696703
new MainnetTransactionValidator(
697704
gasCalculator,
705+
gasLimitCalculator,
698706
londonFeeMarket,
699707
true,
700708
chainId,
@@ -721,11 +729,14 @@ static ProtocolSpecBuilder cancunDefinition(
721729
final int contractSizeLimit =
722730
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
723731
final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L);
724-
final BaseFeeMarket londonFeeMarket =
732+
final BaseFeeMarket cancunFeeMarket =
725733
genesisConfigOptions.isZeroBaseFee()
726734
? FeeMarket.zeroBaseFee(londonForkBlockNumber)
727735
: FeeMarket.cancun(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas());
728736

737+
final GasLimitCalculator cancunGasLimitCalculator =
738+
new CancunTargetingGasLimitCalculator(londonForkBlockNumber, cancunFeeMarket);
739+
729740
return shanghaiDefinition(
730741
chainId,
731742
configContractSizeLimit,
@@ -736,6 +747,8 @@ static ProtocolSpecBuilder cancunDefinition(
736747
evmConfiguration)
737748
// gas calculator for EIP-4844 data gas
738749
.gasCalculator(CancunGasCalculator::new)
750+
// gas limit with EIP-4844 max data gas per block
751+
.gasLimitCalculator(cancunGasLimitCalculator)
739752
// EVM changes to support EOF EIPs (3670, 4200, 4750, 5450)
740753
.evmBuilder(
741754
(gasCalculator, jdCacheConfig) ->
@@ -754,10 +767,11 @@ static ProtocolSpecBuilder cancunDefinition(
754767
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
755768
// change to check for max data gas per block for EIP-4844
756769
.transactionValidatorBuilder(
757-
gasCalculator ->
770+
(gasCalculator, gasLimitCalculator) ->
758771
new MainnetTransactionValidator(
759772
gasCalculator,
760-
londonFeeMarket,
773+
gasLimitCalculator,
774+
cancunFeeMarket,
761775
true,
762776
chainId,
763777
Set.of(

0 commit comments

Comments
 (0)