Mining options refactor (#6027)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/6090/head
Fabio Di Fabio 1 year ago committed by GitHub
parent c839a3b022
commit 20a82d4548
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java
  2. 18
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java
  3. 13
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java
  4. 13
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java
  5. 2
      besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java
  6. 169
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  7. 8
      besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java
  8. 303
      besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java
  9. 151
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java
  10. 35
      besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java
  11. 3
      besu/src/main/java/org/hyperledger/besu/cli/util/CommandLineUtils.java
  12. 2
      besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java
  13. 8
      besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java
  14. 2
      besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java
  15. 6
      besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java
  16. 2
      besu/src/test/java/org/hyperledger/besu/PrivacyTest.java
  17. 2
      besu/src/test/java/org/hyperledger/besu/RunnerTest.java
  18. 2
      besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java
  19. 12
      besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java
  20. 6
      besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java
  21. 389
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  22. 39
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  23. 29
      besu/src/test/java/org/hyperledger/besu/cli/options/AbstractCLIOptionsTest.java
  24. 340
      besu/src/test/java/org/hyperledger/besu/cli/options/MiningOptionsTest.java
  25. 3
      besu/src/test/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommandTest.java
  26. 3
      besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java
  27. 7
      besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java
  28. 9
      besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java
  29. 8
      besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java
  30. 19
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java
  31. 12
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java
  32. 39
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  33. 40
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java
  34. 16
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java
  35. 33
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java
  36. 15
      consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java
  37. 23
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java
  38. 28
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java
  39. 82
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java
  40. 31
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java
  41. 7
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java
  42. 15
      consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java
  43. 3
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactory.java
  44. 13
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java
  45. 2
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java
  46. 2
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java
  47. 6
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java
  48. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java
  49. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
  50. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java
  51. 25
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java
  52. 22
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMinerExecutor.java
  53. 16
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java
  54. 35
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java
  55. 4
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockSelectionContext.java
  56. 8
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java
  57. 4
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java
  58. 8
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/PriceTransactionSelector.java
  59. 29
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java
  60. 25
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java
  61. 67
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java
  62. 14
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java
  63. 4
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinatorTest.java
  64. 481
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/MiningParameters.java
  65. 26
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolver.java
  66. 31
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java
  67. 77
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PoWSolverTest.java
  68. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java
  69. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java
  70. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetPooledTransactionsFromPeerTaskTest.java
  71. 5
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java
  72. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java
  73. 5
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java
  74. 42
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java
  75. 12
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java

@ -110,9 +110,11 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
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");

@ -22,7 +22,6 @@ import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PK
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.ipc.JsonRpcIpcConfiguration;
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<Path> 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 class BesuNodeConfigurationBuilder {
}
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;
}

@ -26,6 +26,8 @@ import org.hyperledger.besu.enclave.EnclaveFactory;
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 class BesuNodeFactory {
.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(

@ -17,6 +17,8 @@ package org.hyperledger.besu.tests.acceptance.bft;
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 class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
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);

@ -768,7 +768,7 @@ public class RunnerBuilder {
powMiningCoordinator,
miningParameters.getStratumPort(),
miningParameters.getStratumNetworkInterface(),
miningParameters.getStratumExtranonce(),
miningParameters.getUnstable().getStratumExtranonce(),
metricsSystem));
miningCoordinator.addEthHashObserver(stratumServer.get());
LOG.debug("added ethash observer: {}", stratumServer.get());

@ -53,6 +53,7 @@ import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty;
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.EthProtocolOptions;
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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
"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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
split = ",")
private final Map<Long, Hash> 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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private Collection<EnodeURL> staticNodes;
private BesuController besuController;
private BesuConfiguration pluginCommonConfiguration;
private MiningParameters miningParameters;
private BesuComponent besuComponent;
private final Supplier<ObservableMetricsSystem> metricsSystem =
@ -1586,7 +1526,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
"--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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
});
}
@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 <Address>)");
}
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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
"--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 class BesuCommand implements DefaultCommandValues, Runnable {
.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 class BesuCommand implements DefaultCommandValues, Runnable {
new PrunerConfiguration(pruningBlockConfirmations, pruningBlocksRetained))
.genesisConfigOverrides(genesisConfigOverrides)
.gasLimitCalculator(
Optional.ofNullable(targetGasLimit)
.<GasLimitCalculator>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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return ImmutableApiConfiguration.builder()
.gasPriceBlocks(apiGasPriceBlocks)
.gasPricePercentile(apiGasPricePercentile)
.gasPriceMin(minTransactionGasPrice.toLong())
.gasPriceMinSupplier(
getMiningParameters().getMinTransactionGasPrice().getAsBigInteger()::longValueExact)
.gasPriceMax(apiGasPriceMax)
.build();
}
@ -2949,6 +2819,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.build();
}
private MiningParameters getMiningParameters() {
if (miningParameters == null) {
miningParameters = miningOptions.toDomainObject();
}
return miningParameters;
}
private boolean isPruningEnabled() {
return pruningEnabled;
}
@ -3344,7 +3221,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
addPortIfEnabled(
effectivePorts, metricsOptionGroup.metricsPort, metricsOptionGroup.isMetricsEnabled);
addPortIfEnabled(
effectivePorts, minerOptionGroup.stratumPort, minerOptionGroup.iStratumMiningEnabled);
effectivePorts,
getMiningParameters().getStratumPort(),
getMiningParameters().isStratumMiningEnabled());
return effectivePorts;
}

@ -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.Path;
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 = "<NETWORK>";
/** The constant MANDATORY_NODE_ID_FORMAT_HELP. */
String MANDATORY_NODE_ID_FORMAT_HELP = "<NODEID>";
/** 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. */

@ -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<MiningParameters> {
@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 <Address>)");
}
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<String> getCLIOptions() {
return CommandLineUtils.getCLIOptions(this, new MiningOptions());
}
}

@ -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;
}
}

@ -16,10 +16,6 @@ package org.hyperledger.besu.cli.subcommands.blocks;
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.datatypes.Wei;
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 @@ public class BlocksSubCommand implements Runnable {
// 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 class BlocksSubCommand implements Runnable {
}
private BesuController createBesuController() {
return parentCommand.parentCommand.buildController();
return parentCommand
.parentCommand
.getControllerBuilder()
.miningParameters(MiningParameters.newDefault())
.build();
}
private void exportRlpFormat(final BesuController controller) throws IOException {

@ -178,9 +178,8 @@ public class CommandLineUtils {
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);

@ -148,6 +148,6 @@ public class CliqueBesuControllerBuilder extends BesuControllerBuilder {
@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);
}
}

@ -55,17 +55,15 @@ public class MainnetBesuControllerBuilder extends BesuControllerBuilder {
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()) {

@ -134,7 +134,7 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
transitionProtocolSchedule.getPreMergeSchedule(),
protocolContext,
transactionPool,
new MiningParameters.Builder(miningParameters).miningEnabled(false).build(),
MiningParameters.MINING_DISABLED,
syncState,
ethProtocolManager),
mergeBesuControllerBuilder.createTransitionMiningCoordinator(

@ -187,11 +187,7 @@ public class PrivacyReorgTest {
.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)

@ -111,7 +111,7 @@ public class PrivacyTest {
.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)

@ -448,7 +448,7 @@ public final class RunnerTest {
.ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig())
.dataDirectory(dataDir)
.networkId(NETWORK_ID)
.miningParameters(new MiningParameters.Builder().miningEnabled(false).build())
.miningParameters(MiningParameters.newDefault())
.nodeKey(nodeKey)
.storageProvider(storageProvider)
.metricsSystem(metricsSystem)

@ -91,7 +91,7 @@ public final class RlpBlockExporterTest {
.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)

@ -29,8 +29,9 @@ import org.hyperledger.besu.ethereum.chain.Blockchain;
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 @@ public abstract class JsonBlockImporterTest {
.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())

@ -67,7 +67,7 @@ public final class RlpBlockImporterTest {
.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 final class RlpBlockImporterTest {
.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 final class RlpBlockImporterTest {
.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)

@ -35,7 +35,6 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ETH;
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.contains;
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.RpcMethod;
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 class BesuCommandTest extends CommandTestAbstract {
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 class BesuCommandTest extends CommandTestAbstract {
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 class BesuCommandTest extends CommandTestAbstract {
.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<MiningParameters> 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<MiningParameters> 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<MiningParameters> 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 class BesuCommandTest extends CommandTestAbstract {
"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 class BesuCommandTest extends CommandTestAbstract {
.contains("Unknown options in TOML configuration file: invalid_option, invalid_option2");
}
@Test
public void targetGasLimitIsEnabledWhenSpecified() {
parseCommand("--target-gas-limit=10000000");
@SuppressWarnings("unchecked")
final ArgumentCaptor<MiningParameters> 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<GasLimitCalculator> 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 class BesuCommandTest extends CommandTestAbstract {
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 class BesuCommandTest extends CommandTestAbstract {
.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<MiningParameters> 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);

@ -31,6 +31,7 @@ import org.hyperledger.besu.chainexport.RlpBlockExporter;
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 java.util.function.Supplier;
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 @@ import picocli.CommandLine.RunLast;
@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 @@ public abstract class CommandTestAbstract {
}
}
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 abstract class CommandTestAbstract {
return stableTransactionPoolOptions;
}
public MiningOptions getMiningOptions() {
return miningOptions;
}
public TransactionPoolOptions getUnstableTransactionPoolOptions() {
return unstableTransactionPoolOptions;
}

@ -16,6 +16,9 @@ package org.hyperledger.besu.cli.options;
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 @@ public abstract class AbstractCLIOptionsTest<D, T extends CLIOptions<D>>
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 @@ public abstract class AbstractCLIOptionsTest<D, T extends CLIOptions<D>>
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).contains(errorMsg);
}
/**
* Check logger calls
*
* <p>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);
}
}

@ -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<MiningParameters, MiningOptions> {
@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 <Address>)",
"--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<GasLimitCalculator> 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();
}
}

@ -174,7 +174,8 @@ public class BlocksSubCommandTest extends CommandTestAbstract {
@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();
}

@ -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;

@ -75,6 +75,7 @@ import org.junit.Rule;
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 class MergeBesuControllerBuilderTest {
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());
}

@ -34,6 +34,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
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 class TransitionControllerBuilderTest {
.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 class TransitionControllerBuilderTest {
@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();
}

@ -33,7 +33,8 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
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 class BesuEventsImplTest {
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);

@ -23,14 +23,13 @@ import org.hyperledger.besu.consensus.clique.CliqueExtraData;
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.ProtocolSchedule;
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<Optional<Long>> 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;

@ -35,7 +35,6 @@ import org.hyperledger.besu.util.Subscribers;
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 class CliqueMinerExecutor extends AbstractMinerExecutor<CliqueBlockMiner>
this.nodeKey = nodeKey;
this.localAddress = Util.publicKeyToAddress(nodeKey.getPublicKey());
this.epochManager = epochManager;
miningParams.setCoinbase(localAddress);
}
@Override
@ -82,15 +82,12 @@ public class CliqueMinerExecutor extends AbstractMinerExecutor<CliqueBlockMiner>
final Function<BlockHeader, CliqueBlockCreator> 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 class CliqueMinerExecutor extends AbstractMinerExecutor<CliqueBlockMiner>
@Override
public Optional<Address> getCoinbase() {
return Optional.of(localAddress);
return miningParameters.getCoinbase();
}
/**
@ -120,7 +117,8 @@ public class CliqueMinerExecutor extends AbstractMinerExecutor<CliqueBlockMiner>
final List<Address> 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)) {

@ -47,6 +47,8 @@ import org.hyperledger.besu.ethereum.core.AddressHelpers;
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 class CliqueBlockCreatorTest {
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 class CliqueBlockCreatorTest {
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 class CliqueBlockCreatorTest {
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 @@ public class CliqueBlockCreatorTest {
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;
}
}

@ -37,6 +37,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
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 class CliqueMinerExecutorTest {
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 class CliqueMinerExecutorTest {
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 class CliqueMinerExecutorTest {
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 @@ public class CliqueMinerExecutorTest {
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();
}
}

@ -20,17 +20,16 @@ import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions;
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<? extends BftConfigOptions> forksSchedule,
final Address localAddress,
final Supplier<Optional<Long>> 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;

@ -40,7 +40,6 @@ import java.util.ArrayList;
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 @@ import org.apache.tuweni.bytes.Bytes;
public class BftBlockCreatorFactory<T extends BftConfigOptions> {
/** The Forks schedule. */
protected final ForksSchedule<T> forksSchedule;
/** The Mining parameters */
protected final MiningParameters miningParameters;
private final TransactionPool transactionPool;
/** The Protocol context. */
@ -63,13 +64,6 @@ public class BftBlockCreatorFactory<T extends BftConfigOptions> {
private final Address localAddress;
/** The Vanity data. */
protected volatile Bytes vanityData;
private volatile Wei minTransactionGasPrice;
private volatile Double minBlockOccupancyRatio;
private volatile Optional<AtomicLong> targetGasLimit;
/**
* Instantiates a new Bft block creator factory.
*
@ -94,11 +88,8 @@ public class BftBlockCreatorFactory<T extends BftConfigOptions> {
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 class BftBlockCreatorFactory<T extends BftConfigOptions> {
*/
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 class BftBlockCreatorFactory<T extends BftConfigOptions> {
* @param extraData the extra data
*/
public void setExtraData(final Bytes extraData) {
this.vanityData = extraData.copy();
miningParameters.setExtraData(extraData.copy());
}
/**
@ -138,7 +128,7 @@ public class BftBlockCreatorFactory<T extends BftConfigOptions> {
* @param minTransactionGasPrice the min transaction gas price
*/
public void setMinTransactionGasPrice(final Wei minTransactionGasPrice) {
this.minTransactionGasPrice = minTransactionGasPrice;
miningParameters.setMinTransactionGasPrice(minTransactionGasPrice);
}
/**
@ -147,7 +137,7 @@ public class BftBlockCreatorFactory<T extends BftConfigOptions> {
* @return the min transaction gas price
*/
public Wei getMinTransactionGasPrice() {
return minTransactionGasPrice;
return miningParameters.getMinTransactionGasPrice();
}
/**
@ -171,7 +161,8 @@ public class BftBlockCreatorFactory<T extends BftConfigOptions> {
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 class BftBlockCreatorFactory<T extends BftConfigOptions> {
*/
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");
}

@ -77,6 +77,8 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
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 @@ public class TestContextBuilder {
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();

@ -41,6 +41,8 @@ import org.hyperledger.besu.ethereum.core.AddressHelpers;
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 class BftBlockCreatorTest {
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 class BftBlockCreatorTest {
transactionPool,
protContext,
protocolSchedule,
Wei.ZERO,
0.8,
parentHeader,
bftExtraDataEncoder);

@ -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 org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
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<Optional<Long>> 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<Address> depositContractAddress) {
super(
miningBeneficiary,
__ -> miningBeneficiary,
targetGasLimitSupplier,
miningParameters,
__ -> miningParameters.getCoinbase().orElseThrow(),
extraDataCalculator,
transactionPool,
protocolContext,
protocolSchedule,
minTransactionGasPrice,
TRY_FILL_BLOCK,
parentHeader,
depositContractAddress);
}

@ -56,8 +56,6 @@ import java.util.concurrent.CompletableFuture;
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 @@ import org.slf4j.LoggerFactory;
/** 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<Bytes> extraData =
new AtomicReference<>(Bytes.fromHexString("0x"));
/** The Latest descends from terminal. */
protected final AtomicReference<BlockHeader> latestDescendsFromTerminal = new AtomicReference<>();
/** The Merge context. */
protected final MergeContext mergeContext;
/** The Protocol context. */
@ -118,28 +118,30 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
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 class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
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 class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
@Override
public void setExtraData(final Bytes extraData) {
this.extraData.set(extraData);
this.miningParameters.setExtraData(extraData);
}
@Override
@ -234,7 +235,7 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
@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 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
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 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
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) {

@ -25,7 +25,6 @@ import static org.mockito.Mockito.atLeast;
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.BlockBody;
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.junit.jupiter.api.extension.ExtendWith;
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 class MergeCoordinatorTest implements MergeGenesisConfigHelper {
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 class MergeCoordinatorTest implements MergeGenesisConfigHelper {
@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 class MergeCoordinatorTest implements MergeGenesisConfigHelper {
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(

@ -33,7 +33,8 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
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 class MergeReorgTest implements MergeGenesisConfigHelper {
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());

@ -90,6 +90,8 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
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 @@ public class TestContextBuilder {
final List<QbftFork> 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();

@ -83,7 +83,8 @@ public class QbftBlockCreatorFactory extends BftBlockCreatorFactory<QbftConfigOp
// 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,

@ -30,6 +30,8 @@ import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
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);

@ -119,7 +119,7 @@ public class EthGetFilterChangesIntegrationTest {
protocolContext,
batchAddedListener,
ethContext,
new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(),
MiningParameters.newDefault(),
new TransactionPoolMetrics(metricsSystem),
TransactionPoolConfiguration.DEFAULT,
null);

@ -119,7 +119,7 @@ public class EthGetFilterChangesIntegrationTest {
protocolContext,
batchAddedListener,
ethContext,
new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(),
MiningParameters.newDefault(),
new TransactionPoolMetrics(metricsSystem),
TransactionPoolConfiguration.DEFAULT,
null);

@ -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 abstract class ApiConfiguration {
}
@Value.Default
public long getGasPriceMin() {
return 1_000_000_000L; // 1 GWei
public LongSupplier getGasPriceMinSupplier() {
return () -> 1_000_000_000L; // 1 GWei
}
@Value.Default

@ -969,7 +969,7 @@ public class BlockchainQueries {
? Optional.empty()
: Optional.of(
Math.max(
apiConfig.getGasPriceMin(),
apiConfig.getGasPriceMinSupplier().getAsLong(),
Math.min(
apiConfig.getGasPriceMax(),
gasCollection[

@ -118,7 +118,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
context.getWorldStateArchive(),
Optional.empty(),
Optional.empty(),
ImmutableApiConfiguration.builder().gasPriceMin(0).build());
ImmutableApiConfiguration.builder().gasPriceMinSupplier(() -> 0).build());
final Set<Capability> supportedCapabilities = new HashSet<>();
supportedCapabilities.add(EthProtocol.ETH62);

@ -67,7 +67,7 @@ public class EthGasPriceTest {
null,
Optional.empty(),
Optional.empty(),
ImmutableApiConfiguration.builder().gasPriceMin(100).build()),
ImmutableApiConfiguration.builder().gasPriceMinSupplier(() -> 100).build()),
miningCoordinator);
}

@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
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.List;
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 abstract class AbstractBlockCreator implements AsyncBlockCreator {
private static final Logger LOG = LoggerFactory.getLogger(AbstractBlockCreator.class);
protected final Address coinbase;
private final MiningBeneficiaryCalculator miningBeneficiaryCalculator;
protected final Supplier<Optional<Long>> 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<Address> depositContractAddress;
private final AtomicBoolean isCancelled = new AtomicBoolean(false);
protected AbstractBlockCreator(
final Address coinbase,
final MiningParameters miningParameters,
final MiningBeneficiaryCalculator miningBeneficiaryCalculator,
final Supplier<Optional<Long>> targetGasLimitSupplier,
final ExtraDataCalculator extraDataCalculator,
final TransactionPool transactionPool,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final Wei minTransactionGasPrice,
final Double minBlockOccupancyRatio,
final BlockHeader parentHeader,
final Optional<Address> 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 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final BlockTransactionSelector selector =
new BlockTransactionSelector(
miningParameters,
transactionProcessor,
protocolContext.getBlockchain(),
disposableWorldState,
transactionPool,
processableBlockHeader,
transactionReceiptFactory,
minTransactionGasPrice,
minBlockOccupancyRatio,
isCancelled::get,
miningBeneficiary,
blobGasPrice,
@ -395,7 +384,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
.getGasLimitCalculator()
.nextGasLimit(
parentHeader.getGasLimit(),
targetGasLimitSupplier.get().orElse(parentHeader.getGasLimit()),
miningParameters.getTargetGasLimit().orElse(parentHeader.getGasLimit()),
newBlockNumber);
final DifficultyCalculator difficultyCalculator = protocolSpec.getDifficultyCalculator();
@ -419,7 +408,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
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)

@ -32,7 +32,6 @@ import java.util.concurrent.Executors;
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<M extends BlockMiner<? extends Abstr
protected final ProtocolSchedule protocolSchedule;
protected final TransactionPool transactionPool;
protected final AbstractBlockScheduler blockScheduler;
protected volatile Bytes extraData;
protected volatile Wei minTransactionGasPrice;
protected volatile Double minBlockOccupancyRatio;
protected volatile Optional<AtomicLong> targetGasLimit;
protected final MiningParameters miningParameters;
private final AtomicBoolean stopped = new AtomicBoolean(false);
protected AbstractMinerExecutor(
@ -64,11 +58,8 @@ public abstract class AbstractMinerExecutor<M extends BlockMiner<? extends Abstr
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<M> startAsyncMining(
@ -103,24 +94,21 @@ public abstract class AbstractMinerExecutor<M extends BlockMiner<? extends Abstr
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<Address> 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");
}

@ -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.math.BigInteger;
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<Optional<Long>> 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());

@ -28,17 +28,12 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
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<PoWBlockMiner> {
protected volatile Optional<Address> coinbase;
protected boolean stratumMiningEnabled;
protected final Iterable<Long> nonceGenerator;
protected final EpochCalculator epochCalculator;
protected final long powJobTimeToLive;
protected final int maxOmmerDepth;
public PoWMinerExecutor(
final ProtocolContext protocolContext,
@ -46,15 +41,12 @@ public class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
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 class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
final Subscribers<MinedBlockObserver> observers,
final Subscribers<PoWObserver> 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 class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
protocolSchedule.getForNextBlockHeader(parentHeader, 0);
final PoWSolver solver =
new PoWSolver(
nonceGenerator,
miningParameters,
nextBlockProtocolSpec.getPoWHasher().get(),
stratumMiningEnabled,
ethHashObservers,
epochCalculator,
powJobTimeToLive,
maxOmmerDepth);
epochCalculator);
final Function<BlockHeader, PoWBlockCreator> 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 class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
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 @@ public class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
@Override
public Optional<Address> getCoinbase() {
return coinbase;
return miningParameters.getCoinbase();
}
public EpochCalculator getEpochCalculator() {

@ -17,16 +17,16 @@ package org.hyperledger.besu.ethereum.blockcreation.txselection;
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,

@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlockSi
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 @@ import org.slf4j.LoggerFactory;
*/
public class BlockTransactionSelector {
private static final Logger LOG = LoggerFactory.getLogger(BlockTransactionSelector.class);
private final Supplier<Boolean> 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<Boolean> isCancelled,
final Address miningBeneficiary,
final Wei blobGasPrice,
@ -111,10 +110,9 @@ public class BlockTransactionSelector {
this.isCancelled = isCancelled;
this.blockSelectionContext =
new BlockSelectionContext(
miningParameters,
gasCalculator,
gasLimitCalculator,
minTransactionGasPrice,
minBlockOccupancyRatio,
processableBlockHeader,
feeMarket,
blobGasPrice,

@ -118,13 +118,13 @@ public class BlockSizeTransactionSelector extends AbstractTransactionSelector {
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();
}
/**

@ -86,11 +86,15 @@ public class PriceTransactionSelector extends AbstractTransactionSelector {
.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;
}
}

@ -49,6 +49,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
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.time.Clock;
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 @@ abstract class AbstractBlockCreatorTest {
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 @@ abstract class AbstractBlockCreatorTest {
static class TestBlockCreator extends AbstractBlockCreator {
protected TestBlockCreator(
final Address coinbase,
final MiningParameters miningParameters,
final MiningBeneficiaryCalculator miningBeneficiaryCalculator,
final Supplier<Optional<Long>> targetGasLimitSupplier,
final ExtraDataCalculator extraDataCalculator,
final TransactionPool transactionPool,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final Wei minTransactionGasPrice,
final Double minBlockOccupancyRatio,
final BlockHeader parentHeader,
final Optional<Address> depositContractAddress) {
super(
coinbase,
miningParameters,
miningBeneficiaryCalculator,
targetGasLimitSupplier,
extraDataCalculator,
transactionPool,
protocolContext,
protocolSchedule,
minTransactionGasPrice,
minBlockOccupancyRatio,
parentHeader,
depositContractAddress);
}

@ -46,6 +46,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
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 abstract class AbstractBlockTransactionSelectorTest {
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 abstract class AbstractBlockTransactionSelectorTest {
createBlockSelectorWithTxSelPlugin(
transactionProcessor,
blockHeader,
Wei.ZERO,
miningBeneficiary,
Wei.ZERO,
MIN_OCCUPANCY_80_PERCENT,
transactionSelectorFactory);
transactionPool.addRemoteTransactions(
@ -648,10 +651,8 @@ public abstract class AbstractBlockTransactionSelectorTest {
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 abstract class AbstractBlockTransactionSelectorTest {
createBlockSelectorWithTxSelPlugin(
transactionProcessor,
createBlock(300_000),
Wei.ZERO,
AddressHelpers.ofValue(1),
Wei.ZERO,
MIN_OCCUPANCY_80_PERCENT,
transactionSelectorFactory)
.buildTransactionListForBlock();
@ -747,14 +746,15 @@ public abstract class AbstractBlockTransactionSelectorTest {
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 @@ public abstract class AbstractBlockTransactionSelectorTest {
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,

@ -31,6 +31,8 @@ import org.hyperledger.besu.ethereum.core.Block;
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 org.hyperledger.besu.util.Subscribers;
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 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
.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 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
.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 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
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 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
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 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
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();
}
}

@ -20,7 +20,6 @@ import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
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 class PoWMinerExecutorTest {
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 class PoWMinerExecutorTest {
@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 class PoWMinerExecutorTest {
transactionPool,
miningParameters,
new DefaultBlockScheduler(1, 10, TestClock.fixed()),
new EpochCalculator.DefaultEpochCalculator(),
1000,
8);
new EpochCalculator.DefaultEpochCalculator());
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> executor.setCoinbase(null))

@ -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;

@ -20,385 +20,262 @@ import org.hyperledger.besu.datatypes.Wei;
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<Address> coinbase;
private final Optional<AtomicLong> 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<Iterable<Long>> 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<Iterable<Long>> 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<Address> getCoinbase() {
return coinbase;
public boolean isMiningEnabled() {
return getMutableRuntimeValues().miningEnabled;
}
public Optional<AtomicLong> 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<Address> 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<Iterable<Long>> 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<Iterable<Long>> getNonceGenerator() {
return getMutableRuntimeValues().nonceGenerator;
}
public long getPowJobTimeToLive() {
return powJobTimeToLive;
public MiningParameters setNonceGenerator(final Iterable<Long> 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<Long> 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<Address> 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<Iterable<Long>> 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<Address> coinbase;
private volatile OptionalLong targetGasLimit;
private volatile Optional<Iterable<Long>> 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<Long> 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";
}
}
}

@ -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 @@ import org.slf4j.LoggerFactory;
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 @@ public class PoWSolver {
private final long NO_MINING_CONDUCTED = -1;
private final Iterable<Long> nonceGenerator;
private final PoWHasher poWHasher;
private volatile long hashesPerSecond = NO_MINING_CONDUCTED;
private final Boolean stratumMiningEnabled;
@ -86,28 +86,26 @@ public class PoWSolver {
private final ExpiringMap<Bytes, PoWSolverJob> currentJobs = new ExpiringMap<>();
public PoWSolver(
final Iterable<Long> nonceGenerator,
final MiningParameters miningParameters,
final PoWHasher poWHasher,
final Boolean stratumMiningEnabled,
final Subscribers<PoWObserver> 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 @@ public class PoWSolver {
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 class PoWSolver {
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 class PoWSolver {
}
public Iterable<Long> getNonceGenerator() {
return nonceGenerator;
return miningParameters.getNonceGenerator().get();
}
}

@ -41,6 +41,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
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.List;
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 abstract class AbstractIsolationTests {
static class TestBlockCreator extends AbstractBlockCreator {
private TestBlockCreator(
final Address coinbase,
final MiningParameters miningParameters,
final MiningBeneficiaryCalculator miningBeneficiaryCalculator,
final Supplier<Optional<Long>> 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 @@ public abstract class AbstractIsolationTests {
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);
}

@ -21,6 +21,9 @@ import static org.mockito.Mockito.doAnswer;
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 class PoWSolverTest {
final List<Long> 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 class PoWSolverTest {
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 class PoWSolverTest {
// 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 class PoWSolverTest {
// 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<PoWSolution> soln1 = new CompletableFuture<>();
CompletableFuture<PoWSolution> soln2 = new CompletableFuture<>();
@ -291,13 +294,15 @@ public class PoWSolverTest {
// 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<PoWSolution> soln1 = new CompletableFuture<>();
CompletableFuture<PoWSolution> soln2 = new CompletableFuture<>();
@ -382,13 +387,15 @@ public class PoWSolverTest {
// 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<PoWSolution> soln1 = new CompletableFuture<>();
CompletableFuture<PoWSolution> soln2 = new CompletableFuture<>();
@ -475,13 +482,15 @@ public class PoWSolverTest {
// 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<PoWSolution> soln1 = new CompletableFuture<>();
CompletableFuture<PoWSolution> soln2 = new CompletableFuture<>();
@ -520,4 +529,16 @@ public class PoWSolverTest {
assertThat(result2.getMixHash()).isEqualTo(expectedSecondOutput.getMixHash());
powThread1.interrupt();
}
private MiningParameters createMiningParameters(
final List<Long> 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();
}
}

@ -27,7 +27,6 @@ import static org.mockito.Mockito.when;
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 final class EthProtocolManagerTest {
TestClock.system(ZoneId.systemDefault()),
metricsSystem,
new SyncState(blockchain, ethManager.ethContext().getEthPeers()),
new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(),
MiningParameters.newDefault(),
TransactionPoolConfiguration.DEFAULT,
null)
.setEnabled();

@ -22,7 +22,6 @@ import org.hyperledger.besu.crypto.SECPPrivateKey;
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 abstract class AbstractMessageTaskTest<T, R> {
TestClock.system(ZoneId.systemDefault()),
metricsSystem,
syncState,
new MiningParameters.Builder().minTransactionGasPrice(Wei.ONE).build(),
MiningParameters.newDefault(),
TransactionPoolConfiguration.DEFAULT,
null);
transactionPool.setEnabled();

@ -43,7 +43,7 @@ public class GetPooledTransactionsFromPeerTaskTest extends PeerMessageTaskTest<L
Transaction tx =
new TransactionTestFixture()
.nonce(genesisAccountNonce + i)
.gasPrice(Wei.ONE)
.gasPrice(Wei.of(2000))
.gasLimit(100000)
.chainId(Optional.empty())
.createTransaction(genesisAccountKeyPair);

@ -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;

@ -26,7 +26,6 @@ import org.hyperledger.besu.config.GenesisConfigFile;
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 class TestNode implements Closeable {
TestClock.system(ZoneId.systemDefault()),
metricsSystem,
syncState,
new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(),
MiningParameters.newDefault(),
TransactionPoolConfiguration.DEFAULT,
null);

@ -27,7 +27,6 @@ import static org.mockito.Mockito.when;
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 @@ public class TransactionPoolFactoryTest {
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 @@ public class TransactionPoolFactoryTest {
TestClock.fixed(),
new NoOpMetricsSystem(),
syncState,
new MiningParameters.Builder().minTransactionGasPrice(Wei.ONE).build(),
MiningParameters.newDefault(),
ImmutableTransactionPoolConfiguration.builder()
.txPoolImplementation(implementation)
.txPoolMaxSize(1)

@ -24,7 +24,6 @@ import org.hyperledger.besu.datatypes.Wei;
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.chain.VariablesStorage;
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 @@ public class RetestethContext {
? HeaderValidationMode.LIGHT
: HeaderValidationMode.FULL;
final Iterable<Long> 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 @@ public class RetestethContext {
retestethClock,
metricsSystem,
syncState,
new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(),
miningParameters,
transactionPoolConfiguration,
null);
@ -307,12 +317,8 @@ public class RetestethContext {
return transactionPool;
}
public Address getCoinbase() {
return coinbase;
}
public Bytes getExtraData() {
return extraData;
public MiningParameters getMiningParameters() {
return miningParameters;
}
public MutableBlockchain getBlockchain() {

@ -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.blockcreation.PoWBlockCreator;
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 @@ public class TestMineBlocks implements JsonRpcMethod {
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();

Loading…
Cancel
Save