diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 18ba82c02dd..cf6edb5a618 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuControllerBuilder; +import org.hyperledger.besu.controller.GasLimitCalculator; import org.hyperledger.besu.controller.KeyPairUtil; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; @@ -148,6 +149,7 @@ public void startNode(final BesuNode node) { .clock(Clock.systemUTC()) .isRevertReasonEnabled(node.isRevertReasonEnabled()) .storageProvider(storageProvider) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); } catch (final IOException e) { throw new RuntimeException("Error building BesuController", e); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 4e2519056f7..29bad3e6da2 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -662,6 +662,12 @@ void setBannedNodeIds(final List values) { "The name of a file containing the private key used to sign privacy marker transactions. If unset, each will be signed with a random key.") private final Path privacyMarkerTransactionSigningKeyPath = null; + @Option( + names = {"--target-gas-limit"}, + description = + "Sets target gas limit per block. If set each blocks gas limit will approach this setting over time if the current gas limit is different.") + private final Long targetGasLimit = null; + @Option( names = {"--tx-pool-max-size"}, paramLabel = MANDATORY_INTEGER_FORMAT_HELP, @@ -1078,7 +1084,8 @@ public BesuControllerBuilder getControllerBuilder() { .storageProvider(keyStorageProvider(keyValueStorageName)) .isPruningEnabled(isPruningEnabled) .pruningConfiguration(buildPruningConfiguration()) - .genesisConfigOverrides(genesisConfigOverrides); + .genesisConfigOverrides(genesisConfigOverrides) + .targetGasLimit(targetGasLimit == null ? Optional.empty() : Optional.of(targetGasLimit)); } catch (final IOException e) { throw new ExecutionException(this.commandLine, "Invalid path", e); } diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 6a82b6197b8..b786c89c6af 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -84,6 +84,7 @@ public abstract class BesuControllerBuilder { protected Clock clock; protected KeyPair nodeKeys; protected boolean isRevertReasonEnabled; + protected GasLimitCalculator gasLimitCalculator; private StorageProvider storageProvider; private final List shutdownActions = new ArrayList<>(); private boolean isPruningEnabled; @@ -181,6 +182,11 @@ public BesuControllerBuilder genesisConfigOverrides( return this; } + public BesuControllerBuilder targetGasLimit(final Optional targetGasLimit) { + this.gasLimitCalculator = new GasLimitCalculator(targetGasLimit); + return this; + } + public BesuController build() { checkNotNull(genesisConfig, "Missing genesis config"); checkNotNull(syncConfig, "Missing sync config"); @@ -194,6 +200,7 @@ public BesuController build() { checkNotNull(transactionPoolConfiguration, "Missing transaction pool configuration"); checkNotNull(nodeKeys, "Missing node keys"); checkNotNull(storageProvider, "Must supply a storage provider"); + checkNotNull(gasLimitCalculator, "Missing gas limit calculator"); prepForBuild(); diff --git a/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java index 1af2f0aab74..bc5ebd1bef9 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java @@ -96,7 +96,8 @@ protected MiningCoordinator createMiningCoordinator( protocolContext.getConsensusState().getVoteTallyCache(), localAddress, secondsBetweenBlocks), - epochManager); + epochManager, + gasLimitCalculator); final CliqueMiningCoordinator miningCoordinator = new CliqueMiningCoordinator( protocolContext.getBlockchain(), diff --git a/besu/src/main/java/org/hyperledger/besu/controller/GasLimitCalculator.java b/besu/src/main/java/org/hyperledger/besu/controller/GasLimitCalculator.java new file mode 100644 index 00000000000..fbcf6bcb7bb --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/controller/GasLimitCalculator.java @@ -0,0 +1,75 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * 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.controller; + +import java.util.Optional; +import java.util.function.Function; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class GasLimitCalculator implements Function { + private static final Logger LOG = LogManager.getLogger(); + public static final long ADJUSTMENT_FACTOR = 1024L; + public static final Optional DEFAULT = Optional.empty(); + private final Optional targetGasLimit; + + public GasLimitCalculator(final Optional targetGasLimit) { + if (targetGasLimit.orElse(0L) < 0L) { + throw new IllegalArgumentException("Invalid target gas limit"); + } + + this.targetGasLimit = targetGasLimit; + } + + @Override + public Long apply(final Long gasLimit) { + long newGasLimit = + targetGasLimit + .map( + target -> { + if (target > gasLimit) { + return Math.min(target, safeAdd(gasLimit)); + } else if (target < gasLimit) { + return Math.max(target, safeSub(gasLimit)); + } else { + return gasLimit; + } + }) + .orElse(gasLimit); + + if (newGasLimit != gasLimit) { + LOG.debug("Adjusting block gas limit from {} to {}", gasLimit, newGasLimit); + } + + return newGasLimit; + } + + private long safeAdd(final long gasLimit) { + try { + return Math.addExact(gasLimit, ADJUSTMENT_FACTOR); + } catch (final ArithmeticException ex) { + return Long.MAX_VALUE; + } + } + + private long safeSub(final long gasLimit) { + try { + return Math.max(Math.subtractExact(gasLimit, ADJUSTMENT_FACTOR), 0); + } catch (final ArithmeticException ex) { + return 0; + } + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java index 80cdd78cc40..993042caa2e 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java @@ -113,7 +113,7 @@ protected MiningCoordinator createMiningCoordinator( final IbftBlockCreatorFactory blockCreatorFactory = new IbftBlockCreatorFactory( - (gasLimit) -> gasLimit, + gasLimitCalculator, transactionPool.getPendingTransactions(), protocolContext, protocolSchedule, diff --git a/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java index d2d4c94e621..617c10c8aff 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java @@ -58,7 +58,8 @@ protected MiningCoordinator createMiningCoordinator( new DefaultBlockScheduler( MainnetBlockHeaderValidator.MINIMUM_SECONDS_SINCE_PARENT, MainnetBlockHeaderValidator.TIMESTAMP_TOLERANCE_S, - clock)); + clock), + gasLimitCalculator); final EthHashMiningCoordinator miningCoordinator = new EthHashMiningCoordinator(protocolContext.getBlockchain(), executor, syncState); diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java index c3eb5b42fd2..3f477978766 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.controller.BesuController; +import org.hyperledger.besu.controller.GasLimitCalculator; import org.hyperledger.besu.crypto.SECP256K1.KeyPair; import org.hyperledger.besu.ethereum.core.Account; import org.hyperledger.besu.ethereum.core.Address; @@ -80,6 +81,7 @@ public void privacyPrecompiled() throws IOException { .clock(TestClock.fixed()) .privacyParameters(privacyParameters) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); final Address privacyContractAddress = Address.privacyPrecompiled(ADDRESS); diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index 6348ac07bf8..4703b1dc5bd 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.controller.BesuController; +import org.hyperledger.besu.controller.GasLimitCalculator; import org.hyperledger.besu.controller.KeyPairUtil; import org.hyperledger.besu.controller.MainnetBesuControllerBuilder; import org.hyperledger.besu.crypto.SECP256K1.KeyPair; @@ -149,6 +150,7 @@ private void syncFromGenesis(final SyncMode mode, final GenesisConfigFile genesi .clock(TestClock.fixed()) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) .storageProvider(createKeyValueStorageProvider(dataDirAhead, dbAhead)) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build()) { setupState(blockCount, controller.getProtocolSchedule(), controller.getProtocolContext()); } @@ -168,6 +170,7 @@ private void syncFromGenesis(final SyncMode mode, final GenesisConfigFile genesi .clock(TestClock.fixed()) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) .storageProvider(createKeyValueStorageProvider(dataDirAhead, dbAhead)) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); final String listenHost = InetAddress.getLoopbackAddress().getHostAddress(); final JsonRpcConfiguration aheadJsonRpcConfiguration = jsonRpcConfiguration(); @@ -226,6 +229,7 @@ private void syncFromGenesis(final SyncMode mode, final GenesisConfigFile genesi .privacyParameters(PrivacyParameters.DEFAULT) .clock(TestClock.fixed()) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); final EnodeURL enode = runnerAhead.getLocalEnode().get(); final EthNetworkConfig behindEthNetworkConfiguration = diff --git a/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java index 59a9bfe4d9f..f6c216f3df0 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.controller.BesuController; +import org.hyperledger.besu.controller.GasLimitCalculator; import org.hyperledger.besu.crypto.SECP256K1.KeyPair; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Block; @@ -90,6 +91,7 @@ private static BesuController createController() throws IOException { .dataDirectory(dataDir) .clock(TestClock.fixed()) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); } diff --git a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java index f1d68461c3f..268bd08843f 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.controller.BesuController; +import org.hyperledger.besu.controller.GasLimitCalculator; import org.hyperledger.besu.crypto.SECP256K1.KeyPair; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Address; @@ -427,6 +428,7 @@ protected BesuController createController(final GenesisConfigFile genesisConf .dataDirectory(dataDir) .clock(TestClock.fixed()) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); } } diff --git a/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java index e52007d6cad..d8cc70b8fd7 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.controller.BesuController; +import org.hyperledger.besu.controller.GasLimitCalculator; import org.hyperledger.besu.crypto.SECP256K1.KeyPair; import org.hyperledger.besu.ethereum.core.InMemoryStorageProvider; import org.hyperledger.besu.ethereum.core.MiningParametersTestBuilder; @@ -68,6 +69,7 @@ public void blockImport() throws IOException { .dataDirectory(dataDir) .clock(TestClock.fixed()) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); final RlpBlockImporter.ImportResult result = rlpBlockImporter.importBlockchain(source, targetController); @@ -107,6 +109,7 @@ public void ibftImport() throws IOException { .dataDirectory(dataDir) .clock(TestClock.fixed()) .transactionPoolConfiguration(TransactionPoolConfiguration.builder().build()) + .targetGasLimit(GasLimitCalculator.DEFAULT) .build(); final RlpBlockImporter.ImportResult result = rlpBlockImporter.importBlockchain(source, controller); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 679f2a4b767..29ca217a55c 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -176,6 +176,7 @@ public void callingBesuCommandWithoutOptionsMustSyncWithDefaultValues() throws E verify(mockControllerBuilder).miningParameters(miningArg.capture()); verify(mockControllerBuilder).nodePrivateKeyFile(isNotNull()); verify(mockControllerBuilder).storageProvider(storageProviderArgumentCaptor.capture()); + verify(mockControllerBuilder).targetGasLimit(eq(Optional.empty())); verify(mockControllerBuilder).build(); assertThat(storageProviderArgumentCaptor.getValue()).isNotNull(); @@ -2753,4 +2754,38 @@ public void tomlThatHasInvalidOptions() throws IOException { assertThat(commandErrorOutput.toString()) .contains("Unknown options in TOML configuration file: invalid_option, invalid_option2"); } + + @Test + public void targetGasLimitIsEnabledWhenSpecified() throws Exception { + parseCommand("--target-gas-limit=10000000"); + + @SuppressWarnings("unchecked") + final ArgumentCaptor> targetGasLimitArg = + ArgumentCaptor.forClass(Optional.class); + + verify(mockControllerBuilder).targetGasLimit(targetGasLimitArg.capture()); + verify(mockControllerBuilder).build(); + + assertThat(commandOutput.toString()).isEmpty(); + assertThat(commandErrorOutput.toString()).isEmpty(); + + assertThat(targetGasLimitArg.getValue()).isEqualTo(Optional.of(10_000_000L)); + } + + @Test + public void targetGasLimitIsDisabledWhenNotSpecified() throws Exception { + parseCommand(); + + @SuppressWarnings("unchecked") + final ArgumentCaptor> targetGasLimitArg = + ArgumentCaptor.forClass(Optional.class); + + verify(mockControllerBuilder).targetGasLimit(targetGasLimitArg.capture()); + verify(mockControllerBuilder).build(); + + assertThat(commandOutput.toString()).isEmpty(); + assertThat(commandErrorOutput.toString()).isEmpty(); + + assertThat(targetGasLimitArg.getValue()).isEqualTo(Optional.empty()); + } } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index cc05087c5c4..0bf32d917b2 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -169,6 +169,7 @@ public void initMocks() throws Exception { when(mockControllerBuilder.isPruningEnabled(anyBoolean())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.pruningConfiguration(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.genesisConfigOverrides(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.targetGasLimit(any())).thenReturn(mockControllerBuilder); // doReturn used because of generic BesuController doReturn(mockController).when(mockControllerBuilder).build(); diff --git a/besu/src/test/java/org/hyperledger/besu/controller/GasLimitCalculatorTest.java b/besu/src/test/java/org/hyperledger/besu/controller/GasLimitCalculatorTest.java new file mode 100644 index 00000000000..a7903a981e2 --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/controller/GasLimitCalculatorTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * 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.controller; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; +import java.util.function.Function; + +import org.junit.Test; + +public class GasLimitCalculatorTest { + @Test + public void verifyGasLimitIsIncreasedWithinLimits() { + Function gasLimitCalculator = new GasLimitCalculator(Optional.of(10_000_000L)); + assertThat(gasLimitCalculator.apply(8_000_000L)) + .isEqualTo(8_000_000L + GasLimitCalculator.ADJUSTMENT_FACTOR); + } + + @Test + public void verifyGasLimitIsDecreasedWithinLimits() { + Function gasLimitCalculator = new GasLimitCalculator(Optional.of(10_000_000L)); + assertThat(gasLimitCalculator.apply(12_000_000L)) + .isEqualTo(12_000_000L - GasLimitCalculator.ADJUSTMENT_FACTOR); + } + + @Test + public void verifyGasLimitReachesTarget() { + final long target = 10_000_000L; + final long offset = GasLimitCalculator.ADJUSTMENT_FACTOR / 2; + Function gasLimitCalculator = new GasLimitCalculator(Optional.of(target)); + assertThat(gasLimitCalculator.apply(target - offset)).isEqualTo(target); + assertThat(gasLimitCalculator.apply(target + offset)).isEqualTo(target); + } + + @Test + public void verifyNoNegative() { + final long target = 0L; + final long offset = GasLimitCalculator.ADJUSTMENT_FACTOR / 2; + Function gasLimitCalculator = new GasLimitCalculator(Optional.of(target)); + assertThat(gasLimitCalculator.apply(target + offset)).isEqualTo(target); + } + + @Test + public void verifyNoOverflow() { + final long target = Long.MAX_VALUE; + final long offset = GasLimitCalculator.ADJUSTMENT_FACTOR / 2; + Function gasLimitCalculator = new GasLimitCalculator(Optional.of(target)); + assertThat(gasLimitCalculator.apply(target - offset)).isEqualTo(target); + } +} diff --git a/besu/src/test/resources/everything_config.toml b/besu/src/test/resources/everything_config.toml index c5ffd7dd9fb..df223091c88 100644 --- a/besu/src/test/resources/everything_config.toml +++ b/besu/src/test/resources/everything_config.toml @@ -109,3 +109,6 @@ revert-reason-enabled=false # Storage plugin to use key-value-storage="rocksdb" + +# Gas limit +target-gas-limit=8000000 \ No newline at end of file diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java index 689e0a28fb8..0a449fdafb4 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java @@ -55,14 +55,16 @@ public CliqueMinerExecutor( final KeyPair nodeKeys, final MiningParameters miningParams, final AbstractBlockScheduler blockScheduler, - final EpochManager epochManager) { + final EpochManager epochManager, + final Function gasLimitCalculator) { super( protocolContext, executorService, protocolSchedule, pendingTransactions, miningParams, - blockScheduler); + blockScheduler, + gasLimitCalculator); this.nodeKeys = nodeKeys; this.localAddress = Util.publicKeyToAddress(nodeKeys.getPublicKey()); this.epochManager = epochManager; @@ -91,7 +93,7 @@ private CliqueBlockMiner createMiner( pendingTransactions, protocolContext, protocolSchedule, - (gasLimit) -> gasLimit, + gasLimitCalculator, nodeKeys, minTransactionGasPrice, header, diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java index f329921bd4d..098359b4cdd 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java @@ -49,6 +49,7 @@ import java.util.List; import java.util.Random; import java.util.concurrent.Executors; +import java.util.function.Function; import com.google.common.collect.Lists; import org.junit.Before; @@ -103,7 +104,8 @@ public void extraDataCreatedOnEpochBlocksContainsValidators() { proposerKeyPair, new MiningParameters(AddressHelpers.ofValue(1), Wei.ZERO, vanityData, false), mock(CliqueBlockScheduler.class), - new EpochManager(EPOCH_LENGTH)); + new EpochManager(EPOCH_LENGTH), + Function.identity()); // NOTE: Passing in the *parent* block, so must be 1 less than EPOCH final BlockHeader header = blockHeaderBuilder.number(EPOCH_LENGTH - 1).buildHeader(); @@ -140,7 +142,8 @@ public void extraDataForNonEpochBlocksDoesNotContainValidaors() { proposerKeyPair, new MiningParameters(AddressHelpers.ofValue(1), Wei.ZERO, vanityData, false), mock(CliqueBlockScheduler.class), - new EpochManager(EPOCH_LENGTH)); + new EpochManager(EPOCH_LENGTH), + Function.identity()); // Parent block was epoch, so the next block should contain no validators. final BlockHeader header = blockHeaderBuilder.number(EPOCH_LENGTH).buildHeader(); @@ -177,7 +180,8 @@ public void shouldUseLatestVanityData() { proposerKeyPair, new MiningParameters(AddressHelpers.ofValue(1), Wei.ZERO, initialVanityData, false), mock(CliqueBlockScheduler.class), - new EpochManager(EPOCH_LENGTH)); + new EpochManager(EPOCH_LENGTH), + Function.identity()); executor.setExtraData(modifiedVanityData); final BytesValue extraDataBytes = executor.calculateExtraData(blockHeaderBuilder.buildHeader()); diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMinerExecutor.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMinerExecutor.java index ae9fa8688cc..ce0ba2a1c0a 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMinerExecutor.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMinerExecutor.java @@ -27,6 +27,7 @@ import java.util.Optional; import java.util.concurrent.ExecutorService; +import java.util.function.Function; public abstract class AbstractMinerExecutor< C, M extends BlockMiner>> { @@ -36,6 +37,7 @@ public abstract class AbstractMinerExecutor< protected final ProtocolSchedule protocolSchedule; protected final PendingTransactions pendingTransactions; protected final AbstractBlockScheduler blockScheduler; + protected final Function gasLimitCalculator; protected volatile BytesValue extraData; protected volatile Wei minTransactionGasPrice; @@ -46,7 +48,8 @@ public AbstractMinerExecutor( final ProtocolSchedule protocolSchedule, final PendingTransactions pendingTransactions, final MiningParameters miningParams, - final AbstractBlockScheduler blockScheduler) { + final AbstractBlockScheduler blockScheduler, + final Function gasLimitCalculator) { this.protocolContext = protocolContext; this.executorService = executorService; this.protocolSchedule = protocolSchedule; @@ -54,6 +57,7 @@ public AbstractMinerExecutor( this.extraData = miningParams.getExtraData(); this.minTransactionGasPrice = miningParams.getMinTransactionGasPrice(); this.blockScheduler = blockScheduler; + this.gasLimitCalculator = gasLimitCalculator; } public abstract M startAsyncMining( diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutor.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutor.java index ed395fe04e8..4298f6e928d 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutor.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutor.java @@ -39,14 +39,16 @@ public EthHashMinerExecutor( final ProtocolSchedule protocolSchedule, final PendingTransactions pendingTransactions, final MiningParameters miningParams, - final AbstractBlockScheduler blockScheduler) { + final AbstractBlockScheduler blockScheduler, + final Function gasLimitCalculator) { super( protocolContext, executorService, protocolSchedule, pendingTransactions, miningParams, - blockScheduler); + blockScheduler, + gasLimitCalculator); this.coinbase = miningParams.getCoinbase(); } @@ -79,7 +81,7 @@ private EthHashBlockMiner createMiner( pendingTransactions, protocolContext, protocolSchedule, - (gasLimit) -> gasLimit, + gasLimitCalculator, solver, minTransactionGasPrice, parentHeader); diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutorTest.java index 5f64e916344..a0137fa2d3b 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/EthHashMinerExecutorTest.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.util.Subscribers; import java.util.concurrent.Executors; +import java.util.function.Function; import org.junit.Test; @@ -51,7 +52,8 @@ public void startingMiningWithoutCoinbaseThrowsException() { null, pendingTransactions, miningParameters, - new DefaultBlockScheduler(1, 10, TestClock.fixed())); + new DefaultBlockScheduler(1, 10, TestClock.fixed()), + Function.identity()); assertThatExceptionOfType(CoinbaseNotSetException.class) .isThrownBy(() -> executor.startAsyncMining(Subscribers.create(), null)) @@ -76,7 +78,8 @@ public void settingCoinbaseToNullThrowsException() { null, pendingTransactions, miningParameters, - new DefaultBlockScheduler(1, 10, TestClock.fixed())); + new DefaultBlockScheduler(1, 10, TestClock.fixed()), + Function.identity()); assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> executor.setCoinbase(null))