diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java index 048e40553ba..f01c58549bc 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java @@ -110,9 +110,11 @@ public void startNode(final BesuNode node) { params.add( Integer.toString(node.getMiningParameters().getMinTransactionGasPrice().intValue())); params.add("--Xminer-remote-sealers-limit"); - params.add(Integer.toString(node.getMiningParameters().getRemoteSealersLimit())); + params.add( + Integer.toString(node.getMiningParameters().getUnstable().getRemoteSealersLimit())); params.add("--Xminer-remote-sealers-hashrate-ttl"); - params.add(Long.toString(node.getMiningParameters().getRemoteSealersTimeToLive())); + params.add( + Long.toString(node.getMiningParameters().getUnstable().getRemoteSealersTimeToLive())); } if (node.getMiningParameters().isStratumMiningEnabled()) { params.add("--miner-stratum-enabled"); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java index 4943aaf60eb..fea87c35088 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java @@ -22,7 +22,6 @@ import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.crypto.KeyPair; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; @@ -30,6 +29,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; import org.hyperledger.besu.ethereum.core.AddressHelpers; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; @@ -56,11 +57,11 @@ public class BesuNodeConfigurationBuilder { private String name; private Optional dataPath = Optional.empty(); private MiningParameters miningParameters = - new MiningParameters.Builder() - .miningEnabled(false) - .coinbase(AddressHelpers.ofValue(1)) - .minTransactionGasPrice(Wei.of(1000)) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder().coinbase(AddressHelpers.ofValue(1)).build()) .build(); + private JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault(); private JsonRpcConfiguration engineRpcConfiguration = JsonRpcConfiguration.createEngineDefault(); private WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault(); @@ -113,12 +114,7 @@ public BesuNodeConfigurationBuilder miningEnabled() { } public BesuNodeConfigurationBuilder miningEnabled(final boolean enabled) { - this.miningParameters = - new MiningParameters.Builder() - .miningEnabled(enabled) - .minTransactionGasPrice(Wei.of(1000)) - .coinbase(AddressHelpers.ofValue(1)) - .build(); + this.miningParameters = miningParameters.setMiningEnabled(enabled); this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER.name()); return this; } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index bd635c6bfcf..9e35d09f2fc 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -26,6 +26,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.core.AddressHelpers; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.InMemoryPrivacyStorageProvider; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; @@ -303,10 +305,13 @@ public BesuNode createNodeWithMultiTenantedPrivacy( .build(); final MiningParameters miningParameters = - new MiningParameters.Builder() - .minTransactionGasPrice(Wei.ZERO) - .coinbase(AddressHelpers.ofValue(1)) - .miningEnabled(true) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .isMiningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(AddressHelpers.ofValue(1)) + .build()) .build(); return create( diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java index e529268cb59..a109a3b8567 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java @@ -17,6 +17,8 @@ import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.AddressHelpers; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; @@ -59,10 +61,13 @@ public void shouldMineOnSingleNodeWithPaidGas_Berlin() throws Exception { public void shouldMineOnSingleNodeWithFreeGas_Berlin() throws Exception { final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); final MiningParameters zeroGasMiningParams = - new MiningParameters.Builder() - .miningEnabled(true) - .minTransactionGasPrice(Wei.ZERO) - .coinbase(AddressHelpers.ofValue(1)) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .isMiningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(AddressHelpers.ofValue(1)) + .build()) .build(); minerNode.setMiningParameters(zeroGasMiningParams); diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index 857fd4e093e..4dc137fe3c7 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -768,7 +768,7 @@ public Runner build() { powMiningCoordinator, miningParameters.getStratumPort(), miningParameters.getStratumNetworkInterface(), - miningParameters.getStratumExtranonce(), + miningParameters.getUnstable().getStratumExtranonce(), metricsSystem)); miningCoordinator.addEthHashObserver(stratumServer.get()); LOG.debug("added ethash observer: {}", stratumServer.get()); 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 d7ce4dfa539..6d6bed2bfcf 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -53,6 +53,7 @@ import org.hyperledger.besu.cli.custom.RpcAuthFileValidator; import org.hyperledger.besu.cli.error.BesuExecutionExceptionHandler; import org.hyperledger.besu.cli.error.BesuParameterExceptionHandler; +import org.hyperledger.besu.cli.options.MiningOptions; import org.hyperledger.besu.cli.options.stable.DataStorageOptions; import org.hyperledger.besu.cli.options.stable.EthstatsOptions; import org.hyperledger.besu.cli.options.stable.LoggingLevelOption; @@ -65,7 +66,6 @@ import org.hyperledger.besu.cli.options.unstable.EvmOptions; import org.hyperledger.besu.cli.options.unstable.IpcOptions; import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions; -import org.hyperledger.besu.cli.options.unstable.MiningOptions; import org.hyperledger.besu.cli.options.unstable.NatOptions; import org.hyperledger.besu.cli.options.unstable.NativeLibraryOptions; import org.hyperledger.besu.cli.options.unstable.NetworkingOptions; @@ -287,7 +287,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable { unstableTransactionPoolOptions = org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions.create(); private final DnsOptions unstableDnsOptions = DnsOptions.create(); - private final MiningOptions unstableMiningOptions = MiningOptions.create(); private final NatOptions unstableNatOptions = NatOptions.create(); private final NativeLibraryOptions unstableNativeLibraryOptions = NativeLibraryOptions.create(); private final RPCOptions unstableRPCOptions = RPCOptions.create(); @@ -307,6 +306,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable { final org.hyperledger.besu.cli.options.stable.TransactionPoolOptions stableTransactionPoolOptions = TransactionPoolOptions.create(); + @CommandLine.ArgGroup(validate = false, heading = "@|bold Block Builder Options|@%n") + final MiningOptions miningOptions = MiningOptions.create(); + private final RunnerBuilder runnerBuilder; private final BesuController.Builder controllerBuilderFactory; private final BesuPluginContextImpl besuPluginContext; @@ -1068,63 +1070,6 @@ static class MetricsOptionGroup { "How deep a chain reorganization must be in order for it to be logged (default: ${DEFAULT-VALUE})") private final Long reorgLoggingThreshold = 6L; - // Miner options group - @CommandLine.ArgGroup(validate = false, heading = "@|bold Miner Options|@%n") - MinerOptionGroup minerOptionGroup = new MinerOptionGroup(); - - static class MinerOptionGroup { - @Option( - names = {"--miner-enabled"}, - description = "Set if node will perform mining (default: ${DEFAULT-VALUE})") - private final Boolean isMiningEnabled = false; - - @Option( - names = {"--miner-stratum-enabled"}, - description = "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})") - private final Boolean iStratumMiningEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--miner-stratum-host"}, - description = "Host for Stratum network mining service (default: ${DEFAULT-VALUE})") - private String stratumNetworkInterface = "0.0.0.0"; - - @Option( - names = {"--miner-stratum-port"}, - description = "Stratum port binding (default: ${DEFAULT-VALUE})") - private final Integer stratumPort = 8008; - - @Option( - names = {"--miner-coinbase"}, - description = - "Account to which mining rewards are paid. You must specify a valid coinbase if " - + "mining is enabled using --miner-enabled option", - arity = "1") - private final Address coinbase = null; - - @Option( - names = {"--miner-extra-data"}, - description = - "A hex string representing the (32) bytes to be included in the extra data " - + "field of a mined block (default: ${DEFAULT-VALUE})", - arity = "1") - private final Bytes extraData = DEFAULT_EXTRA_DATA; - } - - @Option( - names = {"--min-gas-price"}, - description = - "Minimum price (in Wei) offered by a transaction for it to be included in a mined " - + "block (default: ${DEFAULT-VALUE})", - arity = "1") - private final Wei minTransactionGasPrice = DEFAULT_MIN_TRANSACTION_GAS_PRICE; - - @Option( - names = {"--min-block-occupancy-ratio"}, - description = "Minimum occupancy ratio for a mined block (default: ${DEFAULT-VALUE})", - arity = "1") - private final Double minBlockOccupancyRatio = DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO; - @Option( names = {"--pruning-enabled"}, description = @@ -1204,12 +1149,6 @@ static class PermissionsOptionGroup { split = ",") private final Map requiredBlocks = new HashMap<>(); - @Option( - names = {"--target-gas-limit"}, - description = - "Sets target gas limit per block. If set, each block's gas limit will approach this setting over time if the current gas limit is different.") - private final Long targetGasLimit = null; - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. @Option( names = {"--key-value-storage"}, @@ -1316,6 +1255,7 @@ static class PermissionsOptionGroup { private Collection staticNodes; private BesuController besuController; private BesuConfiguration pluginCommonConfiguration; + private MiningParameters miningParameters; private BesuComponent besuComponent; private final Supplier metricsSystem = @@ -1586,7 +1526,6 @@ private void handleUnstableOptions() { .put("Privacy Plugin Configuration", unstablePrivacyPluginOptions) .put("Synchronizer", unstableSynchronizerOptions) .put("TransactionPool", unstableTransactionPoolOptions) - .put("Mining", unstableMiningOptions) .put("Native Library", unstableNativeLibraryOptions) .put("EVM Options", unstableEvmOptions) .put("IPC Options", unstableIpcOptions) @@ -1728,7 +1667,7 @@ private void validatePluginOptions() { "--privacy-marker-transaction-signing-key-file can not be used in conjunction with a plugin that specifies a PrivateMarkerTransactionFactory"); } - if (Wei.ZERO.compareTo(minTransactionGasPrice) < 0 + if (Wei.ZERO.compareTo(getMiningParameters().getMinTransactionGasPrice()) < 0 && (privacyOptionGroup.privateMarkerTransactionSigningKeyPath == null && (privacyPluginService == null || privacyPluginService.getPrivateMarkerTransactionFactory() == null))) { @@ -1871,35 +1810,9 @@ private void validateRequiredOptions() { }); } - @SuppressWarnings("ConstantConditions") private void validateMiningParams() { - if (Boolean.TRUE.equals(minerOptionGroup.isMiningEnabled) - && minerOptionGroup.coinbase == null) { - throw new ParameterException( - this.commandLine, - "Unable to mine without a valid coinbase. Either disable mining (remove --miner-enabled) " - + "or specify the beneficiary of mining (via --miner-coinbase
)"); - } - if (Boolean.FALSE.equals(minerOptionGroup.isMiningEnabled) - && Boolean.TRUE.equals(minerOptionGroup.iStratumMiningEnabled)) { - throw new ParameterException( - this.commandLine, - "Unable to mine with Stratum if mining is disabled. Either disable Stratum mining (remove --miner-stratum-enabled) " - + "or specify mining is enabled (--miner-enabled)"); - } - if (unstableMiningOptions.getPosBlockCreationMaxTime() <= 0 - || unstableMiningOptions.getPosBlockCreationMaxTime() - > MiningParameters.DEFAULT_POS_BLOCK_CREATION_MAX_TIME) { - throw new ParameterException( - this.commandLine, "--Xpos-block-creation-max-time must be positive and ≤ 12000"); - } - - if (unstableMiningOptions.getPosBlockCreationRepetitionMinDuration() <= 0 - || unstableMiningOptions.getPosBlockCreationRepetitionMinDuration() > 2000) { - throw new ParameterException( - this.commandLine, - "--Xpos-block-creation-repetition-min-duration must be positive and ≤ 2000"); - } + miningOptions.validate( + commandLine, logger, isMergeEnabled(), getActualGenesisConfigOptions().isEthHash()); } /** @@ -2072,31 +1985,6 @@ private void issueOptionWarnings() { "--p2p-port", "--remote-connections-max-percentage")); - // Check that block producer options work - if (!isMergeEnabled() && getActualGenesisConfigOptions().isEthHash()) { - CommandLineUtils.checkOptionDependencies( - logger, - commandLine, - "--miner-enabled", - !minerOptionGroup.isMiningEnabled, - asList( - "--miner-coinbase", - "--min-gas-price", - "--min-block-occupancy-ratio", - "--miner-extra-data")); - - // Check that mining options are able to work - CommandLineUtils.checkOptionDependencies( - logger, - commandLine, - "--miner-enabled", - !minerOptionGroup.isMiningEnabled, - asList( - "--miner-stratum-enabled", - "--Xminer-remote-sealers-limit", - "--Xminer-remote-sealers-hashrate-ttl")); - } - CommandLineUtils.failIfOptionDoesntMeetRequirement( commandLine, "--fast-sync-min-peers can't be used with FULL sync-mode", @@ -2250,26 +2138,7 @@ public BesuControllerBuilder getControllerBuilder() { .transactionSelectorFactory(getTransactionSelectorFactory()) .pluginTransactionValidatorFactory(getPluginTransactionValidatorFactory()) .dataDirectory(dataDir()) - .miningParameters( - new MiningParameters.Builder() - .coinbase(minerOptionGroup.coinbase) - .targetGasLimit(targetGasLimit) - .minTransactionGasPrice(minTransactionGasPrice) - .extraData(minerOptionGroup.extraData) - .miningEnabled(minerOptionGroup.isMiningEnabled) - .stratumMiningEnabled(minerOptionGroup.iStratumMiningEnabled) - .stratumNetworkInterface(minerOptionGroup.stratumNetworkInterface) - .stratumPort(minerOptionGroup.stratumPort) - .stratumExtranonce(unstableMiningOptions.getStratumExtranonce()) - .minBlockOccupancyRatio(minBlockOccupancyRatio) - .remoteSealersLimit(unstableMiningOptions.getRemoteSealersLimit()) - .remoteSealersTimeToLive(unstableMiningOptions.getRemoteSealersTimeToLive()) - .powJobTimeToLive(unstableMiningOptions.getPowJobTimeToLive()) - .maxOmmerDepth(unstableMiningOptions.getMaxOmmersDepth()) - .posBlockCreationMaxTime(unstableMiningOptions.getPosBlockCreationMaxTime()) - .posBlockCreationRepetitionMinDuration( - unstableMiningOptions.getPosBlockCreationRepetitionMinDuration()) - .build()) + .miningParameters(getMiningParameters()) .transactionPoolConfiguration(buildTransactionPoolConfiguration()) .nodeKey(new NodeKey(securityModule())) .metricsSystem(metricsSystem.get()) @@ -2284,9 +2153,9 @@ public BesuControllerBuilder getControllerBuilder() { new PrunerConfiguration(pruningBlockConfirmations, pruningBlocksRetained)) .genesisConfigOverrides(genesisConfigOverrides) .gasLimitCalculator( - Optional.ofNullable(targetGasLimit) - .map(z -> new FrontierTargetingGasLimitCalculator()) - .orElse(GasLimitCalculator.constant())) + getMiningParameters().getTargetGasLimit().isPresent() + ? new FrontierTargetingGasLimitCalculator() + : GasLimitCalculator.constant()) .requiredBlocks(requiredBlocks) .reorgLoggingThreshold(reorgLoggingThreshold) .evmConfiguration(unstableEvmOptions.toDomainObject()) @@ -2613,7 +2482,8 @@ private ApiConfiguration apiConfiguration() { return ImmutableApiConfiguration.builder() .gasPriceBlocks(apiGasPriceBlocks) .gasPricePercentile(apiGasPricePercentile) - .gasPriceMin(minTransactionGasPrice.toLong()) + .gasPriceMinSupplier( + getMiningParameters().getMinTransactionGasPrice().getAsBigInteger()::longValueExact) .gasPriceMax(apiGasPriceMax) .build(); } @@ -2949,6 +2819,13 @@ private TransactionPoolConfiguration buildTransactionPoolConfiguration() { .build(); } + private MiningParameters getMiningParameters() { + if (miningParameters == null) { + miningParameters = miningOptions.toDomainObject(); + } + return miningParameters; + } + private boolean isPruningEnabled() { return pruningEnabled; } @@ -3344,7 +3221,9 @@ private List getEffectivePorts() { addPortIfEnabled( effectivePorts, metricsOptionGroup.metricsPort, metricsOptionGroup.isMetricsEnabled); addPortIfEnabled( - effectivePorts, minerOptionGroup.stratumPort, minerOptionGroup.iStratumMiningEnabled); + effectivePorts, + getMiningParameters().getStratumPort(), + getMiningParameters().isStratumMiningEnabled()); return effectivePorts; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java b/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java index 8b837268327..b7d603b8caa 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.cli; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; import org.hyperledger.besu.nat.NatMethod; @@ -28,7 +27,6 @@ import java.nio.file.Paths; import java.util.List; -import org.apache.tuweni.bytes.Bytes; import picocli.CommandLine; /** The interface Default command values. */ @@ -58,12 +56,6 @@ public interface DefaultCommandValues { String MANDATORY_NETWORK_FORMAT_HELP = ""; /** The constant MANDATORY_NODE_ID_FORMAT_HELP. */ String MANDATORY_NODE_ID_FORMAT_HELP = ""; - /** The constant DEFAULT_MIN_TRANSACTION_GAS_PRICE. */ - Wei DEFAULT_MIN_TRANSACTION_GAS_PRICE = Wei.of(1000); - /** The constant DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO. */ - Double DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO = 0.8; - /** The constant DEFAULT_EXTRA_DATA. */ - Bytes DEFAULT_EXTRA_DATA = Bytes.EMPTY; /** The constant PERMISSIONING_CONFIG_LOCATION. */ String PERMISSIONING_CONFIG_LOCATION = "permissions_config.toml"; /** The constant MANDATORY_HOST_FORMAT_HELP. */ diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java new file mode 100644 index 00000000000..af4e423b416 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java @@ -0,0 +1,303 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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.cli.options; + +import static java.util.Arrays.asList; +import static org.hyperledger.besu.ethereum.core.MiningParameters.MutableInitValues.DEFAULT_EXTRA_DATA; +import static org.hyperledger.besu.ethereum.core.MiningParameters.MutableInitValues.DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO; +import static org.hyperledger.besu.ethereum.core.MiningParameters.MutableInitValues.DEFAULT_MIN_TRANSACTION_GAS_PRICE; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_MAX_OMMERS_DEPTH; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_POS_BLOCK_CREATION_MAX_TIME; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_POW_JOB_TTL; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_REMOTE_SEALERS_LIMIT; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_REMOTE_SEALERS_TTL; + +import org.hyperledger.besu.cli.util.CommandLineUtils; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; +import org.hyperledger.besu.ethereum.core.MiningParameters; + +import java.util.List; + +import org.apache.tuweni.bytes.Bytes; +import org.slf4j.Logger; +import picocli.CommandLine; +import picocli.CommandLine.Option; +import picocli.CommandLine.ParameterException; + +/** The Mining CLI options. */ +public class MiningOptions implements CLIOptions { + + @Option( + names = {"--miner-enabled"}, + description = "Set if node will perform mining (default: ${DEFAULT-VALUE})") + private Boolean isMiningEnabled = false; + + @Option( + names = {"--miner-stratum-enabled"}, + description = "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})") + private Boolean iStratumMiningEnabled = false; + + @Option( + names = {"--miner-stratum-host"}, + description = "Host for Stratum network mining service (default: ${DEFAULT-VALUE})") + private String stratumNetworkInterface = "0.0.0.0"; + + @Option( + names = {"--miner-stratum-port"}, + description = "Stratum port binding (default: ${DEFAULT-VALUE})") + private Integer stratumPort = 8008; + + @Option( + names = {"--miner-coinbase"}, + description = + "Account to which mining rewards are paid. You must specify a valid coinbase if " + + "mining is enabled using --miner-enabled option", + arity = "1") + private Address coinbase = null; + + @Option( + names = {"--miner-extra-data"}, + description = + "A hex string representing the (32) bytes to be included in the extra data " + + "field of a mined block (default: ${DEFAULT-VALUE})", + arity = "1") + private Bytes extraData = DEFAULT_EXTRA_DATA; + + @Option( + names = {"--min-block-occupancy-ratio"}, + description = "Minimum occupancy ratio for a mined block (default: ${DEFAULT-VALUE})", + arity = "1") + private Double minBlockOccupancyRatio = DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO; + + @Option( + names = {"--min-gas-price"}, + description = + "Minimum price (in Wei) offered by a transaction for it to be included in a mined " + + "block (default: ${DEFAULT-VALUE})", + arity = "1") + private Wei minTransactionGasPrice = DEFAULT_MIN_TRANSACTION_GAS_PRICE; + + @Option( + names = {"--target-gas-limit"}, + description = + "Sets target gas limit per block. If set, each block's gas limit will approach this setting over time if the current gas limit is different.") + private Long targetGasLimit = null; + + @CommandLine.ArgGroup(validate = false) + private final Unstable unstableOptions = new Unstable(); + + static class Unstable { + @CommandLine.Option( + hidden = true, + names = {"--Xminer-remote-sealers-limit"}, + description = + "Limits the number of remote sealers that can submit their hashrates (default: ${DEFAULT-VALUE})") + private Integer remoteSealersLimit = DEFAULT_REMOTE_SEALERS_LIMIT; + + @CommandLine.Option( + hidden = true, + names = {"--Xminer-remote-sealers-hashrate-ttl"}, + description = + "Specifies the lifetime of each entry in the cache. An entry will be automatically deleted if no update has been received before the deadline (default: ${DEFAULT-VALUE} minutes)") + private Long remoteSealersTimeToLive = DEFAULT_REMOTE_SEALERS_TTL; + + @CommandLine.Option( + hidden = true, + names = {"--Xminer-pow-job-ttl"}, + description = + "Specifies the time PoW jobs are kept in cache and will accept a solution from miners (default: ${DEFAULT-VALUE} milliseconds)") + private Long powJobTimeToLive = DEFAULT_POW_JOB_TTL; + + @CommandLine.Option( + hidden = true, + names = {"--Xmax-ommers-depth"}, + description = + "Specifies the depth of ommer blocks to accept when receiving solutions (default: ${DEFAULT-VALUE})") + private Integer maxOmmersDepth = DEFAULT_MAX_OMMERS_DEPTH; + + @CommandLine.Option( + hidden = true, + names = {"--Xminer-stratum-extranonce"}, + description = "Extranonce for Stratum network miners (default: ${DEFAULT-VALUE})") + private String stratumExtranonce = "080c"; + + @CommandLine.Option( + hidden = true, + names = {"--Xpos-block-creation-max-time"}, + description = + "Specifies the maximum time, in milliseconds, a PoS block creation jobs is allowed to run. Must be positive and ≤ 12000 (default: ${DEFAULT-VALUE} milliseconds)") + private Long posBlockCreationMaxTime = DEFAULT_POS_BLOCK_CREATION_MAX_TIME; + + @CommandLine.Option( + hidden = true, + names = {"--Xpos-block-creation-repetition-min-duration"}, + description = + "If a PoS block creation repetition takes less than this duration, in milliseconds," + + " then it waits before next repetition. Must be positive and ≤ 2000 (default: ${DEFAULT-VALUE} milliseconds)") + private Long posBlockCreationRepetitionMinDuration = + DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; + } + + private MiningOptions() {} + + /** + * Create mining options. + * + * @return the mining options + */ + public static MiningOptions create() { + return new MiningOptions(); + } + + /** + * Validate that there are no inconsistencies in the specified options. For example that the + * options are valid for the selected implementation. + * + * @param commandLine the full commandLine to check all the options specified by the user + * @param logger the logger + * @param isMergeEnabled is the Merge enabled? + * @param isEthHash is EthHash? + */ + public void validate( + final CommandLine commandLine, + final Logger logger, + final boolean isMergeEnabled, + final boolean isEthHash) { + if (Boolean.TRUE.equals(isMiningEnabled) && coinbase == null) { + throw new ParameterException( + commandLine, + "Unable to mine without a valid coinbase. Either disable mining (remove --miner-enabled) " + + "or specify the beneficiary of mining (via --miner-coinbase
)"); + } + if (Boolean.FALSE.equals(isMiningEnabled) && Boolean.TRUE.equals(iStratumMiningEnabled)) { + throw new ParameterException( + commandLine, + "Unable to mine with Stratum if mining is disabled. Either disable Stratum mining (remove --miner-stratum-enabled) " + + "or specify mining is enabled (--miner-enabled)"); + } + + // Check that block producer options work + if (!isMergeEnabled && isEthHash) { + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--miner-enabled", + !isMiningEnabled, + asList( + "--miner-coinbase", + "--min-gas-price", + "--min-block-occupancy-ratio", + "--miner-extra-data")); + + // Check that mining options are able to work + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--miner-enabled", + !isMiningEnabled, + asList( + "--miner-stratum-enabled", + "--Xminer-remote-sealers-limit", + "--Xminer-remote-sealers-hashrate-ttl")); + } + + if (unstableOptions.posBlockCreationMaxTime <= 0 + || unstableOptions.posBlockCreationMaxTime > DEFAULT_POS_BLOCK_CREATION_MAX_TIME) { + throw new ParameterException( + commandLine, "--Xpos-block-creation-max-time must be positive and ≤ 12000"); + } + + if (unstableOptions.posBlockCreationRepetitionMinDuration <= 0 + || unstableOptions.posBlockCreationRepetitionMinDuration > 2000) { + throw new ParameterException( + commandLine, "--Xpos-block-creation-repetition-min-duration must be positive and ≤ 2000"); + } + } + + static MiningOptions fromConfig(final MiningParameters miningParameters) { + final MiningOptions miningOptions = MiningOptions.create(); + miningOptions.isMiningEnabled = miningParameters.isMiningEnabled(); + miningOptions.iStratumMiningEnabled = miningParameters.isStratumMiningEnabled(); + miningOptions.stratumNetworkInterface = miningParameters.getStratumNetworkInterface(); + miningOptions.stratumPort = miningParameters.getStratumPort(); + miningOptions.extraData = miningParameters.getExtraData(); + miningOptions.minTransactionGasPrice = miningParameters.getMinTransactionGasPrice(); + miningOptions.minBlockOccupancyRatio = miningParameters.getMinBlockOccupancyRatio(); + miningOptions.unstableOptions.remoteSealersLimit = + miningParameters.getUnstable().getRemoteSealersLimit(); + miningOptions.unstableOptions.remoteSealersTimeToLive = + miningParameters.getUnstable().getRemoteSealersTimeToLive(); + miningOptions.unstableOptions.powJobTimeToLive = + miningParameters.getUnstable().getPowJobTimeToLive(); + miningOptions.unstableOptions.maxOmmersDepth = + miningParameters.getUnstable().getMaxOmmerDepth(); + miningOptions.unstableOptions.stratumExtranonce = + miningParameters.getUnstable().getStratumExtranonce(); + miningOptions.unstableOptions.posBlockCreationMaxTime = + miningParameters.getUnstable().getPosBlockCreationMaxTime(); + miningOptions.unstableOptions.posBlockCreationRepetitionMinDuration = + miningParameters.getUnstable().getPosBlockCreationRepetitionMinDuration(); + + miningParameters.getCoinbase().ifPresent(coinbase -> miningOptions.coinbase = coinbase); + miningParameters.getTargetGasLimit().ifPresent(tgl -> miningOptions.targetGasLimit = tgl); + return miningOptions; + } + + @Override + public MiningParameters toDomainObject() { + final var updatableInitValuesBuilder = + MutableInitValues.builder() + .isMiningEnabled(isMiningEnabled) + .extraData(extraData) + .minTransactionGasPrice(minTransactionGasPrice) + .minBlockOccupancyRatio(minBlockOccupancyRatio); + + if (targetGasLimit != null) { + updatableInitValuesBuilder.targetGasLimit(targetGasLimit); + } + if (coinbase != null) { + updatableInitValuesBuilder.coinbase(coinbase); + } + + final var miningParametersBuilder = + ImmutableMiningParameters.builder() + .mutableInitValues(updatableInitValuesBuilder.build()) + .isStratumMiningEnabled(iStratumMiningEnabled) + .stratumNetworkInterface(stratumNetworkInterface) + .stratumPort(stratumPort) + .unstable( + ImmutableMiningParameters.Unstable.builder() + .remoteSealersLimit(unstableOptions.remoteSealersLimit) + .remoteSealersTimeToLive(unstableOptions.remoteSealersTimeToLive) + .powJobTimeToLive(unstableOptions.powJobTimeToLive) + .maxOmmerDepth(unstableOptions.maxOmmersDepth) + .stratumExtranonce(unstableOptions.stratumExtranonce) + .posBlockCreationMaxTime(unstableOptions.posBlockCreationMaxTime) + .posBlockCreationRepetitionMinDuration( + unstableOptions.posBlockCreationRepetitionMinDuration) + .build()); + + return miningParametersBuilder.build(); + } + + @Override + public List getCLIOptions() { + return CommandLineUtils.getCLIOptions(this, new MiningOptions()); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java deleted file mode 100644 index 232554722e2..00000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 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.cli.options.unstable; - -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_MAX_OMMERS_DEPTH; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POS_BLOCK_CREATION_MAX_TIME; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POW_JOB_TTL; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_LIMIT; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_TTL; - -import picocli.CommandLine; - -/** The Mining CLI options. */ -public class MiningOptions { - - @CommandLine.Option( - hidden = true, - names = {"--Xminer-remote-sealers-limit"}, - description = - "Limits the number of remote sealers that can submit their hashrates (default: ${DEFAULT-VALUE})") - private final Integer remoteSealersLimit = DEFAULT_REMOTE_SEALERS_LIMIT; - - @CommandLine.Option( - hidden = true, - names = {"--Xminer-remote-sealers-hashrate-ttl"}, - description = - "Specifies the lifetime of each entry in the cache. An entry will be automatically deleted if no update has been received before the deadline (default: ${DEFAULT-VALUE} minutes)") - private final Long remoteSealersTimeToLive = DEFAULT_REMOTE_SEALERS_TTL; - - @CommandLine.Option( - hidden = true, - names = {"--Xminer-pow-job-ttl"}, - description = - "Specifies the time PoW jobs are kept in cache and will accept a solution from miners (default: ${DEFAULT-VALUE} milliseconds)") - private final Long powJobTimeToLive = DEFAULT_POW_JOB_TTL; - - @CommandLine.Option( - hidden = true, - names = {"--Xmax-ommers-depth"}, - description = - "Specifies the depth of ommer blocks to accept when receiving solutions (default: ${DEFAULT-VALUE})") - private final Integer maxOmmersDepth = DEFAULT_MAX_OMMERS_DEPTH; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @CommandLine.Option( - hidden = true, - names = {"--Xminer-stratum-extranonce"}, - description = "Extranonce for Stratum network miners (default: ${DEFAULT-VALUE})") - private String stratumExtranonce = "080c"; - - @CommandLine.Option( - hidden = true, - names = {"--Xpos-block-creation-max-time"}, - description = - "Specifies the maximum time, in milliseconds, a PoS block creation jobs is allowed to run. Must be positive and ≤ 12000 (default: ${DEFAULT-VALUE} milliseconds)") - private final Long posBlockCreationMaxTime = DEFAULT_POS_BLOCK_CREATION_MAX_TIME; - - @CommandLine.Option( - hidden = true, - names = {"--Xpos-block-creation-repetition-min-duration"}, - description = - "If a PoS block creation repetition takes less than this duration, in milliseconds," - + " then it waits before next repetition. Must be positive and ≤ 2000 (default: ${DEFAULT-VALUE} milliseconds)") - private final Long posBlockCreationRepetitionMinDuration = - DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; - - /** - * Create mining options. - * - * @return the mining options - */ - public static MiningOptions create() { - return new MiningOptions(); - } - - /** - * Gets remote sealers limit. - * - * @return the remote sealers limit - */ - public Integer getRemoteSealersLimit() { - return remoteSealersLimit; - } - - /** - * Gets remote sealers time to live. - * - * @return the remote sealers time to live - */ - public Long getRemoteSealersTimeToLive() { - return remoteSealersTimeToLive; - } - - /** - * Gets stratum extra nonce. - * - * @return the stratum extra nonce - */ - public String getStratumExtranonce() { - return stratumExtranonce; - } - - /** - * Gets pow job time to live. - * - * @return the pow job time to live - */ - public Long getPowJobTimeToLive() { - return powJobTimeToLive; - } - - /** - * Gets max ommers depth. - * - * @return the max ommers depth - */ - public int getMaxOmmersDepth() { - return maxOmmersDepth; - } - - /** - * Gets pos block creation max time. - * - * @return the pos block creation max time - */ - public Long getPosBlockCreationMaxTime() { - return posBlockCreationMaxTime; - } - - /** - * Gets pos block creation repetition min duration. - * - * @return the pos block creation repetition min duration. - */ - public Long getPosBlockCreationRepetitionMinDuration() { - return posBlockCreationRepetitionMinDuration; - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java index 9417aad8f55..ea8bfab8d14 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java @@ -16,10 +16,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand.COMMAND_NAME; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_MAX_OMMERS_DEPTH; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POW_JOB_TTL; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_LIMIT; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_TTL; import org.hyperledger.besu.chainexport.RlpBlockExporter; import org.hyperledger.besu.chainimport.JsonBlockImporter; @@ -35,6 +31,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.blockcreation.IncrementingNonceGenerator; import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.metrics.MetricsService; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -271,21 +269,14 @@ private MiningParameters getMiningParameters() { // Extradata and coinbase can be configured on a per-block level via the json file final Address coinbase = Address.ZERO; final Bytes extraData = Bytes.EMPTY; - return new MiningParameters.Builder() - .coinbase(coinbase) - .minTransactionGasPrice(minTransactionGasPrice) - .extraData(extraData) - .miningEnabled(false) - .stratumMiningEnabled(false) - .stratumNetworkInterface("0.0.0.0") - .stratumPort(8008) - .stratumExtranonce("080c") - .maybeNonceGenerator(new IncrementingNonceGenerator(0)) - .minBlockOccupancyRatio(0.0) - .remoteSealersLimit(DEFAULT_REMOTE_SEALERS_LIMIT) - .remoteSealersTimeToLive(DEFAULT_REMOTE_SEALERS_TTL) - .powJobTimeToLive(DEFAULT_POW_JOB_TTL) - .maxOmmerDepth(DEFAULT_MAX_OMMERS_DEPTH) + return ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .nonceGenerator(new IncrementingNonceGenerator(0)) + .extraData(extraData) + .minTransactionGasPrice(minTransactionGasPrice) + .coinbase(coinbase) + .build()) .build(); } @@ -381,7 +372,11 @@ public void run() { } private BesuController createBesuController() { - return parentCommand.parentCommand.buildController(); + return parentCommand + .parentCommand + .getControllerBuilder() + .miningParameters(MiningParameters.newDefault()) + .build(); } private void exportRlpFormat(final BesuController controller) throws IOException { diff --git a/besu/src/main/java/org/hyperledger/besu/cli/util/CommandLineUtils.java b/besu/src/main/java/org/hyperledger/besu/cli/util/CommandLineUtils.java index a44e616bd3d..33b531b5903 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/util/CommandLineUtils.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/util/CommandLineUtils.java @@ -178,9 +178,8 @@ public static List getCLIOptions(final Object currOptions, final Object var optVal = field.get(currOptions); if (!Objects.equals(optVal, field.get(defaults))) { var optAnn = CommandLine.Option.class.cast(ann); - cliOpts.add(optAnn.names()[0]); final var optConverter = optAnn.converter(); - cliOpts.add(formatValue(optConverter, optVal)); + cliOpts.add(optAnn.names()[0] + "=" + formatValue(optConverter, optVal)); } } catch (IllegalAccessException e) { throw new RuntimeException(e); 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 1e894e0d9c5..baad246a76b 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java @@ -148,6 +148,6 @@ protected CliqueContext createConsensusContext( @Override public MiningParameters getMiningParameterOverrides(final MiningParameters fromCli) { // Clique mines by default, reflect that with in the mining parameters: - return new MiningParameters.Builder(fromCli).miningEnabled(true).build(); + return fromCli.setMiningEnabled(true); } } 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 0fce7f484ce..6f034e6f759 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java @@ -55,17 +55,15 @@ protected MiningCoordinator createMiningCoordinator( MainnetBlockHeaderValidator.MINIMUM_SECONDS_SINCE_PARENT, MainnetBlockHeaderValidator.TIMESTAMP_TOLERANCE_S, clock), - epochCalculator, - miningParameters.getPowJobTimeToLive(), - miningParameters.getMaxOmmerDepth()); + epochCalculator); final PoWMiningCoordinator miningCoordinator = new PoWMiningCoordinator( protocolContext.getBlockchain(), executor, syncState, - miningParameters.getRemoteSealersLimit(), - miningParameters.getRemoteSealersTimeToLive()); + miningParameters.getUnstable().getRemoteSealersLimit(), + miningParameters.getUnstable().getRemoteSealersTimeToLive()); miningCoordinator.addMinedBlockObserver(ethProtocolManager); miningCoordinator.setStratumMiningEnabled(miningParameters.isStratumMiningEnabled()); if (miningParameters.isMiningEnabled()) { diff --git a/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java index 6db71ef81ca..d4541d91b9c 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java @@ -134,7 +134,7 @@ protected MiningCoordinator createMiningCoordinator( transitionProtocolSchedule.getPreMergeSchedule(), protocolContext, transactionPool, - new MiningParameters.Builder(miningParameters).miningEnabled(false).build(), + MiningParameters.MINING_DISABLED, syncState, ethProtocolManager), mergeBesuControllerBuilder.createTransitionMiningCoordinator( diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java index f831e1ecd59..276740fbfed 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java @@ -187,11 +187,7 @@ public void setUp() throws IOException { .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) .networkId(BigInteger.ONE) - .miningParameters( - new MiningParameters.Builder() - .minTransactionGasPrice(Wei.of(1000)) - .miningEnabled(false) - .build()) + .miningParameters(MiningParameters.newDefault()) .nodeKey(NodeKeyUtils.generate()) .metricsSystem(new NoOpMetricsSystem()) .dataDirectory(folder) diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java index bfdd71b3d2a..c71d44284fb 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java @@ -111,7 +111,7 @@ private BesuController setUpControllerWithPrivacyEnabled(final boolean flexibleE .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) .networkId(BigInteger.ONE) - .miningParameters(new MiningParameters.Builder().miningEnabled(false).build()) + .miningParameters(MiningParameters.newDefault()) .nodeKey(NodeKeyUtils.generate()) .metricsSystem(new NoOpMetricsSystem()) .dataDirectory(dataDir) diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index 93207b1d11a..43a4d2cd963 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -448,7 +448,7 @@ private BesuController getController( .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .dataDirectory(dataDir) .networkId(NETWORK_ID) - .miningParameters(new MiningParameters.Builder().miningEnabled(false).build()) + .miningParameters(MiningParameters.newDefault()) .nodeKey(nodeKey) .storageProvider(storageProvider) .metricsSystem(metricsSystem) 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 e6b60dad197..89e1b255479 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java @@ -91,7 +91,7 @@ private static BesuController createController() throws IOException { .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) .networkId(BigInteger.ONE) - .miningParameters(new MiningParameters.Builder().miningEnabled(false).build()) + .miningParameters(MiningParameters.newDefault()) .nodeKey(NodeKeyUtils.generate()) .metricsSystem(new NoOpMetricsSystem()) .privacyParameters(PrivacyParameters.DEFAULT) 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 00c86133ea6..00ebc610823 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java @@ -29,8 +29,9 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; -import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; @@ -421,9 +422,12 @@ protected BesuController createController(final GenesisConfigFile genesisConfigF .storageProvider(new InMemoryKeyValueStorageProvider()) .networkId(BigInteger.valueOf(10)) .miningParameters( - new MiningParameters.Builder() - .minTransactionGasPrice(Wei.ZERO) - .miningEnabled(true) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .isMiningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .build()) .build()) .nodeKey(NodeKeyUtils.generate()) .metricsSystem(new NoOpMetricsSystem()) 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 3260b8ee55b..f9d543aca9f 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java @@ -67,7 +67,7 @@ public void blockImport() throws IOException { .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) .networkId(BigInteger.ONE) - .miningParameters(new MiningParameters.Builder().miningEnabled(false).build()) + .miningParameters(MiningParameters.newDefault()) .nodeKey(NodeKeyUtils.generate()) .metricsSystem(new NoOpMetricsSystem()) .privacyParameters(PrivacyParameters.DEFAULT) @@ -100,7 +100,7 @@ public void blockImportRejectsBadPow() throws IOException { .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) .networkId(BigInteger.ONE) - .miningParameters(new MiningParameters.Builder().miningEnabled(false).build()) + .miningParameters(MiningParameters.newDefault()) .nodeKey(NodeKeyUtils.generate()) .metricsSystem(new NoOpMetricsSystem()) .privacyParameters(PrivacyParameters.DEFAULT) @@ -130,7 +130,7 @@ public void blockImportCanSkipPow() throws IOException { .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) .networkId(BigInteger.ONE) - .miningParameters(new MiningParameters.Builder().miningEnabled(false).build()) + .miningParameters(MiningParameters.newDefault()) .nodeKey(NodeKeyUtils.generate()) .metricsSystem(new NoOpMetricsSystem()) .privacyParameters(PrivacyParameters.DEFAULT) 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 af28e7ba7c2..91a203ff576 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -35,7 +35,6 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.NET; import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.PERM; import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.WEB3; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POS_BLOCK_CREATION_MAX_TIME; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.GOERLI_BOOTSTRAP_NODES; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.GOERLI_DISCOVERY_URL; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.MAINNET_BOOTSTRAP_NODES; @@ -48,7 +47,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNotNull; import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.atMost; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -72,6 +70,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; @@ -161,20 +161,6 @@ public class BesuCommandTest extends CommandTestAbstract { (new JsonObject()).put("config", new JsonObject().put("ecCurve", "secp256k1")); private static final String ENCLAVE_PUBLIC_KEY_PATH = BesuCommand.class.getResource("/orion_publickey.pub").getPath(); - private static final JsonObject VALID_GENESIS_QBFT_POST_LONDON = - (new JsonObject()) - .put( - "config", - new JsonObject() - .put("londonBlock", 0) - .put("qbft", new JsonObject().put("blockperiodseconds", 5))); - private static final JsonObject VALID_GENESIS_IBFT2_POST_LONDON = - (new JsonObject()) - .put( - "config", - new JsonObject() - .put("londonBlock", 0) - .put("ibft2", new JsonObject().put("blockperiodseconds", 5))); private static final String[] VALID_ENODE_STRINGS = { "enode://" + VALID_NODE_ID + "@192.168.0.1:4567", @@ -916,11 +902,11 @@ public void envVariableOverridesValueFromConfigFile() { verify(mockControllerBuilder) .miningParameters( - new MiningParameters.Builder() - .coinbase(Address.fromHexString(expectedCoinbase)) - .minTransactionGasPrice(DefaultCommandValues.DEFAULT_MIN_TRANSACTION_GAS_PRICE) - .extraData(DefaultCommandValues.DEFAULT_EXTRA_DATA) - .miningEnabled(false) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .coinbase(Address.fromHexString(expectedCoinbase)) + .build()) .build()); } @@ -933,11 +919,11 @@ public void cliOptionOverridesEnvVariableAndConfig() { verify(mockControllerBuilder) .miningParameters( - new MiningParameters.Builder() - .coinbase(Address.fromHexString(expectedCoinbase)) - .minTransactionGasPrice(DefaultCommandValues.DEFAULT_MIN_TRANSACTION_GAS_PRICE) - .extraData(DefaultCommandValues.DEFAULT_EXTRA_DATA) - .miningEnabled(false) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .coinbase(Address.fromHexString(expectedCoinbase)) + .build()) .build()); } @@ -3652,261 +3638,6 @@ public void metricsAndMetricsPushMustNotBeUsedTogether() { .startsWith("--metrics-enabled option and --metrics-push-enabled option can't be used"); } - @Test - public void besuDoesNotStartInMiningModeIfCoinbaseNotSet() { - parseCommand("--miner-enabled"); - - Mockito.verifyNoInteractions(mockControllerBuilder); - } - - @Test - public void miningIsEnabledWhenSpecified() throws Exception { - final String coinbaseStr = String.format("%040x", 1); - parseCommand("--miner-enabled", "--miner-coinbase=" + coinbaseStr); - - final ArgumentCaptor miningArg = - ArgumentCaptor.forClass(MiningParameters.class); - - verify(mockControllerBuilder).miningParameters(miningArg.capture()); - verify(mockControllerBuilder).build(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - assertThat(miningArg.getValue().isMiningEnabled()).isTrue(); - assertThat(miningArg.getValue().getCoinbase()) - .isEqualTo(Optional.of(Address.fromHexString(coinbaseStr))); - } - - @Test - public void stratumMiningIsEnabledWhenSpecified() throws Exception { - final String coinbaseStr = String.format("%040x", 1); - parseCommand("--miner-enabled", "--miner-coinbase=" + coinbaseStr, "--miner-stratum-enabled"); - - final ArgumentCaptor miningArg = - ArgumentCaptor.forClass(MiningParameters.class); - - verify(mockControllerBuilder).miningParameters(miningArg.capture()); - verify(mockControllerBuilder).build(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - assertThat(miningArg.getValue().isMiningEnabled()).isTrue(); - assertThat(miningArg.getValue().getCoinbase()) - .isEqualTo(Optional.of(Address.fromHexString(coinbaseStr))); - assertThat(miningArg.getValue().isStratumMiningEnabled()).isTrue(); - } - - @Test - public void stratumMiningOptionsRequiresServiceToBeEnabled() { - - parseCommand("--network", "dev", "--miner-stratum-enabled"); - - verifyOptionsConstraintLoggerCall("--miner-enabled", "--miner-stratum-enabled"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)) - .startsWith( - "Unable to mine with Stratum if mining is disabled. Either disable Stratum mining (remove --miner-stratum-enabled) or specify mining is enabled (--miner-enabled)"); - } - - @Test - public void stratumMiningOptionsRequiresServiceToBeEnabledToml() throws IOException { - final Path toml = createTempFile("toml", "miner-stratum-enabled=true\n"); - - parseCommand("--network", "dev", "--config-file", toml.toString()); - - verifyOptionsConstraintLoggerCall("--miner-enabled", "--miner-stratum-enabled"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)) - .startsWith( - "Unable to mine with Stratum if mining is disabled. Either disable Stratum mining (remove --miner-stratum-enabled) or specify mining is enabled (--miner-enabled)"); - } - - @Test - public void blockProducingOptionsWarnsMinerShouldBeEnabled() { - - final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); - parseCommand( - "--network", - "dev", - "--miner-coinbase", - requestedCoinbase.toString(), - "--min-gas-price", - "42", - "--miner-extra-data", - "0x1122334455667788990011223344556677889900112233445566778899001122"); - - verifyOptionsConstraintLoggerCall( - "--miner-enabled", "--miner-coinbase", "--min-gas-price", "--miner-extra-data"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void blockProducingOptionsWarnsMinerShouldBeEnabledToml() throws IOException { - - final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); - - final Path toml = - createTempFile( - "toml", - "network=\"dev\"\n" - + "miner-coinbase=\"" - + requestedCoinbase - + "\"\n" - + "min-gas-price=42\n" - + "miner-extra-data=\"0x1122334455667788990011223344556677889900112233445566778899001122\"\n"); - - parseCommand("--config-file", toml.toString()); - - verifyOptionsConstraintLoggerCall( - "--miner-enabled", "--miner-coinbase", "--min-gas-price", "--miner-extra-data"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void blockProducingOptionsDoNotWarnWhenPoA() throws IOException { - - final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON); - parseCommand( - "--genesis-file", - genesisFileQBFT.toString(), - "--min-gas-price", - "42", - "--miner-extra-data", - "0x1122334455667788990011223344556677889900112233445566778899001122"); - - verify(mockLogger, atMost(0)) - .warn( - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture()); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - - final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON); - parseCommand( - "--genesis-file", - genesisFileIBFT2.toString(), - "--min-gas-price", - "42", - "--miner-extra-data", - "0x1122334455667788990011223344556677889900112233445566778899001122"); - - verify(mockLogger, atMost(0)) - .warn( - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture()); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void blockProducingOptionsDoNotWarnWhenMergeEnabled() { - - final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); - // TODO: once we have mainnet TTD, we can remove the TTD override parameter here - // https://github.com/hyperledger/besu/issues/3874 - parseCommand( - "--override-genesis-config", - "terminalTotalDifficulty=1337", - "--miner-coinbase", - requestedCoinbase.toString(), - "--min-gas-price", - "42", - "--miner-extra-data", - "0x1122334455667788990011223344556677889900112233445566778899001122"); - - verify(mockLogger, atMost(0)) - .warn( - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture()); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void minGasPriceRequiresMainOption() { - parseCommand("--min-gas-price", "0", "--network", "dev"); - - verifyOptionsConstraintLoggerCall("--miner-enabled", "--min-gas-price"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void minGasPriceRequiresMainOptionToml() throws IOException { - final Path toml = createTempFile("toml", "min-gas-price=0\nnetwork=\"dev\"\n"); - - parseCommand("--config-file", toml.toString()); - - verifyOptionsConstraintLoggerCall("--miner-enabled", "--min-gas-price"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void minGasPriceDoesNotRequireMainOptionWhenPoA() throws IOException { - final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON); - parseCommand("--genesis-file", genesisFileQBFT.toString(), "--min-gas-price", "0"); - - verify(mockLogger, atMost(0)) - .warn( - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture()); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - - final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON); - parseCommand("--genesis-file", genesisFileIBFT2.toString(), "--min-gas-price", "0"); - - verify(mockLogger, atMost(0)) - .warn( - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture(), - stringArgumentCaptor.capture()); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void miningParametersAreCaptured() { - final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); - final String extraDataString = - "0x1122334455667788990011223344556677889900112233445566778899001122"; - parseCommand( - "--miner-enabled", - "--miner-coinbase=" + requestedCoinbase.toString(), - "--min-gas-price=15", - "--miner-extra-data=" + extraDataString); - - final ArgumentCaptor miningArg = - ArgumentCaptor.forClass(MiningParameters.class); - - verify(mockControllerBuilder).miningParameters(miningArg.capture()); - verify(mockControllerBuilder).build(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - assertThat(miningArg.getValue().getCoinbase()).isEqualTo(Optional.of(requestedCoinbase)); - assertThat(miningArg.getValue().getMinTransactionGasPrice()).isEqualTo(Wei.of(15)); - assertThat(miningArg.getValue().getExtraData()).isEqualTo(Bytes.fromHexString(extraDataString)); - } - @Test public void colorCanBeEnabledOrDisabledExplicitly() { Stream.of(true, false) @@ -4471,31 +4202,6 @@ public void canNotUseFlexiblePrivacyWhenPrivacyPluginEnabled() { "No Payload Provider has been provided. You must register one when enabling privacy plugin!"); } - private Path createFakeGenesisFile(final JsonObject jsonGenesis) throws IOException { - final Path genesisFile = Files.createTempFile("genesisFile", ""); - Files.write(genesisFile, encodeJsonGenesis(jsonGenesis).getBytes(UTF_8)); - genesisFile.toFile().deleteOnExit(); - return genesisFile; - } - - private Path createTempFile(final String filename, final String contents) throws IOException { - final Path file = Files.createTempFile(filename, ""); - Files.write(file, contents.getBytes(UTF_8)); - file.toFile().deleteOnExit(); - return file; - } - - private Path createTempFile(final String filename, final byte[] contents) throws IOException { - final Path file = Files.createTempFile(filename, ""); - Files.write(file, contents); - file.toFile().deleteOnExit(); - return file; - } - - private String encodeJsonGenesis(final JsonObject jsonGenesis) { - return jsonGenesis.encodePrettily(); - } - private static String escapeTomlString(final String s) { return StringEscapeUtils.escapeJava(s); } @@ -4619,42 +4325,6 @@ public void tomlThatHasInvalidOptions() throws IOException { .contains("Unknown options in TOML configuration file: invalid_option, invalid_option2"); } - @Test - public void targetGasLimitIsEnabledWhenSpecified() { - parseCommand("--target-gas-limit=10000000"); - - @SuppressWarnings("unchecked") - final ArgumentCaptor miningParametersArgumentCaptor = - ArgumentCaptor.forClass(MiningParameters.class); - - verify(mockControllerBuilder).miningParameters(miningParametersArgumentCaptor.capture()); - verify(mockControllerBuilder).build(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - - assertThat(miningParametersArgumentCaptor.getValue().getTargetGasLimit().get().longValue()) - .isEqualTo(10_000_000L); - } - - @Test - public void targetGasLimitIsDisabledWhenNotSpecified() { - parseCommand(); - - @SuppressWarnings("unchecked") - final ArgumentCaptor gasLimitCalculatorArgumentCaptor = - ArgumentCaptor.forClass(GasLimitCalculator.class); - - verify(mockControllerBuilder).gasLimitCalculator(gasLimitCalculatorArgumentCaptor.capture()); - verify(mockControllerBuilder).build(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - - assertThat(gasLimitCalculatorArgumentCaptor.getValue()) - .isEqualTo(GasLimitCalculator.constant()); - } - @Test public void requiredBlocksSetWhenSpecified() { final long blockNumber = 8675309L; @@ -5069,11 +4739,7 @@ public void assertThatCheckPortClashRejectsAsExpected() throws Exception { public void assertThatCheckPortClashRejectsAsExpectedForEngineApi() throws Exception { // use WS port for HTTP final int port = 8545; - // TODO: once we have mainnet TTD, we can remove the TTD override parameter here - // https://github.com/hyperledger/besu/issues/3874 parseCommand( - "--override-genesis-config", - "terminalTotalDifficulty=1337", "--rpc-http-enabled", "--rpc-http-port", String.valueOf(port), @@ -5275,37 +4941,6 @@ public void logWarnIfFastSyncMinPeersUsedWithFullSync() { .contains("--fast-sync-min-peers can't be used with FULL sync-mode"); } - @Test - public void posBlockCreationMaxTimeDefaultValue() { - parseCommand(); - assertThat(getPosBlockCreationMaxTimeValue()).isEqualTo(DEFAULT_POS_BLOCK_CREATION_MAX_TIME); - } - - @Test - public void posBlockCreationMaxTimeOption() { - parseCommand("--Xpos-block-creation-max-time", "7000"); - assertThat(getPosBlockCreationMaxTimeValue()).isEqualTo(7000L); - } - - private long getPosBlockCreationMaxTimeValue() { - final ArgumentCaptor miningArg = - ArgumentCaptor.forClass(MiningParameters.class); - - verify(mockControllerBuilder).miningParameters(miningArg.capture()); - verify(mockControllerBuilder).build(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - return miningArg.getValue().getPosBlockCreationMaxTime(); - } - - @Test - public void posBlockCreationMaxTimeOutOfAllowedRange() { - parseCommand("--Xpos-block-creation-max-time", "17000"); - assertThat(commandErrorOutput.toString(UTF_8)) - .contains("--Xpos-block-creation-max-time must be positive and ≤ 12000"); - } - @Test public void portInUseReportsError() throws IOException { final ServerSocket serverSocket = new ServerSocket(8545); 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 1c991d64935..bccf28c4522 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.chainimport.JsonBlockImporter; import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.cli.config.EthNetworkConfig; +import org.hyperledger.besu.cli.options.MiningOptions; import org.hyperledger.besu.cli.options.stable.EthstatsOptions; import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions; import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions; @@ -105,6 +106,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; +import io.vertx.core.json.JsonObject; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.awaitility.Awaitility; @@ -126,6 +128,20 @@ @RunWith(MockitoJUnitRunner.class) public abstract class CommandTestAbstract { private static final Logger TEST_LOGGER = LoggerFactory.getLogger(CommandTestAbstract.class); + protected static final JsonObject VALID_GENESIS_QBFT_POST_LONDON = + (new JsonObject()) + .put( + "config", + new JsonObject() + .put("londonBlock", 0) + .put("qbft", new JsonObject().put("blockperiodseconds", 5))); + protected static final JsonObject VALID_GENESIS_IBFT2_POST_LONDON = + (new JsonObject()) + .put( + "config", + new JsonObject() + .put("londonBlock", 0) + .put("ibft2", new JsonObject().put("blockperiodseconds", 5))); protected final PrintStream originalOut = System.out; protected final PrintStream originalErr = System.err; protected final ByteArrayOutputStream commandOutput = new ByteArrayOutputStream(); @@ -460,6 +476,25 @@ private TestBesuCommand getTestBesuCommand(final TestType testType) { } } + protected Path createTempFile(final String filename, final byte[] contents) throws IOException { + final Path file = Files.createTempFile(filename, ""); + Files.write(file, contents); + file.toFile().deleteOnExit(); + return file; + } + + protected Path createFakeGenesisFile(final JsonObject jsonGenesis) throws IOException { + return createTempFile("genesisFile", encodeJsonGenesis(jsonGenesis).getBytes(UTF_8)); + } + + protected String encodeJsonGenesis(final JsonObject jsonGenesis) { + return jsonGenesis.encodePrettily(); + } + + protected Path createTempFile(final String filename, final String contents) throws IOException { + return createTempFile(filename, contents.getBytes(UTF_8)); + } + @CommandLine.Command public static class TestBesuCommand extends BesuCommand { @@ -530,6 +565,10 @@ public EthProtocolOptions getEthProtocolOptions() { return stableTransactionPoolOptions; } + public MiningOptions getMiningOptions() { + return miningOptions; + } + public TransactionPoolOptions getUnstableTransactionPoolOptions() { return unstableTransactionPoolOptions; } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/AbstractCLIOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/AbstractCLIOptionsTest.java index ef7da0c7669..09b4e3b1365 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/AbstractCLIOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/AbstractCLIOptionsTest.java @@ -16,6 +16,9 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.verify; import org.hyperledger.besu.cli.CommandTestAbstract; @@ -113,6 +116,7 @@ protected void internalTestSuccess(final Consumer assertion, final String... assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + verify(mockControllerBuilder).build(); } protected void internalTestFailure(final String errorMsg, final String... args) { @@ -121,4 +125,29 @@ protected void internalTestFailure(final String errorMsg, final String... args) assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).contains(errorMsg); } + + /** + * Check logger calls + * + *

Here we check the calls to logger and not the result of the log line as we don't test the + * logger itself but the fact that we call it. + * + * @param dependentOptions the string representing the list of dependent options names + * @param mainOption the main option name + */ + protected void verifyOptionsConstraintLoggerCall( + final String mainOption, final String... dependentOptions) { + verify(mockLogger, atLeast(1)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()); + assertThat(stringArgumentCaptor.getAllValues().get(0)).isEqualTo(DEPENDENCY_WARNING_MSG); + + for (final String option : dependentOptions) { + assertThat(stringArgumentCaptor.getAllValues().get(1)).contains(option); + } + + assertThat(stringArgumentCaptor.getAllValues().get(2)).isEqualTo(mainOption); + } } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/MiningOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/MiningOptionsTest.java new file mode 100644 index 00000000000..7d6d3cfe06e --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/MiningOptionsTest.java @@ -0,0 +1,340 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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.cli.options; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_POS_BLOCK_CREATION_MAX_TIME; +import static org.mockito.Mockito.atMost; +import static org.mockito.Mockito.verify; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.Unstable; +import org.hyperledger.besu.ethereum.core.MiningParameters; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MiningOptionsTest extends AbstractCLIOptionsTest { + + @Test + public void besuDoesNotStartInMiningModeIfCoinbaseNotSet() { + internalTestFailure( + "Unable to mine without a valid coinbase. Either disable mining (remove --miner-enabled) or specify the beneficiary of mining (via --miner-coinbase

)", + "--miner-enabled"); + } + + @Test + public void miningIsEnabledWhenSpecified() { + final String coinbaseStr = String.format("%040x", 1); + internalTestSuccess( + miningOpts -> { + assertThat(miningOpts.isMiningEnabled()).isTrue(); + assertThat(miningOpts.getCoinbase()) + .isEqualTo(Optional.of(Address.fromHexString(coinbaseStr))); + }, + "--miner-enabled", + "--miner-coinbase=" + coinbaseStr); + } + + @Test + public void stratumMiningIsEnabledWhenSpecified() { + final String coinbaseStr = String.format("%040x", 1); + internalTestSuccess( + miningOpts -> { + assertThat(miningOpts.isMiningEnabled()).isTrue(); + assertThat(miningOpts.getCoinbase()) + .isEqualTo(Optional.of(Address.fromHexString(coinbaseStr))); + assertThat(miningOpts.isStratumMiningEnabled()).isTrue(); + }, + "--miner-enabled", + "--miner-coinbase=" + coinbaseStr, + "--miner-stratum-enabled"); + } + + @Test + public void stratumMiningOptionsRequiresServiceToBeEnabled() { + internalTestFailure( + "Unable to mine with Stratum if mining is disabled. Either disable Stratum mining (remove --miner-stratum-enabled) or specify mining is enabled (--miner-enabled)", + "--network", + "dev", + "--miner-stratum-enabled"); + } + + @Test + public void stratumMiningOptionsRequiresServiceToBeEnabledToml() throws IOException { + final Path toml = createTempFile("toml", "miner-stratum-enabled=true\n"); + internalTestFailure( + "Unable to mine with Stratum if mining is disabled. Either disable Stratum mining (remove --miner-stratum-enabled) or specify mining is enabled (--miner-enabled)", + "--network", + "dev", + "--config-file", + toml.toString()); + } + + @Test + public void blockProducingOptionsWarnsMinerShouldBeEnabled() { + final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); + internalTestSuccess( + miningOpts -> + verifyOptionsConstraintLoggerCall( + "--miner-enabled", "--miner-coinbase", "--min-gas-price", "--miner-extra-data"), + "--network", + "dev", + "--miner-coinbase", + requestedCoinbase.toString(), + "--min-gas-price", + "42", + "--miner-extra-data", + "0x1122334455667788990011223344556677889900112233445566778899001122"); + } + + @Test + public void blockProducingOptionsWarnsMinerShouldBeEnabledToml() throws IOException { + + final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); + + final Path toml = + createTempFile( + "toml", + "network=\"dev\"\n" + + "miner-coinbase=\"" + + requestedCoinbase + + "\"\n" + + "min-gas-price=42\n" + + "miner-extra-data=\"0x1122334455667788990011223344556677889900112233445566778899001122\"\n"); + + internalTestSuccess( + miningOpts -> + verifyOptionsConstraintLoggerCall( + "--miner-enabled", "--miner-coinbase", "--min-gas-price", "--miner-extra-data"), + "--config-file", + toml.toString()); + } + + @Test + public void blockProducingOptionsDoNotWarnWhenPoAQBFT() throws IOException { + + final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON); + internalTestSuccess( + miningOpts -> + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()), + "--genesis-file", + genesisFileQBFT.toString(), + "--min-gas-price", + "42", + "--miner-extra-data", + "0x1122334455667788990011223344556677889900112233445566778899001122"); + } + + @Test + public void blockProducingOptionsDoNotWarnWhenPoAIBFT2() throws IOException { + + final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON); + internalTestSuccess( + miningOpts -> + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()), + "--genesis-file", + genesisFileIBFT2.toString(), + "--min-gas-price", + "42", + "--miner-extra-data", + "0x1122334455667788990011223344556677889900112233445566778899001122"); + } + + @Test + public void blockProducingOptionsDoNotWarnWhenMergeEnabled() { + + final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); + internalTestSuccess( + miningOpt -> + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()), + "--miner-coinbase", + requestedCoinbase.toString(), + "--min-gas-price", + "42", + "--miner-extra-data", + "0x1122334455667788990011223344556677889900112233445566778899001122"); + } + + @Test + public void minGasPriceRequiresMainOption() { + internalTestSuccess( + miningOpt -> verifyOptionsConstraintLoggerCall("--miner-enabled", "--min-gas-price"), + "--min-gas-price", + "0", + "--network", + "dev"); + } + + @Test + public void minGasPriceRequiresMainOptionToml() throws IOException { + final Path toml = createTempFile("toml", "min-gas-price=0\nnetwork=\"dev\"\n"); + internalTestSuccess( + miningOpt -> verifyOptionsConstraintLoggerCall("--miner-enabled", "--min-gas-price"), + "--config-file", + toml.toString()); + } + + @Test + public void minGasPriceDoesNotRequireMainOptionWhenPoAQBFT() throws IOException { + final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON); + internalTestSuccess( + miningOpt -> + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()), + "--genesis-file", + genesisFileQBFT.toString(), + "--min-gas-price", + "0"); + } + + @Test + public void minGasPriceDoesNotRequireMainOptionWhenPoAIBFT2() throws IOException { + final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON); + + internalTestSuccess( + miningOpt -> + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()), + "--genesis-file", + genesisFileIBFT2.toString(), + "--min-gas-price", + "0"); + } + + @Test + public void miningParametersAreCaptured() { + final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); + final String extraDataString = + "0x1122334455667788990011223344556677889900112233445566778899001122"; + internalTestSuccess( + miningParams -> { + assertThat(miningParams.getCoinbase()).isEqualTo(Optional.of(requestedCoinbase)); + assertThat(miningParams.getMinTransactionGasPrice()).isEqualTo(Wei.of(15)); + assertThat(miningParams.getExtraData()).isEqualTo(Bytes.fromHexString(extraDataString)); + }, + "--miner-enabled", + "--miner-coinbase=" + requestedCoinbase.toString(), + "--min-gas-price=15", + "--miner-extra-data=" + extraDataString); + } + + @Test + public void targetGasLimitIsEnabledWhenSpecified() { + internalTestSuccess( + miningParams -> + assertThat(miningParams.getTargetGasLimit().getAsLong()).isEqualTo(10_000_000L), + "--target-gas-limit=10000000"); + } + + @Test + public void targetGasLimitIsDisabledWhenNotSpecified() { + internalTestSuccess( + miningParams -> { + final ArgumentCaptor gasLimitCalculatorArgumentCaptor = + ArgumentCaptor.forClass(GasLimitCalculator.class); + + verify(mockControllerBuilder) + .gasLimitCalculator(gasLimitCalculatorArgumentCaptor.capture()); + assertThat(gasLimitCalculatorArgumentCaptor.getValue()) + .isEqualTo(GasLimitCalculator.constant()); + }); + } + + @Test + public void posBlockCreationMaxTimeDefaultValue() { + internalTestSuccess( + miningParams -> + assertThat(miningParams.getUnstable().getPosBlockCreationMaxTime()) + .isEqualTo(DEFAULT_POS_BLOCK_CREATION_MAX_TIME)); + } + + @Test + public void posBlockCreationMaxTimeOption() { + internalTestSuccess( + miningParams -> + assertThat(miningParams.getUnstable().getPosBlockCreationMaxTime()).isEqualTo(7000L), + "--Xpos-block-creation-max-time", + "7000"); + } + + @Test + public void posBlockCreationMaxTimeOutOfAllowedRange() { + internalTestFailure( + "--Xpos-block-creation-max-time must be positive and ≤ 12000", + "--Xpos-block-creation-max-time", + "17000"); + } + + @Override + protected MiningParameters createDefaultDomainObject() { + return MiningParameters.newDefault(); + } + + @Override + protected MiningParameters createCustomizedDomainObject() { + return ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .isMiningEnabled(true) + .extraData(Bytes.fromHexString("0xabc321")) + .minBlockOccupancyRatio(0.5) + .coinbase(Address.ZERO) + .build()) + .isStratumMiningEnabled(true) + .unstable(Unstable.builder().posBlockCreationMaxTime(1000).build()) + .build(); + } + + @Override + protected MiningOptions optionsFromDomainObject(final MiningParameters domainObject) { + return MiningOptions.fromConfig(domainObject); + } + + @Override + protected MiningOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) { + return besuCommand.getMiningOptions(); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommandTest.java index 6a0b5592d27..5c62076e692 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommandTest.java @@ -174,7 +174,8 @@ public void callingBlockImportSubCommandWithJSONAndSkipPOWFails() { @Test public void callingBlockImportSubCommandHelpMustDisplayUsage() { parseCommand(BLOCK_SUBCOMMAND_NAME, BLOCK_IMPORT_SUBCOMMAND_NAME, "--help"); - assertThat(commandOutput.toString(UTF_8)).isEqualTo(EXPECTED_BLOCK_IMPORT_USAGE); + assertThat(commandOutput.toString(UTF_8)) + .isEqualToNormalizingNewlines(EXPECTED_BLOCK_IMPORT_USAGE); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java index c7c6466e602..a24479e8617 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java @@ -84,7 +84,6 @@ public class BesuControllerBuilderTest { @Mock CheckpointConfigOptions checkpointConfigOptions; @Mock SynchronizerConfiguration synchronizerConfiguration; @Mock EthProtocolConfiguration ethProtocolConfiguration; - @Mock MiningParameters miningParameters; @Mock PrivacyParameters privacyParameters; @Mock Clock clock; @Mock StorageProvider storageProvider; @@ -95,6 +94,8 @@ public class BesuControllerBuilderTest { @Mock WorldStatePreimageStorage worldStatePreimageStorage; private final TransactionPoolConfiguration poolConfiguration = TransactionPoolConfiguration.DEFAULT; + private final MiningParameters miningParameters = MiningParameters.newDefault(); + private final ObservableMetricsSystem observableMetricsSystem = new NoOpMetricsSystem(); BigInteger networkId = BigInteger.ONE; diff --git a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java index b1f59554af3..33a539f8bc2 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java @@ -75,6 +75,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; +import org.mockito.Answers; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @@ -89,7 +90,10 @@ public class MergeBesuControllerBuilderTest { @Mock SynchronizerConfiguration synchronizerConfiguration; @Mock EthProtocolConfiguration ethProtocolConfiguration; @Mock CheckpointConfigOptions checkpointConfigOptions; - @Mock MiningParameters miningParameters; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + MiningParameters miningParameters; + @Mock PrivacyParameters privacyParameters; @Mock Clock clock; @Mock StorageProvider storageProvider; @@ -143,6 +147,7 @@ public void setup() { when(worldStatePreimageStorage.updater()) .thenReturn(mock(WorldStatePreimageStorage.Updater.class)); when(worldStateStorage.updater()).thenReturn(mock(WorldStateStorage.Updater.class)); + when(miningParameters.getTargetGasLimit()).thenReturn(OptionalLong.empty()); besuControllerBuilder = visitWithMockConfigs(new MergeBesuControllerBuilder()); } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java index 9fc337095f2..0b1a98a210f 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java @@ -34,6 +34,8 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; @@ -99,7 +101,7 @@ public void setup() { .thenReturn(mock(CliqueContext.class)); when(protocolContext.getConsensusContext(PostMergeContext.class)).thenReturn(mergeContext); when(protocolContext.getConsensusContext(MergeContext.class)).thenReturn(mergeContext); - miningParameters = new MiningParameters.Builder().miningEnabled(false).build(); + miningParameters = MiningParameters.newDefault(); } @Test @@ -118,7 +120,10 @@ public void assertPoWIsNotMiningPreMerge() { @Test public void assertPowMiningPreMerge() { - miningParameters = new MiningParameters.Builder().miningEnabled(true).build(); + miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues(MutableInitValues.builder().isMiningEnabled(true).build()) + .build(); var transCoordinator = buildTransitionCoordinator(powBuilder, postMergeBuilder); assertThat(transCoordinator.isMiningBeforeMerge()).isTrue(); } diff --git a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java index 8b6b10f5493..921d4e7fbe6 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java @@ -33,7 +33,8 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; -import org.hyperledger.besu.ethereum.core.MiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; @@ -155,7 +156,10 @@ public void setUp() { TestClock.system(ZoneId.systemDefault()), new NoOpMetricsSystem(), syncState, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder().minTransactionGasPrice(Wei.ZERO).build()) + .build(), txPoolConfig, null); diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java index 30bf9b6476d..d991fb9db4c 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java @@ -23,14 +23,13 @@ import org.hyperledger.besu.consensus.common.EpochManager; import org.hyperledger.besu.consensus.common.validator.ValidatorVote; import org.hyperledger.besu.cryptoservices.NodeKey; -import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockCreator; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; import org.hyperledger.besu.ethereum.core.Util; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; @@ -38,7 +37,6 @@ import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import java.util.Optional; -import java.util.function.Supplier; /** The Clique block creator. */ public class CliqueBlockCreator extends AbstractBlockCreator { @@ -49,40 +47,31 @@ public class CliqueBlockCreator extends AbstractBlockCreator { /** * Instantiates a new Clique block creator. * - * @param coinbase the coinbase - * @param targetGasLimitSupplier the target gas limit supplier + * @param miningParameters the mining parameters * @param extraDataCalculator the extra data calculator * @param transactionPool the pending transactions * @param protocolContext the protocol context * @param protocolSchedule the protocol schedule * @param nodeKey the node key - * @param minTransactionGasPrice the min transaction gas price - * @param minBlockOccupancyRatio the min block occupancy ratio * @param parentHeader the parent header * @param epochManager the epoch manager */ public CliqueBlockCreator( - final Address coinbase, - final Supplier> targetGasLimitSupplier, + final MiningParameters miningParameters, final ExtraDataCalculator extraDataCalculator, final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final NodeKey nodeKey, - final Wei minTransactionGasPrice, - final Double minBlockOccupancyRatio, final BlockHeader parentHeader, final EpochManager epochManager) { super( - coinbase, + miningParameters, __ -> Util.publicKeyToAddress(nodeKey.getPublicKey()), - targetGasLimitSupplier, extraDataCalculator, transactionPool, protocolContext, protocolSchedule, - minTransactionGasPrice, - minBlockOccupancyRatio, parentHeader, Optional.empty()); this.nodeKey = nodeKey; 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 9f2be2e1e76..81b754b267c 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 @@ -35,7 +35,6 @@ import java.util.Collection; import java.util.List; import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import com.google.common.annotations.VisibleForTesting; @@ -72,6 +71,7 @@ public CliqueMinerExecutor( this.nodeKey = nodeKey; this.localAddress = Util.publicKeyToAddress(nodeKey.getPublicKey()); this.epochManager = epochManager; + miningParams.setCoinbase(localAddress); } @Override @@ -82,15 +82,12 @@ public CliqueBlockMiner createMiner( final Function blockCreator = (header) -> new CliqueBlockCreator( - localAddress, // TOOD(tmm): This can be removed (used for voting not coinbase). - () -> targetGasLimit.map(AtomicLong::longValue), + miningParameters, this::calculateExtraData, transactionPool, protocolContext, protocolSchedule, nodeKey, - minTransactionGasPrice, - minBlockOccupancyRatio, header, epochManager); @@ -106,7 +103,7 @@ public CliqueBlockMiner createMiner( @Override public Optional
getCoinbase() { - return Optional.of(localAddress); + return miningParameters.getCoinbase(); } /** @@ -120,7 +117,8 @@ Bytes calculateExtraData(final BlockHeader parentHeader) { final List
validators = Lists.newArrayList(); final Bytes vanityDataToInsert = - ConsensusHelpers.zeroLeftPad(extraData, CliqueExtraData.EXTRA_VANITY_LENGTH); + ConsensusHelpers.zeroLeftPad( + miningParameters.getExtraData(), CliqueExtraData.EXTRA_VANITY_LENGTH); // Building ON TOP of canonical head, if the next block is epoch, include validators. if (epochManager.isEpochBlock(parentHeader.getNumber() + 1)) { diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index 0b0210d4ef3..3ddfdb1149d 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -47,6 +47,8 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.Util; import org.hyperledger.besu.ethereum.eth.manager.EthContext; @@ -134,17 +136,17 @@ public void proposerAddressCanBeExtractFromAConstructedBlock() { CliqueExtraData.createWithoutProposerSeal(Bytes.wrap(new byte[32]), validatorList); final Address coinbase = AddressHelpers.ofValue(1); + + final MiningParameters miningParameters = createMiningParameters(extraData, coinbase); + final CliqueBlockCreator blockCreator = new CliqueBlockCreator( - coinbase, - () -> Optional.of(10_000_000L), + miningParameters, parent -> extraData, createTransactionPool(), protocolContext, protocolSchedule, proposerNodeKey, - Wei.ZERO, - 0.8, blockchain.getChainHeadHeader(), epochManager); @@ -163,17 +165,16 @@ public void insertsValidVoteIntoConstructedBlock() { when(voteProvider.getVoteAfterBlock(any(), any())) .thenReturn(Optional.of(new ValidatorVote(VoteType.ADD, coinbase, a1))); + final MiningParameters miningParameters = createMiningParameters(extraData, coinbase); + final CliqueBlockCreator blockCreator = new CliqueBlockCreator( - coinbase, - () -> Optional.of(10_000_000L), + miningParameters, parent -> extraData, createTransactionPool(), protocolContext, protocolSchedule, proposerNodeKey, - Wei.ZERO, - 0.8, blockchain.getChainHeadHeader(), epochManager); @@ -197,17 +198,16 @@ public void insertsNoVoteWhenAtEpoch() { when(mockVoteProvider.getVoteAfterBlock(any(), any())) .thenReturn(Optional.of(new ValidatorVote(VoteType.ADD, coinbase, a1))); + final MiningParameters miningParameters = createMiningParameters(extraData, coinbase); + final CliqueBlockCreator blockCreator = new CliqueBlockCreator( - coinbase, - () -> Optional.of(10_000_000L), + miningParameters, parent -> extraData, createTransactionPool(), protocolContext, protocolSchedule, proposerNodeKey, - Wei.ZERO, - 0.8, blockchain.getChainHeadHeader(), epochManager); @@ -240,4 +240,19 @@ private TransactionPool createTransactionPool() { transactionPool.setEnabled(); return transactionPool; } + + private static MiningParameters createMiningParameters( + final Bytes extraData, final Address coinbase) { + final MiningParameters miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .extraData(extraData) + .targetGasLimit(10_000_000L) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(coinbase) + .build()) + .build(); + return miningParameters; + } } 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 4a3bf5424d7..7a089f2ef37 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 @@ -37,6 +37,8 @@ import org.hyperledger.besu.ethereum.core.AddressHelpers; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.Util; import org.hyperledger.besu.ethereum.eth.manager.EthContext; @@ -101,18 +103,15 @@ public void setup() { public void extraDataCreatedOnEpochBlocksContainsValidators() { final Bytes vanityData = generateRandomVanityData(); + final MiningParameters miningParameters = createMiningParameters(vanityData); + final CliqueMinerExecutor executor = new CliqueMinerExecutor( cliqueProtocolContext, cliqueProtocolSchedule, createTransactionPool(), proposerNodeKey, - new MiningParameters.Builder() - .coinbase(AddressHelpers.ofValue(1)) - .minTransactionGasPrice(Wei.ZERO) - .extraData(vanityData) - .miningEnabled(false) - .build(), + miningParameters, mock(CliqueBlockScheduler.class), new EpochManager(EPOCH_LENGTH)); @@ -138,18 +137,15 @@ public void extraDataCreatedOnEpochBlocksContainsValidators() { public void extraDataForNonEpochBlocksDoesNotContainValidaors() { final Bytes vanityData = generateRandomVanityData(); + final MiningParameters miningParameters = createMiningParameters(vanityData); + final CliqueMinerExecutor executor = new CliqueMinerExecutor( cliqueProtocolContext, cliqueProtocolSchedule, createTransactionPool(), proposerNodeKey, - new MiningParameters.Builder() - .coinbase(AddressHelpers.ofValue(1)) - .minTransactionGasPrice(Wei.ZERO) - .extraData(vanityData) - .miningEnabled(false) - .build(), + miningParameters, mock(CliqueBlockScheduler.class), new EpochManager(EPOCH_LENGTH)); @@ -175,18 +171,15 @@ public void shouldUseLatestVanityData() { final Bytes initialVanityData = generateRandomVanityData(); final Bytes modifiedVanityData = generateRandomVanityData(); + final MiningParameters miningParameters = createMiningParameters(initialVanityData); + final CliqueMinerExecutor executor = new CliqueMinerExecutor( cliqueProtocolContext, cliqueProtocolSchedule, createTransactionPool(), proposerNodeKey, - new MiningParameters.Builder() - .coinbase(AddressHelpers.ofValue(1)) - .minTransactionGasPrice(Wei.ZERO) - .extraData(initialVanityData) - .miningEnabled(false) - .build(), + miningParameters, mock(CliqueBlockScheduler.class), new EpochManager(EPOCH_LENGTH)); @@ -240,4 +233,15 @@ private Bytes generateRandomVanityData() { random.nextBytes(vanityData); return Bytes.wrap(vanityData); } + + private static MiningParameters createMiningParameters(final Bytes vanityData) { + return ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .extraData(vanityData) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(AddressHelpers.ofValue(1)) + .build()) + .build(); + } } diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java index 4e5a39f335f..4c5e773966f 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java @@ -20,17 +20,16 @@ import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockCreator; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import java.util.Optional; -import java.util.function.Supplier; /** The Bft block creator. */ // This class is responsible for creating a block without committer seals (basically it was just @@ -42,40 +41,33 @@ public class BftBlockCreator extends AbstractBlockCreator { /** * Instantiates a new Bft block creator. * + * @param miningParameters the mining parameters * @param forksSchedule the forks schedule * @param localAddress the local address - * @param targetGasLimitSupplier the target gas limit supplier * @param extraDataCalculator the extra data calculator * @param transactionPool the pending transactions * @param protocolContext the protocol context * @param protocolSchedule the protocol schedule - * @param minTransactionGasPrice the min transaction gas price - * @param minBlockOccupancyRatio the min block occupancy ratio * @param parentHeader the parent header * @param bftExtraDataCodec the bft extra data codec */ public BftBlockCreator( + final MiningParameters miningParameters, final ForksSchedule forksSchedule, final Address localAddress, - final Supplier> targetGasLimitSupplier, final ExtraDataCalculator extraDataCalculator, final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final Wei minTransactionGasPrice, - final Double minBlockOccupancyRatio, final BlockHeader parentHeader, final BftExtraDataCodec bftExtraDataCodec) { super( - localAddress, + miningParameters.setCoinbase(localAddress), miningBeneficiaryCalculator(localAddress, forksSchedule), - targetGasLimitSupplier, extraDataCalculator, transactionPool, protocolContext, protocolSchedule, - minTransactionGasPrice, - minBlockOccupancyRatio, parentHeader, Optional.empty()); this.bftExtraDataCodec = bftExtraDataCodec; diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java index 35c6a33c94e..fab04b1a770 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java @@ -40,7 +40,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; import org.apache.tuweni.bytes.Bytes; @@ -52,6 +51,8 @@ public class BftBlockCreatorFactory { /** The Forks schedule. */ protected final ForksSchedule forksSchedule; + /** The Mining parameters */ + protected final MiningParameters miningParameters; private final TransactionPool transactionPool; /** The Protocol context. */ @@ -63,13 +64,6 @@ public class BftBlockCreatorFactory { private final Address localAddress; - /** The Vanity data. */ - protected volatile Bytes vanityData; - - private volatile Wei minTransactionGasPrice; - private volatile Double minBlockOccupancyRatio; - private volatile Optional targetGasLimit; - /** * Instantiates a new Bft block creator factory. * @@ -94,11 +88,8 @@ public BftBlockCreatorFactory( this.protocolSchedule = protocolSchedule; this.forksSchedule = forksSchedule; this.localAddress = localAddress; - this.minTransactionGasPrice = miningParams.getMinTransactionGasPrice(); - this.minBlockOccupancyRatio = miningParams.getMinBlockOccupancyRatio(); - this.vanityData = miningParams.getExtraData(); + this.miningParameters = miningParams; this.bftExtraDataCodec = bftExtraDataCodec; - this.targetGasLimit = miningParams.getTargetGasLimit(); } /** @@ -110,15 +101,13 @@ public BftBlockCreatorFactory( */ public BlockCreator create(final BlockHeader parentHeader, final int round) { return new BftBlockCreator( + miningParameters, forksSchedule, localAddress, - () -> targetGasLimit.map(AtomicLong::longValue), ph -> createExtraData(round, ph), transactionPool, protocolContext, protocolSchedule, - minTransactionGasPrice, - minBlockOccupancyRatio, parentHeader, bftExtraDataCodec); } @@ -129,7 +118,8 @@ public BlockCreator create(final BlockHeader parentHeader, final int round) { * @param extraData the extra data */ public void setExtraData(final Bytes extraData) { - this.vanityData = extraData.copy(); + + miningParameters.setExtraData(extraData.copy()); } /** @@ -138,7 +128,7 @@ public void setExtraData(final Bytes extraData) { * @param minTransactionGasPrice the min transaction gas price */ public void setMinTransactionGasPrice(final Wei minTransactionGasPrice) { - this.minTransactionGasPrice = minTransactionGasPrice; + miningParameters.setMinTransactionGasPrice(minTransactionGasPrice); } /** @@ -147,7 +137,7 @@ public void setMinTransactionGasPrice(final Wei minTransactionGasPrice) { * @return the min transaction gas price */ public Wei getMinTransactionGasPrice() { - return minTransactionGasPrice; + return miningParameters.getMinTransactionGasPrice(); } /** @@ -171,7 +161,8 @@ public Bytes createExtraData(final int round, final BlockHeader parentHeader) { final BftExtraData extraData = new BftExtraData( - ConsensusHelpers.zeroLeftPad(vanityData, BftExtraDataCodec.EXTRA_VANITY_LENGTH), + ConsensusHelpers.zeroLeftPad( + miningParameters.getExtraData(), BftExtraDataCodec.EXTRA_VANITY_LENGTH), Collections.emptyList(), toVote(proposal), round, @@ -187,9 +178,7 @@ public Bytes createExtraData(final int round, final BlockHeader parentHeader) { */ public void changeTargetGasLimit(final Long newTargetGasLimit) { if (AbstractGasLimitSpecification.isValidTargetGasLimit(newTargetGasLimit)) { - this.targetGasLimit.ifPresentOrElse( - existing -> existing.set(newTargetGasLimit), - () -> this.targetGasLimit = Optional.of(new AtomicLong(newTargetGasLimit))); + miningParameters.setTargetGasLimit(newTargetGasLimit); } else { throw new UnsupportedOperationException("Specified target gas limit is invalid"); } diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java index 42d68250821..9b0d9f65ad9 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java @@ -77,6 +77,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.Util; import org.hyperledger.besu.ethereum.eth.manager.EthContext; @@ -304,11 +306,14 @@ private static ControllerAndState createControllerAndFinalState( final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); final MiningParameters miningParams = - new MiningParameters.Builder() - .coinbase(AddressHelpers.ofValue(1)) - .minTransactionGasPrice(Wei.ZERO) - .extraData(Bytes.wrap("Ibft Int tests".getBytes(UTF_8))) - .miningEnabled(true) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .isMiningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .extraData(Bytes.wrap("Ibft Int tests".getBytes(UTF_8))) + .coinbase(AddressHelpers.ofValue(1)) + .build()) .build(); final StubGenesisConfigOptions genesisConfigOptions = new StubGenesisConfigOptions(); diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java index 1039b3579c1..6065c269be7 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java @@ -41,6 +41,8 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.eth.manager.EthContext; @@ -150,11 +152,28 @@ public BlockHeaderValidator.Builder createBlockHeaderRuleset( transactionPool.setEnabled(); + final MiningParameters miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .extraData( + bftExtraDataEncoder.encode( + new BftExtraData( + Bytes.wrap(new byte[32]), + Collections.emptyList(), + Optional.empty(), + 0, + initialValidatorList))) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(AddressHelpers.ofValue(1)) + .build()) + .build(); + final BftBlockCreator blockCreator = new BftBlockCreator( + miningParameters, forksSchedule, initialValidatorList.get(0), - () -> Optional.of(10_000_000L), parent -> bftExtraDataEncoder.encode( new BftExtraData( @@ -166,8 +185,6 @@ public BlockHeaderValidator.Builder createBlockHeaderRuleset( transactionPool, protContext, protocolSchedule, - Wei.ZERO, - 0.8, parentHeader, bftExtraDataEncoder); diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java index dd8adae7e9b..b81a941816a 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java @@ -15,12 +15,12 @@ package org.hyperledger.besu.consensus.merge.blockcreation; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockCreator; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Withdrawal; @@ -30,55 +30,37 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.function.Supplier; import org.apache.tuweni.bytes.Bytes32; /** The Merge block creator. */ class MergeBlockCreator extends AbstractBlockCreator { - /** - * On PoS you do not need to compete with other nodes for block production, since you have an - * allocated slot for that, so in this case make sense to always try to fill the block, if there - * are enough pending transactions, until the remaining gas is less than the minimum needed for - * the smaller transaction. So for PoS the min-block-occupancy-ratio option is set to always try - * to fill 100% of the block. - */ - private static final double TRY_FILL_BLOCK = 1.0; /** * Instantiates a new Merge block creator. * - * @param coinbase the coinbase - * @param targetGasLimitSupplier the target gas limit supplier + * @param miningParameters the mining parameters * @param extraDataCalculator the extra data calculator * @param transactionPool the pending transactions * @param protocolContext the protocol context * @param protocolSchedule the protocol schedule - * @param minTransactionGasPrice the min transaction gas price - * @param miningBeneficiary the mining beneficiary * @param parentHeader the parent header */ public MergeBlockCreator( - final Address coinbase, - final Supplier> targetGasLimitSupplier, + final MiningParameters miningParameters, final ExtraDataCalculator extraDataCalculator, final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final Wei minTransactionGasPrice, - final Address miningBeneficiary, final BlockHeader parentHeader, final Optional
depositContractAddress) { super( - miningBeneficiary, - __ -> miningBeneficiary, - targetGasLimitSupplier, + miningParameters, + __ -> miningParameters.getCoinbase().orElseThrow(), extraDataCalculator, transactionPool, protocolContext, protocolSchedule, - minTransactionGasPrice, - TRY_FILL_BLOCK, parentHeader, depositContractAddress); } diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java index ffd57c4b27e..9a5d26f1c63 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java @@ -56,8 +56,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import com.google.common.annotations.VisibleForTesting; @@ -69,18 +67,20 @@ /** The Merge coordinator. */ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListener { private static final Logger LOG = LoggerFactory.getLogger(MergeCoordinator.class); + /** + * On PoS you do not need to compete with other nodes for block production, since you have an + * allocated slot for that, so in this case make sense to always try to fill the block, if there + * are enough pending transactions, until the remaining gas is less than the minimum needed for + * the smaller transaction. So for PoS the min-block-occupancy-ratio option is set to always try + * to fill 100% of the block. + */ + private static final double TRY_FILL_BLOCK = 1.0; - /** The Target gas limit. */ - protected final AtomicLong targetGasLimit; + private static final long DEFAULT_TARGET_GAS_LIMIT = 30000000L; /** The Mining parameters. */ protected final MiningParameters miningParameters; /** The Merge block creator factory. */ protected final MergeBlockCreatorFactory mergeBlockCreatorFactory; - /** The Extra data. */ - protected final AtomicReference extraData = - new AtomicReference<>(Bytes.fromHexString("0x")); - /** The Latest descends from terminal. */ - protected final AtomicReference latestDescendsFromTerminal = new AtomicReference<>(); /** The Merge context. */ protected final MergeContext mergeContext; /** The Protocol context. */ @@ -118,28 +118,30 @@ public MergeCoordinator( this.protocolSchedule = protocolSchedule; this.blockBuilderExecutor = blockBuilderExecutor; this.mergeContext = protocolContext.getConsensusContext(MergeContext.class); - this.miningParameters = miningParams; this.backwardSyncContext = backwardSyncContext; - this.targetGasLimit = - miningParameters - .getTargetGasLimit() - // TODO: revisit default target gas limit - .orElse(new AtomicLong(30000000L)); - this.extraData.set(miningParams.getExtraData()); + + if (miningParams.getCoinbase().isEmpty()) { + miningParams.setCoinbase(Address.ZERO); + } + if (miningParams.getTargetGasLimit().isEmpty()) { + miningParams.setTargetGasLimit(DEFAULT_TARGET_GAS_LIMIT); + } + miningParams.setMinBlockOccupancyRatio(TRY_FILL_BLOCK); + + this.miningParameters = miningParams; this.mergeBlockCreatorFactory = - (parentHeader, address) -> - new MergeBlockCreator( - address.or(miningParameters::getCoinbase).orElse(Address.ZERO), - () -> Optional.of(targetGasLimit.longValue()), - parent -> extraData.get(), - transactionPool, - protocolContext, - protocolSchedule, - this.miningParameters.getMinTransactionGasPrice(), - address.or(miningParameters::getCoinbase).orElse(Address.ZERO), - parentHeader, - depositContractAddress); + (parentHeader, address) -> { + address.ifPresent(miningParams::setCoinbase); + return new MergeBlockCreator( + miningParameters, + parent -> miningParameters.getExtraData(), + transactionPool, + protocolContext, + protocolSchedule, + parentHeader, + depositContractAddress); + }; this.backwardSyncContext.subscribeBadChainListener(this); } @@ -166,13 +168,12 @@ public MergeCoordinator( this.protocolSchedule = protocolSchedule; this.blockBuilderExecutor = blockBuilderExecutor; this.mergeContext = protocolContext.getConsensusContext(MergeContext.class); - this.miningParameters = miningParams; this.backwardSyncContext = backwardSyncContext; - this.targetGasLimit = - miningParameters - .getTargetGasLimit() - // TODO: revisit default target gas limit - .orElse(new AtomicLong(30000000L)); + if (miningParams.getTargetGasLimit().isEmpty()) { + miningParams.setTargetGasLimit(DEFAULT_TARGET_GAS_LIMIT); + } + miningParams.setMinBlockOccupancyRatio(TRY_FILL_BLOCK); + this.miningParameters = miningParams; this.mergeBlockCreatorFactory = mergeBlockCreatorFactory; @@ -210,7 +211,7 @@ public Wei getMinTransactionGasPrice() { @Override public void setExtraData(final Bytes extraData) { - this.extraData.set(extraData); + this.miningParameters.setExtraData(extraData); } @Override @@ -234,7 +235,7 @@ public Optional createBlock(final BlockHeader parentHeader, final long ti @Override public void changeTargetGasLimit(final Long newTargetGasLimit) { if (AbstractGasLimitSpecification.isValidTargetGasLimit(newTargetGasLimit)) { - this.targetGasLimit.set(newTargetGasLimit); + this.miningParameters.setTargetGasLimit(newTargetGasLimit); } else { throw new IllegalArgumentException("Specified target gas limit is invalid"); } @@ -363,11 +364,12 @@ private void tryToBuildBetterBlock( LOG.debug( "Block creation started for payload id {}, remaining time is {}ms", payloadIdentifier, - miningParameters.getPosBlockCreationMaxTime()); + miningParameters.getUnstable().getPosBlockCreationMaxTime()); blockBuilderExecutor .buildProposal(() -> retryBlockCreationUntilUseful(payloadIdentifier, blockCreator)) - .orTimeout(miningParameters.getPosBlockCreationMaxTime(), TimeUnit.MILLISECONDS) + .orTimeout( + miningParameters.getUnstable().getPosBlockCreationMaxTime(), TimeUnit.MILLISECONDS) .whenComplete( (unused, throwable) -> { if (throwable != null) { @@ -393,7 +395,9 @@ private Void retryBlockCreationUntilUseful( final long lastDuration = System.currentTimeMillis() - lastStartAt; final long waitBeforeRepetition = Math.max( - 100, miningParameters.getPosBlockCreationRepetitionMinDuration() - lastDuration); + 100, + miningParameters.getUnstable().getPosBlockCreationRepetitionMinDuration() + - lastDuration); LOG.debug("Waiting {}ms before repeating block creation", waitBeforeRepetition); Thread.sleep(waitBeforeRepetition); } catch (final CancellationException | InterruptedException ce) { diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index bc7e424133d..7c54b9260f9 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -25,7 +25,6 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -57,6 +56,9 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.Unstable; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; import org.hyperledger.besu.ethereum.eth.manager.EthContext; @@ -98,7 +100,6 @@ import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; @@ -132,11 +133,13 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper { @Mock ProposalBuilderExecutor proposalBuilderExecutor; private final Address coinbase = genesisAllocations(getPosGenesisConfigFile()).findFirst().get(); - @Spy MiningParameters miningParameters = - new MiningParameters.Builder() - .coinbase(coinbase) - .posBlockCreationRepetitionMinDuration(REPETITION_MIN_DURATION) + ImmutableMiningParameters.builder() + .mutableInitValues(MutableInitValues.builder().coinbase(coinbase).build()) + .unstable( + Unstable.builder() + .posBlockCreationRepetitionMinDuration(REPETITION_MIN_DURATION) + .build()) .build(); private MergeCoordinator coordinator; @@ -278,14 +281,11 @@ public void exceptionDuringBuildingBlockShouldNotBeInvalid() MergeBlockCreator beingSpiedOn = spy( new MergeBlockCreator( - address.or(miningParameters::getCoinbase).orElse(Address.ZERO), - () -> Optional.of(30000000L), + miningParameters, parent -> Bytes.EMPTY, transactionPool, protocolContext, protocolSchedule, - this.miningParameters.getMinTransactionGasPrice(), - address.or(miningParameters::getCoinbase).orElse(Address.ZERO), parentHeader, Optional.empty())); @@ -548,7 +548,11 @@ public void shouldRetryBlockCreationOnRecoverableError() @Test public void shouldStopRetryBlockCreationIfTimeExpired() throws InterruptedException { final AtomicLong retries = new AtomicLong(0); - doReturn(100L).when(miningParameters).getPosBlockCreationMaxTime(); + miningParameters = + ImmutableMiningParameters.builder() + .from(miningParameters) + .unstable(Unstable.builder().posBlockCreationMaxTime(100).build()) + .build(); doAnswer( invocation -> { retries.incrementAndGet(); @@ -738,7 +742,10 @@ public void shouldCancelPreviousBlockCreationJobIfCalledAgainWithNewPayloadId() public void shouldUseExtraDataFromMiningParameters() { final Bytes extraData = Bytes.fromHexString("0x1234"); - miningParameters = new MiningParameters.Builder().extraData(extraData).build(); + miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues(MutableInitValues.builder().extraData(extraData).build()) + .build(); this.coordinator = new MergeCoordinator( diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java index d5dbd139c6c..cd96d9cbdbb 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java @@ -33,7 +33,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; -import org.hyperledger.besu.ethereum.core.MiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BackwardSyncContext; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; @@ -93,7 +94,9 @@ public void setUp() { mockProtocolSchedule, CompletableFuture::runAsync, mockTransactionPool, - new MiningParameters.Builder().coinbase(coinbase).build(), + ImmutableMiningParameters.builder() + .mutableInitValues(MutableInitValues.builder().coinbase(coinbase).build()) + .build(), mock(BackwardSyncContext.class), Optional.empty()); mergeContext.setIsPostMerge(genesisState.getBlock().getHeader().getDifficulty()); diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java index ac824df6c0f..2b0386d9066 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java @@ -90,6 +90,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.core.Util; @@ -365,11 +367,14 @@ private static ControllerAndState createControllerAndFinalState( final List qbftForks) { final MiningParameters miningParams = - new MiningParameters.Builder() - .coinbase(AddressHelpers.ofValue(1)) - .minTransactionGasPrice(Wei.ZERO) - .extraData(Bytes.wrap("Qbft Int tests".getBytes(UTF_8))) - .miningEnabled(true) + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .isMiningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .extraData(Bytes.wrap("Qbft Int tests".getBytes(UTF_8))) + .coinbase(AddressHelpers.ofValue(1)) + .build()) .build(); final StubGenesisConfigOptions genesisConfigOptions = new StubGenesisConfigOptions(); diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactory.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactory.java index c2007ededf7..2f993c4d1bb 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactory.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactory.java @@ -83,7 +83,8 @@ public Bytes createExtraData(final int round, final BlockHeader parentHeader) { // vote and validators will come from contract instead of block final BftExtraData extraData = new BftExtraData( - ConsensusHelpers.zeroLeftPad(vanityData, BftExtraDataCodec.EXTRA_VANITY_LENGTH), + ConsensusHelpers.zeroLeftPad( + miningParameters.getExtraData(), BftExtraDataCodec.EXTRA_VANITY_LENGTH), Collections.emptyList(), Optional.empty(), round, diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java index fa2e8158530..d7b63bc215c 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java @@ -30,6 +30,8 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -46,9 +48,14 @@ public class QbftBlockCreatorFactoryTest { @BeforeEach @SuppressWarnings("unchecked") - public void setUp() throws Exception { - final MiningParameters miningParams = mock(MiningParameters.class); - when(miningParams.getExtraData()).thenReturn(Bytes.wrap("Qbft tests".getBytes(UTF_8))); + public void setUp() { + final MiningParameters miningParams = + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .extraData(Bytes.wrap("Qbft tests".getBytes(UTF_8))) + .build()) + .build(); final MutableQbftConfigOptions qbftConfigOptions = new MutableQbftConfigOptions(JsonQbftConfigOptions.DEFAULT); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java index 555146ca7cb..116c2d75181 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java @@ -119,7 +119,7 @@ public void setUp() { protocolContext, batchAddedListener, ethContext, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), + MiningParameters.newDefault(), new TransactionPoolMetrics(metricsSystem), TransactionPoolConfiguration.DEFAULT, null); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java index 873956d34b1..70025eeef07 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java @@ -119,7 +119,7 @@ public void setUp() { protocolContext, batchAddedListener, ethContext, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), + MiningParameters.newDefault(), new TransactionPoolMetrics(metricsSystem), TransactionPoolConfiguration.DEFAULT, null); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java index f8b52054d57..6652682fc4f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java @@ -16,6 +16,8 @@ package org.hyperledger.besu.ethereum.api; +import java.util.function.LongSupplier; + import org.immutables.value.Value; @Value.Immutable @@ -33,8 +35,8 @@ public double getGasPricePercentile() { } @Value.Default - public long getGasPriceMin() { - return 1_000_000_000L; // 1 GWei + public LongSupplier getGasPriceMinSupplier() { + return () -> 1_000_000_000L; // 1 GWei } @Value.Default diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java index 04bfdd9727a..eede84fb82b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java @@ -969,7 +969,7 @@ public Optional gasPrice() { ? Optional.empty() : Optional.of( Math.max( - apiConfig.getGasPriceMin(), + apiConfig.getGasPriceMinSupplier().getAsLong(), Math.min( apiConfig.getGasPriceMax(), gasCollection[ diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java index bba69967d52..9a03f782e5b 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java @@ -118,7 +118,7 @@ public void setupTest() throws Exception { context.getWorldStateArchive(), Optional.empty(), Optional.empty(), - ImmutableApiConfiguration.builder().gasPriceMin(0).build()); + ImmutableApiConfiguration.builder().gasPriceMinSupplier(() -> 0).build()); final Set supportedCapabilities = new HashSet<>(); supportedCapabilities.add(EthProtocol.ETH62); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java index eef2b4422e8..27462501010 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java @@ -67,7 +67,7 @@ public void setUp() { null, Optional.empty(), Optional.empty(), - ImmutableApiConfiguration.builder().gasPriceMin(100).build()), + ImmutableApiConfiguration.builder().gasPriceMinSupplier(() -> 100).build()), miningCoordinator); } diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index 3fa80f1dd0a..a8bb17e93cd 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; @@ -61,7 +62,6 @@ import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; @@ -79,43 +79,33 @@ public interface ExtraDataCalculator { private static final Logger LOG = LoggerFactory.getLogger(AbstractBlockCreator.class); - protected final Address coinbase; private final MiningBeneficiaryCalculator miningBeneficiaryCalculator; - protected final Supplier> targetGasLimitSupplier; - private final ExtraDataCalculator extraDataCalculator; private final TransactionPool transactionPool; + protected final MiningParameters miningParameters; protected final ProtocolContext protocolContext; protected final ProtocolSchedule protocolSchedule; protected final BlockHeaderFunctions blockHeaderFunctions; - private final Wei minTransactionGasPrice; - private final Double minBlockOccupancyRatio; protected final BlockHeader parentHeader; private final Optional
depositContractAddress; private final AtomicBoolean isCancelled = new AtomicBoolean(false); protected AbstractBlockCreator( - final Address coinbase, + final MiningParameters miningParameters, final MiningBeneficiaryCalculator miningBeneficiaryCalculator, - final Supplier> targetGasLimitSupplier, final ExtraDataCalculator extraDataCalculator, final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final Wei minTransactionGasPrice, - final Double minBlockOccupancyRatio, final BlockHeader parentHeader, final Optional
depositContractAddress) { - this.coinbase = coinbase; + this.miningParameters = miningParameters; this.miningBeneficiaryCalculator = miningBeneficiaryCalculator; - this.targetGasLimitSupplier = targetGasLimitSupplier; this.extraDataCalculator = extraDataCalculator; this.transactionPool = transactionPool; this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; - this.minTransactionGasPrice = minTransactionGasPrice; - this.minBlockOccupancyRatio = minBlockOccupancyRatio; this.parentHeader = parentHeader; this.depositContractAddress = depositContractAddress; blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); @@ -341,14 +331,13 @@ private TransactionSelectionResults selectTransactions( final BlockTransactionSelector selector = new BlockTransactionSelector( + miningParameters, transactionProcessor, protocolContext.getBlockchain(), disposableWorldState, transactionPool, processableBlockHeader, transactionReceiptFactory, - minTransactionGasPrice, - minBlockOccupancyRatio, isCancelled::get, miningBeneficiary, blobGasPrice, @@ -395,7 +384,7 @@ private ProcessableBlockHeader createPendingBlockHeader( .getGasLimitCalculator() .nextGasLimit( parentHeader.getGasLimit(), - targetGasLimitSupplier.get().orElse(parentHeader.getGasLimit()), + miningParameters.getTargetGasLimit().orElse(parentHeader.getGasLimit()), newBlockNumber); final DifficultyCalculator difficultyCalculator = protocolSpec.getDifficultyCalculator(); @@ -419,7 +408,7 @@ private ProcessableBlockHeader createPendingBlockHeader( final Bytes32 parentBeaconBlockRoot = maybeParentBeaconBlockRoot.orElse(null); return BlockHeaderBuilder.create() .parentHash(parentHeader.getHash()) - .coinbase(coinbase) + .coinbase(miningParameters.getCoinbase().orElseThrow()) .difficulty(Difficulty.of(difficulty)) .number(newBlockNumber) .gasLimit(gasLimit) 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 3434c6f1b26..1432afb34a7 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 @@ -32,7 +32,6 @@ import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; import org.apache.tuweni.bytes.Bytes; import org.slf4j.Logger; @@ -47,12 +46,7 @@ public abstract class AbstractMinerExecutor targetGasLimit; - + protected final MiningParameters miningParameters; private final AtomicBoolean stopped = new AtomicBoolean(false); protected AbstractMinerExecutor( @@ -64,11 +58,8 @@ protected AbstractMinerExecutor( this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; this.transactionPool = transactionPool; - this.extraData = miningParams.getExtraData(); - this.minTransactionGasPrice = miningParams.getMinTransactionGasPrice(); this.blockScheduler = blockScheduler; - this.minBlockOccupancyRatio = miningParams.getMinBlockOccupancyRatio(); - this.targetGasLimit = miningParams.getTargetGasLimit(); + this.miningParameters = miningParams; } public Optional startAsyncMining( @@ -103,24 +94,21 @@ public abstract M createMiner( final BlockHeader parentHeader); public void setExtraData(final Bytes extraData) { - this.extraData = extraData.copy(); + miningParameters.setExtraData(extraData.copy()); } public void setMinTransactionGasPrice(final Wei minTransactionGasPrice) { - this.minTransactionGasPrice = minTransactionGasPrice; + miningParameters.setMinTransactionGasPrice(minTransactionGasPrice); } public Wei getMinTransactionGasPrice() { - return minTransactionGasPrice; + return miningParameters.getMinTransactionGasPrice(); } public abstract Optional
getCoinbase(); public void changeTargetGasLimit(final Long newTargetGasLimit) { if (AbstractGasLimitSpecification.isValidTargetGasLimit(newTargetGasLimit)) { - this.targetGasLimit.ifPresentOrElse( - existing -> existing.set(newTargetGasLimit), - () -> this.targetGasLimit = Optional.of(new AtomicLong(newTargetGasLimit))); } else { throw new UnsupportedOperationException("Specified target gas limit is invalid"); } diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java index 46eb9d5c5ff..66c57379ccb 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java @@ -14,11 +14,10 @@ */ package org.hyperledger.besu.ethereum.blockcreation; -import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.EthHash; @@ -31,7 +30,6 @@ import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; -import java.util.function.Supplier; import org.apache.tuweni.units.bigints.UInt256; @@ -40,26 +38,20 @@ public class PoWBlockCreator extends AbstractBlockCreator { private final PoWSolver nonceSolver; public PoWBlockCreator( - final Address coinbase, - final Supplier> targetGasLimitSupplier, + final MiningParameters miningParameters, final ExtraDataCalculator extraDataCalculator, final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final PoWSolver nonceSolver, - final Wei minTransactionGasPrice, - final Double minBlockOccupancyRatio, final BlockHeader parentHeader) { super( - coinbase, - __ -> coinbase, - targetGasLimitSupplier, + miningParameters, + __ -> miningParameters.getCoinbase().orElseThrow(), extraDataCalculator, transactionPool, protocolContext, protocolSchedule, - minTransactionGasPrice, - minBlockOccupancyRatio, parentHeader, Optional.empty()); diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java index 49f7e702c23..cd44318e960 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java @@ -28,17 +28,12 @@ import org.hyperledger.besu.util.Subscribers; import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; public class PoWMinerExecutor extends AbstractMinerExecutor { - protected volatile Optional
coinbase; protected boolean stratumMiningEnabled; - protected final Iterable nonceGenerator; protected final EpochCalculator epochCalculator; - protected final long powJobTimeToLive; - protected final int maxOmmerDepth; public PoWMinerExecutor( final ProtocolContext protocolContext, @@ -46,15 +41,12 @@ public PoWMinerExecutor( final TransactionPool transactionPool, final MiningParameters miningParams, final AbstractBlockScheduler blockScheduler, - final EpochCalculator epochCalculator, - final long powJobTimeToLive, - final int maxOmmerDepth) { + final EpochCalculator epochCalculator) { super(protocolContext, protocolSchedule, transactionPool, miningParams, blockScheduler); - this.coinbase = miningParams.getCoinbase(); - this.nonceGenerator = miningParams.getNonceGenerator().orElse(new RandomNonceGenerator()); + if (miningParams.getNonceGenerator().isEmpty()) { + miningParams.setNonceGenerator(new RandomNonceGenerator()); + } this.epochCalculator = epochCalculator; - this.powJobTimeToLive = powJobTimeToLive; - this.maxOmmerDepth = maxOmmerDepth; } @Override @@ -62,7 +54,7 @@ public Optional startAsyncMining( final Subscribers observers, final Subscribers ethHashObservers, final BlockHeader parentHeader) { - if (coinbase.isEmpty()) { + if (miningParameters.getCoinbase().isEmpty()) { throw new CoinbaseNotSetException("Unable to start mining without a coinbase."); } return super.startAsyncMining(observers, ethHashObservers, parentHeader); @@ -79,25 +71,20 @@ public PoWBlockMiner createMiner( protocolSchedule.getForNextBlockHeader(parentHeader, 0); final PoWSolver solver = new PoWSolver( - nonceGenerator, + miningParameters, nextBlockProtocolSpec.getPoWHasher().get(), stratumMiningEnabled, ethHashObservers, - epochCalculator, - powJobTimeToLive, - maxOmmerDepth); + epochCalculator); final Function blockCreator = (header) -> new PoWBlockCreator( - coinbase.orElse(Address.ZERO), - () -> targetGasLimit.map(AtomicLong::longValue), - parent -> extraData, + miningParameters, + parent -> miningParameters.getExtraData(), transactionPool, protocolContext, protocolSchedule, solver, - minTransactionGasPrice, - minBlockOccupancyRatio, parentHeader); return new PoWBlockMiner( @@ -108,7 +95,7 @@ public void setCoinbase(final Address coinbase) { if (coinbase == null) { throw new IllegalArgumentException("Coinbase cannot be unset."); } else { - this.coinbase = Optional.of(Address.wrap(coinbase.copy())); + miningParameters.setCoinbase(Address.wrap(coinbase.copy())); } } @@ -118,7 +105,7 @@ void setStratumMiningEnabled(final boolean stratumMiningEnabled) { @Override public Optional
getCoinbase() { - return coinbase; + return miningParameters.getCoinbase(); } public EpochCalculator getEpochCalculator() { diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockSelectionContext.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockSelectionContext.java index 0292f0bf67c..8204b3d9e43 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockSelectionContext.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockSelectionContext.java @@ -17,16 +17,16 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.evm.gascalculator.GasCalculator; public record BlockSelectionContext( + MiningParameters miningParameters, GasCalculator gasCalculator, GasLimitCalculator gasLimitCalculator, - Wei minTransactionGasPrice, - Double minBlockOccupancyRatio, ProcessableBlockHeader processableBlockHeader, FeeMarket feeMarket, Wei blobGasPrice, diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java index 03c6ef28951..2c4382234dc 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.PriceTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.ProcessingResultTransactionSelector; import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; @@ -75,7 +76,6 @@ */ public class BlockTransactionSelector { private static final Logger LOG = LoggerFactory.getLogger(BlockTransactionSelector.class); - private final Supplier isCancelled; private final MainnetTransactionProcessor transactionProcessor; private final Blockchain blockchain; @@ -89,14 +89,13 @@ public class BlockTransactionSelector { private final OperationTracer pluginOperationTracer; public BlockTransactionSelector( + final MiningParameters miningParameters, final MainnetTransactionProcessor transactionProcessor, final Blockchain blockchain, final MutableWorldState worldState, final TransactionPool transactionPool, final ProcessableBlockHeader processableBlockHeader, final AbstractBlockProcessor.TransactionReceiptFactory transactionReceiptFactory, - final Wei minTransactionGasPrice, - final Double minBlockOccupancyRatio, final Supplier isCancelled, final Address miningBeneficiary, final Wei blobGasPrice, @@ -111,10 +110,9 @@ public BlockTransactionSelector( this.isCancelled = isCancelled; this.blockSelectionContext = new BlockSelectionContext( + miningParameters, gasCalculator, gasLimitCalculator, - minTransactionGasPrice, - minBlockOccupancyRatio, processableBlockHeader, feeMarket, blobGasPrice, diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java index 5d60ef8fc62..96f357546f3 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java @@ -118,13 +118,13 @@ private boolean blockOccupancyAboveThreshold( LOG.trace( "Min block occupancy ratio {}, gas used {}, available {}, remaining {}, used/available {}", - context.minBlockOccupancyRatio(), + context.miningParameters().getMinBlockOccupancyRatio(), gasUsed, gasAvailable, gasRemaining, occupancyRatio); - return occupancyRatio >= context.minBlockOccupancyRatio(); + return occupancyRatio >= context.miningParameters().getMinBlockOccupancyRatio(); } /** diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/PriceTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/PriceTransactionSelector.java index 9828650b41b..dee4316245c 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/PriceTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/PriceTransactionSelector.java @@ -86,11 +86,15 @@ private boolean transactionCurrentPriceBelowMin(final PendingTransaction pending .feeMarket() .getTransactionPriceCalculator() .price(transaction, context.processableBlockHeader().getBaseFee()); - if (context.minTransactionGasPrice().compareTo(currentMinTransactionGasPriceInBlock) > 0) { + if (context + .miningParameters() + .getMinTransactionGasPrice() + .compareTo(currentMinTransactionGasPriceInBlock) + > 0) { LOG.trace( "Current gas fee of {} is lower than configured minimum {}, skipping", pendingTransaction, - context.minTransactionGasPrice()); + context.miningParameters().getMinTransactionGasPrice()); return true; } } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index b5ad06d8248..413f9bb9ce6 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -49,6 +49,8 @@ import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; @@ -81,7 +83,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -385,16 +386,24 @@ private AbstractBlockCreator createBlockCreator( null); transactionPool.setEnabled(); + final MiningParameters miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .extraData(Bytes.fromHexString("deadbeef")) + .minTransactionGasPrice(Wei.ONE) + .minBlockOccupancyRatio(0d) + .coinbase(Address.ZERO) + .build()) + .build(); + return new TestBlockCreator( - Address.ZERO, + miningParameters, __ -> Address.ZERO, - () -> Optional.of(30_000_000L), __ -> Bytes.fromHexString("deadbeef"), transactionPool, executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), - Wei.of(1L), - 0d, blockchain.getChainHeadHeader(), depositContractAddress); } @@ -402,27 +411,21 @@ private AbstractBlockCreator createBlockCreator( static class TestBlockCreator extends AbstractBlockCreator { protected TestBlockCreator( - final Address coinbase, + final MiningParameters miningParameters, final MiningBeneficiaryCalculator miningBeneficiaryCalculator, - final Supplier> targetGasLimitSupplier, final ExtraDataCalculator extraDataCalculator, final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final Wei minTransactionGasPrice, - final Double minBlockOccupancyRatio, final BlockHeader parentHeader, final Optional
depositContractAddress) { super( - coinbase, + miningParameters, miningBeneficiaryCalculator, - targetGasLimitSupplier, extraDataCalculator, transactionPool, protocolContext, protocolSchedule, - minTransactionGasPrice, - minBlockOccupancyRatio, parentHeader, depositContractAddress); } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java index 863d164df43..1ddcd264ea0 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java @@ -46,6 +46,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MutableWorldState; @@ -111,12 +113,12 @@ public abstract class AbstractBlockTransactionSelectorTest { protected TransactionPool transactionPool; protected MutableWorldState worldState; protected ProtocolSchedule protocolSchedule; + protected MiningParameters miningParameters; @Mock(answer = Answers.RETURNS_DEEP_STUBS) protected ProtocolContext protocolContext; @Mock protected MainnetTransactionProcessor transactionProcessor; - @Mock protected MiningParameters miningParameters; @Mock(answer = Answers.RETURNS_DEEP_STUBS) protected EthContext ethContext; @@ -148,7 +150,10 @@ public void setup() { when(protocolContext.getWorldStateArchive().getMutable(any(), anyBoolean())) .thenReturn(Optional.of(worldState)); when(ethContext.getEthPeers().subscribeConnect(any())).thenReturn(1L); - when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ONE); + miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues(MutableInitValues.builder().minTransactionGasPrice(Wei.ONE).build()) + .build(); transactionPool = createTransactionPool(); } @@ -584,10 +589,8 @@ public TransactionSelectionResult evaluateTransactionPostProcessing( createBlockSelectorWithTxSelPlugin( transactionProcessor, blockHeader, - Wei.ZERO, miningBeneficiary, Wei.ZERO, - MIN_OCCUPANCY_80_PERCENT, transactionSelectorFactory); transactionPool.addRemoteTransactions( @@ -648,10 +651,8 @@ public TransactionSelectionResult evaluateTransactionPostProcessing( createBlockSelectorWithTxSelPlugin( transactionProcessor, blockHeader, - Wei.ZERO, miningBeneficiary, Wei.ZERO, - MIN_OCCUPANCY_80_PERCENT, transactionSelectorFactory); transactionPool.addRemoteTransactions(List.of(selected, notSelected, selected3)); @@ -682,10 +683,8 @@ public void transactionSelectionPluginShouldBeNotifiedWhenTransactionSelectionCo createBlockSelectorWithTxSelPlugin( transactionProcessor, createBlock(300_000), - Wei.ZERO, AddressHelpers.ofValue(1), Wei.ZERO, - MIN_OCCUPANCY_80_PERCENT, transactionSelectorFactory) .buildTransactionListForBlock(); @@ -747,14 +746,15 @@ protected BlockTransactionSelector createBlockSelector( final double minBlockOccupancyRatio) { final BlockTransactionSelector selector = new BlockTransactionSelector( + miningParameters + .setMinTransactionGasPrice(minGasPrice) + .setMinBlockOccupancyRatio(minBlockOccupancyRatio), transactionProcessor, blockchain, worldState, transactionPool, blockHeader, this::createReceipt, - minGasPrice, - minBlockOccupancyRatio, this::isCancelled, miningBeneficiary, blobGasPrice, @@ -769,21 +769,18 @@ protected BlockTransactionSelector createBlockSelector( protected BlockTransactionSelector createBlockSelectorWithTxSelPlugin( final MainnetTransactionProcessor transactionProcessor, final ProcessableBlockHeader blockHeader, - final Wei minGasPrice, final Address miningBeneficiary, final Wei blobGasPrice, - final double minBlockOccupancyRatio, final PluginTransactionSelectorFactory transactionSelectorFactory) { final BlockTransactionSelector selector = new BlockTransactionSelector( + miningParameters, transactionProcessor, blockchain, worldState, transactionPool, blockHeader, this::createReceipt, - minGasPrice, - minBlockOccupancyRatio, this::isCancelled, miningBeneficiary, blobGasPrice, diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java index 818210f88a4..80c0a3d4426 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java @@ -31,6 +31,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.PrivacyParameters; @@ -58,7 +60,6 @@ import java.io.IOException; import java.math.BigInteger; import java.util.Collections; -import java.util.Optional; import java.util.function.Function; import com.google.common.collect.Lists; @@ -94,29 +95,26 @@ void createMainnetBlock1() throws IOException { .createProtocolSchedule()) .build(); + final MiningParameters miningParameters = createMiningParameters(); + final PoWSolver solver = new PoWSolver( - Lists.newArrayList(BLOCK_1_NONCE), + miningParameters, PoWHasher.ETHASH_LIGHT, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); final TransactionPool transactionPool = createTransactionPool(executionContextTestFixture); final PoWBlockCreator blockCreator = new PoWBlockCreator( - BLOCK_1_COINBASE, - Optional::empty, + miningParameters, parent -> BLOCK_1_EXTRA_DATA, transactionPool, executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - Wei.ZERO, - 0.8, executionContextTestFixture.getBlockchain().getChainHeadHeader()); // A Hashrate should not exist in the block creator prior to creating a block @@ -150,29 +148,26 @@ void createMainnetBlock1_fixedDifficulty1() { .createProtocolSchedule()) .build(); + final MiningParameters miningParameters = createMiningParameters(); + final PoWSolver solver = new PoWSolver( - Lists.newArrayList(BLOCK_1_NONCE), + miningParameters, PoWHasher.ETHASH_LIGHT, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); final TransactionPool transactionPool = createTransactionPool(executionContextTestFixture); final PoWBlockCreator blockCreator = new PoWBlockCreator( - BLOCK_1_COINBASE, - Optional::empty, + miningParameters, parent -> BLOCK_1_EXTRA_DATA, transactionPool, executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - Wei.ZERO, - 0.8, executionContextTestFixture.getBlockchain().getChainHeadHeader()); assertThat(blockCreator.createBlock(BLOCK_1_TIMESTAMP)).isNotNull(); @@ -197,29 +192,26 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { final ExecutionContextTestFixture executionContextTestFixture = ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build(); + final MiningParameters miningParameters = createMiningParameters(); + final PoWSolver solver = new PoWSolver( - Lists.newArrayList(BLOCK_1_NONCE), + miningParameters, PoWHasher.ETHASH_LIGHT, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); final TransactionPool transactionPool = createTransactionPool(executionContextTestFixture); final PoWBlockCreator blockCreator = new PoWBlockCreator( - BLOCK_1_COINBASE, - () -> Optional.of(10_000_000L), + miningParameters, parent -> BLOCK_1_EXTRA_DATA, transactionPool, executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - Wei.ZERO, - 0.8, executionContextTestFixture.getBlockchain().getChainHeadHeader()); final MutableWorldState mutableWorldState = @@ -266,29 +258,26 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() { final ExecutionContextTestFixture executionContextTestFixture = ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build(); + final MiningParameters miningParameters = createMiningParameters(); + final PoWSolver solver = new PoWSolver( - Lists.newArrayList(BLOCK_1_NONCE), + miningParameters, PoWHasher.ETHASH_LIGHT, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); final TransactionPool transactionPool = createTransactionPool(executionContextTestFixture); final PoWBlockCreator blockCreator = new PoWBlockCreator( - BLOCK_1_COINBASE, - () -> Optional.of(10_000_000L), + miningParameters, parent -> BLOCK_1_EXTRA_DATA, transactionPool, executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - Wei.ZERO, - 0.8, executionContextTestFixture.getBlockchain().getChainHeadHeader()); final MutableWorldState mutableWorldState = @@ -347,4 +336,16 @@ private TransactionPool createTransactionPool( return transactionPool; } + + private MiningParameters createMiningParameters() { + return ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .nonceGenerator(Lists.newArrayList(BLOCK_1_NONCE)) + .extraData(BLOCK_1_EXTRA_DATA) + .minTransactionGasPrice(Wei.ONE) + .coinbase(BLOCK_1_COINBASE) + .build()) + .build(); + } } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java index b3ab4ff0688..b074e2146a8 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java @@ -20,7 +20,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MiningParameters; @@ -48,8 +47,7 @@ public class PoWMinerExecutorTest { @Test public void startingMiningWithoutCoinbaseThrowsException() { - final MiningParameters miningParameters = - new MiningParameters.Builder().coinbase(null).minTransactionGasPrice(Wei.of(1000)).build(); + final MiningParameters miningParameters = MiningParameters.newDefault(); final TransactionPool transactionPool = createTransactionPool(miningParameters); @@ -60,9 +58,7 @@ public void startingMiningWithoutCoinbaseThrowsException() { transactionPool, miningParameters, new DefaultBlockScheduler(1, 10, TestClock.fixed()), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); assertThatExceptionOfType(CoinbaseNotSetException.class) .isThrownBy(() -> executor.startAsyncMining(Subscribers.create(), Subscribers.none(), null)) @@ -71,7 +67,7 @@ public void startingMiningWithoutCoinbaseThrowsException() { @Test public void settingCoinbaseToNullThrowsException() { - final MiningParameters miningParameters = new MiningParameters.Builder().build(); + final MiningParameters miningParameters = MiningParameters.newDefault(); final TransactionPool transactionPool = createTransactionPool(miningParameters); @@ -82,9 +78,7 @@ public void settingCoinbaseToNullThrowsException() { transactionPool, miningParameters, new DefaultBlockScheduler(1, 10, TestClock.fixed()), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> executor.setCoinbase(null)) diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinatorTest.java index b60b1f2cd43..6efd63fbaed 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinatorTest.java @@ -15,8 +15,8 @@ package org.hyperledger.besu.ethereum.blockcreation; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_LIMIT; -import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_TTL; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_REMOTE_SEALERS_LIMIT; +import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_REMOTE_SEALERS_TTL; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/MiningParameters.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/MiningParameters.java index e90efaba5b9..014c0c2ae8a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/MiningParameters.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/MiningParameters.java @@ -20,385 +20,262 @@ import java.time.Duration; import java.util.Objects; import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; +import java.util.OptionalLong; import org.apache.tuweni.bytes.Bytes; - -public class MiningParameters { - - public static final int DEFAULT_REMOTE_SEALERS_LIMIT = 1000; - - public static final long DEFAULT_REMOTE_SEALERS_TTL = Duration.ofMinutes(10).toMinutes(); - - public static final long DEFAULT_POW_JOB_TTL = Duration.ofMinutes(5).toMillis(); - - public static final int DEFAULT_MAX_OMMERS_DEPTH = 8; - - public static final long DEFAULT_POS_BLOCK_CREATION_MAX_TIME = Duration.ofSeconds(12).toMillis(); - - public static final long DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION = - Duration.ofMillis(500).toMillis(); - - private final Optional
coinbase; - private final Optional targetGasLimit; - private final Wei minTransactionGasPrice; - private final Bytes extraData; - private final boolean miningEnabled; - private final boolean stratumMiningEnabled; - private final String stratumNetworkInterface; - private final int stratumPort; - private final String stratumExtranonce; - private final Optional> maybeNonceGenerator; - private final Double minBlockOccupancyRatio; - private final int remoteSealersLimit; - private final long remoteSealersTimeToLive; - private final long powJobTimeToLive; - private final int maxOmmerDepth; - private final long posBlockCreationMaxTime; - private final long posBlockCreationRepetitionMinDuration; - - private MiningParameters( - final Address coinbase, - final Long targetGasLimit, - final Wei minTransactionGasPrice, - final Bytes extraData, - final boolean miningEnabled, - final boolean stratumMiningEnabled, - final String stratumNetworkInterface, - final int stratumPort, - final String stratumExtranonce, - final Optional> maybeNonceGenerator, - final Double minBlockOccupancyRatio, - final int remoteSealersLimit, - final long remoteSealersTimeToLive, - final long powJobTimeToLive, - final int maxOmmerDepth, - final long posBlockCreationMaxTime, - final long posBlockCreationRepetitionMinDuration) { - this.coinbase = Optional.ofNullable(coinbase); - this.targetGasLimit = Optional.ofNullable(targetGasLimit).map(AtomicLong::new); - this.minTransactionGasPrice = minTransactionGasPrice; - this.extraData = extraData; - this.miningEnabled = miningEnabled; - this.stratumMiningEnabled = stratumMiningEnabled; - this.stratumNetworkInterface = stratumNetworkInterface; - this.stratumPort = stratumPort; - this.stratumExtranonce = stratumExtranonce; - this.maybeNonceGenerator = maybeNonceGenerator; - this.minBlockOccupancyRatio = minBlockOccupancyRatio; - this.remoteSealersLimit = remoteSealersLimit; - this.remoteSealersTimeToLive = remoteSealersTimeToLive; - this.powJobTimeToLive = powJobTimeToLive; - this.maxOmmerDepth = maxOmmerDepth; - this.posBlockCreationMaxTime = posBlockCreationMaxTime; - this.posBlockCreationRepetitionMinDuration = posBlockCreationRepetitionMinDuration; +import org.immutables.value.Value; + +@Value.Immutable +@Value.Enclosing +public abstract class MiningParameters { + public static final MiningParameters MINING_DISABLED = + ImmutableMiningParameters.builder() + .mutableInitValues( + ImmutableMiningParameters.MutableInitValues.builder().isMiningEnabled(false).build()) + .build(); + + public static final MiningParameters newDefault() { + return ImmutableMiningParameters.builder().build(); } - public Optional
getCoinbase() { - return coinbase; + public boolean isMiningEnabled() { + return getMutableRuntimeValues().miningEnabled; } - public Optional getTargetGasLimit() { - return targetGasLimit; + public MiningParameters setMiningEnabled(final boolean miningEnabled) { + getMutableRuntimeValues().miningEnabled = miningEnabled; + return this; } - public Wei getMinTransactionGasPrice() { - return minTransactionGasPrice; + public Bytes getExtraData() { + return getMutableRuntimeValues().extraData; } - public Bytes getExtraData() { - return extraData; + public MiningParameters setExtraData(final Bytes extraData) { + getMutableRuntimeValues().extraData = extraData; + return this; } - public boolean isMiningEnabled() { - return miningEnabled; + public Wei getMinTransactionGasPrice() { + return getMutableRuntimeValues().minTransactionGasPrice; } - public boolean isStratumMiningEnabled() { - return stratumMiningEnabled; + public MiningParameters setMinTransactionGasPrice(final Wei minTransactionGasPrice) { + getMutableRuntimeValues().minTransactionGasPrice = minTransactionGasPrice; + return this; } - public String getStratumNetworkInterface() { - return stratumNetworkInterface; + public Optional
getCoinbase() { + return getMutableRuntimeValues().coinbase; } - public int getStratumPort() { - return stratumPort; + public MiningParameters setCoinbase(final Address coinbase) { + getMutableRuntimeValues().coinbase = Optional.of(coinbase); + return this; } - public String getStratumExtranonce() { - return stratumExtranonce; + public OptionalLong getTargetGasLimit() { + return getMutableRuntimeValues().targetGasLimit; } - public Optional> getNonceGenerator() { - return maybeNonceGenerator; + public MiningParameters setTargetGasLimit(final long targetGasLimit) { + getMutableRuntimeValues().targetGasLimit = OptionalLong.of(targetGasLimit); + return this; } - public Double getMinBlockOccupancyRatio() { - return minBlockOccupancyRatio; + public double getMinBlockOccupancyRatio() { + return getMutableRuntimeValues().minBlockOccupancyRatio; } - public int getRemoteSealersLimit() { - return remoteSealersLimit; + public MiningParameters setMinBlockOccupancyRatio(final double minBlockOccupancyRatio) { + getMutableRuntimeValues().minBlockOccupancyRatio = minBlockOccupancyRatio; + return this; } - public long getRemoteSealersTimeToLive() { - return remoteSealersTimeToLive; + public Optional> getNonceGenerator() { + return getMutableRuntimeValues().nonceGenerator; } - public long getPowJobTimeToLive() { - return powJobTimeToLive; + public MiningParameters setNonceGenerator(final Iterable nonceGenerator) { + getMutableRuntimeValues().nonceGenerator = Optional.of(nonceGenerator); + return this; } - public int getMaxOmmerDepth() { - return maxOmmerDepth; + @Value.Default + public boolean isStratumMiningEnabled() { + return false; } - public long getPosBlockCreationMaxTime() { - return posBlockCreationMaxTime; + @Value.Default + public String getStratumNetworkInterface() { + return "0.0.0.0"; } - public long getPosBlockCreationRepetitionMinDuration() { - return posBlockCreationRepetitionMinDuration; + @Value.Default + public int getStratumPort() { + return 8008; } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MiningParameters that = (MiningParameters) o; - return stratumPort == that.stratumPort - && Objects.equals(coinbase, that.coinbase) - && Objects.equals(targetGasLimit, that.targetGasLimit) - && Objects.equals(minTransactionGasPrice, that.minTransactionGasPrice) - && Objects.equals(extraData, that.extraData) - && miningEnabled == that.miningEnabled - && stratumMiningEnabled == that.stratumMiningEnabled - && Objects.equals(stratumNetworkInterface, that.stratumNetworkInterface) - && Objects.equals(stratumExtranonce, that.stratumExtranonce) - && Objects.equals(minBlockOccupancyRatio, that.minBlockOccupancyRatio) - && remoteSealersTimeToLive == that.remoteSealersTimeToLive - && remoteSealersLimit == that.remoteSealersLimit - && powJobTimeToLive == that.powJobTimeToLive - && posBlockCreationMaxTime == that.posBlockCreationMaxTime - && posBlockCreationRepetitionMinDuration == that.posBlockCreationRepetitionMinDuration; + @Value.Default + protected MutableRuntimeValues getMutableRuntimeValues() { + return new MutableRuntimeValues(getMutableInitValues()); } - @Override - public int hashCode() { - return Objects.hash( - coinbase, - targetGasLimit, - minTransactionGasPrice, - extraData, - miningEnabled, - stratumMiningEnabled, - stratumNetworkInterface, - stratumPort, - stratumExtranonce, - minBlockOccupancyRatio, - remoteSealersLimit, - remoteSealersTimeToLive, - powJobTimeToLive, - posBlockCreationMaxTime, - posBlockCreationRepetitionMinDuration); + @Value.Default + public Unstable getUnstable() { + return Unstable.DEFAULT; } - @Override - public String toString() { - return "MiningParameters{" - + "coinbase=" - + coinbase - + ", targetGasLimit=" - + targetGasLimit.map(Object::toString).orElse("null") - + ", minTransactionGasPrice=" - + minTransactionGasPrice - + ", extraData=" - + extraData - + ", miningEnabled=" - + miningEnabled - + ", stratumMiningEnabled=" - + stratumMiningEnabled - + ", stratumNetworkInterface='" - + stratumNetworkInterface - + '\'' - + ", stratumPort=" - + stratumPort - + ", stratumExtranonce='" - + stratumExtranonce - + '\'' - + ", maybeNonceGenerator=" - + maybeNonceGenerator - + ", minBlockOccupancyRatio=" - + minBlockOccupancyRatio - + ", remoteSealersLimit=" - + remoteSealersLimit - + ", remoteSealersTimeToLive=" - + remoteSealersTimeToLive - + ", powJobTimeToLive=" - + powJobTimeToLive - + ", posBlockCreationMaxTime=" - + posBlockCreationMaxTime - + ", posBlockCreationRepetitionMinDuration=" - + posBlockCreationRepetitionMinDuration - + '}'; + @Value.Default + public MutableInitValues getMutableInitValues() { + return MutableInitValues.DEFAULT; } - public static class Builder { - - private Address coinbase = null; - private Long targetGasLimit = null; - private Wei minTransactionGasPrice = Wei.ZERO; - private Bytes extraData = Bytes.EMPTY; - private boolean miningEnabled = false; - private boolean stratumMiningEnabled = false; - private String stratumNetworkInterface = "0.0.0.0"; - private int stratumPort = 8008; - private String stratumExtranonce = "080c"; - private Iterable maybeNonceGenerator; - private Double minBlockOccupancyRatio = 0.8; - private int remoteSealersLimit = DEFAULT_REMOTE_SEALERS_LIMIT; - private long remoteSealersTimeToLive = DEFAULT_REMOTE_SEALERS_TTL; - private long powJobTimeToLive = DEFAULT_POW_JOB_TTL; - private int maxOmmerDepth = DEFAULT_MAX_OMMERS_DEPTH; - private long posBlockCreationMaxTime = DEFAULT_POS_BLOCK_CREATION_MAX_TIME; - - private long posBlockCreationRepetitionMinDuration = - DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; - - public Builder() { - // zero arg - } + @Value.Immutable + public interface MutableInitValues { + Bytes DEFAULT_EXTRA_DATA = Bytes.EMPTY; + Wei DEFAULT_MIN_TRANSACTION_GAS_PRICE = Wei.of(1000); + double DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO = 0.8; - public Builder(final MiningParameters existing) { - existing.getCoinbase().ifPresent(cb -> this.coinbase = cb); - existing - .getTargetGasLimit() - .map(AtomicLong::longValue) - .ifPresent(gasLimit -> this.targetGasLimit = gasLimit); - this.minTransactionGasPrice = existing.getMinTransactionGasPrice(); - this.extraData = existing.getExtraData(); - this.miningEnabled = existing.isMiningEnabled(); - this.stratumMiningEnabled = existing.isStratumMiningEnabled(); - this.stratumNetworkInterface = existing.getStratumNetworkInterface(); - this.stratumPort = existing.getStratumPort(); - this.stratumExtranonce = existing.getStratumExtranonce(); - existing.getNonceGenerator().ifPresent(ng -> this.maybeNonceGenerator = ng); - this.minBlockOccupancyRatio = existing.getMinBlockOccupancyRatio(); - this.remoteSealersLimit = existing.getRemoteSealersLimit(); - this.remoteSealersTimeToLive = existing.getRemoteSealersTimeToLive(); - this.powJobTimeToLive = existing.getPowJobTimeToLive(); - this.maxOmmerDepth = existing.getMaxOmmerDepth(); - this.posBlockCreationMaxTime = existing.getPosBlockCreationMaxTime(); - this.posBlockCreationRepetitionMinDuration = - existing.getPosBlockCreationRepetitionMinDuration(); - } + MutableInitValues DEFAULT = ImmutableMiningParameters.MutableInitValues.builder().build(); - public Builder coinbase(final Address address) { - this.coinbase = address; - return this; + @Value.Default + default boolean isMiningEnabled() { + return false; } - public Builder targetGasLimit(final Long targetGasLimit) { - this.targetGasLimit = targetGasLimit; - return this; + @Value.Default + default Bytes getExtraData() { + return DEFAULT_EXTRA_DATA; } - public Builder minTransactionGasPrice(final Wei minTransactionGasPrice) { - this.minTransactionGasPrice = minTransactionGasPrice; - return this; + @Value.Default + default Wei getMinTransactionGasPrice() { + return DEFAULT_MIN_TRANSACTION_GAS_PRICE; } - public Builder extraData(final Bytes extraData) { - this.extraData = extraData; - return this; + @Value.Default + default double getMinBlockOccupancyRatio() { + return DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO; } - public Builder miningEnabled(final boolean miningEnabled) { - this.miningEnabled = miningEnabled; - return this; - } + Optional
getCoinbase(); - public Builder stratumMiningEnabled(final boolean stratumMiningEnabled) { - this.stratumMiningEnabled = stratumMiningEnabled; - return this; - } + OptionalLong getTargetGasLimit(); - public Builder stratumNetworkInterface(final String stratumNetworkInterface) { - this.stratumNetworkInterface = stratumNetworkInterface; - return this; - } + Optional> nonceGenerator(); + } - public Builder stratumPort(final int stratumPort) { - this.stratumPort = stratumPort; - return this; + static class MutableRuntimeValues { + private volatile boolean miningEnabled; + private volatile Bytes extraData; + private volatile Wei minTransactionGasPrice; + private volatile double minBlockOccupancyRatio; + private volatile Optional
coinbase; + private volatile OptionalLong targetGasLimit; + private volatile Optional> nonceGenerator; + + private MutableRuntimeValues(final MutableInitValues initValues) { + miningEnabled = initValues.isMiningEnabled(); + extraData = initValues.getExtraData(); + minTransactionGasPrice = initValues.getMinTransactionGasPrice(); + minBlockOccupancyRatio = initValues.getMinBlockOccupancyRatio(); + coinbase = initValues.getCoinbase(); + targetGasLimit = initValues.getTargetGasLimit(); + nonceGenerator = initValues.nonceGenerator(); } - public Builder stratumExtranonce(final String stratumExtranonce) { - this.stratumExtranonce = stratumExtranonce; - return this; + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final MutableRuntimeValues that = (MutableRuntimeValues) o; + return miningEnabled == that.miningEnabled + && Double.compare(minBlockOccupancyRatio, that.minBlockOccupancyRatio) == 0 + && Objects.equals(extraData, that.extraData) + && Objects.equals(minTransactionGasPrice, that.minTransactionGasPrice) + && Objects.equals(coinbase, that.coinbase) + && Objects.equals(targetGasLimit, that.targetGasLimit) + && Objects.equals(nonceGenerator, that.nonceGenerator); } - public Builder maybeNonceGenerator(final Iterable maybeNonceGenerator) { - this.maybeNonceGenerator = maybeNonceGenerator; - return this; + @Override + public int hashCode() { + return Objects.hash( + miningEnabled, + extraData, + minTransactionGasPrice, + minBlockOccupancyRatio, + coinbase, + targetGasLimit, + nonceGenerator); } - public Builder minBlockOccupancyRatio(final Double minBlockOccupancyRatio) { - this.minBlockOccupancyRatio = minBlockOccupancyRatio; - return this; + @Override + public String toString() { + return "UpdatableRuntimeValues{" + + "miningEnabled=" + + miningEnabled + + ", extraData=" + + extraData + + ", minTransactionGasPrice=" + + minTransactionGasPrice + + ", minBlockOccupancyRatio=" + + minBlockOccupancyRatio + + ", coinbase=" + + coinbase + + ", targetGasLimit=" + + targetGasLimit + + ", nonceGenerator=" + + nonceGenerator + + '}'; } + } + + @Value.Immutable + public interface Unstable { + int DEFAULT_REMOTE_SEALERS_LIMIT = 1000; + long DEFAULT_REMOTE_SEALERS_TTL = Duration.ofMinutes(10).toMinutes(); + long DEFAULT_POW_JOB_TTL = Duration.ofMinutes(5).toMillis(); + int DEFAULT_MAX_OMMERS_DEPTH = 8; + long DEFAULT_POS_BLOCK_CREATION_MAX_TIME = Duration.ofSeconds(12).toMillis(); + long DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION = Duration.ofMillis(500).toMillis(); + + MiningParameters.Unstable DEFAULT = ImmutableMiningParameters.Unstable.builder().build(); - public Builder remoteSealersLimit(final int remoteSealersLimit) { - this.remoteSealersLimit = remoteSealersLimit; - return this; + @Value.Default + default int getRemoteSealersLimit() { + return DEFAULT_REMOTE_SEALERS_LIMIT; } - public Builder remoteSealersTimeToLive(final long remoteSealersTimeToLive) { - this.remoteSealersTimeToLive = remoteSealersTimeToLive; - return this; + @Value.Default + default long getRemoteSealersTimeToLive() { + return DEFAULT_REMOTE_SEALERS_TTL; } - public Builder powJobTimeToLive(final long powJobTimeToLive) { - this.powJobTimeToLive = powJobTimeToLive; - return this; + @Value.Default + default long getPowJobTimeToLive() { + return DEFAULT_POW_JOB_TTL; } - public Builder maxOmmerDepth(final int maxOmmerDepth) { - this.maxOmmerDepth = maxOmmerDepth; - return this; + @Value.Default + default int getMaxOmmerDepth() { + return DEFAULT_MAX_OMMERS_DEPTH; } - public Builder posBlockCreationMaxTime(final long posBlockCreationMaxTime) { - this.posBlockCreationMaxTime = posBlockCreationMaxTime; - return this; + @Value.Default + default long getPosBlockCreationMaxTime() { + return DEFAULT_POS_BLOCK_CREATION_MAX_TIME; } - public Builder posBlockCreationRepetitionMinDuration( - final long posBlockCreationRepetitionMinDuration) { - this.posBlockCreationRepetitionMinDuration = posBlockCreationRepetitionMinDuration; - return this; + @Value.Default + default long getPosBlockCreationRepetitionMinDuration() { + return DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; } - public MiningParameters build() { - return new MiningParameters( - coinbase, - targetGasLimit, - minTransactionGasPrice, - extraData, - miningEnabled, - stratumMiningEnabled, - stratumNetworkInterface, - stratumPort, - stratumExtranonce, - Optional.ofNullable(maybeNonceGenerator), - minBlockOccupancyRatio, - remoteSealersLimit, - remoteSealersTimeToLive, - powJobTimeToLive, - maxOmmerDepth, - posBlockCreationMaxTime, - posBlockCreationRepetitionMinDuration); + @Value.Default + default String getStratumExtranonce() { + return "080c"; } } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolver.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolver.java index 3248f304100..3161490478e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolver.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolver.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.mainnet; import org.hyperledger.besu.ethereum.chain.PoWObserver; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.util.Subscribers; import java.util.Optional; @@ -31,9 +32,9 @@ public class PoWSolver { - private final int maxOmmerDepth; private static final Logger LOG = LoggerFactory.getLogger(PoWSolver.class); - private final long powJobTimeToLive; + + private final MiningParameters miningParameters; public static class PoWSolverJob { @@ -76,7 +77,6 @@ PoWSolution getSolution() throws InterruptedException, ExecutionException { private final long NO_MINING_CONDUCTED = -1; - private final Iterable nonceGenerator; private final PoWHasher poWHasher; private volatile long hashesPerSecond = NO_MINING_CONDUCTED; private final Boolean stratumMiningEnabled; @@ -86,28 +86,26 @@ PoWSolution getSolution() throws InterruptedException, ExecutionException { private final ExpiringMap currentJobs = new ExpiringMap<>(); public PoWSolver( - final Iterable nonceGenerator, + final MiningParameters miningParameters, final PoWHasher poWHasher, final Boolean stratumMiningEnabled, final Subscribers ethHashObservers, - final EpochCalculator epochCalculator, - final long powJobTimeToLive, - final int maxOmmerDepth) { - this.nonceGenerator = nonceGenerator; + final EpochCalculator epochCalculator) { + this.miningParameters = miningParameters; this.poWHasher = poWHasher; this.stratumMiningEnabled = stratumMiningEnabled; this.ethHashObservers = ethHashObservers; ethHashObservers.forEach(observer -> observer.setSubmitWorkCallback(this::submitSolution)); this.epochCalculator = epochCalculator; - this.powJobTimeToLive = powJobTimeToLive; - this.maxOmmerDepth = maxOmmerDepth; } public PoWSolution solveFor(final PoWSolverJob job) throws InterruptedException, ExecutionException { currentJob = Optional.of(job); currentJobs.put( - job.getInputs().getPrePowHash(), job, System.currentTimeMillis() + powJobTimeToLive); + job.getInputs().getPrePowHash(), + job, + System.currentTimeMillis() + miningParameters.getUnstable().getPowJobTimeToLive()); if (stratumMiningEnabled) { LOG.debug( "solving with stratum miner for {} observers", ethHashObservers.getSubscriberCount()); @@ -123,7 +121,7 @@ private void findValidNonce() { final Stopwatch operationTimer = Stopwatch.createStarted(); final PoWSolverJob job = currentJob.get(); long hashesExecuted = 0; - for (final Long n : nonceGenerator) { + for (final Long n : miningParameters.getNonceGenerator().get()) { if (job.isDone()) { return; @@ -183,7 +181,7 @@ public boolean submitSolution(final PoWSolution solution) { solution.getPowHash(), ommerCandidate.getInputs().getBlockNumber(), distanceToHead); - if (distanceToHead <= maxOmmerDepth) { + if (distanceToHead <= miningParameters.getUnstable().getMaxOmmerDepth()) { jobToTestWith = ommerCandidate; } else { LOG.debug("Discarded ommer solution as too far from head {}", distanceToHead); @@ -213,6 +211,6 @@ public boolean submitSolution(final PoWSolution solution) { } public Iterable getNonceGenerator() { - return nonceGenerator; + return miningParameters.getNonceGenerator().get(); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java index da12289afa8..a6441f970fb 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java @@ -41,6 +41,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; @@ -77,7 +79,6 @@ import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.apache.tuweni.bytes.Bytes; @@ -205,26 +206,20 @@ public int getDatabaseVersion() { static class TestBlockCreator extends AbstractBlockCreator { private TestBlockCreator( - final Address coinbase, + final MiningParameters miningParameters, final MiningBeneficiaryCalculator miningBeneficiaryCalculator, - final Supplier> targetGasLimitSupplier, final ExtraDataCalculator extraDataCalculator, final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final Wei minTransactionGasPrice, - final Double minBlockOccupancyRatio, final BlockHeader parentHeader) { super( - coinbase, + miningParameters, miningBeneficiaryCalculator, - targetGasLimitSupplier, extraDataCalculator, transactionPool, protocolContext, protocolSchedule, - minTransactionGasPrice, - minBlockOccupancyRatio, parentHeader, Optional.empty()); } @@ -234,16 +229,26 @@ static TestBlockCreator forHeader( final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final TransactionPool transactionPool) { + + final MiningParameters miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .extraData(Bytes.fromHexString("deadbeef")) + .targetGasLimit(30_000_000L) + .minTransactionGasPrice(Wei.ONE) + .minBlockOccupancyRatio(0d) + .coinbase(Address.ZERO) + .build()) + .build(); + return new TestBlockCreator( - Address.ZERO, + miningParameters, __ -> Address.ZERO, - () -> Optional.of(30_000_000L), __ -> Bytes.fromHexString("deadbeef"), transactionPool, protocolContext, protocolSchedule, - Wei.of(1L), - 0d, parentHeader); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PoWSolverTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PoWSolverTest.java index 92cdce6eb0e..91553afed33 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PoWSolverTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PoWSolverTest.java @@ -21,6 +21,9 @@ import static org.mockito.Mockito.mock; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.util.Subscribers; import java.util.Arrays; @@ -48,13 +51,11 @@ public void emptyHashRateAndWorkDefinitionIsReportedPriorToSolverStarting() { final List noncesToTry = Arrays.asList(1L, 1L, 1L, 1L, 1L, 1L, 0L); final PoWSolver solver = new PoWSolver( - noncesToTry, + createMiningParameters(noncesToTry, 1000, 8), PoWHasher.ETHASH_LIGHT, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); assertThat(solver.hashesPerSecond()).isEqualTo(Optional.empty()); assertThat(solver.getWorkDefinition()).isEqualTo(Optional.empty()); @@ -83,13 +84,11 @@ public void hashRateIsProducedSuccessfully() throws InterruptedException, Execut final PoWSolver solver = new PoWSolver( - noncesToTry, + createMiningParameters(noncesToTry, 1000, 8), hasher, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); final Stopwatch operationTimer = Stopwatch.createStarted(); final PoWSolverInputs inputs = new PoWSolverInputs(UInt256.ONE, Bytes.EMPTY, 5); @@ -150,13 +149,15 @@ public void ifInvokedTwiceProducesCorrectAnswerForSecondInvocation() // Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver. final PoWSolver solver = new PoWSolver( - Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + createMiningParameters( + Lists.newArrayList( + expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + 1000, + 8), PoWHasher.ETHASH_LIGHT, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); PoWSolution soln = solver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(firstInputs)); assertThat(soln.getMixHash()).isEqualTo(expectedFirstOutput.getMixHash()); @@ -210,13 +211,15 @@ public void canAcceptSolutionsSerially() // Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver. final PoWSolver solver = new PoWSolver( - Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + createMiningParameters( + Lists.newArrayList( + expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + 1000, + 8), PoWHasher.ETHASH_LIGHT, true, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); CompletableFuture soln1 = new CompletableFuture<>(); CompletableFuture soln2 = new CompletableFuture<>(); @@ -291,13 +294,15 @@ public void canAcceptSolutionsForMultipleJobs() // Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver. final PoWSolver solver = new PoWSolver( - Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + createMiningParameters( + Lists.newArrayList( + expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + 10000, + 8), PoWHasher.ETHASH_LIGHT, true, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 10000, - 8); + new EpochCalculator.DefaultEpochCalculator()); CompletableFuture soln1 = new CompletableFuture<>(); CompletableFuture soln2 = new CompletableFuture<>(); @@ -382,13 +387,15 @@ public void canAcceptAtMostOneSolution() // Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver. final PoWSolver solver = new PoWSolver( - Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + createMiningParameters( + Lists.newArrayList( + expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + 1000, + 8), PoWHasher.ETHASH_LIGHT, true, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); CompletableFuture soln1 = new CompletableFuture<>(); CompletableFuture soln2 = new CompletableFuture<>(); @@ -475,13 +482,15 @@ public void rejectsSolutionsForOldBlocks() // Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver. final PoWSolver solver = new PoWSolver( - Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + createMiningParameters( + Lists.newArrayList( + expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), + 1000, + 8), PoWHasher.ETHASH_LIGHT, true, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); CompletableFuture soln1 = new CompletableFuture<>(); CompletableFuture soln2 = new CompletableFuture<>(); @@ -520,4 +529,16 @@ public void rejectsSolutionsForOldBlocks() assertThat(result2.getMixHash()).isEqualTo(expectedSecondOutput.getMixHash()); powThread1.interrupt(); } + + private MiningParameters createMiningParameters( + final List nonceToTry, final int powJobTimeToLive, final int maxOmmerDepth) { + return ImmutableMiningParameters.builder() + .mutableInitValues(MutableInitValues.builder().nonceGenerator(nonceToTry).build()) + .unstable( + ImmutableMiningParameters.Unstable.builder() + .maxOmmerDepth(maxOmmerDepth) + .powJobTimeToLive(powJobTimeToLive) + .build()) + .build(); + } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java index 60574c92152..8884eefdd6e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java @@ -27,7 +27,6 @@ import org.hyperledger.besu.consensus.merge.ForkchoiceEvent; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; @@ -1116,7 +1115,7 @@ public void transactionMessagesGoToTheCorrectExecutor() { TestClock.system(ZoneId.systemDefault()), metricsSystem, new SyncState(blockchain, ethManager.ethContext().getEthPeers()), - new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), + MiningParameters.newDefault(), TransactionPoolConfiguration.DEFAULT, null) .setEnabled(); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java index dc410937341..88f5457a121 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java @@ -22,7 +22,6 @@ import org.hyperledger.besu.crypto.SECPPublicKey; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; @@ -136,7 +135,7 @@ public void setupTest() { TestClock.system(ZoneId.systemDefault()), metricsSystem, syncState, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ONE).build(), + MiningParameters.newDefault(), TransactionPoolConfiguration.DEFAULT, null); transactionPool.setEnabled(); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetPooledTransactionsFromPeerTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetPooledTransactionsFromPeerTaskTest.java index f50237515e4..4c7d521a16b 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetPooledTransactionsFromPeerTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetPooledTransactionsFromPeerTaskTest.java @@ -43,7 +43,7 @@ protected List generateDataToBeRequested() { Transaction tx = new TransactionTestFixture() .nonce(genesisAccountNonce + i) - .gasPrice(Wei.ONE) + .gasPrice(Wei.of(2000)) .gasLimit(100000) .chainId(Optional.empty()) .createTransaction(genesisAccountKeyPair); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java index d9c98f3a92b..ee3b6da2425 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java @@ -132,7 +132,10 @@ public abstract class AbstractTransactionPoolTest { protected TransactionValidatorFactory transactionValidatorFactory; @Mock protected PendingTransactionAddedListener listener; - @Mock protected MiningParameters miningParameters; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + protected MiningParameters miningParameters; + @Mock protected TransactionsMessageSender transactionsMessageSender; @Mock protected NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender; @Mock protected ProtocolSpec protocolSpec; diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java index 6d3eb668f8f..90f77a783f3 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java @@ -26,7 +26,6 @@ import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; @@ -163,7 +162,7 @@ public boolean isMessagePermitted(final EnodeURL destinationEnode, final int cod TestClock.system(ZoneId.systemDefault()), metricsSystem, syncState, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), + MiningParameters.newDefault(), TransactionPoolConfiguration.DEFAULT, null); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java index 3da9bb9c66d..e902c2c1dd8 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java @@ -27,7 +27,6 @@ import org.hyperledger.besu.config.StubGenesisConfigOptions; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.BlockAddedObserver; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; @@ -241,7 +240,7 @@ private void setupInitialSyncPhase(final boolean hasInitialSyncPhase) { TestClock.fixed(), new TransactionPoolMetrics(new NoOpMetricsSystem()), syncState, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ONE).build(), + MiningParameters.newDefault(), ImmutableTransactionPoolConfiguration.builder() .txPoolMaxSize(1) .pendingTxRetentionPeriod(1) @@ -350,7 +349,7 @@ private TransactionPool createTransactionPool( TestClock.fixed(), new NoOpMetricsSystem(), syncState, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ONE).build(), + MiningParameters.newDefault(), ImmutableTransactionPoolConfiguration.builder() .txPoolImplementation(implementation) .txPoolMaxSize(1) diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java index 4d29bfd213e..bed7652c6d7 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java @@ -24,7 +24,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; -import org.hyperledger.besu.ethereum.blockcreation.IncrementingNonceGenerator; import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; @@ -32,6 +31,9 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.Unstable; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; @@ -99,7 +101,7 @@ public class RetestethContext { private HeaderValidationMode headerValidationMode; private BlockReplay blockReplay; private RetestethClock retestethClock; - + private MiningParameters miningParameters; private TransactionPool transactionPool; private EthScheduler ethScheduler; private PoWSolver poWSolver; @@ -180,25 +182,33 @@ private boolean buildContext( ? HeaderValidationMode.LIGHT : HeaderValidationMode.FULL; - final Iterable nonceGenerator = new IncrementingNonceGenerator(0); + miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues( + MutableInitValues.builder() + .coinbase(coinbase) + .extraData(extraData) + .targetGasLimit(blockchain.getChainHeadHeader().getGasLimit()) + .minBlockOccupancyRatio(0.0) + .minTransactionGasPrice(Wei.ZERO) + .build()) + .unstable(Unstable.builder().powJobTimeToLive(1000).maxOmmerDepth(8).build()) + .build(); + miningParameters.setMinTransactionGasPrice(Wei.ZERO); poWSolver = ("NoProof".equals(sealengine) || "NoReward".equals(sealEngine)) ? new PoWSolver( - nonceGenerator, + miningParameters, NO_WORK_HASHER, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8) + new EpochCalculator.DefaultEpochCalculator()) : new PoWSolver( - nonceGenerator, + miningParameters, PoWHasher.ETHASH_LIGHT, false, Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator(), - 1000, - 8); + new EpochCalculator.DefaultEpochCalculator()); blockReplay = new BlockReplay(protocolSchedule, blockchainQueries.getBlockchain()); @@ -239,7 +249,7 @@ private boolean buildContext( retestethClock, metricsSystem, syncState, - new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), + miningParameters, transactionPoolConfiguration, null); @@ -307,12 +317,8 @@ public TransactionPool getTransactionPool() { return transactionPool; } - public Address getCoinbase() { - return coinbase; - } - - public Bytes getExtraData() { - return extraData; + public MiningParameters getMiningParameters() { + return miningParameters; } public MutableBlockchain getBlockchain() { diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java index f802ee73e4b..6c3fddae1c7 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.retesteth.methods; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; @@ -24,14 +23,13 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.retesteth.RetestethClock; import org.hyperledger.besu.ethereum.retesteth.RetestethContext; -import java.util.Optional; - public class TestMineBlocks implements JsonRpcMethod { private final RetestethContext context; @@ -62,17 +60,15 @@ private boolean mineNewBlock() { final ProtocolContext protocolContext = context.getProtocolContext(); final MutableBlockchain blockchain = context.getBlockchain(); final HeaderValidationMode headerValidationMode = context.getHeaderValidationMode(); + final MiningParameters miningParameters = context.getMiningParameters(); final PoWBlockCreator blockCreator = new PoWBlockCreator( - context.getCoinbase(), - () -> Optional.of(blockchain.getChainHeadHeader().getGasLimit()), - header -> context.getExtraData(), + miningParameters, + header -> miningParameters.getExtraData(), context.getTransactionPool(), protocolContext, protocolSchedule, context.getEthHashSolver(), - Wei.ZERO, - 0.0, blockchain.getChainHeadHeader()); final Block block = blockCreator.createBlock(retesethClock.instant().getEpochSecond()).getBlock();