Keccak256 mining (#1882)

* Decouple PoW from ethash

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Address code review comments, create a dev network for ecip1049, prepare for keccak hasher

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Add PoW function and a few simple tests as test vectors

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Make the PoWHasher hash function a bit easier to understand

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* simplify and call out the code of the keccak hash function

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* support fixed difficulty for keccak mining

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Fix the dev network config

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Add comment to KeccakHasher

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Increase fixed difficulty for the ecip1049 dev network to produce hashes a bit less often

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* spotless

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* fix test expectations

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Fix javadoc issue

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* add acceptance test using keccak mining

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* add changelog entry

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>

* Address code review comments

Signed-off-by: Antoine Toulme <antoine@lunar-ocean.com>
pull/1985/head
Antoine Toulme 4 years ago committed by GitHub
parent a729dbd774
commit db23aef122
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 8
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java
  3. 3
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java
  4. 8
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java
  5. 8
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java
  6. 1
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java
  7. 1
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java
  8. 67
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/mining/KeccakMiningAcceptanceTest.java
  9. 7
      besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java
  10. 7
      besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java
  11. 3
      besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java
  12. 3
      besu/src/main/java/org/hyperledger/besu/controller/BesuController.java
  13. 13
      besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java
  14. 4
      besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java
  15. 9
      config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java
  16. 21
      config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java
  17. 34
      config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java
  18. 43
      config/src/main/java/org/hyperledger/besu/config/Keccak256ConfigOptions.java
  19. 31
      config/src/main/java/org/hyperledger/besu/config/PowAlgorithm.java
  20. 32
      config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java
  21. 33
      config/src/main/resources/ecip1049_dev.json
  22. 21
      config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java
  23. 4
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java
  24. 4
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java
  25. 14
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetWork.java
  26. 14
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitWork.java
  27. 5
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
  28. 5
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceCorsTest.java
  29. 5
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceHostWhitelistTest.java
  30. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceTest.java
  31. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java
  32. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java
  33. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java
  34. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java
  35. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTest.java
  36. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java
  37. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java
  38. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java
  39. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java
  40. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java
  41. 7
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java
  42. 26
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetWorkTest.java
  43. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthHashrateTest.java
  44. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMiningTest.java
  45. 32
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitWorkTest.java
  46. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStartTest.java
  47. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStopTest.java
  48. 6
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMinerExecutor.java
  49. 6
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMiningCoordinator.java
  50. 12
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/MiningCoordinator.java
  51. 30
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java
  52. 18
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockMiner.java
  53. 29
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java
  54. 22
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinator.java
  55. 8
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMiningCoordinatorTest.java
  56. 16
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java
  57. 6
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/HashRateMiningCoordinatorTest.java
  58. 46
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java
  59. 10
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java
  60. 18
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinatorTest.java
  61. 12
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/PoWObserver.java
  62. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedDifficultyCalculators.java
  63. 31
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java
  64. 26
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/EthHash.java
  65. 57
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/KeccakHasher.java
  66. 42
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java
  67. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java
  68. 16
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java
  69. 44
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWHasher.java
  70. 27
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolution.java
  71. 79
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolver.java
  72. 16
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PoWSolverInputs.java
  73. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java
  74. 16
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpec.java
  75. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java
  76. 24
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRule.java
  77. 32
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java
  78. 44
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/EthHashTest.java
  79. 120
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/KeccakHasherTest.java
  80. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidatorTest.java
  81. 82
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PoWSolverTest.java
  82. 26
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRuleTest.java
  83. 3
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java
  84. 27
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java
  85. 6
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java
  86. 32
      ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1EthProxyProtocol.java
  87. 30
      ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1Protocol.java
  88. 8
      ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumProtocol.java
  89. 17
      ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumServer.java
  90. 4
      ethereum/stratum/src/test/java/org/hyperledger/besu/ethereum/stratum/Stratum1EthProxyProtocolTest.java
  91. 11
      ethereum/stratum/src/test/java/org/hyperledger/besu/ethereum/stratum/StratumConnectionTest.java

@ -6,7 +6,7 @@
* Added `besu_transaction_pool_transactions` to the reported metrics, counting the mempool size [\#1869](https://github.com/hyperledger/besu/pull/1869) * Added `besu_transaction_pool_transactions` to the reported metrics, counting the mempool size [\#1869](https://github.com/hyperledger/besu/pull/1869)
* Distributions and maven artifacts have been moved off of bintray [\#1886](https://github.com/hyperledger/besu/pull/1886) * Distributions and maven artifacts have been moved off of bintray [\#1886](https://github.com/hyperledger/besu/pull/1886)
* admin_peers json RPC response now includes the remote nodes enode URL * admin_peers json RPC response now includes the remote nodes enode URL
* add support for keccak mining and a ecip1049_dev network [\#1882](https://github.com/hyperledger/besu/pull/1882)
### Bug Fixes ### Bug Fixes
* Fixed incorrect `groupId` in published maven pom files. * Fixed incorrect `groupId` in published maven pom files.
* Fixed GraphQL response for missing account, return empty account instead [\#1946](https://github.com/hyperledger/besu/issues/1946) * Fixed GraphQL response for missing account, return empty account instead [\#1946](https://github.com/hyperledger/besu/issues/1946)

@ -18,6 +18,7 @@ import static java.util.Collections.unmodifiableList;
import static org.apache.logging.log4j.LogManager.getLogger; import static org.apache.logging.log4j.LogManager.getLogger;
import static org.apache.tuweni.io.file.Files.copyResource; import static org.apache.tuweni.io.file.Files.copyResource;
import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.KeyPairUtil; import org.hyperledger.besu.crypto.KeyPairUtil;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
@ -97,6 +98,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
private Optional<PermissioningConfiguration> permissioningConfiguration; private Optional<PermissioningConfiguration> permissioningConfiguration;
private final GenesisConfigurationProvider genesisConfigProvider; private final GenesisConfigurationProvider genesisConfigProvider;
private final boolean devMode; private final boolean devMode;
private final NetworkName network;
private final boolean discoveryEnabled; private final boolean discoveryEnabled;
private final List<URI> bootnodes = new ArrayList<>(); private final List<URI> bootnodes = new ArrayList<>();
private final boolean bootnodeEligible; private final boolean bootnodeEligible;
@ -123,6 +125,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
final Optional<PermissioningConfiguration> permissioningConfiguration, final Optional<PermissioningConfiguration> permissioningConfiguration,
final Optional<String> keyfilePath, final Optional<String> keyfilePath,
final boolean devMode, final boolean devMode,
final NetworkName network,
final GenesisConfigurationProvider genesisConfigProvider, final GenesisConfigurationProvider genesisConfigProvider,
final boolean p2pEnabled, final boolean p2pEnabled,
final NetworkingConfiguration networkingConfiguration, final NetworkingConfiguration networkingConfiguration,
@ -156,6 +159,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
this.permissioningConfiguration = permissioningConfiguration; this.permissioningConfiguration = permissioningConfiguration;
this.genesisConfigProvider = genesisConfigProvider; this.genesisConfigProvider = genesisConfigProvider;
this.devMode = devMode; this.devMode = devMode;
this.network = network;
this.p2pEnabled = p2pEnabled; this.p2pEnabled = p2pEnabled;
this.networkingConfiguration = networkingConfiguration; this.networkingConfiguration = networkingConfiguration;
this.discoveryEnabled = discoveryEnabled; this.discoveryEnabled = discoveryEnabled;
@ -579,6 +583,10 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
return devMode; return devMode;
} }
public NetworkName getNetwork() {
return network;
}
public boolean isSecp256k1Native() { public boolean isSecp256k1Native() {
return secp256k1Native; return secp256k1Native;
} }

@ -81,6 +81,9 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
if (node.isDevMode()) { if (node.isDevMode()) {
params.add("--network"); params.add("--network");
params.add("DEV"); params.add("DEV");
} else if (node.getNetwork() != null) {
params.add("--network");
params.add(node.getNetwork().name());
} }
params.add("--sync-mode"); params.add("--sync-mode");

@ -14,6 +14,7 @@
*/ */
package org.hyperledger.besu.tests.acceptance.dsl.node.configuration; package org.hyperledger.besu.tests.acceptance.dsl.node.configuration;
import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MiningParameters;
@ -52,6 +53,7 @@ public class BesuNodeConfiguration {
private final boolean isDnsEnabled; private final boolean isDnsEnabled;
private final Optional<PrivacyParameters> privacyParameters; private final Optional<PrivacyParameters> privacyParameters;
private final List<String> runCommand; private final List<String> runCommand;
private final NetworkName network;
BesuNodeConfiguration( BesuNodeConfiguration(
final String name, final String name,
@ -63,6 +65,7 @@ public class BesuNodeConfiguration {
final Optional<PermissioningConfiguration> permissioningConfiguration, final Optional<PermissioningConfiguration> permissioningConfiguration,
final Optional<String> keyFilePath, final Optional<String> keyFilePath,
final boolean devMode, final boolean devMode,
final NetworkName network,
final GenesisConfigurationProvider genesisConfigProvider, final GenesisConfigurationProvider genesisConfigProvider,
final boolean p2pEnabled, final boolean p2pEnabled,
final NetworkingConfiguration networkingConfiguration, final NetworkingConfiguration networkingConfiguration,
@ -86,6 +89,7 @@ public class BesuNodeConfiguration {
this.keyFilePath = keyFilePath; this.keyFilePath = keyFilePath;
this.dataPath = dataPath; this.dataPath = dataPath;
this.devMode = devMode; this.devMode = devMode;
this.network = network;
this.genesisConfigProvider = genesisConfigProvider; this.genesisConfigProvider = genesisConfigProvider;
this.p2pEnabled = p2pEnabled; this.p2pEnabled = p2pEnabled;
this.networkingConfiguration = networkingConfiguration; this.networkingConfiguration = networkingConfiguration;
@ -193,4 +197,8 @@ public class BesuNodeConfiguration {
public List<String> getRunCommand() { public List<String> getRunCommand() {
return runCommand; return runCommand;
} }
public NetworkName getNetwork() {
return network;
}
} }

@ -17,6 +17,7 @@ package org.hyperledger.besu.tests.acceptance.dsl.node.configuration;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
@ -55,6 +56,7 @@ public class BesuNodeConfigurationBuilder {
private boolean discoveryEnabled = true; private boolean discoveryEnabled = true;
private boolean bootnodeEligible = true; private boolean bootnodeEligible = true;
private boolean revertReasonEnabled = false; private boolean revertReasonEnabled = false;
private NetworkName network = null;
private boolean secp256K1Native = false; private boolean secp256K1Native = false;
private boolean altbn128Native = false; private boolean altbn128Native = false;
private final List<String> plugins = new ArrayList<>(); private final List<String> plugins = new ArrayList<>();
@ -165,6 +167,11 @@ public class BesuNodeConfigurationBuilder {
return this; return this;
} }
public BesuNodeConfigurationBuilder network(final NetworkName network) {
this.network = network;
return this;
}
public BesuNodeConfigurationBuilder webSocketEnabled() { public BesuNodeConfigurationBuilder webSocketEnabled() {
final WebSocketConfiguration config = WebSocketConfiguration.createDefault(); final WebSocketConfiguration config = WebSocketConfiguration.createDefault();
config.setEnabled(true); config.setEnabled(true);
@ -295,6 +302,7 @@ public class BesuNodeConfigurationBuilder {
permissioningConfiguration, permissioningConfiguration,
Optional.ofNullable(keyFilePath), Optional.ofNullable(keyFilePath),
devMode, devMode,
network,
genesisConfigProvider, genesisConfigProvider,
p2pEnabled, p2pEnabled,
networkingConfiguration, networkingConfiguration,

@ -60,6 +60,7 @@ public class BesuNodeFactory {
config.getPermissioningConfiguration(), config.getPermissioningConfiguration(),
config.getKeyFilePath(), config.getKeyFilePath(),
config.isDevMode(), config.isDevMode(),
config.getNetwork(),
config.getGenesisConfigProvider(), config.getGenesisConfigProvider(),
config.isP2pEnabled(), config.isP2pEnabled(),
config.getNetworkingConfiguration(), config.getNetworkingConfiguration(),

@ -94,6 +94,7 @@ public class PrivacyNode implements AutoCloseable {
besuConfig.getPermissioningConfiguration(), besuConfig.getPermissioningConfiguration(),
besuConfig.getKeyFilePath(), besuConfig.getKeyFilePath(),
besuConfig.isDevMode(), besuConfig.isDevMode(),
besuConfig.getNetwork(),
besuConfig.getGenesisConfigProvider(), besuConfig.getGenesisConfigProvider(),
besuConfig.isP2pEnabled(), besuConfig.isP2pEnabled(),
besuConfig.getNetworkingConfiguration(), besuConfig.getNetworkingConfiguration(),

@ -0,0 +1,67 @@
/*
* 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.tests.acceptance.mining;
import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder;
import org.junit.Before;
import org.junit.Test;
public class KeccakMiningAcceptanceTest extends AcceptanceTestBase {
private Node minerNode;
@Before
public void setUp() throws Exception {
minerNode =
besu.create(
new BesuNodeConfigurationBuilder()
.name("miner1")
.devMode(false)
.network(NetworkName.ECIP1049_DEV)
.miningEnabled()
.jsonRpcEnabled()
.webSocketEnabled()
.build());
cluster.start(minerNode);
}
@Test
public void shouldMineTransactions() {
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode.execute(accountTransactions.createTransfer(sender, 50));
cluster.verify(sender.balanceEquals(50));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1));
cluster.verify(receiver.balanceEquals(1));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2));
cluster.verify(receiver.balanceEquals(3));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3));
cluster.verify(receiver.balanceEquals(6));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 4));
cluster.verify(receiver.balanceEquals(10));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 5));
cluster.verify(receiver.balanceEquals(15));
}
}

@ -17,6 +17,7 @@ package org.hyperledger.besu.chainimport;
import org.hyperledger.besu.chainimport.internal.BlockData; import org.hyperledger.besu.chainimport.internal.BlockData;
import org.hyperledger.besu.chainimport.internal.ChainData; import org.hyperledger.besu.chainimport.internal.ChainData;
import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
@ -119,9 +120,9 @@ public class JsonBlockImporter {
final BlockData blockData, final BlockData blockData,
final GenesisConfigOptions genesisConfig) { final GenesisConfigOptions genesisConfig) {
// Some fields can only be configured for ethash // Some fields can only be configured for ethash
if (genesisConfig.isEthHash()) { if (genesisConfig.getPowAlgorithm() != PowAlgorithm.UNSUPPORTED) {
// For simplicity only set these for ethash. Other consensus algorithms use these fields for // For simplicity only set these for PoW consensus algorithms.
// special purposes or ignore them // Other consensus algorithms use these fields for special purposes or ignore them.
miner.setCoinbase(blockData.getCoinbase().orElse(Address.ZERO)); miner.setCoinbase(blockData.getCoinbase().orElse(Address.ZERO));
miner.setExtraData(blockData.getExtraData().orElse(Bytes.EMPTY)); miner.setExtraData(blockData.getExtraData().orElse(Bytes.EMPTY));
} else if (blockData.getCoinbase().isPresent() || blockData.getExtraData().isPresent()) { } else if (blockData.getCoinbase().isPresent() || blockData.getExtraData().isPresent()) {

@ -47,6 +47,7 @@ public class EthNetworkConfig {
public static final BigInteger RINKEBY_NETWORK_ID = BigInteger.valueOf(4); public static final BigInteger RINKEBY_NETWORK_ID = BigInteger.valueOf(4);
public static final BigInteger GOERLI_NETWORK_ID = BigInteger.valueOf(5); public static final BigInteger GOERLI_NETWORK_ID = BigInteger.valueOf(5);
public static final BigInteger DEV_NETWORK_ID = BigInteger.valueOf(2018); public static final BigInteger DEV_NETWORK_ID = BigInteger.valueOf(2018);
public static final BigInteger ECIP1049_DEV_NETWORK_ID = BigInteger.valueOf(2021);
public static final BigInteger CLASSIC_NETWORK_ID = BigInteger.valueOf(1); public static final BigInteger CLASSIC_NETWORK_ID = BigInteger.valueOf(1);
public static final BigInteger KOTTI_NETWORK_ID = BigInteger.valueOf(6); public static final BigInteger KOTTI_NETWORK_ID = BigInteger.valueOf(6);
public static final BigInteger MORDOR_NETWORK_ID = BigInteger.valueOf(7); public static final BigInteger MORDOR_NETWORK_ID = BigInteger.valueOf(7);
@ -56,6 +57,7 @@ public class EthNetworkConfig {
private static final String RINKEBY_GENESIS = "/rinkeby.json"; private static final String RINKEBY_GENESIS = "/rinkeby.json";
private static final String GOERLI_GENESIS = "/goerli.json"; private static final String GOERLI_GENESIS = "/goerli.json";
private static final String DEV_GENESIS = "/dev.json"; private static final String DEV_GENESIS = "/dev.json";
private static final String DEV_ECIP1049_GENESIS = "/ecip1049_dev.json";
private static final String CLASSIC_GENESIS = "/classic.json"; private static final String CLASSIC_GENESIS = "/classic.json";
private static final String KOTTI_GENESIS = "/kotti.json"; private static final String KOTTI_GENESIS = "/kotti.json";
private static final String MORDOR_GENESIS = "/mordor.json"; private static final String MORDOR_GENESIS = "/mordor.json";
@ -154,6 +156,9 @@ public class EthNetworkConfig {
case CLASSIC: case CLASSIC:
return new EthNetworkConfig( return new EthNetworkConfig(
jsonConfig(CLASSIC_GENESIS), CLASSIC_NETWORK_ID, CLASSIC_BOOTSTRAP_NODES, null); jsonConfig(CLASSIC_GENESIS), CLASSIC_NETWORK_ID, CLASSIC_BOOTSTRAP_NODES, null);
case ECIP1049_DEV:
return new EthNetworkConfig(
jsonConfig(DEV_ECIP1049_GENESIS), ECIP1049_DEV_NETWORK_ID, new ArrayList<>(), null);
case KOTTI: case KOTTI:
return new EthNetworkConfig( return new EthNetworkConfig(
jsonConfig(KOTTI_GENESIS), KOTTI_NETWORK_ID, KOTTI_BOOTSTRAP_NODES, null); jsonConfig(KOTTI_GENESIS), KOTTI_NETWORK_ID, KOTTI_BOOTSTRAP_NODES, null);
@ -194,6 +199,8 @@ public class EthNetworkConfig {
return jsonConfig(GOERLI_GENESIS); return jsonConfig(GOERLI_GENESIS);
case DEV: case DEV:
return jsonConfig(DEV_GENESIS); return jsonConfig(DEV_GENESIS);
case ECIP1049_DEV:
return jsonConfig(DEV_ECIP1049_GENESIS);
case CLASSIC: case CLASSIC:
return jsonConfig(CLASSIC_GENESIS); return jsonConfig(CLASSIC_GENESIS);
case KOTTI: case KOTTI:

@ -23,5 +23,6 @@ public enum NetworkName {
CLASSIC, CLASSIC,
KOTTI, KOTTI,
MORDOR, MORDOR,
YOLO_V3 YOLO_V3,
ECIP1049_DEV
} }

@ -17,6 +17,7 @@ package org.hyperledger.besu.controller;
import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.crypto.NodeKey; import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi;
@ -191,7 +192,7 @@ public class BesuController implements java.io.Closeable {
genesisConfig.getConfigOptions(genesisConfigOverrides); genesisConfig.getConfigOptions(genesisConfigOverrides);
final BesuControllerBuilder builder; final BesuControllerBuilder builder;
if (configOptions.isEthHash()) { if (configOptions.getPowAlgorithm() != PowAlgorithm.UNSUPPORTED) {
builder = new MainnetBesuControllerBuilder(); builder = new MainnetBesuControllerBuilder();
} else if (configOptions.isIbft2()) { } else if (configOptions.isIbft2()) {
builder = new IbftBesuControllerBuilder(); builder = new IbftBesuControllerBuilder();

@ -16,9 +16,9 @@ package org.hyperledger.besu.controller;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.DefaultBlockScheduler; import org.hyperledger.besu.ethereum.blockcreation.DefaultBlockScheduler;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMinerExecutor;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.PoWMinerExecutor;
import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager;
@ -42,8 +42,9 @@ public class MainnetBesuControllerBuilder extends BesuControllerBuilder {
final MiningParameters miningParameters, final MiningParameters miningParameters,
final SyncState syncState, final SyncState syncState,
final EthProtocolManager ethProtocolManager) { final EthProtocolManager ethProtocolManager) {
final EthHashMinerExecutor executor =
new EthHashMinerExecutor( final PoWMinerExecutor executor =
new PoWMinerExecutor(
protocolContext, protocolContext,
protocolSchedule, protocolSchedule,
transactionPool.getPendingTransactions(), transactionPool.getPendingTransactions(),
@ -55,8 +56,8 @@ public class MainnetBesuControllerBuilder extends BesuControllerBuilder {
gasLimitCalculator, gasLimitCalculator,
epochCalculator); epochCalculator);
final EthHashMiningCoordinator miningCoordinator = final PoWMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator( new PoWMiningCoordinator(
protocolContext.getBlockchain(), protocolContext.getBlockchain(),
executor, executor,
syncState, syncState,

@ -24,6 +24,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.config.EthashConfigOptions; import org.hyperledger.besu.config.EthashConfigOptions;
import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.Keccak256ConfigOptions;
import org.hyperledger.besu.crypto.NodeKey; import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator; import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
@ -66,6 +67,7 @@ public class BesuControllerBuilderTest {
@Mock GenesisConfigFile genesisConfigFile; @Mock GenesisConfigFile genesisConfigFile;
@Mock GenesisConfigOptions genesisConfigOptions; @Mock GenesisConfigOptions genesisConfigOptions;
@Mock EthashConfigOptions ethashConfigOptions; @Mock EthashConfigOptions ethashConfigOptions;
@Mock Keccak256ConfigOptions keccak256ConfigOptions;
@Mock SynchronizerConfiguration synchronizerConfiguration; @Mock SynchronizerConfiguration synchronizerConfiguration;
@Mock EthProtocolConfiguration ethProtocolConfiguration; @Mock EthProtocolConfiguration ethProtocolConfiguration;
@Mock MiningParameters miningParameters; @Mock MiningParameters miningParameters;
@ -95,6 +97,8 @@ public class BesuControllerBuilderTest {
when(genesisConfigOptions.getThanosBlockNumber()).thenReturn(OptionalLong.empty()); when(genesisConfigOptions.getThanosBlockNumber()).thenReturn(OptionalLong.empty());
when(genesisConfigOptions.getEthashConfigOptions()).thenReturn(ethashConfigOptions); when(genesisConfigOptions.getEthashConfigOptions()).thenReturn(ethashConfigOptions);
when(ethashConfigOptions.getFixedDifficulty()).thenReturn(OptionalLong.empty()); when(ethashConfigOptions.getFixedDifficulty()).thenReturn(OptionalLong.empty());
when(genesisConfigOptions.getKeccak256ConfigOptions()).thenReturn(keccak256ConfigOptions);
when(keccak256ConfigOptions.getFixedDifficulty()).thenReturn(OptionalLong.empty());
when(storageProvider.getStorageBySegmentIdentifier(any())) when(storageProvider.getStorageBySegmentIdentifier(any()))
.thenReturn(new InMemoryKeyValueStorage()); .thenReturn(new InMemoryKeyValueStorage());
when(storageProvider.createBlockchainStorage(any())) when(storageProvider.createBlockchainStorage(any()))

@ -67,6 +67,15 @@ public class GenesisConfigFile {
} }
} }
public static GenesisConfigFile ecip1049dev() {
try {
return fromConfig(
Resources.toString(GenesisConfigFile.class.getResource("/ecip1049_dev.json"), UTF_8));
} catch (final IOException e) {
throw new IllegalStateException(e);
}
}
public static GenesisConfigFile fromConfig(final String jsonString) { public static GenesisConfigFile fromConfig(final String jsonString) {
return fromConfig(JsonUtil.objectNodeFromString(jsonString, false)); return fromConfig(JsonUtil.objectNodeFromString(jsonString, false));
} }

@ -25,6 +25,8 @@ public interface GenesisConfigOptions {
boolean isEthHash(); boolean isEthHash();
boolean isKeccak256();
boolean isIbftLegacy(); boolean isIbftLegacy();
boolean isIbft2(); boolean isIbft2();
@ -43,6 +45,8 @@ public interface GenesisConfigOptions {
EthashConfigOptions getEthashConfigOptions(); EthashConfigOptions getEthashConfigOptions();
Keccak256ConfigOptions getKeccak256ConfigOptions();
OptionalLong getHomesteadBlockNumber(); OptionalLong getHomesteadBlockNumber();
OptionalLong getDaoForkBlock(); OptionalLong getDaoForkBlock();
@ -173,6 +177,16 @@ public interface GenesisConfigOptions {
*/ */
OptionalLong getThanosBlockNumber(); OptionalLong getThanosBlockNumber();
/**
* Block number to activate ECIP-1049 on Classic networks. Changes the hashing algorithm to
* keccak-256.
*
* @return block number of ECIP-1049 fork on Classic networks
* @see <a
* href="https://ecips.ethereumclassic.org/ECIPs/ecip-1049">https://ecips.ethereumclassic.org/ECIPs/ecip-1049</a>
*/
OptionalLong getEcip1049BlockNumber();
Optional<BigInteger> getChainId(); Optional<BigInteger> getChainId();
OptionalInt getContractSizeLimit(); OptionalInt getContractSizeLimit();
@ -209,4 +223,11 @@ public interface GenesisConfigOptions {
* @return block number to activate Quorum Permissioning * @return block number to activate Quorum Permissioning
*/ */
OptionalLong getQip714BlockNumber(); OptionalLong getQip714BlockNumber();
/**
* The PoW algorithm associated with the genesis file.
*
* @return the PoW algorithm in use.
*/
PowAlgorithm getPowAlgorithm();
} }

@ -37,6 +37,7 @@ import com.google.common.collect.ImmutableMap;
public class JsonGenesisConfigOptions implements GenesisConfigOptions { public class JsonGenesisConfigOptions implements GenesisConfigOptions {
private static final String ETHASH_CONFIG_KEY = "ethash"; private static final String ETHASH_CONFIG_KEY = "ethash";
private static final String KECCAK256_CONFIG_KEY = "keccak256";
private static final String IBFT_LEGACY_CONFIG_KEY = "ibft"; private static final String IBFT_LEGACY_CONFIG_KEY = "ibft";
private static final String IBFT2_CONFIG_KEY = "ibft2"; private static final String IBFT2_CONFIG_KEY = "ibft2";
private static final String QBFT_CONFIG_KEY = "qbft"; private static final String QBFT_CONFIG_KEY = "qbft";
@ -94,6 +95,8 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
public String getConsensusEngine() { public String getConsensusEngine() {
if (isEthHash()) { if (isEthHash()) {
return ETHASH_CONFIG_KEY; return ETHASH_CONFIG_KEY;
} else if (isKeccak256()) {
return KECCAK256_CONFIG_KEY;
} else if (isIbft2()) { } else if (isIbft2()) {
return IBFT2_CONFIG_KEY; return IBFT2_CONFIG_KEY;
} else if (isIbftLegacy()) { } else if (isIbftLegacy()) {
@ -112,6 +115,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return configRoot.has(ETHASH_CONFIG_KEY); return configRoot.has(ETHASH_CONFIG_KEY);
} }
@Override
public boolean isKeccak256() {
return configRoot.has(KECCAK256_CONFIG_KEY);
}
@Override @Override
public boolean isIbftLegacy() { public boolean isIbftLegacy() {
return configRoot.has(IBFT_LEGACY_CONFIG_KEY); return configRoot.has(IBFT_LEGACY_CONFIG_KEY);
@ -161,6 +169,13 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
.orElse(EthashConfigOptions.DEFAULT); .orElse(EthashConfigOptions.DEFAULT);
} }
@Override
public Keccak256ConfigOptions getKeccak256ConfigOptions() {
return JsonUtil.getObjectNode(configRoot, KECCAK256_CONFIG_KEY)
.map(Keccak256ConfigOptions::new)
.orElse(Keccak256ConfigOptions.DEFAULT);
}
@Override @Override
public TransitionsConfigOptions getTransitions() { public TransitionsConfigOptions getTransitions() {
return transitions; return transitions;
@ -289,6 +304,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return getOptionalLong("thanosblock"); return getOptionalLong("thanosblock");
} }
@Override
public OptionalLong getEcip1049BlockNumber() {
return getOptionalLong("ecip1049block");
}
@Override @Override
public Optional<BigInteger> getChainId() { public Optional<BigInteger> getChainId() {
return getOptionalBigInteger("chainid"); return getOptionalBigInteger("chainid");
@ -319,6 +339,13 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return getOptionalLong("qip714block"); return getOptionalLong("qip714block");
} }
@Override
public PowAlgorithm getPowAlgorithm() {
return isEthHash()
? PowAlgorithm.ETHASH
: isKeccak256() ? PowAlgorithm.KECCAK256 : PowAlgorithm.UNSUPPORTED;
}
@Override @Override
public Map<String, Object> asMap() { public Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder(); final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
@ -358,6 +385,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l)); getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l));
getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l)); getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l));
getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l)); getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l));
getEcip1049BlockNumber().ifPresent(l -> builder.put("ecip1049Block", l));
getEIP1559BlockNumber().ifPresent(l -> builder.put("eip1559Block", l)); getEIP1559BlockNumber().ifPresent(l -> builder.put("eip1559Block", l));
getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l)); getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l));
@ -370,6 +398,9 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
if (isEthHash()) { if (isEthHash()) {
builder.put("ethash", getEthashConfigOptions().asMap()); builder.put("ethash", getEthashConfigOptions().asMap());
} }
if (isKeccak256()) {
builder.put("keccak256", getKeccak256ConfigOptions().asMap());
}
if (isIbftLegacy()) { if (isIbftLegacy()) {
builder.put("ibft", getIbftLegacyConfigOptions().asMap()); builder.put("ibft", getIbftLegacyConfigOptions().asMap());
} }
@ -451,7 +482,8 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
getAtlantisBlockNumber(), getAtlantisBlockNumber(),
getAghartaBlockNumber(), getAghartaBlockNumber(),
getPhoenixBlockNumber(), getPhoenixBlockNumber(),
getThanosBlockNumber()); getThanosBlockNumber(),
getEcip1049BlockNumber());
return forkBlockNumbers return forkBlockNumbers
.filter(OptionalLong::isPresent) .filter(OptionalLong::isPresent)

@ -0,0 +1,43 @@
/*
* 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.config;
import java.util.Map;
import java.util.OptionalLong;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableMap;
public class Keccak256ConfigOptions {
public static final Keccak256ConfigOptions DEFAULT =
new Keccak256ConfigOptions(JsonUtil.createEmptyObjectNode());
private final ObjectNode keccak256ConfigRoot;
Keccak256ConfigOptions(final ObjectNode keccak256ConfigRoot) {
this.keccak256ConfigRoot = keccak256ConfigRoot;
}
public OptionalLong getFixedDifficulty() {
return JsonUtil.getLong(keccak256ConfigRoot, "fixeddifficulty");
}
Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
getFixedDifficulty().ifPresent(l -> builder.put("fixeddifficulty", l));
return builder.build();
}
}

@ -0,0 +1,31 @@
/*
* 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.config;
/** An enumeration of supported Proof-of-work algorithms. */
public enum PowAlgorithm {
UNSUPPORTED,
ETHASH,
KECCAK256;
public static PowAlgorithm fromString(final String str) {
for (final PowAlgorithm powAlgorithm : PowAlgorithm.values()) {
if (powAlgorithm.name().equalsIgnoreCase(str)) {
return powAlgorithm;
}
}
return null;
}
}

@ -49,6 +49,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
private OptionalLong aghartaBlockNumber = OptionalLong.empty(); private OptionalLong aghartaBlockNumber = OptionalLong.empty();
private OptionalLong phoenixBlockNumber = OptionalLong.empty(); private OptionalLong phoenixBlockNumber = OptionalLong.empty();
private OptionalLong thanosBlockNumber = OptionalLong.empty(); private OptionalLong thanosBlockNumber = OptionalLong.empty();
private OptionalLong ecip1049BlockNumber = OptionalLong.empty();
private Optional<BigInteger> chainId = Optional.empty(); private Optional<BigInteger> chainId = Optional.empty();
private OptionalInt contractSizeLimit = OptionalInt.empty(); private OptionalInt contractSizeLimit = OptionalInt.empty();
private OptionalInt stackSizeLimit = OptionalInt.empty(); private OptionalInt stackSizeLimit = OptionalInt.empty();
@ -64,6 +65,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return true; return true;
} }
@Override
public boolean isKeccak256() {
return false;
}
@Override @Override
public boolean isIbftLegacy() { public boolean isIbftLegacy() {
return false; return false;
@ -104,6 +110,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return EthashConfigOptions.DEFAULT; return EthashConfigOptions.DEFAULT;
} }
@Override
public Keccak256ConfigOptions getKeccak256ConfigOptions() {
return Keccak256ConfigOptions.DEFAULT;
}
@Override @Override
public OptionalLong getHomesteadBlockNumber() { public OptionalLong getHomesteadBlockNumber() {
return homesteadBlockNumber; return homesteadBlockNumber;
@ -205,6 +216,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return thanosBlockNumber; return thanosBlockNumber;
} }
@Override
public OptionalLong getEcip1049BlockNumber() {
return ecip1049BlockNumber;
}
@Override @Override
public OptionalInt getContractSizeLimit() { public OptionalInt getContractSizeLimit() {
return contractSizeLimit; return contractSizeLimit;
@ -262,6 +278,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l)); getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l));
getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l)); getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l));
getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l)); getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l));
getEcip1049BlockNumber().ifPresent(l -> builder.put("ecip1049Block", l));
getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l)); getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l));
getEvmStackSize().ifPresent(l -> builder.put("evmStackSize", l)); getEvmStackSize().ifPresent(l -> builder.put("evmStackSize", l));
@ -271,6 +288,9 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
if (isEthHash()) { if (isEthHash()) {
builder.put("ethash", getEthashConfigOptions().asMap()); builder.put("ethash", getEthashConfigOptions().asMap());
} }
if (isKeccak256()) {
builder.put("keccak256", getKeccak256ConfigOptions().asMap());
}
if (isIbftLegacy()) { if (isIbftLegacy()) {
builder.put("ibft", getIbftLegacyConfigOptions().asMap()); builder.put("ibft", getIbftLegacyConfigOptions().asMap());
} }
@ -295,6 +315,13 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return OptionalLong.empty(); return OptionalLong.empty();
} }
@Override
public PowAlgorithm getPowAlgorithm() {
return isEthHash()
? PowAlgorithm.ETHASH
: isKeccak256() ? PowAlgorithm.KECCAK256 : PowAlgorithm.UNSUPPORTED;
}
@Override @Override
public List<Long> getForks() { public List<Long> getForks() {
return Collections.emptyList(); return Collections.emptyList();
@ -395,6 +422,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return this; return this;
} }
public StubGenesisConfigOptions ecip1049(final long blockNumber) {
ecip1049BlockNumber = OptionalLong.of(blockNumber);
return this;
}
public StubGenesisConfigOptions chainId(final BigInteger chainId) { public StubGenesisConfigOptions chainId(final BigInteger chainId) {
this.chainId = Optional.ofNullable(chainId); this.chainId = Optional.ofNullable(chainId);
return this; return this;

@ -0,0 +1,33 @@
{
"config": {
"chainId": 2021,
"ecip1049Block": 0,
"keccak256": {
"fixeddifficulty": 10000
}
},
"nonce": "0x42",
"timestamp": "0x0",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x1fffffffffffff",
"difficulty": "0x1000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
}
}

@ -37,12 +37,25 @@ public class GenesisConfigOptionsTest {
assertThat(config.getConsensusEngine()).isEqualTo("ethash"); assertThat(config.getConsensusEngine()).isEqualTo("ethash");
} }
@Test
public void shouldUseKeccak256WhenKeccak256InConfig() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("keccak256", emptyMap()));
assertThat(config.isKeccak256()).isTrue();
assertThat(config.getConsensusEngine()).isEqualTo("keccak256");
}
@Test @Test
public void shouldNotUseEthHashIfEthHashNotPresent() { public void shouldNotUseEthHashIfEthHashNotPresent() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap()); final GenesisConfigOptions config = fromConfigOptions(emptyMap());
assertThat(config.isEthHash()).isFalse(); assertThat(config.isEthHash()).isFalse();
} }
@Test
public void shouldNotUseKeccak256IfEthHashNotPresent() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap());
assertThat(config.isKeccak256()).isFalse();
}
@Test @Test
public void shouldUseIbftLegacyWhenIbftInConfig() { public void shouldUseIbftLegacyWhenIbftInConfig() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("ibft", emptyMap())); final GenesisConfigOptions config = fromConfigOptions(singletonMap("ibft", emptyMap()));
@ -185,6 +198,13 @@ public class GenesisConfigOptionsTest {
} }
} }
@Test
// TODO ECIP-1049 change for the actual fork name when known
public void shouldGetECIP1049BlockNumber() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("ecip1049block", 1000));
assertThat(config.getEcip1049BlockNumber()).hasValue(1000);
}
@Test @Test
public void shouldNotReturnEmptyOptionalWhenBlockNumberNotSpecified() { public void shouldNotReturnEmptyOptionalWhenBlockNumberNotSpecified() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap()); final GenesisConfigOptions config = fromConfigOptions(emptyMap());
@ -198,6 +218,7 @@ public class GenesisConfigOptionsTest {
assertThat(config.getIstanbulBlockNumber()).isEmpty(); assertThat(config.getIstanbulBlockNumber()).isEmpty();
assertThat(config.getMuirGlacierBlockNumber()).isEmpty(); assertThat(config.getMuirGlacierBlockNumber()).isEmpty();
assertThat(config.getBerlinBlockNumber()).isEmpty(); assertThat(config.getBerlinBlockNumber()).isEmpty();
assertThat(config.getEcip1049BlockNumber()).isEmpty();
} }
@Test @Test

@ -24,8 +24,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockScheduler; import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockScheduler;
import org.hyperledger.besu.ethereum.blockcreation.AbstractMinerExecutor; import org.hyperledger.besu.ethereum.blockcreation.AbstractMinerExecutor;
import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator; import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator;
import org.hyperledger.besu.ethereum.chain.EthHashObserver;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MiningParameters;
@ -72,7 +72,7 @@ public class CliqueMinerExecutor extends AbstractMinerExecutor<CliqueBlockMiner>
@Override @Override
public CliqueBlockMiner createMiner( public CliqueBlockMiner createMiner(
final Subscribers<MinedBlockObserver> observers, final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers, final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) { final BlockHeader parentHeader) {
final Function<BlockHeader, CliqueBlockCreator> blockCreator = final Function<BlockHeader, CliqueBlockCreator> blockCreator =
(header) -> (header) ->

@ -26,7 +26,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.BlockImporter;
@ -90,7 +90,7 @@ public class JsonRpcTestMethodsFactory {
final P2PNetwork peerDiscovery = mock(P2PNetwork.class); final P2PNetwork peerDiscovery = mock(P2PNetwork.class);
final EthPeers ethPeers = mock(EthPeers.class); final EthPeers ethPeers = mock(EthPeers.class);
final TransactionPool transactionPool = mock(TransactionPool.class); final TransactionPool transactionPool = mock(TransactionPool.class);
final EthHashMiningCoordinator miningCoordinator = mock(EthHashMiningCoordinator.class); final PoWMiningCoordinator miningCoordinator = mock(PoWMiningCoordinator.class);
final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem(); final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem();
final Optional<AccountLocalConfigPermissioningController> accountWhitelistController = final Optional<AccountLocalConfigPermissioningController> accountWhitelistController =
Optional.of(mock(AccountLocalConfigPermissioningController.class)); Optional.of(mock(AccountLocalConfigPermissioningController.class));

@ -23,11 +23,11 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorR
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed; import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional; import java.util.Optional;
@ -42,8 +42,8 @@ public class EthGetWork implements JsonRpcMethod {
public EthGetWork(final MiningCoordinator miner) { public EthGetWork(final MiningCoordinator miner) {
this.miner = miner; this.miner = miner;
if (miner instanceof EthHashMiningCoordinator) { if (miner instanceof PoWMiningCoordinator) {
this.epochCalculator = ((EthHashMiningCoordinator) miner).getEpochCalculator(); this.epochCalculator = ((PoWMiningCoordinator) miner).getEpochCalculator();
} else { } else {
this.epochCalculator = new EpochCalculator.DefaultEpochCalculator(); this.epochCalculator = new EpochCalculator.DefaultEpochCalculator();
} }
@ -56,13 +56,13 @@ public class EthGetWork implements JsonRpcMethod {
@Override @Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
final Optional<EthHashSolverInputs> solver = miner.getWorkDefinition(); final Optional<PoWSolverInputs> solver = miner.getWorkDefinition();
if (solver.isPresent()) { if (solver.isPresent()) {
final EthHashSolverInputs rawResult = solver.get(); final PoWSolverInputs rawResult = solver.get();
final byte[] dagSeed = final byte[] dagSeed =
DirectAcyclicGraphSeed.dagSeed(rawResult.getBlockNumber(), epochCalculator); DirectAcyclicGraphSeed.dagSeed(rawResult.getBlockNumber(), epochCalculator);
final String[] result = { final String[] result = {
"0x" + BaseEncoding.base16().lowerCase().encode(rawResult.getPrePowHash()), rawResult.getPrePowHash().toHexString(),
"0x" + BaseEncoding.base16().lowerCase().encode(dagSeed), "0x" + BaseEncoding.base16().lowerCase().encode(dagSeed),
rawResult.getTarget().toHexString(), rawResult.getTarget().toHexString(),
Quantity.create(rawResult.getBlockNumber()) Quantity.create(rawResult.getBlockNumber())

@ -24,8 +24,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcRespon
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional; import java.util.Optional;
@ -48,14 +48,14 @@ public class EthSubmitWork implements JsonRpcMethod {
@Override @Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
final Optional<EthHashSolverInputs> solver = miner.getWorkDefinition(); final Optional<PoWSolverInputs> solver = miner.getWorkDefinition();
if (solver.isPresent()) { if (solver.isPresent()) {
final EthHashSolution solution = final PoWSolution solution =
new EthHashSolution( new PoWSolution(
Bytes.fromHexString(requestContext.getRequiredParameter(0, String.class)).getLong(0), Bytes.fromHexString(requestContext.getRequiredParameter(0, String.class)).getLong(0),
requestContext.getRequiredParameter(2, Hash.class), requestContext.getRequiredParameter(2, Hash.class),
Bytes.fromHexString(requestContext.getRequiredParameter(1, String.class)) null,
.toArrayUnsafe()); Bytes.fromHexString(requestContext.getRequiredParameter(1, String.class)));
final boolean result = miner.submitWork(solution); final boolean result = miner.submitWork(solution);
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result); return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result);
} else { } else {

@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.graphql;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.GenesisState;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
@ -123,8 +123,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
final SyncStatus status = new DefaultSyncStatus(1, 2, 3, Optional.of(4L), Optional.of(5L)); final SyncStatus status = new DefaultSyncStatus(1, 2, 3, Optional.of(4L), Optional.of(5L));
Mockito.when(synchronizerMock.getSyncStatus()).thenReturn(Optional.of(status)); Mockito.when(synchronizerMock.getSyncStatus()).thenReturn(Optional.of(status));
final EthHashMiningCoordinator miningCoordinatorMock = final PoWMiningCoordinator miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class);
Mockito.mock(EthHashMiningCoordinator.class);
Mockito.when(miningCoordinatorMock.getMinTransactionGasPrice()).thenReturn(Wei.of(16)); Mockito.when(miningCoordinatorMock.getMinTransactionGasPrice()).thenReturn(Wei.of(16));
final TransactionPool transactionPoolMock = Mockito.mock(TransactionPool.class); final TransactionPool transactionPoolMock = Mockito.mock(TransactionPool.class);

@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.api.graphql; package org.hyperledger.besu.ethereum.api.graphql;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
@ -210,8 +210,7 @@ public class GraphQLHttpServiceCorsTest {
final BlockchainQueries blockchainQueries = Mockito.mock(BlockchainQueries.class); final BlockchainQueries blockchainQueries = Mockito.mock(BlockchainQueries.class);
final Synchronizer synchronizer = Mockito.mock(Synchronizer.class); final Synchronizer synchronizer = Mockito.mock(Synchronizer.class);
final EthHashMiningCoordinator miningCoordinatorMock = final PoWMiningCoordinator miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class);
Mockito.mock(EthHashMiningCoordinator.class);
final GraphQLDataFetcherContextImpl dataFetcherContext = final GraphQLDataFetcherContextImpl dataFetcherContext =
Mockito.mock(GraphQLDataFetcherContextImpl.class); Mockito.mock(GraphQLDataFetcherContextImpl.class);

@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.api.graphql; package org.hyperledger.besu.ethereum.api.graphql;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
@ -71,8 +71,7 @@ public class GraphQLHttpServiceHostWhitelistTest {
final BlockchainQueries blockchainQueries = Mockito.mock(BlockchainQueries.class); final BlockchainQueries blockchainQueries = Mockito.mock(BlockchainQueries.class);
final Synchronizer synchronizer = Mockito.mock(Synchronizer.class); final Synchronizer synchronizer = Mockito.mock(Synchronizer.class);
final EthHashMiningCoordinator miningCoordinatorMock = final PoWMiningCoordinator miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class);
Mockito.mock(EthHashMiningCoordinator.class);
final GraphQLDataFetcherContextImpl dataFetcherContext = final GraphQLDataFetcherContextImpl dataFetcherContext =
Mockito.mock(GraphQLDataFetcherContextImpl.class); Mockito.mock(GraphQLDataFetcherContextImpl.class);

@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata; import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.core.Wei;
@ -70,7 +70,7 @@ public class GraphQLHttpServiceTest {
private static BlockchainQueries blockchainQueries; private static BlockchainQueries blockchainQueries;
private static GraphQL graphQL; private static GraphQL graphQL;
private static GraphQLDataFetcherContextImpl dataFetcherContext; private static GraphQLDataFetcherContextImpl dataFetcherContext;
private static EthHashMiningCoordinator miningCoordinatorMock; private static PoWMiningCoordinator miningCoordinatorMock;
private final GraphQLTestHelper testHelper = new GraphQLTestHelper(); private final GraphQLTestHelper testHelper = new GraphQLTestHelper();
@ -80,7 +80,7 @@ public class GraphQLHttpServiceTest {
final Synchronizer synchronizer = Mockito.mock(Synchronizer.class); final Synchronizer synchronizer = Mockito.mock(Synchronizer.class);
graphQL = Mockito.mock(GraphQL.class); graphQL = Mockito.mock(GraphQL.class);
miningCoordinatorMock = Mockito.mock(EthHashMiningCoordinator.class); miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class);
dataFetcherContext = Mockito.mock(GraphQLDataFetcherContextImpl.class); dataFetcherContext = Mockito.mock(GraphQLDataFetcherContextImpl.class);
Mockito.when(dataFetcherContext.getBlockchainQueries()).thenReturn(blockchainQueries); Mockito.when(dataFetcherContext.getBlockchainQueries()).thenReturn(blockchainQueries);

@ -30,7 +30,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
@ -117,7 +117,7 @@ public abstract class AbstractJsonRpcHttpServiceTest {
final Synchronizer synchronizerMock = mock(Synchronizer.class); final Synchronizer synchronizerMock = mock(Synchronizer.class);
final P2PNetwork peerDiscoveryMock = mock(P2PNetwork.class); final P2PNetwork peerDiscoveryMock = mock(P2PNetwork.class);
final TransactionPool transactionPoolMock = mock(TransactionPool.class); final TransactionPool transactionPoolMock = mock(TransactionPool.class);
final EthHashMiningCoordinator miningCoordinatorMock = mock(EthHashMiningCoordinator.class); final PoWMiningCoordinator miningCoordinatorMock = mock(PoWMiningCoordinator.class);
when(transactionPoolMock.addLocalTransaction(any(Transaction.class))) when(transactionPoolMock.addLocalTransaction(any(Transaction.class)))
.thenReturn(ValidationResult.valid()); .thenReturn(ValidationResult.valid());
// nonce too low tests uses a tx with nonce=16 // nonce too low tests uses a tx with nonce=16

@ -25,7 +25,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -108,7 +108,7 @@ public class JsonRpcHttpServiceHostWhitelistTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)), new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(AccountLocalConfigPermissioningController.class)),

@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.Web3Sha3;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -134,7 +134,7 @@ public class JsonRpcHttpServiceLoginTest {
MainnetProtocolSchedule.fromConfig(genesisConfigOptions), MainnetProtocolSchedule.fromConfig(genesisConfigOptions),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.empty(), Optional.empty(),

@ -28,7 +28,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.InMemoryStorageProvider; import org.hyperledger.besu.ethereum.core.InMemoryStorageProvider;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
@ -205,7 +205,7 @@ public class JsonRpcHttpServiceRpcApisTest {
ProtocolScheduleFixture.MAINNET, ProtocolScheduleFixture.MAINNET,
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(AccountLocalConfigPermissioningController.class)),
@ -302,7 +302,7 @@ public class JsonRpcHttpServiceRpcApisTest {
ProtocolScheduleFixture.MAINNET, ProtocolScheduleFixture.MAINNET,
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(AccountLocalConfigPermissioningController.class)),

@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguratio
import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata; import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.ChainHead; import org.hyperledger.besu.ethereum.chain.ChainHead;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
@ -144,7 +144,7 @@ public class JsonRpcHttpServiceTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)), new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(AccountLocalConfigPermissioningController.class)),

@ -35,7 +35,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider;
import org.hyperledger.besu.ethereum.api.tls.SelfSignedP12Certificate; import org.hyperledger.besu.ethereum.api.tls.SelfSignedP12Certificate;
import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration; import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -126,7 +126,7 @@ public class JsonRpcHttpServiceTlsClientAuthTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)), new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(AccountLocalConfigPermissioningController.class)),

@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider;
import org.hyperledger.besu.ethereum.api.tls.SelfSignedP12Certificate; import org.hyperledger.besu.ethereum.api.tls.SelfSignedP12Certificate;
import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration; import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -114,7 +114,7 @@ public class JsonRpcHttpServiceTlsMisconfigurationTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)), new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(AccountLocalConfigPermissioningController.class)),

@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider;
import org.hyperledger.besu.ethereum.api.tls.SelfSignedP12Certificate; import org.hyperledger.besu.ethereum.api.tls.SelfSignedP12Certificate;
import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration; import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -117,7 +117,7 @@ public class JsonRpcHttpServiceTlsTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)), new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
supportedCapabilities, supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(AccountLocalConfigPermissioningController.class)),

@ -367,7 +367,8 @@ public class AdminNodeInfoTest {
.atlantis(6) .atlantis(6)
.agharta(7) .agharta(7)
.phoenix(8) .phoenix(8)
.thanos(9); .thanos(9)
.ecip1049(10);
final AdminNodeInfo methodClassic = final AdminNodeInfo methodClassic =
new AdminNodeInfo( new AdminNodeInfo(
@ -390,7 +391,8 @@ public class AdminNodeInfoTest {
"atlantisBlock", 6L, "atlantisBlock", 6L,
"aghartaBlock", 7L, "aghartaBlock", 7L,
"phoenixBlock", 8L, "phoenixBlock", 8L,
"thanosBlock", 9L); "thanosBlock", 9L,
"ecip1049Block", 10L);
final JsonRpcResponse response = methodClassic.response(request); final JsonRpcResponse response = methodClassic.response(request);
assertThat(response).isInstanceOf(JsonRpcSuccessResponse.class); assertThat(response).isInstanceOf(JsonRpcSuccessResponse.class);

@ -26,7 +26,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
@ -52,7 +52,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class EthGasPriceTest { public class EthGasPriceTest {
@Mock private EthHashMiningCoordinator miningCoordinator; @Mock private PoWMiningCoordinator miningCoordinator;
@Mock private Blockchain blockchain; @Mock private Blockchain blockchain;
private EthGasPrice method; private EthGasPrice method;
private final String JSON_RPC_VERSION = "2.0"; private final String JSON_RPC_VERSION = "2.0";

@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.fees.TransactionGasBudgetCalculator; import org.hyperledger.besu.ethereum.core.fees.TransactionGasBudgetCalculator;
import org.hyperledger.besu.ethereum.core.fees.TransactionPriceCalculator; import org.hyperledger.besu.ethereum.core.fees.TransactionPriceCalculator;
import org.hyperledger.besu.ethereum.mainnet.PoWHasher;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
@ -105,7 +106,8 @@ public class EthGetTransactionReceiptTest {
TransactionPriceCalculator.frontier(), TransactionPriceCalculator.frontier(),
Optional.empty(), Optional.empty(),
TransactionGasBudgetCalculator.frontier(), TransactionGasBudgetCalculator.frontier(),
null); null,
Optional.of(PoWHasher.ETHASH_LIGHT));
private final ProtocolSpec statusTransactionTypeSpec = private final ProtocolSpec statusTransactionTypeSpec =
new ProtocolSpec( new ProtocolSpec(
"status", "status",
@ -130,7 +132,8 @@ public class EthGetTransactionReceiptTest {
TransactionPriceCalculator.frontier(), TransactionPriceCalculator.frontier(),
Optional.empty(), Optional.empty(),
TransactionGasBudgetCalculator.frontier(), TransactionGasBudgetCalculator.frontier(),
null); null,
Optional.of(PoWHasher.ETHASH_LIGHT));
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class); private final ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class);

@ -23,14 +23,15 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed; import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional; import java.util.Optional;
import com.google.common.io.BaseEncoding; import com.google.common.io.BaseEncoding;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -46,7 +47,7 @@ public class EthGetWorkTest {
private final String hexValue = private final String hexValue =
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
@Mock private EthHashMiningCoordinator miningCoordinator; @Mock private PoWMiningCoordinator miningCoordinator;
@Before @Before
public void setUp() { public void setUp() {
@ -63,9 +64,8 @@ public class EthGetWorkTest {
@Test @Test
public void shouldReturnCorrectResultOnGenesisDAG() { public void shouldReturnCorrectResultOnGenesisDAG() {
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values = final PoWSolverInputs values =
new EthHashSolverInputs( new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 0);
UInt256.fromHexString(hexValue), BaseEncoding.base16().lowerCase().decode(hexValue), 0);
final String[] expectedValue = { final String[] expectedValue = {
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000",
@ -83,11 +83,8 @@ public class EthGetWorkTest {
@Test @Test
public void shouldReturnCorrectResultOnHighBlockSeed() { public void shouldReturnCorrectResultOnHighBlockSeed() {
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values = final PoWSolverInputs values =
new EthHashSolverInputs( new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 30000);
UInt256.fromHexString(hexValue),
BaseEncoding.base16().lowerCase().decode(hexValue),
30000);
final String[] expectedValue = { final String[] expectedValue = {
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -113,11 +110,8 @@ public class EthGetWorkTest {
.thenReturn(new EpochCalculator.Ecip1099EpochCalculator()); .thenReturn(new EpochCalculator.Ecip1099EpochCalculator());
method = new EthGetWork(miningCoordinator); method = new EthGetWork(miningCoordinator);
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values = final PoWSolverInputs values =
new EthHashSolverInputs( new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 60000);
UInt256.fromHexString(hexValue),
BaseEncoding.base16().lowerCase().decode(hexValue),
60000);
final String[] expectedValue = { final String[] expectedValue = {
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",

@ -21,7 +21,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import java.util.Optional; import java.util.Optional;
@ -34,7 +34,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class EthHashrateTest { public class EthHashrateTest {
@Mock private EthHashMiningCoordinator miningCoordinator; @Mock private PoWMiningCoordinator miningCoordinator;
private EthHashrate method; private EthHashrate method;
private final String JSON_RPC_VERSION = "2.0"; private final String JSON_RPC_VERSION = "2.0";
private final String ETH_METHOD = "eth_hashrate"; private final String ETH_METHOD = "eth_hashrate";

@ -23,7 +23,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -34,7 +34,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class EthMiningTest { public class EthMiningTest {
@Mock private EthHashMiningCoordinator miningCoordinator; @Mock private PoWMiningCoordinator miningCoordinator;
private EthMining method; private EthMining method;
private final String JSON_RPC_VERSION = "2.0"; private final String JSON_RPC_VERSION = "2.0";
private final String ETH_METHOD = "eth_mining"; private final String ETH_METHOD = "eth_mining";

@ -25,14 +25,13 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional; import java.util.Optional;
import com.google.common.io.BaseEncoding;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.junit.Before; import org.junit.Before;
@ -49,7 +48,7 @@ public class EthSubmitWorkTest {
private final String hexValue = private final String hexValue =
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
@Mock private EthHashMiningCoordinator miningCoordinator; @Mock private PoWMiningCoordinator miningCoordinator;
@Before @Before
public void setUp() { public void setUp() {
@ -73,9 +72,8 @@ public class EthSubmitWorkTest {
@Test @Test
public void shouldFailIfMissingArguments() { public void shouldFailIfMissingArguments() {
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values = final PoWSolverInputs values =
new EthHashSolverInputs( new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 0);
UInt256.fromHexString(hexValue), BaseEncoding.base16().lowerCase().decode(hexValue), 0);
when(miningCoordinator.getWorkDefinition()).thenReturn(Optional.of(values)); when(miningCoordinator.getWorkDefinition()).thenReturn(Optional.of(values));
assertThatThrownBy( assertThatThrownBy(
() -> method.response(request), "Missing required json rpc parameter at index 0") () -> method.response(request), "Missing required json rpc parameter at index 0")
@ -84,21 +82,23 @@ public class EthSubmitWorkTest {
@Test @Test
public void shouldReturnTrueIfGivenCorrectResult() { public void shouldReturnTrueIfGivenCorrectResult() {
final EthHashSolverInputs firstInputs = final PoWSolverInputs firstInputs =
new EthHashSolverInputs( new PoWSolverInputs(
UInt256.fromHexString( UInt256.fromHexString(
"0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"), "0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"),
new byte[] { Bytes.wrap(
15, -114, -104, 87, -95, -36, -17, 120, 52, 1, 124, 61, -6, -66, 78, -27, -57, 118, new byte[] {
-18, -64, -103, -91, -74, -121, 42, 91, -14, -98, 101, 86, -43, -51 15, -114, -104, 87, -95, -36, -17, 120, 52, 1, 124, 61, -6, -66, 78, -27, -57,
}, 118, -18, -64, -103, -91, -74, -121, 42, 91, -14, -98, 101, 86, -43, -51
}),
468); 468);
final EthHashSolution expectedFirstOutput = final PoWSolution expectedFirstOutput =
new EthHashSolution( new PoWSolution(
-6506032554016940193L, -6506032554016940193L,
Hash.fromHexString( Hash.fromHexString(
"0xc5e3c33c86d64d0641dd3c86e8ce4628fe0aac0ef7b4c087c5fcaa45d5046d90"), "0xc5e3c33c86d64d0641dd3c86e8ce4628fe0aac0ef7b4c087c5fcaa45d5046d90"),
null,
firstInputs.getPrePowHash()); firstInputs.getPrePowHash());
final JsonRpcRequestContext request = final JsonRpcRequestContext request =
requestWithParams( requestWithParams(

@ -25,7 +25,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorR
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.CoinbaseNotSetException; import org.hyperledger.besu.ethereum.blockcreation.CoinbaseNotSetException;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -38,7 +38,7 @@ public class MinerStartTest {
private MinerStart method; private MinerStart method;
@Mock private EthHashMiningCoordinator miningCoordinator; @Mock private PoWMiningCoordinator miningCoordinator;
@Before @Before
public void before() { public void before() {

@ -21,7 +21,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -34,7 +34,7 @@ public class MinerStopTest {
private MinerStop method; private MinerStop method;
@Mock private EthHashMiningCoordinator miningCoordinator; @Mock private PoWMiningCoordinator miningCoordinator;
@Before @Before
public void before() { public void before() {

@ -15,8 +15,8 @@
package org.hyperledger.besu.ethereum.blockcreation; package org.hyperledger.besu.ethereum.blockcreation;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.EthHashObserver;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MiningParameters;
@ -72,7 +72,7 @@ public abstract class AbstractMinerExecutor<M extends BlockMiner<? extends Abstr
public Optional<M> startAsyncMining( public Optional<M> startAsyncMining(
final Subscribers<MinedBlockObserver> observers, final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers, final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) { final BlockHeader parentHeader) {
try { try {
final M currentRunningMiner = createMiner(observers, ethHashObservers, parentHeader); final M currentRunningMiner = createMiner(observers, ethHashObservers, parentHeader);
@ -98,7 +98,7 @@ public abstract class AbstractMinerExecutor<M extends BlockMiner<? extends Abstr
public abstract M createMiner( public abstract M createMiner(
final Subscribers<MinedBlockObserver> subscribers, final Subscribers<MinedBlockObserver> subscribers,
final Subscribers<EthHashObserver> ethHashObservers, final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader); final BlockHeader parentHeader);
public void setExtraData(final Bytes extraData) { public void setExtraData(final Bytes extraData) {

@ -17,8 +17,8 @@ package org.hyperledger.besu.ethereum.blockcreation;
import org.hyperledger.besu.ethereum.chain.BlockAddedEvent; import org.hyperledger.besu.ethereum.chain.BlockAddedEvent;
import org.hyperledger.besu.ethereum.chain.BlockAddedObserver; import org.hyperledger.besu.ethereum.chain.BlockAddedObserver;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.EthHashObserver;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
@ -44,7 +44,7 @@ public abstract class AbstractMiningCoordinator<
} }
private final Subscribers<MinedBlockObserver> minedBlockObservers = Subscribers.create(); private final Subscribers<MinedBlockObserver> minedBlockObservers = Subscribers.create();
private final Subscribers<EthHashObserver> ethHashObservers = Subscribers.create(); private final Subscribers<PoWObserver> ethHashObservers = Subscribers.create();
private final AbstractMinerExecutor<M> executor; private final AbstractMinerExecutor<M> executor;
private final SyncState syncState; private final SyncState syncState;
protected final Blockchain blockchain; protected final Blockchain blockchain;
@ -189,7 +189,7 @@ public abstract class AbstractMiningCoordinator<
} }
@Override @Override
public void addEthHashObserver(final EthHashObserver obs) { public void addEthHashObserver(final PoWObserver obs) {
ethHashObservers.subscribe(obs); ethHashObservers.subscribe(obs);
} }

@ -14,14 +14,14 @@
*/ */
package org.hyperledger.besu.ethereum.blockcreation; package org.hyperledger.besu.ethereum.blockcreation;
import org.hyperledger.besu.ethereum.chain.EthHashObserver; import org.hyperledger.besu.ethereum.chain.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -71,12 +71,12 @@ public interface MiningCoordinator {
return Optional.empty(); return Optional.empty();
} }
default Optional<EthHashSolverInputs> getWorkDefinition() { default Optional<PoWSolverInputs> getWorkDefinition() {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Current consensus mechanism prevents querying work definition."); "Current consensus mechanism prevents querying work definition.");
} }
default boolean submitWork(final EthHashSolution solution) { default boolean submitWork(final PoWSolution solution) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Current consensus mechanism prevents submission of work solutions."); "Current consensus mechanism prevents submission of work solutions.");
} }
@ -105,7 +105,7 @@ public interface MiningCoordinator {
final List<Transaction> transactions, final List<Transaction> transactions,
final List<BlockHeader> ommers); final List<BlockHeader> ommers);
default void addEthHashObserver(final EthHashObserver observer) {} default void addEthHashObserver(final PoWObserver observer) {}
void changeTargetGasLimit(final Long targetGasLimit); void changeTargetGasLimit(final Long targetGasLimit);
} }

@ -22,9 +22,9 @@ import org.hyperledger.besu.ethereum.core.SealableBlockHeader;
import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.mainnet.EthHash; import org.hyperledger.besu.ethereum.mainnet.EthHash;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolver; import org.hyperledger.besu.ethereum.mainnet.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.math.BigInteger; import java.math.BigInteger;
@ -34,18 +34,18 @@ import java.util.concurrent.ExecutionException;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
public class EthHashBlockCreator extends AbstractBlockCreator { public class PoWBlockCreator extends AbstractBlockCreator {
private final EthHashSolver nonceSolver; private final PoWSolver nonceSolver;
public EthHashBlockCreator( public PoWBlockCreator(
final Address coinbase, final Address coinbase,
final ExtraDataCalculator extraDataCalculator, final ExtraDataCalculator extraDataCalculator,
final PendingTransactions pendingTransactions, final PendingTransactions pendingTransactions,
final ProtocolContext protocolContext, final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule, final ProtocolSchedule protocolSchedule,
final GasLimitCalculator gasLimitCalculator, final GasLimitCalculator gasLimitCalculator,
final EthHashSolver nonceSolver, final PoWSolver nonceSolver,
final Wei minTransactionGasPrice, final Wei minTransactionGasPrice,
final Double minBlockOccupancyRatio, final Double minBlockOccupancyRatio,
final BlockHeader parentHeader) { final BlockHeader parentHeader) {
@ -66,11 +66,10 @@ public class EthHashBlockCreator extends AbstractBlockCreator {
@Override @Override
protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) { protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) {
final EthHashSolverInputs workDefinition = generateNonceSolverInputs(sealableBlockHeader); final PoWSolverInputs workDefinition = generateNonceSolverInputs(sealableBlockHeader);
final EthHashSolution solution; final PoWSolution solution;
try { try {
solution = solution = nonceSolver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(workDefinition));
nonceSolver.solveFor(EthHashSolver.EthHashSolverJob.createFromInputs(workDefinition));
} catch (final InterruptedException ex) { } catch (final InterruptedException ex) {
throw new CancellationException(); throw new CancellationException();
} catch (final ExecutionException ex) { } catch (final ExecutionException ex) {
@ -84,19 +83,18 @@ public class EthHashBlockCreator extends AbstractBlockCreator {
.buildBlockHeader(); .buildBlockHeader();
} }
private EthHashSolverInputs generateNonceSolverInputs( private PoWSolverInputs generateNonceSolverInputs(final SealableBlockHeader sealableBlockHeader) {
final SealableBlockHeader sealableBlockHeader) {
final BigInteger difficulty = sealableBlockHeader.getDifficulty().toBigInteger(); final BigInteger difficulty = sealableBlockHeader.getDifficulty().toBigInteger();
final UInt256 target = final UInt256 target =
difficulty.equals(BigInteger.ONE) difficulty.equals(BigInteger.ONE)
? UInt256.MAX_VALUE ? UInt256.MAX_VALUE
: UInt256.valueOf(EthHash.TARGET_UPPER_BOUND.divide(difficulty)); : UInt256.valueOf(EthHash.TARGET_UPPER_BOUND.divide(difficulty));
return new EthHashSolverInputs( return new PoWSolverInputs(
target, EthHash.hashHeader(sealableBlockHeader), sealableBlockHeader.getNumber()); target, EthHash.hashHeader(sealableBlockHeader), sealableBlockHeader.getNumber());
} }
public Optional<EthHashSolverInputs> getWorkDefinition() { public Optional<PoWSolverInputs> getWorkDefinition() {
return nonceSolver.getWorkDefinition(); return nonceSolver.getWorkDefinition();
} }
@ -104,7 +102,7 @@ public class EthHashBlockCreator extends AbstractBlockCreator {
return nonceSolver.hashesPerSecond(); return nonceSolver.hashesPerSecond();
} }
public boolean submitWork(final EthHashSolution solution) { public boolean submitWork(final PoWSolution solution) {
return nonceSolver.submitSolution(solution); return nonceSolver.submitSolution(solution);
} }

@ -17,8 +17,8 @@ package org.hyperledger.besu.ethereum.blockcreation;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.util.Subscribers; import org.hyperledger.besu.util.Subscribers;
@ -26,16 +26,16 @@ import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
/** /**
* Provides the EthHash specific aspects of the mining operation - i.e. getting the work definition, * Provides the proof-of-work specific aspects of the mining operation - i.e. getting the work
* reporting the hashrate of the miner and accepting work submissions. * definition, reporting the hashrate of the miner and accepting work submissions.
* *
* <p>All other aspects of mining (i.e. pre-block delays, block creation and importing to the chain) * <p>All other aspects of mining (i.e. pre-block delays, block creation and importing to the chain)
* are all conducted by the parent class. * are all conducted by the parent class.
*/ */
public class EthHashBlockMiner extends BlockMiner<EthHashBlockCreator> { public class PoWBlockMiner extends BlockMiner<PoWBlockCreator> {
public EthHashBlockMiner( public PoWBlockMiner(
final Function<BlockHeader, EthHashBlockCreator> blockCreator, final Function<BlockHeader, PoWBlockCreator> blockCreator,
final ProtocolSchedule protocolSchedule, final ProtocolSchedule protocolSchedule,
final ProtocolContext protocolContext, final ProtocolContext protocolContext,
final Subscribers<MinedBlockObserver> observers, final Subscribers<MinedBlockObserver> observers,
@ -44,7 +44,7 @@ public class EthHashBlockMiner extends BlockMiner<EthHashBlockCreator> {
super(blockCreator, protocolSchedule, protocolContext, observers, scheduler, parentHeader); super(blockCreator, protocolSchedule, protocolContext, observers, scheduler, parentHeader);
} }
public Optional<EthHashSolverInputs> getWorkDefinition() { public Optional<PoWSolverInputs> getWorkDefinition() {
return minerBlockCreator.getWorkDefinition(); return minerBlockCreator.getWorkDefinition();
} }
@ -52,7 +52,7 @@ public class EthHashBlockMiner extends BlockMiner<EthHashBlockCreator> {
return minerBlockCreator.getHashesPerSecond(); return minerBlockCreator.getHashesPerSecond();
} }
public boolean submitWork(final EthHashSolution solution) { public boolean submitWork(final PoWSolution solution) {
return minerBlockCreator.submitWork(solution); return minerBlockCreator.submitWork(solution);
} }
} }

@ -15,29 +15,28 @@
package org.hyperledger.besu.ethereum.blockcreation; package org.hyperledger.besu.ethereum.blockcreation;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.EthHashObserver;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolver; import org.hyperledger.besu.ethereum.mainnet.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.EthHasher;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.util.Subscribers; import org.hyperledger.besu.util.Subscribers;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMiner> { public class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
protected volatile Optional<Address> coinbase; protected volatile Optional<Address> coinbase;
protected boolean stratumMiningEnabled; protected boolean stratumMiningEnabled;
protected final Iterable<Long> nonceGenerator; protected final Iterable<Long> nonceGenerator;
protected final EpochCalculator epochCalculator; protected final EpochCalculator epochCalculator;
public EthHashMinerExecutor( public PoWMinerExecutor(
final ProtocolContext protocolContext, final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule, final ProtocolSchedule protocolSchedule,
final PendingTransactions pendingTransactions, final PendingTransactions pendingTransactions,
@ -58,9 +57,9 @@ public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMine
} }
@Override @Override
public Optional<EthHashBlockMiner> startAsyncMining( public Optional<PoWBlockMiner> startAsyncMining(
final Subscribers<MinedBlockObserver> observers, final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers, final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) { final BlockHeader parentHeader) {
if (coinbase.isEmpty()) { if (coinbase.isEmpty()) {
throw new CoinbaseNotSetException("Unable to start mining without a coinbase."); throw new CoinbaseNotSetException("Unable to start mining without a coinbase.");
@ -69,20 +68,20 @@ public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMine
} }
@Override @Override
public EthHashBlockMiner createMiner( public PoWBlockMiner createMiner(
final Subscribers<MinedBlockObserver> observers, final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers, final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) { final BlockHeader parentHeader) {
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
nonceGenerator, nonceGenerator,
new EthHasher.Light(), protocolSchedule.getByBlockNumber(parentHeader.getNumber() + 1).getPoWHasher().get(),
stratumMiningEnabled, stratumMiningEnabled,
ethHashObservers, ethHashObservers,
epochCalculator); epochCalculator);
final Function<BlockHeader, EthHashBlockCreator> blockCreator = final Function<BlockHeader, PoWBlockCreator> blockCreator =
(header) -> (header) ->
new EthHashBlockCreator( new PoWBlockCreator(
coinbase.get(), coinbase.get(),
parent -> extraData, parent -> extraData,
pendingTransactions, pendingTransactions,
@ -94,7 +93,7 @@ public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMine
minBlockOccupancyRatio, minBlockOccupancyRatio,
parentHeader); parentHeader);
return new EthHashBlockMiner( return new PoWBlockMiner(
blockCreator, protocolSchedule, protocolContext, observers, blockScheduler, parentHeader); blockCreator, protocolSchedule, protocolContext, observers, blockScheduler, parentHeader);
} }

@ -22,8 +22,8 @@ import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -36,20 +36,20 @@ import org.apache.logging.log4j.Logger;
* Responsible for determining when a block mining operation should be started/stopped, then * Responsible for determining when a block mining operation should be started/stopped, then
* creating an appropriate miner and starting it running in a thread. * creating an appropriate miner and starting it running in a thread.
*/ */
public class EthHashMiningCoordinator extends AbstractMiningCoordinator<EthHashBlockMiner> public class PoWMiningCoordinator extends AbstractMiningCoordinator<PoWBlockMiner>
implements BlockAddedObserver { implements BlockAddedObserver {
private static final Logger LOG = getLogger(); private static final Logger LOG = getLogger();
private final EthHashMinerExecutor executor; private final PoWMinerExecutor executor;
private final Cache<String, Long> sealerHashRate; private final Cache<String, Long> sealerHashRate;
private volatile Optional<Long> cachedHashesPerSecond = Optional.empty(); private volatile Optional<Long> cachedHashesPerSecond = Optional.empty();
public EthHashMiningCoordinator( public PoWMiningCoordinator(
final Blockchain blockchain, final Blockchain blockchain,
final EthHashMinerExecutor executor, final PoWMinerExecutor executor,
final SyncState syncState, final SyncState syncState,
final int remoteSealersLimit, final int remoteSealersLimit,
final long remoteSealersTimeToLive) { final long remoteSealersTimeToLive) {
@ -96,7 +96,7 @@ public class EthHashMiningCoordinator extends AbstractMiningCoordinator<EthHashB
private Optional<Long> localHashesPerSecond() { private Optional<Long> localHashesPerSecond() {
final Optional<Long> currentHashesPerSecond = final Optional<Long> currentHashesPerSecond =
currentRunningMiner.flatMap(EthHashBlockMiner::getHashesPerSecond); currentRunningMiner.flatMap(PoWBlockMiner::getHashesPerSecond);
if (currentHashesPerSecond.isPresent()) { if (currentHashesPerSecond.isPresent()) {
cachedHashesPerSecond = currentHashesPerSecond; cachedHashesPerSecond = currentHashesPerSecond;
@ -122,19 +122,19 @@ public class EthHashMiningCoordinator extends AbstractMiningCoordinator<EthHashB
} }
@Override @Override
public Optional<EthHashSolverInputs> getWorkDefinition() { public Optional<PoWSolverInputs> getWorkDefinition() {
return currentRunningMiner.flatMap(EthHashBlockMiner::getWorkDefinition); return currentRunningMiner.flatMap(PoWBlockMiner::getWorkDefinition);
} }
@Override @Override
public boolean submitWork(final EthHashSolution solution) { public boolean submitWork(final PoWSolution solution) {
synchronized (this) { synchronized (this) {
return currentRunningMiner.map(miner -> miner.submitWork(solution)).orElse(false); return currentRunningMiner.map(miner -> miner.submitWork(solution)).orElse(false);
} }
} }
@Override @Override
protected void haltMiner(final EthHashBlockMiner miner) { protected void haltMiner(final PoWBlockMiner miner) {
miner.cancel(); miner.cancel();
miner.getHashesPerSecond().ifPresent(val -> cachedHashesPerSecond = Optional.of(val)); miner.getHashesPerSecond().ifPresent(val -> cachedHashesPerSecond = Optional.of(val));
} }

@ -44,9 +44,9 @@ public class AbstractMiningCoordinatorTest {
new BlockHeaderTestFixture().buildHeader(), new BlockHeaderTestFixture().buildHeader(),
new BlockBody(Collections.emptyList(), Collections.emptyList())); new BlockBody(Collections.emptyList(), Collections.emptyList()));
private final Blockchain blockchain = mock(Blockchain.class); private final Blockchain blockchain = mock(Blockchain.class);
private final EthHashMinerExecutor minerExecutor = mock(EthHashMinerExecutor.class); private final PoWMinerExecutor minerExecutor = mock(PoWMinerExecutor.class);
private final SyncState syncState = mock(SyncState.class); private final SyncState syncState = mock(SyncState.class);
private final EthHashBlockMiner blockMiner = mock(EthHashBlockMiner.class); private final PoWBlockMiner blockMiner = mock(PoWBlockMiner.class);
private final TestMiningCoordinator miningCoordinator = private final TestMiningCoordinator miningCoordinator =
new TestMiningCoordinator(blockchain, minerExecutor, syncState); new TestMiningCoordinator(blockchain, minerExecutor, syncState);
@ -222,11 +222,11 @@ public class AbstractMiningCoordinatorTest {
verifyNoMoreInteractions(minerExecutor, blockMiner); verifyNoMoreInteractions(minerExecutor, blockMiner);
} }
public static class TestMiningCoordinator extends AbstractMiningCoordinator<EthHashBlockMiner> { public static class TestMiningCoordinator extends AbstractMiningCoordinator<PoWBlockMiner> {
public TestMiningCoordinator( public TestMiningCoordinator(
final Blockchain blockchain, final Blockchain blockchain,
final AbstractMinerExecutor<EthHashBlockMiner> executor, final AbstractMinerExecutor<PoWBlockMiner> executor,
final SyncState syncState) { final SyncState syncState) {
super(blockchain, executor, syncState); super(blockchain, executor, syncState);
} }

@ -53,8 +53,8 @@ public class BlockMinerTest {
final ProtocolContext protocolContext = new ProtocolContext(null, null, null); final ProtocolContext protocolContext = new ProtocolContext(null, null, null);
final EthHashBlockCreator blockCreator = mock(EthHashBlockCreator.class); final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class);
final Function<BlockHeader, EthHashBlockCreator> blockCreatorSupplier = final Function<BlockHeader, PoWBlockCreator> blockCreatorSupplier =
(parentHeader) -> blockCreator; (parentHeader) -> blockCreator;
when(blockCreator.createBlock(anyLong())).thenReturn(blockToCreate); when(blockCreator.createBlock(anyLong())).thenReturn(blockToCreate);
@ -69,8 +69,8 @@ public class BlockMinerTest {
final MinedBlockObserver observer = mock(MinedBlockObserver.class); final MinedBlockObserver observer = mock(MinedBlockObserver.class);
final DefaultBlockScheduler scheduler = mock(DefaultBlockScheduler.class); final DefaultBlockScheduler scheduler = mock(DefaultBlockScheduler.class);
when(scheduler.waitUntilNextBlockCanBeMined(any())).thenReturn(5L); when(scheduler.waitUntilNextBlockCanBeMined(any())).thenReturn(5L);
final BlockMiner<EthHashBlockCreator> miner = final BlockMiner<PoWBlockCreator> miner =
new EthHashBlockMiner( new PoWBlockMiner(
blockCreatorSupplier, blockCreatorSupplier,
protocolSchedule, protocolSchedule,
protocolContext, protocolContext,
@ -93,8 +93,8 @@ public class BlockMinerTest {
final ProtocolContext protocolContext = new ProtocolContext(null, null, null); final ProtocolContext protocolContext = new ProtocolContext(null, null, null);
final EthHashBlockCreator blockCreator = mock(EthHashBlockCreator.class); final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class);
final Function<BlockHeader, EthHashBlockCreator> blockCreatorSupplier = final Function<BlockHeader, PoWBlockCreator> blockCreatorSupplier =
(parentHeader) -> blockCreator; (parentHeader) -> blockCreator;
when(blockCreator.createBlock(anyLong())).thenReturn(blockToCreate); when(blockCreator.createBlock(anyLong())).thenReturn(blockToCreate);
@ -108,8 +108,8 @@ public class BlockMinerTest {
final MinedBlockObserver observer = mock(MinedBlockObserver.class); final MinedBlockObserver observer = mock(MinedBlockObserver.class);
final DefaultBlockScheduler scheduler = mock(DefaultBlockScheduler.class); final DefaultBlockScheduler scheduler = mock(DefaultBlockScheduler.class);
when(scheduler.waitUntilNextBlockCanBeMined(any())).thenReturn(5L); when(scheduler.waitUntilNextBlockCanBeMined(any())).thenReturn(5L);
final BlockMiner<EthHashBlockCreator> miner = final BlockMiner<PoWBlockCreator> miner =
new EthHashBlockMiner( new PoWBlockMiner(
blockCreatorSupplier, blockCreatorSupplier,
protocolSchedule, protocolSchedule,
protocolContext, protocolContext,

@ -33,7 +33,7 @@ import org.junit.runners.Parameterized.Parameters;
public class HashRateMiningCoordinatorTest { public class HashRateMiningCoordinatorTest {
private final Blockchain blockchain = mock(Blockchain.class); private final Blockchain blockchain = mock(Blockchain.class);
private final SyncState syncState = mock(SyncState.class); private final SyncState syncState = mock(SyncState.class);
private final EthHashMinerExecutor minerExecutor = mock(EthHashMinerExecutor.class); private final PoWMinerExecutor minerExecutor = mock(PoWMinerExecutor.class);
private final String id; private final String id;
private final Long hashRate; private final Long hashRate;
private final Long wantTotalHashrate; private final Long wantTotalHashrate;
@ -66,8 +66,8 @@ public class HashRateMiningCoordinatorTest {
@Test @Test
public void test() { public void test() {
final EthHashMiningCoordinator miningCoordinator = final PoWMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(blockchain, minerExecutor, syncState, 1000, 10); new PoWMiningCoordinator(blockchain, minerExecutor, syncState, 1000, 10);
for (int i = 0; i < startSealersSize; i++) { for (int i = 0; i < startSealersSize; i++) {
miningCoordinator.submitHashRate(UUID.randomUUID().toString(), 1L); miningCoordinator.submitHashRate(UUID.randomUUID().toString(), 1L);
} }

@ -31,8 +31,8 @@ import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolver; import org.hyperledger.besu.ethereum.mainnet.PoWHasher;
import org.hyperledger.besu.ethereum.mainnet.EthHasher; import org.hyperledger.besu.ethereum.mainnet.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder; import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
import org.hyperledger.besu.ethereum.mainnet.ValidationTestUtils; import org.hyperledger.besu.ethereum.mainnet.ValidationTestUtils;
@ -50,7 +50,7 @@ import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.junit.Test; import org.junit.Test;
public class EthHashBlockCreatorTest { public class PoWBlockCreatorTest {
private final Address BLOCK_1_COINBASE = private final Address BLOCK_1_COINBASE =
Address.fromHexString("0x05a56e2d52c817161883f50c441c3228cfe54d9f"); Address.fromHexString("0x05a56e2d52c817161883f50c441c3228cfe54d9f");
@ -79,10 +79,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE), Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(), PoWHasher.ETHASH_LIGHT,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
@ -97,8 +97,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader, executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP); TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator = final PoWBlockCreator blockCreator =
new EthHashBlockCreator( new PoWBlockCreator(
BLOCK_1_COINBASE, BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA, parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions, pendingTransactions,
@ -138,10 +138,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE), Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(), PoWHasher.ETHASH_LIGHT,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
@ -156,8 +156,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader, executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP); TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator = final PoWBlockCreator blockCreator =
new EthHashBlockCreator( new PoWBlockCreator(
BLOCK_1_COINBASE, BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA, parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions, pendingTransactions,
@ -192,10 +192,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE), Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(), PoWHasher.ETHASH_LIGHT,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
@ -210,8 +210,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader, executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP); TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator = final PoWBlockCreator blockCreator =
new EthHashBlockCreator( new PoWBlockCreator(
BLOCK_1_COINBASE, BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA, parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions, pendingTransactions,
@ -262,10 +262,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE), Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(), PoWHasher.ETHASH_LIGHT,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
@ -280,8 +280,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader, executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP); TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator = final PoWBlockCreator blockCreator =
new EthHashBlockCreator( new PoWBlockCreator(
BLOCK_1_COINBASE, BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA, parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions, pendingTransactions,

@ -28,7 +28,7 @@ import org.hyperledger.besu.util.Subscribers;
import org.junit.Test; import org.junit.Test;
public class EthHashMinerExecutorTest { public class PoWMinerExecutorTest {
private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
@Test @Test
@ -46,8 +46,8 @@ public class EthHashMinerExecutorTest {
() -> null, () -> null,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP); TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashMinerExecutor executor = final PoWMinerExecutor executor =
new EthHashMinerExecutor( new PoWMinerExecutor(
null, null,
null, null,
pendingTransactions, pendingTransactions,
@ -75,8 +75,8 @@ public class EthHashMinerExecutorTest {
() -> null, () -> null,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP); TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashMinerExecutor executor = final PoWMinerExecutor executor =
new EthHashMinerExecutor( new PoWMinerExecutor(
null, null,
null, null,
pendingTransactions, pendingTransactions,

@ -24,7 +24,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import java.util.Optional; import java.util.Optional;
@ -32,12 +32,12 @@ import org.apache.tuweni.bytes.Bytes32;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
public class EthHashMiningCoordinatorTest { public class PoWMiningCoordinatorTest {
private final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create(); private final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create();
private final SyncState syncState = mock(SyncState.class); private final SyncState syncState = mock(SyncState.class);
private final EthHashMinerExecutor executor = mock(EthHashMinerExecutor.class); private final PoWMinerExecutor executor = mock(PoWMinerExecutor.class);
private final EthHashBlockMiner miner = mock(EthHashBlockMiner.class); private final PoWBlockMiner miner = mock(PoWBlockMiner.class);
@Before @Before
public void setUp() { public void setUp() {
@ -46,14 +46,14 @@ public class EthHashMiningCoordinatorTest {
@Test @Test
public void miningCoordinatorIsCreatedDisabledWithNoReportableMiningStatistics() { public void miningCoordinatorIsCreatedDisabledWithNoReportableMiningStatistics() {
final EthHashMiningCoordinator miningCoordinator = final PoWMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator( new PoWMiningCoordinator(
executionContext.getBlockchain(), executionContext.getBlockchain(),
executor, executor,
syncState, syncState,
DEFAULT_REMOTE_SEALERS_LIMIT, DEFAULT_REMOTE_SEALERS_LIMIT,
DEFAULT_REMOTE_SEALERS_TTL); DEFAULT_REMOTE_SEALERS_TTL);
final EthHashSolution solution = new EthHashSolution(1L, Hash.EMPTY, new byte[Bytes32.SIZE]); final PoWSolution solution = new PoWSolution(1L, Hash.EMPTY, null, Bytes32.ZERO);
assertThat(miningCoordinator.isMining()).isFalse(); assertThat(miningCoordinator.isMining()).isFalse();
assertThat(miningCoordinator.hashesPerSecond()).isEqualTo(Optional.empty()); assertThat(miningCoordinator.hashesPerSecond()).isEqualTo(Optional.empty());
@ -72,8 +72,8 @@ public class EthHashMiningCoordinatorTest {
when(executor.startAsyncMining(any(), any(), any())).thenReturn(Optional.of(miner)); when(executor.startAsyncMining(any(), any(), any())).thenReturn(Optional.of(miner));
final EthHashMiningCoordinator miningCoordinator = final PoWMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator( new PoWMiningCoordinator(
executionContext.getBlockchain(), executionContext.getBlockchain(),
executor, executor,
syncState, syncState,

@ -14,20 +14,20 @@
*/ */
package org.hyperledger.besu.ethereum.chain; package org.hyperledger.besu.ethereum.chain;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.function.Function; import java.util.function.Function;
/** Observer of new work for the EthHash PoW algorithm */ /** Observer of new work for the PoW algorithm */
public interface EthHashObserver { public interface PoWObserver {
/** /**
* Send a new proof-of-work job to observers * Send a new proof-of-work job to observers
* *
* @param jobInput the proof-of-work job * @param jobInput the proof-of-work job
*/ */
void newJob(EthHashSolverInputs jobInput); void newJob(PoWSolverInputs jobInput);
/** /**
* Sets a callback for the observer to provide solutions to jobs. * Sets a callback for the observer to provide solutions to jobs.
@ -35,5 +35,5 @@ public interface EthHashObserver {
* @param submitSolutionCallback the callback to set on the observer, consuming a solution and * @param submitSolutionCallback the callback to set on the observer, consuming a solution and
* returning true if the solution is accepted, false if rejected. * returning true if the solution is accepted, false if rejected.
*/ */
void setSubmitWorkCallback(Function<EthHashSolution, Boolean> submitSolutionCallback); void setSubmitWorkCallback(Function<PoWSolution, Boolean> submitSolutionCallback);
} }

@ -29,11 +29,16 @@ public class FixedDifficultyCalculators {
public static final int DEFAULT_DIFFICULTY = 100; public static final int DEFAULT_DIFFICULTY = 100;
public static boolean isFixedDifficultyInConfig(final GenesisConfigOptions config) { public static boolean isFixedDifficultyInConfig(final GenesisConfigOptions config) {
return config.getEthashConfigOptions().getFixedDifficulty().isPresent(); return config.getEthashConfigOptions().getFixedDifficulty().isPresent()
|| config.getKeccak256ConfigOptions().getFixedDifficulty().isPresent();
} }
public static DifficultyCalculator calculator(final GenesisConfigOptions config) { public static DifficultyCalculator calculator(final GenesisConfigOptions config) {
long difficulty = config.getEthashConfigOptions().getFixedDifficulty().getAsLong(); long difficulty =
config
.getEthashConfigOptions()
.getFixedDifficulty()
.orElseGet(() -> config.getKeccak256ConfigOptions().getFixedDifficulty().getAsLong());
return (time, parent, context) -> BigInteger.valueOf(difficulty); return (time, parent, context) -> BigInteger.valueOf(difficulty);
} }
} }

@ -14,6 +14,9 @@
*/ */
package org.hyperledger.besu.ethereum.mainnet; package org.hyperledger.besu.ethereum.mainnet;
import static org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSpecs.powHasher;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.ethereum.core.Account; import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.core.Wei;
@ -232,10 +235,10 @@ public class ClassicProtocolSpecs {
quorumCompatibilityMode) quorumCompatibilityMode)
.blockHeaderValidatorBuilder( .blockHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createBlockHeaderValidator( MainnetBlockHeaderValidator.createBlockHeaderValidator(
new EpochCalculator.Ecip1099EpochCalculator())) new EpochCalculator.Ecip1099EpochCalculator(), powHasher(PowAlgorithm.ETHASH)))
.ommerHeaderValidatorBuilder( .ommerHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createOmmerValidator( MainnetBlockHeaderValidator.createOmmerValidator(
new EpochCalculator.Ecip1099EpochCalculator())) new EpochCalculator.Ecip1099EpochCalculator(), powHasher(PowAlgorithm.ETHASH)))
.name("Thanos"); .name("Thanos");
} }
@ -258,4 +261,28 @@ public class ClassicProtocolSpecs {
return new TransactionReceipt( return new TransactionReceipt(
result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), result.getRevertReason()); result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), result.getRevertReason());
} }
public static ProtocolSpecBuilder ecip1049Definition(
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final OptionalLong ecip1017EraRounds,
final boolean quorumCompatibilityMode) {
return thanosDefinition(
chainId,
configContractSizeLimit,
configStackSizeLimit,
enableRevertReason,
ecip1017EraRounds,
quorumCompatibilityMode)
.blockHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createBlockHeaderValidator(
new EpochCalculator.Ecip1099EpochCalculator(), powHasher(PowAlgorithm.KECCAK256)))
.ommerHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createOmmerValidator(
new EpochCalculator.Ecip1099EpochCalculator(), powHasher(PowAlgorithm.KECCAK256)))
.powHasher(powHasher(PowAlgorithm.KECCAK256))
.name("ecip1049");
}
} }

@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.mainnet; package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.config.experimental.ExperimentalEIPs; import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.SealableBlockHeader; import org.hyperledger.besu.ethereum.core.SealableBlockHeader;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
@ -23,10 +24,13 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.security.DigestException; import java.security.DigestException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.Arrays;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.bouncycastle.jcajce.provider.digest.Keccak; import org.bouncycastle.jcajce.provider.digest.Keccak;
/** Implementation of EthHash. */ /** Implementation of EthHash. */
@ -71,19 +75,19 @@ public final class EthHash {
* @return A byte array holding MixHash in its first 32 bytes and the EthHash result in the in * @return A byte array holding MixHash in its first 32 bytes and the EthHash result in the in
* bytes 32 to 63 * bytes 32 to 63
*/ */
public static byte[] hashimotoLight( public static PoWSolution hashimotoLight(
final long size, final int[] cache, final byte[] header, final long nonce) { final long size, final int[] cache, final Bytes header, final long nonce) {
return hashimoto(header, size, nonce, (target, ind) -> calcDatasetItem(target, cache, ind)); return hashimoto(header, size, nonce, (target, ind) -> calcDatasetItem(target, cache, ind));
} }
public static byte[] hashimoto( public static PoWSolution hashimoto(
final byte[] header, final Bytes header,
final long size, final long size,
final long nonce, final long nonce,
final BiConsumer<byte[], Integer> datasetLookup) { final BiConsumer<byte[], Integer> datasetLookup) {
final int n = (int) Long.divideUnsigned(size, MIX_BYTES); final int n = (int) Long.divideUnsigned(size, MIX_BYTES);
final MessageDigest keccak512 = KECCAK_512.get(); final MessageDigest keccak512 = KECCAK_512.get();
keccak512.update(header); keccak512.update(header.toArrayUnsafe());
keccak512.update(Longs.toByteArray(Long.reverseBytes(nonce))); keccak512.update(Longs.toByteArray(Long.reverseBytes(nonce)));
final byte[] seed = keccak512.digest(); final byte[] seed = keccak512.digest();
final ByteBuffer mixBuffer = ByteBuffer.allocate(MIX_BYTES).order(ByteOrder.LITTLE_ENDIAN); final ByteBuffer mixBuffer = ByteBuffer.allocate(MIX_BYTES).order(ByteOrder.LITTLE_ENDIAN);
@ -121,7 +125,12 @@ public final class EthHash {
} catch (final DigestException ex) { } catch (final DigestException ex) {
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
return result;
return new PoWSolution(
nonce,
Hash.wrap(Bytes32.wrap(Arrays.copyOf(result, 32))),
Bytes32.wrap(result, 32),
header);
} }
/** /**
@ -163,7 +172,7 @@ public final class EthHash {
* @param header Block Header * @param header Block Header
* @return Truncated BlockHeader hash * @return Truncated BlockHeader hash
*/ */
public static byte[] hashHeader(final SealableBlockHeader header) { public static Bytes32 hashHeader(final SealableBlockHeader header) {
final BytesValueRLPOutput out = new BytesValueRLPOutput(); final BytesValueRLPOutput out = new BytesValueRLPOutput();
out.startList(); out.startList();
out.writeBytes(header.getParentHash()); out.writeBytes(header.getParentHash());
@ -184,7 +193,8 @@ public final class EthHash {
out.writeLongScalar(header.getBaseFee().get()); out.writeLongScalar(header.getBaseFee().get());
} }
out.endList(); out.endList();
return DirectAcyclicGraphSeed.KECCAK_256.get().digest(out.encoded().toArray()); return Bytes32.wrap(
DirectAcyclicGraphSeed.KECCAK_256.get().digest(out.encoded().toArrayUnsafe()));
} }
/** /**

@ -0,0 +1,57 @@
/*
* 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.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Hash;
import java.security.MessageDigest;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.bouncycastle.jcajce.provider.digest.Keccak;
/**
* Hasher for Keccak-256 PoW.
*
* <p>Block is valid if keccak256(keccak256(rlp(unsealed header)), nonce) is less than or equal to
* 2^256 / difficulty mixhash = keccak256(rlp(unsealed header)) which is stored in the block.
* Currently this process is ethash(rlp(unsealed header)) So to validate a block we check
* keccak256(mixhash, nonce) is less than or equal to 2^256 / difficulty
*/
public class KeccakHasher implements PoWHasher {
public static final KeccakHasher KECCAK256 = new KeccakHasher();
private KeccakHasher() {}
private static final ThreadLocal<MessageDigest> KECCAK_256 =
ThreadLocal.withInitial(Keccak.Digest256::new);
@Override
public PoWSolution hash(
final long nonce,
final long number,
final EpochCalculator epochCalc,
final Bytes prePowHash) {
MessageDigest digest = KECCAK_256.get();
digest.update(prePowHash.toArrayUnsafe());
digest.update(Bytes.ofUnsignedLong(nonce).toArrayUnsafe());
Bytes32 solution = Bytes32.wrap(digest.digest());
Hash mixHash = Hash.wrap(solution);
return new PoWSolution(nonce, mixHash, solution, prePowHash);
}
}

@ -41,7 +41,11 @@ public final class MainnetBlockHeaderValidator {
Bytes.fromHexString("0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f"); Bytes.fromHexString("0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f");
public static BlockHeaderValidator.Builder create() { public static BlockHeaderValidator.Builder create() {
return createValidator(); return createValidator(PoWHasher.ETHASH_LIGHT);
}
public static BlockHeaderValidator.Builder create(final PoWHasher hasher) {
return createValidator(hasher);
} }
public static BlockHeaderValidator.Builder createDaoValidator() { public static BlockHeaderValidator.Builder createDaoValidator() {
@ -52,7 +56,11 @@ public final class MainnetBlockHeaderValidator {
} }
public static BlockHeaderValidator.Builder createClassicValidator() { public static BlockHeaderValidator.Builder createClassicValidator() {
return createValidator() return createClassicValidator(PoWHasher.ETHASH_LIGHT);
}
public static BlockHeaderValidator.Builder createClassicValidator(final PoWHasher hasher) {
return createValidator(hasher)
.addRule( .addRule(
new ConstantFieldValidationRule<>( new ConstantFieldValidationRule<>(
"hash", "hash",
@ -69,10 +77,16 @@ public final class MainnetBlockHeaderValidator {
} }
static BlockHeaderValidator.Builder createOmmerValidator() { static BlockHeaderValidator.Builder createOmmerValidator() {
return createOmmerValidator(new EpochCalculator.DefaultEpochCalculator()); return createOmmerValidator(
new EpochCalculator.DefaultEpochCalculator(), PoWHasher.ETHASH_LIGHT);
} }
static BlockHeaderValidator.Builder createOmmerValidator(final EpochCalculator epochCalculator) { static BlockHeaderValidator.Builder createOmmerValidator(final PoWHasher hasher) {
return createOmmerValidator(new EpochCalculator.DefaultEpochCalculator(), hasher);
}
static BlockHeaderValidator.Builder createOmmerValidator(
final EpochCalculator epochCalculator, final PoWHasher hasher) {
return new BlockHeaderValidator.Builder() return new BlockHeaderValidator.Builder()
.addRule(CalculatedDifficultyValidationRule::new) .addRule(CalculatedDifficultyValidationRule::new)
.addRule(new AncestryValidationRule()) .addRule(new AncestryValidationRule())
@ -80,15 +94,19 @@ public final class MainnetBlockHeaderValidator {
.addRule(new GasUsageValidationRule()) .addRule(new GasUsageValidationRule())
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT)) .addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule(epochCalculator)); .addRule(new ProofOfWorkValidationRule(epochCalculator, false, hasher));
} }
private static BlockHeaderValidator.Builder createValidator() { private static BlockHeaderValidator.Builder createValidator() {
return createBlockHeaderValidator(new EpochCalculator.DefaultEpochCalculator()); return createValidator(PoWHasher.ETHASH_LIGHT);
}
private static BlockHeaderValidator.Builder createValidator(final PoWHasher hasher) {
return createBlockHeaderValidator(new EpochCalculator.DefaultEpochCalculator(), hasher);
} }
static BlockHeaderValidator.Builder createBlockHeaderValidator( static BlockHeaderValidator.Builder createBlockHeaderValidator(
final EpochCalculator epochCalculator) { final EpochCalculator epochCalculator, final PoWHasher hasher) {
return new BlockHeaderValidator.Builder() return new BlockHeaderValidator.Builder()
.addRule(CalculatedDifficultyValidationRule::new) .addRule(CalculatedDifficultyValidationRule::new)
.addRule(new AncestryValidationRule()) .addRule(new AncestryValidationRule())
@ -97,7 +115,7 @@ public final class MainnetBlockHeaderValidator {
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT)) .addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S)) .addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule(epochCalculator)); .addRule(new ProofOfWorkValidationRule(epochCalculator, false, hasher));
} }
static BlockHeaderValidator.Builder createEip1559Validator(final EIP1559 eip1559) { static BlockHeaderValidator.Builder createEip1559Validator(final EIP1559 eip1559) {
@ -109,7 +127,9 @@ public final class MainnetBlockHeaderValidator {
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT)) .addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S)) .addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule(new EpochCalculator.DefaultEpochCalculator(), true)) .addRule(
new ProofOfWorkValidationRule(
new EpochCalculator.DefaultEpochCalculator(), true, PoWHasher.ETHASH_LIGHT))
.addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559))); .addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559)));
} }
@ -121,7 +141,9 @@ public final class MainnetBlockHeaderValidator {
.addRule(new GasUsageValidationRule()) .addRule(new GasUsageValidationRule())
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT)) .addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule(new EpochCalculator.DefaultEpochCalculator(), true)) .addRule(
new ProofOfWorkValidationRule(
new EpochCalculator.DefaultEpochCalculator(), true, PoWHasher.ETHASH_LIGHT))
.addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559))); .addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559)));
} }
} }

@ -160,4 +160,14 @@ public class MainnetProtocolSpecFactory {
ecip1017EraRounds, ecip1017EraRounds,
quorumCompatibilityMode); quorumCompatibilityMode);
} }
public ProtocolSpecBuilder ecip1049Definition() {
return ClassicProtocolSpecs.ecip1049Definition(
chainId,
contractSizeLimit,
evmStackSize,
isRevertReasonEnabled,
ecip1017EraRounds,
quorumCompatibilityMode);
}
} }

@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.mainnet; package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.config.experimental.ExperimentalEIPs; import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.ethereum.MainnetBlockValidator; import org.hyperledger.besu.ethereum.MainnetBlockValidator;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
@ -151,6 +152,21 @@ public abstract class MainnetProtocolSpecs {
.name("Frontier"); .name("Frontier");
} }
public static PoWHasher powHasher(final PowAlgorithm powAlgorithm) {
if (powAlgorithm == null) {
return PoWHasher.UNSUPPORTED;
}
switch (powAlgorithm) {
case ETHASH:
return PoWHasher.ETHASH_LIGHT;
case KECCAK256:
return KeccakHasher.KECCAK256;
case UNSUPPORTED:
default:
return PoWHasher.UNSUPPORTED;
}
}
public static BlockValidatorBuilder blockValidatorBuilder(final boolean goQuorumMode) { public static BlockValidatorBuilder blockValidatorBuilder(final boolean goQuorumMode) {
if (goQuorumMode) { if (goQuorumMode) {
return GoQuorumBlockValidator::new; return GoQuorumBlockValidator::new;

@ -14,35 +14,57 @@
*/ */
package org.hyperledger.besu.ethereum.mainnet; package org.hyperledger.besu.ethereum.mainnet;
public interface EthHasher { import org.apache.tuweni.bytes.Bytes;
public interface PoWHasher {
PoWHasher ETHASH_LIGHT = new EthashLight();
PoWHasher UNSUPPORTED = new Unsupported();
/** /**
* Hash of a particular block and nonce. * Hash of a particular block and nonce.
* *
* @param buffer At least 64 bytes long buffer to store EthHash result in
* @param nonce Block Nonce * @param nonce Block Nonce
* @param number Block Number * @param number Block Number
* @param epochCalc EpochCalculator for calculating epoch * @param epochCalc EpochCalculator for calculating epoch
* @param headerHash Block Header (without mix digest and nonce) Hash * @param prePowHash Block Header (without mix digest and nonce) Hash
* @return the PoW solution computed by the hashing function
*/ */
void hash(byte[] buffer, long nonce, long number, EpochCalculator epochCalc, byte[] headerHash); PoWSolution hash(long nonce, long number, EpochCalculator epochCalc, Bytes prePowHash);
final class Light implements EthHasher { /** Implementation of Ethash Hashimoto Light Implementation. */
final class EthashLight implements PoWHasher {
private static final EthHashCacheFactory cacheFactory = new EthHashCacheFactory(); private static final EthHashCacheFactory cacheFactory = new EthHashCacheFactory();
private EthashLight() {}
@Override @Override
public void hash( public PoWSolution hash(
final byte[] buffer,
final long nonce, final long nonce,
final long number, final long number,
final EpochCalculator epochCalc, final EpochCalculator epochCalc,
final byte[] headerHash) { final Bytes prePowHash) {
final EthHashCacheFactory.EthHashDescriptor cache = final EthHashCacheFactory.EthHashDescriptor cache =
cacheFactory.ethHashCacheFor(number, epochCalc); cacheFactory.ethHashCacheFor(number, epochCalc);
final byte[] hash = final PoWSolution solution =
EthHash.hashimotoLight(cache.getDatasetSize(), cache.getCache(), headerHash, nonce); EthHash.hashimotoLight(cache.getDatasetSize(), cache.getCache(), prePowHash, nonce);
System.arraycopy(hash, 0, buffer, 0, hash.length); return solution;
}
}
/** Implementation of an inoperative hasher. */
final class Unsupported implements PoWHasher {
private Unsupported() {}
@Override
public PoWSolution hash(
final long nonce,
final long number,
final EpochCalculator epochCalc,
final Bytes prePowHash) {
throw new UnsupportedOperationException("Hashing is unsupported");
} }
} }
} }

@ -16,17 +16,21 @@ package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
public class EthHashSolution { import org.apache.tuweni.bytes.Bytes;
public class PoWSolution {
private final long nonce; private final long nonce;
private final Hash mixHash; private final Hash mixHash;
private final byte[] powHash; private final Bytes powHash;
private final Bytes solution;
public EthHashSolution(final long nonce, final Hash mixHash, final byte[] powHash) { public PoWSolution(
final long nonce, final Hash mixHash, final Bytes solution, final Bytes powHash) {
this.nonce = nonce; this.nonce = nonce;
this.mixHash = mixHash; this.mixHash = mixHash;
this.solution = solution;
this.powHash = powHash; this.powHash = powHash;
} }
@ -38,24 +42,27 @@ public class EthHashSolution {
return mixHash; return mixHash;
} }
public byte[] getPowHash() { public Bytes getPowHash() {
return powHash; return powHash;
} }
public Bytes getSolution() {
return solution;
}
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object o) {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
EthHashSolution that = (EthHashSolution) o; PoWSolution that = (PoWSolution) o;
return nonce == that.nonce return nonce == that.nonce
&& Objects.equals(mixHash, that.mixHash) && Objects.equals(mixHash, that.mixHash)
&& Arrays.equals(powHash, that.powHash); && Objects.equals(solution, that.solution)
&& Objects.equals(powHash, that.powHash);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = Objects.hash(nonce, mixHash); return Objects.hash(nonce, mixHash, solution, powHash);
result = 31 * result + Arrays.hashCode(powHash);
return result;
} }
} }

@ -16,11 +16,9 @@ package org.hyperledger.besu.ethereum.mainnet;
import static org.apache.logging.log4j.LogManager.getLogger; import static org.apache.logging.log4j.LogManager.getLogger;
import org.hyperledger.besu.ethereum.chain.EthHashObserver; import org.hyperledger.besu.ethereum.chain.PoWObserver;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.util.Subscribers; import org.hyperledger.besu.util.Subscribers;
import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -28,30 +26,27 @@ import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
public class EthHashSolver { public class PoWSolver {
private static final Logger LOG = getLogger(); private static final Logger LOG = getLogger();
public static class EthHashSolverJob { public static class PoWSolverJob {
private final EthHashSolverInputs inputs; private final PoWSolverInputs inputs;
private final CompletableFuture<EthHashSolution> nonceFuture; private final CompletableFuture<PoWSolution> nonceFuture;
EthHashSolverJob( PoWSolverJob(final PoWSolverInputs inputs, final CompletableFuture<PoWSolution> nonceFuture) {
final EthHashSolverInputs inputs, final CompletableFuture<EthHashSolution> nonceFuture) {
this.inputs = inputs; this.inputs = inputs;
this.nonceFuture = nonceFuture; this.nonceFuture = nonceFuture;
} }
public static EthHashSolverJob createFromInputs(final EthHashSolverInputs inputs) { public static PoWSolverJob createFromInputs(final PoWSolverInputs inputs) {
return new EthHashSolverJob(inputs, new CompletableFuture<>()); return new PoWSolverJob(inputs, new CompletableFuture<>());
} }
EthHashSolverInputs getInputs() { PoWSolverInputs getInputs() {
return inputs; return inputs;
} }
@ -59,7 +54,7 @@ public class EthHashSolver {
return nonceFuture.isDone(); return nonceFuture.isDone();
} }
void solvedWith(final EthHashSolution solution) { void solvedWith(final PoWSolution solution) {
nonceFuture.complete(solution); nonceFuture.complete(solution);
} }
@ -71,7 +66,7 @@ public class EthHashSolver {
nonceFuture.completeExceptionally(ex); nonceFuture.completeExceptionally(ex);
} }
EthHashSolution getSolution() throws InterruptedException, ExecutionException { PoWSolution getSolution() throws InterruptedException, ExecutionException {
return nonceFuture.get(); return nonceFuture.get();
} }
} }
@ -79,28 +74,28 @@ public class EthHashSolver {
private final long NO_MINING_CONDUCTED = -1; private final long NO_MINING_CONDUCTED = -1;
private final Iterable<Long> nonceGenerator; private final Iterable<Long> nonceGenerator;
private final EthHasher ethHasher; private final PoWHasher poWHasher;
private volatile long hashesPerSecond = NO_MINING_CONDUCTED; private volatile long hashesPerSecond = NO_MINING_CONDUCTED;
private final Boolean stratumMiningEnabled; private final Boolean stratumMiningEnabled;
private final Subscribers<EthHashObserver> ethHashObservers; private final Subscribers<PoWObserver> ethHashObservers;
private final EpochCalculator epochCalculator; private final EpochCalculator epochCalculator;
private volatile Optional<EthHashSolverJob> currentJob = Optional.empty(); private volatile Optional<PoWSolverJob> currentJob = Optional.empty();
public EthHashSolver( public PoWSolver(
final Iterable<Long> nonceGenerator, final Iterable<Long> nonceGenerator,
final EthHasher ethHasher, final PoWHasher poWHasher,
final Boolean stratumMiningEnabled, final Boolean stratumMiningEnabled,
final Subscribers<EthHashObserver> ethHashObservers, final Subscribers<PoWObserver> ethHashObservers,
final EpochCalculator epochCalculator) { final EpochCalculator epochCalculator) {
this.nonceGenerator = nonceGenerator; this.nonceGenerator = nonceGenerator;
this.ethHasher = ethHasher; this.poWHasher = poWHasher;
this.stratumMiningEnabled = stratumMiningEnabled; this.stratumMiningEnabled = stratumMiningEnabled;
this.ethHashObservers = ethHashObservers; this.ethHashObservers = ethHashObservers;
ethHashObservers.forEach(observer -> observer.setSubmitWorkCallback(this::submitSolution)); ethHashObservers.forEach(observer -> observer.setSubmitWorkCallback(this::submitSolution));
this.epochCalculator = epochCalculator; this.epochCalculator = epochCalculator;
} }
public EthHashSolution solveFor(final EthHashSolverJob job) public PoWSolution solveFor(final PoWSolverJob job)
throws InterruptedException, ExecutionException { throws InterruptedException, ExecutionException {
currentJob = Optional.of(job); currentJob = Optional.of(job);
if (stratumMiningEnabled) { if (stratumMiningEnabled) {
@ -113,16 +108,15 @@ public class EthHashSolver {
private void findValidNonce() { private void findValidNonce() {
final Stopwatch operationTimer = Stopwatch.createStarted(); final Stopwatch operationTimer = Stopwatch.createStarted();
final EthHashSolverJob job = currentJob.get(); final PoWSolverJob job = currentJob.get();
long hashesExecuted = 0; long hashesExecuted = 0;
final byte[] hashBuffer = new byte[64];
for (final Long n : nonceGenerator) { for (final Long n : nonceGenerator) {
if (job.isDone()) { if (job.isDone()) {
return; return;
} }
final Optional<EthHashSolution> solution = testNonce(job.getInputs(), n, hashBuffer); final Optional<PoWSolution> solution = testNonce(job.getInputs(), n);
solution.ifPresent(job::solvedWith); solution.ifPresent(job::solvedWith);
hashesExecuted++; hashesExecuted++;
@ -132,24 +126,21 @@ public class EthHashSolver {
job.failed(new IllegalStateException("No valid nonce found.")); job.failed(new IllegalStateException("No valid nonce found."));
} }
private Optional<EthHashSolution> testNonce( private Optional<PoWSolution> testNonce(final PoWSolverInputs inputs, final long nonce) {
final EthHashSolverInputs inputs, final long nonce, final byte[] hashBuffer) { PoWSolution solution =
ethHasher.hash( poWHasher.hash(nonce, inputs.getBlockNumber(), epochCalculator, inputs.getPrePowHash());
hashBuffer, nonce, inputs.getBlockNumber(), epochCalculator, inputs.getPrePowHash()); final UInt256 x = UInt256.fromBytes(solution.getSolution());
final UInt256 x = UInt256.fromBytes(Bytes32.wrap(hashBuffer, 32));
if (x.compareTo(inputs.getTarget()) <= 0) { if (x.compareTo(inputs.getTarget()) <= 0) {
final Hash mixedHash = return Optional.of(solution);
Hash.wrap(Bytes32.leftPad(Bytes.wrap(hashBuffer).slice(0, Bytes32.SIZE)));
return Optional.of(new EthHashSolution(nonce, mixedHash, inputs.getPrePowHash()));
} }
return Optional.empty(); return Optional.empty();
} }
public void cancel() { public void cancel() {
currentJob.ifPresent(EthHashSolverJob::cancel); currentJob.ifPresent(PoWSolverJob::cancel);
} }
public Optional<EthHashSolverInputs> getWorkDefinition() { public Optional<PoWSolverInputs> getWorkDefinition() {
return currentJob.flatMap(job -> Optional.of(job.getInputs())); return currentJob.flatMap(job -> Optional.of(job.getInputs()));
} }
@ -160,22 +151,20 @@ public class EthHashSolver {
return Optional.of(hashesPerSecond); return Optional.of(hashesPerSecond);
} }
public boolean submitSolution(final EthHashSolution solution) { public boolean submitSolution(final PoWSolution solution) {
final Optional<EthHashSolverJob> jobSnapshot = currentJob; final Optional<PoWSolverJob> jobSnapshot = currentJob;
if (jobSnapshot.isEmpty()) { if (jobSnapshot.isEmpty()) {
LOG.debug("No current job, rejecting miner work"); LOG.debug("No current job, rejecting miner work");
return false; return false;
} }
final EthHashSolverJob job = jobSnapshot.get(); final PoWSolverJob job = jobSnapshot.get();
final EthHashSolverInputs inputs = job.getInputs(); final PoWSolverInputs inputs = job.getInputs();
if (!Arrays.equals(inputs.getPrePowHash(), solution.getPowHash())) { if (!inputs.getPrePowHash().equals(solution.getPowHash())) {
LOG.debug("Miner's solution does not match current job"); LOG.debug("Miner's solution does not match current job");
return false; return false;
} }
final byte[] hashBuffer = new byte[64]; final Optional<PoWSolution> calculatedSolution = testNonce(inputs, solution.getNonce());
final Optional<EthHashSolution> calculatedSolution =
testNonce(inputs, solution.getNonce(), hashBuffer);
if (calculatedSolution.isPresent()) { if (calculatedSolution.isPresent()) {
LOG.debug("Accepting a solution from a miner"); LOG.debug("Accepting a solution from a miner");

@ -14,17 +14,15 @@
*/ */
package org.hyperledger.besu.ethereum.mainnet; package org.hyperledger.besu.ethereum.mainnet;
import java.util.Arrays; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
public class EthHashSolverInputs { public class PoWSolverInputs {
private final UInt256 target; private final UInt256 target;
private final byte[] prePowHash; private final Bytes prePowHash;
private final long blockNumber; private final long blockNumber;
public EthHashSolverInputs( public PoWSolverInputs(final UInt256 target, final Bytes prePowHash, final long blockNumber) {
final UInt256 target, final byte[] prePowHash, final long blockNumber) {
this.target = target; this.target = target;
this.prePowHash = prePowHash; this.prePowHash = prePowHash;
this.blockNumber = blockNumber; this.blockNumber = blockNumber;
@ -34,7 +32,7 @@ public class EthHashSolverInputs {
return target; return target;
} }
public byte[] getPrePowHash() { public Bytes getPrePowHash() {
return prePowHash; return prePowHash;
} }
@ -44,11 +42,11 @@ public class EthHashSolverInputs {
@Override @Override
public String toString() { public String toString() {
return "EthHashSolverInputs{" return "PoWSolverInputs{"
+ "target=" + "target="
+ target + target
+ ", prePowHash=" + ", prePowHash="
+ Arrays.toString(prePowHash) + prePowHash
+ ", blockNumber=" + ", blockNumber="
+ blockNumber + blockNumber
+ '}'; + '}';

@ -233,7 +233,8 @@ public class ProtocolScheduleBuilder {
create(config.getAtlantisBlockNumber(), specFactory.atlantisDefinition()), create(config.getAtlantisBlockNumber(), specFactory.atlantisDefinition()),
create(config.getAghartaBlockNumber(), specFactory.aghartaDefinition()), create(config.getAghartaBlockNumber(), specFactory.aghartaDefinition()),
create(config.getPhoenixBlockNumber(), specFactory.phoenixDefinition()), create(config.getPhoenixBlockNumber(), specFactory.phoenixDefinition()),
create(config.getThanosBlockNumber(), specFactory.thanosDefinition())) create(config.getThanosBlockNumber(), specFactory.thanosDefinition()),
create(config.getEcip1049BlockNumber(), specFactory.ecip1049Definition()))
.stream() .stream()
.filter(Optional::isPresent) .filter(Optional::isPresent)
.map(Optional::get) .map(Optional::get)

@ -77,6 +77,8 @@ public class ProtocolSpec {
private final BadBlockManager badBlockManager; private final BadBlockManager badBlockManager;
private final Optional<PoWHasher> powHasher;
/** /**
* Creates a new protocol specification instance. * Creates a new protocol specification instance.
* *
@ -103,6 +105,7 @@ public class ProtocolSpec {
* @param eip1559 an {@link Optional} wrapping {@link EIP1559} manager class if appropriate. * @param eip1559 an {@link Optional} wrapping {@link EIP1559} manager class if appropriate.
* @param gasBudgetCalculator the gas budget calculator to use. * @param gasBudgetCalculator the gas budget calculator to use.
* @param badBlockManager the cache to use to keep invalid blocks * @param badBlockManager the cache to use to keep invalid blocks
* @param powHasher the proof-of-work hasher
*/ */
public ProtocolSpec( public ProtocolSpec(
final String name, final String name,
@ -127,7 +130,8 @@ public class ProtocolSpec {
final TransactionPriceCalculator transactionPriceCalculator, final TransactionPriceCalculator transactionPriceCalculator,
final Optional<EIP1559> eip1559, final Optional<EIP1559> eip1559,
final TransactionGasBudgetCalculator gasBudgetCalculator, final TransactionGasBudgetCalculator gasBudgetCalculator,
final BadBlockManager badBlockManager) { final BadBlockManager badBlockManager,
final Optional<PoWHasher> powHasher) {
this.name = name; this.name = name;
this.evm = evm; this.evm = evm;
this.transactionValidator = transactionValidator; this.transactionValidator = transactionValidator;
@ -151,6 +155,7 @@ public class ProtocolSpec {
this.eip1559 = eip1559; this.eip1559 = eip1559;
this.gasBudgetCalculator = gasBudgetCalculator; this.gasBudgetCalculator = gasBudgetCalculator;
this.badBlockManager = badBlockManager; this.badBlockManager = badBlockManager;
this.powHasher = powHasher;
} }
/** /**
@ -350,4 +355,13 @@ public class ProtocolSpec {
public BadBlockManager getBadBlocksManager() { public BadBlockManager getBadBlocksManager() {
return badBlockManager; return badBlockManager;
} }
/**
* Returns the Proof-of-Work hasher
*
* @return the Proof-of-Work hasher
*/
public Optional<PoWHasher> getPoWHasher() {
return powHasher;
}
} }

@ -72,6 +72,7 @@ public class ProtocolSpecBuilder {
private TransactionGasBudgetCalculator gasBudgetCalculator = private TransactionGasBudgetCalculator gasBudgetCalculator =
TransactionGasBudgetCalculator.frontier(); TransactionGasBudgetCalculator.frontier();
private BadBlockManager badBlockManager; private BadBlockManager badBlockManager;
private PoWHasher powHasher = PoWHasher.ETHASH_LIGHT;
public ProtocolSpecBuilder gasCalculator(final Supplier<GasCalculator> gasCalculatorBuilder) { public ProtocolSpecBuilder gasCalculator(final Supplier<GasCalculator> gasCalculatorBuilder) {
this.gasCalculatorBuilder = gasCalculatorBuilder; this.gasCalculatorBuilder = gasCalculatorBuilder;
@ -238,6 +239,11 @@ public class ProtocolSpecBuilder {
return this; return this;
} }
public ProtocolSpecBuilder powHasher(final PoWHasher powHasher) {
this.powHasher = powHasher;
return this;
}
public ProtocolSpec build(final ProtocolSchedule protocolSchedule) { public ProtocolSpec build(final ProtocolSchedule protocolSchedule) {
checkNotNull(gasCalculatorBuilder, "Missing gasCalculator"); checkNotNull(gasCalculatorBuilder, "Missing gasCalculator");
checkNotNull(evmBuilder, "Missing operation registry"); checkNotNull(evmBuilder, "Missing operation registry");
@ -364,7 +370,8 @@ public class ProtocolSpecBuilder {
transactionPriceCalculator, transactionPriceCalculator,
eip1559, eip1559,
gasBudgetCalculator, gasBudgetCalculator,
badBlockManager); badBlockManager,
Optional.ofNullable(powHasher));
} }
public interface TransactionProcessorBuilder { public interface TransactionProcessorBuilder {

@ -19,15 +19,14 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule; import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHasher; import org.hyperledger.besu.ethereum.mainnet.PoWHasher;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.math.BigInteger; import java.math.BigInteger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValidationRule { public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValidationRule {
@ -36,19 +35,16 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid
private static final BigInteger ETHASH_TARGET_UPPER_BOUND = BigInteger.valueOf(2).pow(256); private static final BigInteger ETHASH_TARGET_UPPER_BOUND = BigInteger.valueOf(2).pow(256);
static final EthHasher HASHER = new EthHasher.Light(); private final PoWHasher hasher;
private final EpochCalculator epochCalculator; private final EpochCalculator epochCalculator;
private final boolean includeBaseFee; private final boolean includeBaseFee;
public ProofOfWorkValidationRule(final EpochCalculator epochCalculator) {
this(epochCalculator, false);
}
public ProofOfWorkValidationRule( public ProofOfWorkValidationRule(
final EpochCalculator epochCalculator, final boolean includeBaseFee) { final EpochCalculator epochCalculator, final boolean includeBaseFee, final PoWHasher hasher) {
this.epochCalculator = epochCalculator; this.epochCalculator = epochCalculator;
this.includeBaseFee = includeBaseFee; this.includeBaseFee = includeBaseFee;
this.hasher = hasher;
} }
@Override @Override
@ -63,10 +59,9 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid
} }
} }
final byte[] hashBuffer = new byte[64];
final Hash headerHash = hashHeader(header); final Hash headerHash = hashHeader(header);
HASHER.hash( PoWSolution solution =
hashBuffer, header.getNonce(), header.getNumber(), epochCalculator, headerHash.toArray()); hasher.hash(header.getNonce(), header.getNumber(), epochCalculator, headerHash);
if (header.getDifficulty().isZero()) { if (header.getDifficulty().isZero()) {
LOG.info("Invalid block header: difficulty is 0"); LOG.info("Invalid block header: difficulty is 0");
@ -77,7 +72,7 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid
difficulty.equals(BigInteger.ONE) difficulty.equals(BigInteger.ONE)
? UInt256.MAX_VALUE ? UInt256.MAX_VALUE
: UInt256.valueOf(ETHASH_TARGET_UPPER_BOUND.divide(difficulty)); : UInt256.valueOf(ETHASH_TARGET_UPPER_BOUND.divide(difficulty));
final UInt256 result = UInt256.fromBytes(Bytes32.wrap(hashBuffer, 32)); final UInt256 result = UInt256.fromBytes(solution.getSolution());
if (result.compareTo(target) > 0) { if (result.compareTo(target) > 0) {
LOG.info( LOG.info(
"Invalid block header: the EthHash result {} was greater than the target {}.\n" "Invalid block header: the EthHash result {} was greater than the target {}.\n"
@ -88,8 +83,7 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid
return false; return false;
} }
final Hash mixedHash = final Hash mixedHash = solution.getMixHash();
Hash.wrap(Bytes32.leftPad(Bytes.wrap(hashBuffer).slice(0, Bytes32.SIZE)));
if (!header.getMixHash().equals(mixedHash)) { if (!header.getMixHash().equals(mixedHash)) {
LOG.info( LOG.info(
"Invalid block header: header mixed hash {} does not equal calculated mixed hash {}.\n" "Invalid block header: header mixed hash {} does not equal calculated mixed hash {}.\n"

@ -56,4 +56,36 @@ public class FixedProtocolScheduleTest {
.nextDifficulty(1, parentHeader, null)) .nextDifficulty(1, parentHeader, null))
.isEqualTo(FixedDifficultyCalculators.DEFAULT_DIFFICULTY); .isEqualTo(FixedDifficultyCalculators.DEFAULT_DIFFICULTY);
} }
@Test
public void reportedDifficultyForAllBlocksIsAFixedValueKeccak() {
final ProtocolSchedule schedule =
FixedDifficultyProtocolSchedule.create(GenesisConfigFile.ecip1049dev().getConfigOptions());
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
final BlockHeader parentHeader = headerBuilder.number(1).buildHeader();
assertThat(
schedule
.getByBlockNumber(0)
.getDifficultyCalculator()
.nextDifficulty(1, parentHeader, null))
.isEqualTo(10000);
assertThat(
schedule
.getByBlockNumber(500)
.getDifficultyCalculator()
.nextDifficulty(1, parentHeader, null))
.isEqualTo(10000);
assertThat(
schedule
.getByBlockNumber(500_000)
.getDifficultyCalculator()
.nextDifficulty(1, parentHeader, null))
.isEqualTo(10000);
}
} }

@ -14,19 +14,17 @@
*/ */
package org.hyperledger.besu.ethereum.mainnet; package org.hyperledger.besu.ethereum.mainnet;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.Arrays;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.assertj.core.api.Assertions;
import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.encoders.Hex;
import org.junit.Test; import org.junit.Test;
@ -50,32 +48,28 @@ public final class EthHashTest {
final long epoch = epochCalculator.cacheEpoch(blockNumber); final long epoch = epochCalculator.cacheEpoch(blockNumber);
final long datasetSize = EthHash.datasetSize(epoch); final long datasetSize = EthHash.datasetSize(epoch);
final long cacheSize = EthHash.cacheSize(epoch); final long cacheSize = EthHash.cacheSize(epoch);
Assertions.assertThat(datasetSize).isEqualTo(1157627776); assertThat(datasetSize).isEqualTo(1157627776);
Assertions.assertThat(cacheSize).isEqualTo(18087488); assertThat(cacheSize).isEqualTo(18087488);
final int[] cache = EthHash.mkCache((int) cacheSize, blockNumber, epochCalculator); final int[] cache = EthHash.mkCache((int) cacheSize, blockNumber, epochCalculator);
Assertions.assertThat( PoWSolution solution =
Hash.wrap( EthHash.hashimotoLight(datasetSize, cache, EthHash.hashHeader(header), header.getNonce());
Bytes32.wrap( assertThat(solution.getMixHash()).isEqualTo(header.getMixHash());
Arrays.copyOf(
EthHash.hashimotoLight(
datasetSize, cache, EthHash.hashHeader(header), header.getNonce()),
32))))
.isEqualTo(header.getMixHash());
} }
@Test @Test
public void hashimotoLightExample() { public void hashimotoLightExample() {
final int[] cache = EthHash.mkCache(1024, 1L, new EpochCalculator.DefaultEpochCalculator()); final int[] cache = EthHash.mkCache(1024, 1L, new EpochCalculator.DefaultEpochCalculator());
Assertions.assertThat( PoWSolution solution =
Hex.toHexString( EthHash.hashimotoLight(
EthHash.hashimotoLight( 32 * 1024,
32 * 1024, cache,
cache, Bytes.fromHexString("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f"),
Hex.decode("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f"), 0L);
0L)))
.isEqualTo( assertThat(solution.getSolution().toHexString())
"e4073cffaef931d37117cefd9afd27ea0f1cad6a981dd2605c4a1ac97c519800" .isEqualTo("0xd3539235ee2e6f8db665c0a72169f55b7f6c605712330b778ec3944f0eb5a557");
+ "d3539235ee2e6f8db665c0a72169f55b7f6c605712330b778ec3944f0eb5a557"); assertThat(solution.getMixHash().toHexString())
.isEqualTo("0xe4073cffaef931d37117cefd9afd27ea0f1cad6a981dd2605c4a1ac97c519800");
} }
@Test @Test
@ -86,7 +80,7 @@ public final class EthHashTest {
for (final int i : cache) { for (final int i : cache) {
buffer.putInt(i); buffer.putInt(i);
} }
Assertions.assertThat(Hex.toHexString(buffer.array())) assertThat(Hex.toHexString(buffer.array()))
.isEqualTo( .isEqualTo(
new StringBuilder() new StringBuilder()
.append( .append(

@ -0,0 +1,120 @@
/*
* 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.ethereum.mainnet;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.LogsBloomFilter;
import org.hyperledger.besu.ethereum.core.SealableBlockHeader;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
public class KeccakHasherTest {
private static class KeccakSealableBlockHeader extends SealableBlockHeader {
protected KeccakSealableBlockHeader(
final Hash parentHash,
final Hash ommersHash,
final Address coinbase,
final Hash stateRoot,
final Hash transactionsRoot,
final Hash receiptsRoot,
final LogsBloomFilter logsBloom,
final Difficulty difficulty,
final long number,
final long gasLimit,
final long gasUsed,
final long timestamp,
final Bytes extraData,
final Long baseFee) {
super(
parentHash,
ommersHash,
coinbase,
stateRoot,
transactionsRoot,
receiptsRoot,
logsBloom,
difficulty,
number,
gasLimit,
gasUsed,
timestamp,
extraData,
baseFee);
}
}
@Test
public void testHasher() {
PoWSolution solution =
KeccakHasher.KECCAK256.hash(
12345678L,
42L,
new EpochCalculator.DefaultEpochCalculator(),
Bytes.fromHexString(
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"));
assertThat(solution.getMixHash())
.isEqualTo(
Bytes.fromHexString(
"0xeffd292d6666dba4d6a4c221dd6d4b34b4ec3972a4cb0d944a8a8936cceca713"));
}
@Test
public void testHasherFromBlock() {
KeccakSealableBlockHeader header =
new KeccakSealableBlockHeader(
Hash.fromHexString(
"0xad22d4d8f0e94032cb32e86027e0a5533d945ed95088264e91dd71e4fbaebeda"),
Hash.fromHexString(
"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
Address.fromHexString("0x6A9ECfa04e99726eC105517AC7ae1aba550BeA6c"),
Hash.fromHexString(
"0x43e3325393fbc583a5a0b56e98073fb81e82d992b52406a79d662b690a4d2753"),
Hash.fromHexString(
"0x40c339f7715932ec591d8c0c588bacfaed9bddc7519a1e6e87cf45be639de810"),
Hash.fromHexString(
"0xeb1e644436f93be8a9938dfe598cb7fd729f9d201b6f7c0695bee883b3ea6a5b"),
LogsBloomFilter.fromHexString(
"0x0800012104000104c00400108000400000003000000040008400000002800100000a00000000000001010401040001000001002000000000020020080000240200000000012260010000084800420200040000100000030800802000112020001a200800020000000000500010100a00000000020401480000000010001048000011104800c002410000000010800000000014200040000400000000000000600020c00000004010080000000020100200000200000800001024c4000000080100004002004808000102920408810000002000008000000008000120400020008200d80000000010010000008028004000010000008220000200000100100800"),
Difficulty.of(3963642329L),
4156209L,
8000000L,
7987824L,
1538483791L,
Bytes.fromHexString("0xd88301080f846765746888676f312e31302e31856c696e7578"),
null);
PoWSolution result =
KeccakHasher.KECCAK256.hash(
Bytes.fromHexString("0xf245822d3412da7f").toLong(),
4156209L,
new EpochCalculator.DefaultEpochCalculator(),
EthHash.hashHeader(header));
assertThat(result.getMixHash())
.isEqualTo(
Bytes.fromHexString(
"0xd033f82e170ff16640e902fad569243c39bce9e4da948ccc298c541b34cd263b"));
}
}

@ -30,7 +30,7 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void validHeaderFrontier() throws Exception { public void validHeaderFrontier() throws Exception {
final BlockHeaderValidator headerValidator = final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create() MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER) .difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.build(); .build();
assertThat( assertThat(
@ -45,7 +45,7 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void validHeaderHomestead() throws Exception { public void validHeaderHomestead() throws Exception {
final BlockHeaderValidator headerValidator = final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create() MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD) .difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
.build(); .build();
assertThat( assertThat(
@ -60,7 +60,7 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void invalidParentHash() throws Exception { public void invalidParentHash() throws Exception {
final BlockHeaderValidator headerValidator = final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create() MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER) .difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.build(); .build();
assertThat( assertThat(
@ -75,7 +75,7 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void validHeaderByzantium() throws Exception { public void validHeaderByzantium() throws Exception {
final BlockHeaderValidator headerValidator = final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create() MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.BYZANTIUM) .difficultyCalculator(MainnetDifficultyCalculators.BYZANTIUM)
.build(); .build();
assertThat( assertThat(

@ -31,18 +31,20 @@ import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.junit.Test; import org.junit.Test;
public class EthHashSolverTest { public class PoWSolverTest {
@Test @Test
public void emptyHashRateAndWorkDefinitionIsReportedPriorToSolverStarting() { public void emptyHashRateAndWorkDefinitionIsReportedPriorToSolverStarting() {
final List<Long> noncesToTry = Arrays.asList(1L, 1L, 1L, 1L, 1L, 1L, 0L); final List<Long> noncesToTry = Arrays.asList(1L, 1L, 1L, 1L, 1L, 1L, 0L);
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
noncesToTry, noncesToTry,
new EthHasher.Light(), PoWHasher.ETHASH_LIGHT,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
@ -55,20 +57,25 @@ public class EthHashSolverTest {
public void hashRateIsProducedSuccessfully() throws InterruptedException, ExecutionException { public void hashRateIsProducedSuccessfully() throws InterruptedException, ExecutionException {
final List<Long> noncesToTry = Arrays.asList(1L, 1L, 1L, 1L, 1L, 1L, 0L); final List<Long> noncesToTry = Arrays.asList(1L, 1L, 1L, 1L, 1L, 1L, 0L);
final EthHasher hasher = mock(EthHasher.class); final PoWHasher hasher = mock(PoWHasher.class);
doAnswer( doAnswer(
invocation -> { invocation -> {
final Object[] args = invocation.getArguments(); final Object[] args = invocation.getArguments();
final byte[] headerHash = ((byte[]) args[0]); final long nonce = ((long) args[0]);
final long nonce = ((long) args[1]); final Bytes prePow = (Bytes) args[3];
headerHash[32] = (byte) (nonce & 0xFF); PoWSolution solution =
return null; new PoWSolution(
nonce,
Hash.wrap(Bytes32.leftPad(Bytes.EMPTY)),
Bytes32.rightPad(Bytes.of((byte) (nonce & 0xFF))),
prePow);
return solution;
}) })
.when(hasher) .when(hasher)
.hash(any(), anyLong(), anyLong(), any(), any()); .hash(anyLong(), anyLong(), any(), any());
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
noncesToTry, noncesToTry,
hasher, hasher,
false, false,
@ -76,8 +83,8 @@ public class EthHashSolverTest {
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
final Stopwatch operationTimer = Stopwatch.createStarted(); final Stopwatch operationTimer = Stopwatch.createStarted();
final EthHashSolverInputs inputs = new EthHashSolverInputs(UInt256.ONE, new byte[0], 5); final PoWSolverInputs inputs = new PoWSolverInputs(UInt256.ONE, Bytes.EMPTY, 5);
solver.solveFor(EthHashSolver.EthHashSolverJob.createFromInputs(inputs)); solver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(inputs));
final double runtimeSeconds = operationTimer.elapsed(TimeUnit.NANOSECONDS) / 1e9; final double runtimeSeconds = operationTimer.elapsed(TimeUnit.NANOSECONDS) / 1e9;
final long worstCaseHashesPerSecond = (long) (noncesToTry.size() / runtimeSeconds); final long worstCaseHashesPerSecond = (long) (noncesToTry.size() / runtimeSeconds);
@ -93,54 +100,57 @@ public class EthHashSolverTest {
public void ifInvokedTwiceProducesCorrectAnswerForSecondInvocation() public void ifInvokedTwiceProducesCorrectAnswerForSecondInvocation()
throws InterruptedException, ExecutionException { throws InterruptedException, ExecutionException {
final EthHashSolverInputs firstInputs = final PoWSolverInputs firstInputs =
new EthHashSolverInputs( new PoWSolverInputs(
UInt256.fromHexString( UInt256.fromHexString(
"0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"), "0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"),
new byte[] { Bytes.wrap(
15, -114, -104, 87, -95, -36, -17, 120, 52, 1, 124, 61, -6, -66, 78, -27, -57, 118, new byte[] {
-18, -64, -103, -91, -74, -121, 42, 91, -14, -98, 101, 86, -43, -51 15, -114, -104, 87, -95, -36, -17, 120, 52, 1, 124, 61, -6, -66, 78, -27, -57,
}, 118, -18, -64, -103, -91, -74, -121, 42, 91, -14, -98, 101, 86, -43, -51
}),
468); 468);
final EthHashSolution expectedFirstOutput = final PoWSolution expectedFirstOutput =
new EthHashSolution( new PoWSolution(
-6506032554016940193L, -6506032554016940193L,
Hash.fromHexString( Hash.fromHexString(
"0xc5e3c33c86d64d0641dd3c86e8ce4628fe0aac0ef7b4c087c5fcaa45d5046d90"), "0xc5e3c33c86d64d0641dd3c86e8ce4628fe0aac0ef7b4c087c5fcaa45d5046d90"),
null,
firstInputs.getPrePowHash()); firstInputs.getPrePowHash());
final EthHashSolverInputs secondInputs = final PoWSolverInputs secondInputs =
new EthHashSolverInputs( new PoWSolverInputs(
UInt256.fromHexString( UInt256.fromHexString(
"0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"), "0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"),
new byte[] { Bytes.wrap(
-62, 121, -81, -31, 55, -38, -68, 102, -32, 95, -94, -83, -3, -48, -122, -68, 14, new byte[] {
-125, -83, 84, -55, -23, -123, -57, -34, 25, -89, 23, 64, -9, -114, -3, -62, 121, -81, -31, 55, -38, -68, 102, -32, 95, -94, -83, -3, -48, -122, -68, 14,
}, -125, -83, 84, -55, -23, -123, -57, -34, 25, -89, 23, 64, -9, -114, -3,
}),
1); 1);
final EthHashSolution expectedSecondOutput = final PoWSolution expectedSecondOutput =
new EthHashSolution( new PoWSolution(
8855952212886464488L, 8855952212886464488L,
Hash.fromHexString( Hash.fromHexString(
"0x2adb0f375dd2d528689cb9e00473c3c9692737109d547130feafbefb2c6c5244"), "0x2adb0f375dd2d528689cb9e00473c3c9692737109d547130feafbefb2c6c5244"),
null,
firstInputs.getPrePowHash()); firstInputs.getPrePowHash());
// Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver. // Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver.
final EthHashSolver solver = final PoWSolver solver =
new EthHashSolver( new PoWSolver(
Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()), Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()),
new EthHasher.Light(), PoWHasher.ETHASH_LIGHT,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
EthHashSolution soln = PoWSolution soln = solver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(firstInputs));
solver.solveFor(EthHashSolver.EthHashSolverJob.createFromInputs(firstInputs));
assertThat(soln.getMixHash()).isEqualTo(expectedFirstOutput.getMixHash()); assertThat(soln.getMixHash()).isEqualTo(expectedFirstOutput.getMixHash());
soln = solver.solveFor(EthHashSolver.EthHashSolverJob.createFromInputs(secondInputs)); soln = solver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(secondInputs));
assertThat(soln.getMixHash()).isEqualTo(expectedSecondOutput.getMixHash()); assertThat(soln.getMixHash()).isEqualTo(expectedSecondOutput.getMixHash());
} }
} }

@ -23,6 +23,8 @@ import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.PoWHasher;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ValidationTestUtils; import org.hyperledger.besu.ethereum.mainnet.ValidationTestUtils;
@ -32,8 +34,6 @@ import java.math.BigInteger;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -51,7 +51,9 @@ public class ProofOfWorkValidationRuleTest {
throws IOException { throws IOException {
blockHeader = ValidationTestUtils.readHeader(parentBlockNum); blockHeader = ValidationTestUtils.readHeader(parentBlockNum);
parentHeader = ValidationTestUtils.readHeader(blockNum); parentHeader = ValidationTestUtils.readHeader(blockNum);
validationRule = new ProofOfWorkValidationRule(new EpochCalculator.DefaultEpochCalculator()); validationRule =
new ProofOfWorkValidationRule(
new EpochCalculator.DefaultEpochCalculator(), false, PoWHasher.ETHASH_LIGHT);
} }
@Parameters(name = "block {1}") @Parameters(name = "block {1}")
@ -89,20 +91,16 @@ public class ProofOfWorkValidationRuleTest {
.blockHeaderFunctions(mainnetBlockHashFunction()) .blockHeaderFunctions(mainnetBlockHashFunction())
.timestamp(1); .timestamp(1);
final BlockHeader preHeader = headerBuilder.buildBlockHeader(); final BlockHeader preHeader = headerBuilder.buildBlockHeader();
final byte[] hashBuffer = new byte[64];
final Hash headerHash = validationRule.hashHeader(preHeader); final Hash headerHash = validationRule.hashHeader(preHeader);
ProofOfWorkValidationRule.HASHER.hash( PoWSolution solution =
hashBuffer, PoWHasher.ETHASH_LIGHT.hash(
preHeader.getNonce(), preHeader.getNonce(),
preHeader.getNumber(), preHeader.getNumber(),
new EpochCalculator.DefaultEpochCalculator(), new EpochCalculator.DefaultEpochCalculator(),
headerHash.toArray()); headerHash);
final BlockHeader header = final BlockHeader header = headerBuilder.mixHash(solution.getMixHash()).buildBlockHeader();
headerBuilder
.mixHash(Hash.wrap(Bytes32.leftPad(Bytes.wrap(hashBuffer).slice(0, Bytes32.SIZE))))
.buildBlockHeader();
assertThat(validationRule.validate(header, parentHeader)).isTrue(); assertThat(validationRule.validate(header, parentHeader)).isTrue();
} }

@ -81,7 +81,8 @@ public class NoRewardProtocolScheduleWrapper implements ProtocolSchedule {
original.getTransactionPriceCalculator(), original.getTransactionPriceCalculator(),
original.getEip1559(), original.getEip1559(),
original.getGasBudgetCalculator(), original.getGasBudgetCalculator(),
original.getBadBlocksManager()); original.getBadBlocksManager(),
Optional.empty());
} }
@Override @Override

@ -43,11 +43,11 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolver;
import org.hyperledger.besu.ethereum.mainnet.EthHasher;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.PoWHasher;
import org.hyperledger.besu.ethereum.mainnet.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
@ -72,12 +72,9 @@ import org.apache.tuweni.bytes.Bytes;
public class RetestethContext { public class RetestethContext {
private static final Logger LOG = LogManager.getLogger(); private static final Logger LOG = LogManager.getLogger();
private static final EthHasher NO_WORK_HASHER = private static final PoWHasher NO_WORK_HASHER =
(final byte[] buffer, (final long nonce, final long number, EpochCalculator epochCalc, final Bytes headerHash) ->
final long nonce, null;
final long number,
EpochCalculator epochCalc,
final byte[] headerHash) -> {};
private final ReentrantLock contextLock = new ReentrantLock(); private final ReentrantLock contextLock = new ReentrantLock();
private Address coinbase; private Address coinbase;
@ -93,7 +90,7 @@ public class RetestethContext {
private TransactionPool transactionPool; private TransactionPool transactionPool;
private EthScheduler ethScheduler; private EthScheduler ethScheduler;
private EthHashSolver ethHashSolver; private PoWSolver poWSolver;
public boolean resetContext( public boolean resetContext(
final String genesisConfigString, final String sealEngine, final Optional<Long> clockTime) { final String genesisConfigString, final String sealEngine, final Optional<Long> clockTime) {
@ -161,17 +158,17 @@ public class RetestethContext {
: HeaderValidationMode.FULL; : HeaderValidationMode.FULL;
final Iterable<Long> nonceGenerator = new IncrementingNonceGenerator(0); final Iterable<Long> nonceGenerator = new IncrementingNonceGenerator(0);
ethHashSolver = poWSolver =
("NoProof".equals(sealengine) || "NoReward".equals(sealEngine)) ("NoProof".equals(sealengine) || "NoReward".equals(sealEngine))
? new EthHashSolver( ? new PoWSolver(
nonceGenerator, nonceGenerator,
NO_WORK_HASHER, NO_WORK_HASHER,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()) new EpochCalculator.DefaultEpochCalculator())
: new EthHashSolver( : new PoWSolver(
nonceGenerator, nonceGenerator,
new EthHasher.Light(), PoWHasher.ETHASH_LIGHT,
false, false,
Subscribers.none(), Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator()); new EpochCalculator.DefaultEpochCalculator());
@ -288,7 +285,7 @@ public class RetestethContext {
return retestethClock; return retestethClock;
} }
public EthHashSolver getEthHashSolver() { public PoWSolver getEthHashSolver() {
return ethHashSolver; return poWSolver;
} }
} }

@ -19,8 +19,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashBlockCreator;
import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator; import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator;
import org.hyperledger.besu.ethereum.blockcreation.PoWBlockCreator;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.BlockImporter;
@ -60,8 +60,8 @@ public class TestMineBlocks implements JsonRpcMethod {
final ProtocolContext protocolContext = context.getProtocolContext(); final ProtocolContext protocolContext = context.getProtocolContext();
final MutableBlockchain blockchain = context.getBlockchain(); final MutableBlockchain blockchain = context.getBlockchain();
final HeaderValidationMode headerValidationMode = context.getHeaderValidationMode(); final HeaderValidationMode headerValidationMode = context.getHeaderValidationMode();
final EthHashBlockCreator blockCreator = final PoWBlockCreator blockCreator =
new EthHashBlockCreator( new PoWBlockCreator(
context.getCoinbase(), context.getCoinbase(),
header -> context.getExtraData(), header -> context.getExtraData(),
context.getTransactionPool().getPendingTransactions(), context.getTransactionPool().getPendingTransactions(),

@ -19,16 +19,15 @@ import static org.apache.logging.log4j.LogManager.getLogger;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed; import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.function.Function; import java.util.function.Function;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
@ -49,18 +48,18 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
private static final JsonMapper mapper = new JsonMapper(); private static final JsonMapper mapper = new JsonMapper();
private final MiningCoordinator miningCoordinator; private final MiningCoordinator miningCoordinator;
private EthHashSolverInputs currentInput; private PoWSolverInputs currentInput;
private Function<EthHashSolution, Boolean> submitCallback; private Function<PoWSolution, Boolean> submitCallback;
private final EpochCalculator epochCalculator; private final EpochCalculator epochCalculator;
public Stratum1EthProxyProtocol(final MiningCoordinator miningCoordinator) { public Stratum1EthProxyProtocol(final MiningCoordinator miningCoordinator) {
if (!(miningCoordinator instanceof EthHashMiningCoordinator)) { if (!(miningCoordinator instanceof PoWMiningCoordinator)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Stratum1 Proxies require an EthHashMiningCoordinator not " "Stratum1 Proxies require an PoWMiningCoordinator not "
+ ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName())); + ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName()));
} }
this.miningCoordinator = miningCoordinator; this.miningCoordinator = miningCoordinator;
this.epochCalculator = ((EthHashMiningCoordinator) miningCoordinator).getEpochCalculator(); this.epochCalculator = ((PoWMiningCoordinator) miningCoordinator).getEpochCalculator();
} }
@Override @Override
@ -91,7 +90,7 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
private void sendNewWork(final StratumConnection conn, final Object id) { private void sendNewWork(final StratumConnection conn, final Object id) {
byte[] dagSeed = DirectAcyclicGraphSeed.dagSeed(currentInput.getBlockNumber(), epochCalculator); byte[] dagSeed = DirectAcyclicGraphSeed.dagSeed(currentInput.getBlockNumber(), epochCalculator);
final String[] result = { final String[] result = {
"0x" + BaseEncoding.base16().lowerCase().encode(currentInput.getPrePowHash()), currentInput.getPrePowHash().toHexString(),
"0x" + BaseEncoding.base16().lowerCase().encode(dagSeed), "0x" + BaseEncoding.base16().lowerCase().encode(dagSeed),
currentInput.getTarget().toHexString() currentInput.getTarget().toHexString()
}; };
@ -127,12 +126,13 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
throws IOException { throws IOException {
LOG.debug("Miner submitted solution {}", req); LOG.debug("Miner submitted solution {}", req);
boolean result = false; boolean result = false;
final EthHashSolution solution = final PoWSolution solution =
new EthHashSolution( new PoWSolution(
Bytes.fromHexString(req.getRequiredParameter(0, String.class)).getLong(0), Bytes.fromHexString(req.getRequiredParameter(0, String.class)).getLong(0),
req.getRequiredParameter(2, Hash.class), req.getRequiredParameter(2, Hash.class),
Bytes.fromHexString(req.getRequiredParameter(1, String.class)).toArrayUnsafe()); null,
if (Arrays.equals(currentInput.getPrePowHash(), solution.getPowHash())) { Bytes.fromHexString(req.getRequiredParameter(1, String.class)));
if (currentInput.getPrePowHash().equals(solution.getPowHash())) {
result = submitCallback.apply(solution); result = submitCallback.apply(solution);
} }
@ -141,12 +141,12 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
} }
@Override @Override
public void setCurrentWorkTask(final EthHashSolverInputs input) { public void setCurrentWorkTask(final PoWSolverInputs input) {
this.currentInput = input; this.currentInput = input;
} }
@Override @Override
public void setSubmitCallback(final Function<EthHashSolution, Boolean> submitSolutionCallback) { public void setSubmitCallback(final Function<PoWSolution, Boolean> submitSolutionCallback) {
this.submitCallback = submitSolutionCallback; this.submitCallback = submitSolutionCallback;
} }
} }

@ -19,18 +19,17 @@ import static org.apache.logging.log4j.LogManager.getLogger;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed; import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.io.IOException; import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.function.Function; import java.util.function.Function;
@ -60,8 +59,8 @@ public class Stratum1Protocol implements StratumProtocol {
private final MiningCoordinator miningCoordinator; private final MiningCoordinator miningCoordinator;
private final String extranonce; private final String extranonce;
private EthHashSolverInputs currentInput; private PoWSolverInputs currentInput;
private Function<EthHashSolution, Boolean> submitCallback; private Function<PoWSolution, Boolean> submitCallback;
private final Supplier<String> jobIdSupplier; private final Supplier<String> jobIdSupplier;
private final Supplier<String> subscriptionIdCreator; private final Supplier<String> subscriptionIdCreator;
private final List<StratumConnection> activeConnections = new ArrayList<>(); private final List<StratumConnection> activeConnections = new ArrayList<>();
@ -83,16 +82,16 @@ public class Stratum1Protocol implements StratumProtocol {
final MiningCoordinator miningCoordinator, final MiningCoordinator miningCoordinator,
final Supplier<String> jobIdSupplier, final Supplier<String> jobIdSupplier,
final Supplier<String> subscriptionIdCreator) { final Supplier<String> subscriptionIdCreator) {
if (!(miningCoordinator instanceof EthHashMiningCoordinator)) { if (!(miningCoordinator instanceof PoWMiningCoordinator)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Stratum1 requires an EthHashMiningCoordinator not " "Stratum1 requires an PoWMiningCoordinator not "
+ ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName())); + ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName()));
} }
this.extranonce = extranonce; this.extranonce = extranonce;
this.miningCoordinator = miningCoordinator; this.miningCoordinator = miningCoordinator;
this.jobIdSupplier = jobIdSupplier; this.jobIdSupplier = jobIdSupplier;
this.subscriptionIdCreator = subscriptionIdCreator; this.subscriptionIdCreator = subscriptionIdCreator;
this.epochCalculator = ((EthHashMiningCoordinator) miningCoordinator).getEpochCalculator(); this.epochCalculator = ((PoWMiningCoordinator) miningCoordinator).getEpochCalculator();
} }
@Override @Override
@ -180,12 +179,13 @@ public class Stratum1Protocol implements StratumProtocol {
throws IOException { throws IOException {
LOG.debug("Miner submitted solution {}", message); LOG.debug("Miner submitted solution {}", message);
boolean result = false; boolean result = false;
final EthHashSolution solution = final PoWSolution solution =
new EthHashSolution( new PoWSolution(
Bytes.fromHexString(message.getRequiredParameter(2, String.class)).getLong(0), Bytes.fromHexString(message.getRequiredParameter(2, String.class)).getLong(0),
Hash.fromHexString(message.getRequiredParameter(4, String.class)), Hash.fromHexString(message.getRequiredParameter(4, String.class)),
Bytes.fromHexString(message.getRequiredParameter(3, String.class)).toArrayUnsafe()); null,
if (Arrays.equals(currentInput.getPrePowHash(), solution.getPowHash())) { Bytes.fromHexString(message.getRequiredParameter(3, String.class)));
if (currentInput.getPrePowHash().equals(solution.getPowHash())) {
result = submitCallback.apply(solution); result = submitCallback.apply(solution);
} }
@ -205,7 +205,7 @@ public class Stratum1Protocol implements StratumProtocol {
} }
@Override @Override
public void setCurrentWorkTask(final EthHashSolverInputs input) { public void setCurrentWorkTask(final PoWSolverInputs input) {
this.currentInput = input; this.currentInput = input;
LOG.debug("Sending new work to miners: {}", input); LOG.debug("Sending new work to miners: {}", input);
for (StratumConnection conn : activeConnections) { for (StratumConnection conn : activeConnections) {
@ -214,7 +214,7 @@ public class Stratum1Protocol implements StratumProtocol {
} }
@Override @Override
public void setSubmitCallback(final Function<EthHashSolution, Boolean> submitSolutionCallback) { public void setSubmitCallback(final Function<PoWSolution, Boolean> submitSolutionCallback) {
this.submitCallback = submitSolutionCallback; this.submitCallback = submitSolutionCallback;
} }
} }

@ -17,8 +17,8 @@ package org.hyperledger.besu.ethereum.stratum;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.io.IOException; import java.io.IOException;
import java.util.function.Function; import java.util.function.Function;
@ -63,9 +63,9 @@ public interface StratumProtocol {
* *
* @param input the new proof-of-work job to send to miners * @param input the new proof-of-work job to send to miners
*/ */
void setCurrentWorkTask(EthHashSolverInputs input); void setCurrentWorkTask(PoWSolverInputs input);
void setSubmitCallback(Function<EthHashSolution, Boolean> submitSolutionCallback); void setSubmitCallback(Function<PoWSolution, Boolean> submitSolutionCallback);
default void handleHashrateSubmit( default void handleHashrateSubmit(
final JsonMapper mapper, final JsonMapper mapper,

@ -17,9 +17,9 @@ package org.hyperledger.besu.ethereum.stratum;
import static org.apache.logging.log4j.LogManager.getLogger; import static org.apache.logging.log4j.LogManager.getLogger;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.chain.EthHashObserver; import org.hyperledger.besu.ethereum.chain.PoWObserver;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution; import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger;
* TCP server allowing miners to connect to the client over persistent TCP connections, using the * TCP server allowing miners to connect to the client over persistent TCP connections, using the
* various Stratum protocols. * various Stratum protocols.
*/ */
public class StratumServer implements EthHashObserver { public class StratumServer implements PoWObserver {
private static final Logger logger = getLogger(); private static final Logger logger = getLogger();
@ -118,19 +118,18 @@ public class StratumServer implements EthHashObserver {
} }
@Override @Override
public void newJob(final EthHashSolverInputs ethHashSolverInputs) { public void newJob(final PoWSolverInputs poWSolverInputs) {
if (!started.get()) { if (!started.get()) {
logger.debug("Discarding {} as stratum server is not started", ethHashSolverInputs); logger.debug("Discarding {} as stratum server is not started", poWSolverInputs);
return; return;
} }
for (StratumProtocol protocol : protocols) { for (StratumProtocol protocol : protocols) {
protocol.setCurrentWorkTask(ethHashSolverInputs); protocol.setCurrentWorkTask(poWSolverInputs);
} }
} }
@Override @Override
public void setSubmitWorkCallback( public void setSubmitWorkCallback(final Function<PoWSolution, Boolean> submitSolutionCallback) {
final Function<EthHashSolution, Boolean> submitSolutionCallback) {
for (StratumProtocol protocol : protocols) { for (StratumProtocol protocol : protocols) {
protocol.setSubmitCallback(submitSolutionCallback); protocol.setSubmitCallback(submitSolutionCallback);
} }

@ -17,8 +17,8 @@ package org.hyperledger.besu.ethereum.stratum;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -34,7 +34,7 @@ public class Stratum1EthProxyProtocolTest {
@Before @Before
public void setUp() { public void setUp() {
MiningCoordinator coordinator = mock(EthHashMiningCoordinator.class); MiningCoordinator coordinator = mock(PoWMiningCoordinator.class);
protocol = new Stratum1EthProxyProtocol(coordinator); protocol = new Stratum1EthProxyProtocol(coordinator);
receivedMessages = new ArrayList<>(); receivedMessages = new ArrayList<>();
conn = new StratumConnection(new StratumProtocol[0], null, receivedMessages::add); conn = new StratumConnection(new StratumProtocol[0], null, receivedMessages::add);

@ -17,9 +17,9 @@ package org.hyperledger.besu.ethereum.stratum;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs; import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -34,11 +34,11 @@ import org.mockito.Mockito;
public class StratumConnectionTest { public class StratumConnectionTest {
@Mock EthHashMiningCoordinator miningCoordinator; @Mock PoWMiningCoordinator miningCoordinator;
@Before @Before
public void setup() { public void setup() {
miningCoordinator = Mockito.mock(EthHashMiningCoordinator.class); miningCoordinator = Mockito.mock(PoWMiningCoordinator.class);
when(miningCoordinator.getEpochCalculator()) when(miningCoordinator.getEpochCalculator())
.thenReturn(new EpochCalculator.DefaultEpochCalculator()); .thenReturn(new EpochCalculator.DefaultEpochCalculator());
} }
@ -128,8 +128,7 @@ public class StratumConnectionTest {
assertThat(called.get()).isFalse(); assertThat(called.get()).isFalse();
// now send work without waiting. // now send work without waiting.
protocol.setCurrentWorkTask( protocol.setCurrentWorkTask(
new EthHashSolverInputs( new PoWSolverInputs(UInt256.valueOf(3), Bytes.fromHexString("deadbeef"), 42));
UInt256.valueOf(3), Bytes.fromHexString("deadbeef").toArrayUnsafe(), 42));
assertThat(message.get()) assertThat(message.get())
.isEqualTo( .isEqualTo(

Loading…
Cancel
Save