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)
* 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
* add support for keccak mining and a ecip1049_dev network [\#1882](https://github.com/hyperledger/besu/pull/1882)
### Bug Fixes
* 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)

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

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

@ -14,6 +14,7 @@
*/
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.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.core.MiningParameters;
@ -52,6 +53,7 @@ public class BesuNodeConfiguration {
private final boolean isDnsEnabled;
private final Optional<PrivacyParameters> privacyParameters;
private final List<String> runCommand;
private final NetworkName network;
BesuNodeConfiguration(
final String name,
@ -63,6 +65,7 @@ public class BesuNodeConfiguration {
final Optional<PermissioningConfiguration> permissioningConfiguration,
final Optional<String> keyFilePath,
final boolean devMode,
final NetworkName network,
final GenesisConfigurationProvider genesisConfigProvider,
final boolean p2pEnabled,
final NetworkingConfiguration networkingConfiguration,
@ -86,6 +89,7 @@ public class BesuNodeConfiguration {
this.keyFilePath = keyFilePath;
this.dataPath = dataPath;
this.devMode = devMode;
this.network = network;
this.genesisConfigProvider = genesisConfigProvider;
this.p2pEnabled = p2pEnabled;
this.networkingConfiguration = networkingConfiguration;
@ -193,4 +197,8 @@ public class BesuNodeConfiguration {
public List<String> getRunCommand() {
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 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.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
@ -55,6 +56,7 @@ public class BesuNodeConfigurationBuilder {
private boolean discoveryEnabled = true;
private boolean bootnodeEligible = true;
private boolean revertReasonEnabled = false;
private NetworkName network = null;
private boolean secp256K1Native = false;
private boolean altbn128Native = false;
private final List<String> plugins = new ArrayList<>();
@ -165,6 +167,11 @@ public class BesuNodeConfigurationBuilder {
return this;
}
public BesuNodeConfigurationBuilder network(final NetworkName network) {
this.network = network;
return this;
}
public BesuNodeConfigurationBuilder webSocketEnabled() {
final WebSocketConfiguration config = WebSocketConfiguration.createDefault();
config.setEnabled(true);
@ -295,6 +302,7 @@ public class BesuNodeConfigurationBuilder {
permissioningConfiguration,
Optional.ofNullable(keyFilePath),
devMode,
network,
genesisConfigProvider,
p2pEnabled,
networkingConfiguration,

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

@ -94,6 +94,7 @@ public class PrivacyNode implements AutoCloseable {
besuConfig.getPermissioningConfiguration(),
besuConfig.getKeyFilePath(),
besuConfig.isDevMode(),
besuConfig.getNetwork(),
besuConfig.getGenesisConfigProvider(),
besuConfig.isP2pEnabled(),
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.ChainData;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.core.Address;
@ -119,9 +120,9 @@ public class JsonBlockImporter {
final BlockData blockData,
final GenesisConfigOptions genesisConfig) {
// Some fields can only be configured for ethash
if (genesisConfig.isEthHash()) {
// For simplicity only set these for ethash. Other consensus algorithms use these fields for
// special purposes or ignore them
if (genesisConfig.getPowAlgorithm() != PowAlgorithm.UNSUPPORTED) {
// For simplicity only set these for PoW consensus algorithms.
// Other consensus algorithms use these fields for special purposes or ignore them.
miner.setCoinbase(blockData.getCoinbase().orElse(Address.ZERO));
miner.setExtraData(blockData.getExtraData().orElse(Bytes.EMPTY));
} 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 GOERLI_NETWORK_ID = BigInteger.valueOf(5);
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 KOTTI_NETWORK_ID = BigInteger.valueOf(6);
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 GOERLI_GENESIS = "/goerli.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 KOTTI_GENESIS = "/kotti.json";
private static final String MORDOR_GENESIS = "/mordor.json";
@ -154,6 +156,9 @@ public class EthNetworkConfig {
case CLASSIC:
return new EthNetworkConfig(
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:
return new EthNetworkConfig(
jsonConfig(KOTTI_GENESIS), KOTTI_NETWORK_ID, KOTTI_BOOTSTRAP_NODES, null);
@ -194,6 +199,8 @@ public class EthNetworkConfig {
return jsonConfig(GOERLI_GENESIS);
case DEV:
return jsonConfig(DEV_GENESIS);
case ECIP1049_DEV:
return jsonConfig(DEV_ECIP1049_GENESIS);
case CLASSIC:
return jsonConfig(CLASSIC_GENESIS);
case KOTTI:

@ -23,5 +23,6 @@ public enum NetworkName {
CLASSIC,
KOTTI,
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.config.GenesisConfigFile;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi;
@ -191,7 +192,7 @@ public class BesuController implements java.io.Closeable {
genesisConfig.getConfigOptions(genesisConfigOverrides);
final BesuControllerBuilder builder;
if (configOptions.isEthHash()) {
if (configOptions.getPowAlgorithm() != PowAlgorithm.UNSUPPORTED) {
builder = new MainnetBesuControllerBuilder();
} else if (configOptions.isIbft2()) {
builder = new IbftBesuControllerBuilder();

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

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

@ -25,6 +25,8 @@ public interface GenesisConfigOptions {
boolean isEthHash();
boolean isKeccak256();
boolean isIbftLegacy();
boolean isIbft2();
@ -43,6 +45,8 @@ public interface GenesisConfigOptions {
EthashConfigOptions getEthashConfigOptions();
Keccak256ConfigOptions getKeccak256ConfigOptions();
OptionalLong getHomesteadBlockNumber();
OptionalLong getDaoForkBlock();
@ -173,6 +177,16 @@ public interface GenesisConfigOptions {
*/
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();
OptionalInt getContractSizeLimit();
@ -209,4 +223,11 @@ public interface GenesisConfigOptions {
* @return block number to activate Quorum Permissioning
*/
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 {
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 IBFT2_CONFIG_KEY = "ibft2";
private static final String QBFT_CONFIG_KEY = "qbft";
@ -94,6 +95,8 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
public String getConsensusEngine() {
if (isEthHash()) {
return ETHASH_CONFIG_KEY;
} else if (isKeccak256()) {
return KECCAK256_CONFIG_KEY;
} else if (isIbft2()) {
return IBFT2_CONFIG_KEY;
} else if (isIbftLegacy()) {
@ -112,6 +115,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return configRoot.has(ETHASH_CONFIG_KEY);
}
@Override
public boolean isKeccak256() {
return configRoot.has(KECCAK256_CONFIG_KEY);
}
@Override
public boolean isIbftLegacy() {
return configRoot.has(IBFT_LEGACY_CONFIG_KEY);
@ -161,6 +169,13 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
.orElse(EthashConfigOptions.DEFAULT);
}
@Override
public Keccak256ConfigOptions getKeccak256ConfigOptions() {
return JsonUtil.getObjectNode(configRoot, KECCAK256_CONFIG_KEY)
.map(Keccak256ConfigOptions::new)
.orElse(Keccak256ConfigOptions.DEFAULT);
}
@Override
public TransitionsConfigOptions getTransitions() {
return transitions;
@ -289,6 +304,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return getOptionalLong("thanosblock");
}
@Override
public OptionalLong getEcip1049BlockNumber() {
return getOptionalLong("ecip1049block");
}
@Override
public Optional<BigInteger> getChainId() {
return getOptionalBigInteger("chainid");
@ -319,6 +339,13 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return getOptionalLong("qip714block");
}
@Override
public PowAlgorithm getPowAlgorithm() {
return isEthHash()
? PowAlgorithm.ETHASH
: isKeccak256() ? PowAlgorithm.KECCAK256 : PowAlgorithm.UNSUPPORTED;
}
@Override
public Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
@ -358,6 +385,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l));
getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l));
getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l));
getEcip1049BlockNumber().ifPresent(l -> builder.put("ecip1049Block", l));
getEIP1559BlockNumber().ifPresent(l -> builder.put("eip1559Block", l));
getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l));
@ -370,6 +398,9 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
if (isEthHash()) {
builder.put("ethash", getEthashConfigOptions().asMap());
}
if (isKeccak256()) {
builder.put("keccak256", getKeccak256ConfigOptions().asMap());
}
if (isIbftLegacy()) {
builder.put("ibft", getIbftLegacyConfigOptions().asMap());
}
@ -451,7 +482,8 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
getAtlantisBlockNumber(),
getAghartaBlockNumber(),
getPhoenixBlockNumber(),
getThanosBlockNumber());
getThanosBlockNumber(),
getEcip1049BlockNumber());
return forkBlockNumbers
.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 phoenixBlockNumber = OptionalLong.empty();
private OptionalLong thanosBlockNumber = OptionalLong.empty();
private OptionalLong ecip1049BlockNumber = OptionalLong.empty();
private Optional<BigInteger> chainId = Optional.empty();
private OptionalInt contractSizeLimit = OptionalInt.empty();
private OptionalInt stackSizeLimit = OptionalInt.empty();
@ -64,6 +65,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return true;
}
@Override
public boolean isKeccak256() {
return false;
}
@Override
public boolean isIbftLegacy() {
return false;
@ -104,6 +110,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return EthashConfigOptions.DEFAULT;
}
@Override
public Keccak256ConfigOptions getKeccak256ConfigOptions() {
return Keccak256ConfigOptions.DEFAULT;
}
@Override
public OptionalLong getHomesteadBlockNumber() {
return homesteadBlockNumber;
@ -205,6 +216,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return thanosBlockNumber;
}
@Override
public OptionalLong getEcip1049BlockNumber() {
return ecip1049BlockNumber;
}
@Override
public OptionalInt getContractSizeLimit() {
return contractSizeLimit;
@ -262,6 +278,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l));
getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l));
getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l));
getEcip1049BlockNumber().ifPresent(l -> builder.put("ecip1049Block", l));
getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l));
getEvmStackSize().ifPresent(l -> builder.put("evmStackSize", l));
@ -271,6 +288,9 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
if (isEthHash()) {
builder.put("ethash", getEthashConfigOptions().asMap());
}
if (isKeccak256()) {
builder.put("keccak256", getKeccak256ConfigOptions().asMap());
}
if (isIbftLegacy()) {
builder.put("ibft", getIbftLegacyConfigOptions().asMap());
}
@ -295,6 +315,13 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return OptionalLong.empty();
}
@Override
public PowAlgorithm getPowAlgorithm() {
return isEthHash()
? PowAlgorithm.ETHASH
: isKeccak256() ? PowAlgorithm.KECCAK256 : PowAlgorithm.UNSUPPORTED;
}
@Override
public List<Long> getForks() {
return Collections.emptyList();
@ -395,6 +422,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return this;
}
public StubGenesisConfigOptions ecip1049(final long blockNumber) {
ecip1049BlockNumber = OptionalLong.of(blockNumber);
return this;
}
public StubGenesisConfigOptions chainId(final BigInteger chainId) {
this.chainId = Optional.ofNullable(chainId);
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");
}
@Test
public void shouldUseKeccak256WhenKeccak256InConfig() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("keccak256", emptyMap()));
assertThat(config.isKeccak256()).isTrue();
assertThat(config.getConsensusEngine()).isEqualTo("keccak256");
}
@Test
public void shouldNotUseEthHashIfEthHashNotPresent() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap());
assertThat(config.isEthHash()).isFalse();
}
@Test
public void shouldNotUseKeccak256IfEthHashNotPresent() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap());
assertThat(config.isKeccak256()).isFalse();
}
@Test
public void shouldUseIbftLegacyWhenIbftInConfig() {
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
public void shouldNotReturnEmptyOptionalWhenBlockNumberNotSpecified() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap());
@ -198,6 +218,7 @@ public class GenesisConfigOptionsTest {
assertThat(config.getIstanbulBlockNumber()).isEmpty();
assertThat(config.getMuirGlacierBlockNumber()).isEmpty();
assertThat(config.getBerlinBlockNumber()).isEmpty();
assertThat(config.getEcip1049BlockNumber()).isEmpty();
}
@Test

@ -24,8 +24,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockScheduler;
import org.hyperledger.besu.ethereum.blockcreation.AbstractMinerExecutor;
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.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters;
@ -72,7 +72,7 @@ public class CliqueMinerExecutor extends AbstractMinerExecutor<CliqueBlockMiner>
@Override
public CliqueBlockMiner createMiner(
final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers,
final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) {
final Function<BlockHeader, CliqueBlockCreator> blockCreator =
(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.websocket.WebSocketConfiguration;
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.core.Block;
import org.hyperledger.besu.ethereum.core.BlockImporter;
@ -90,7 +90,7 @@ public class JsonRpcTestMethodsFactory {
final P2PNetwork peerDiscovery = mock(P2PNetwork.class);
final EthPeers ethPeers = mock(EthPeers.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 Optional<AccountLocalConfigPermissioningController> accountWhitelistController =
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.JsonRpcSuccessResponse;
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.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed;
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;
@ -42,8 +42,8 @@ public class EthGetWork implements JsonRpcMethod {
public EthGetWork(final MiningCoordinator miner) {
this.miner = miner;
if (miner instanceof EthHashMiningCoordinator) {
this.epochCalculator = ((EthHashMiningCoordinator) miner).getEpochCalculator();
if (miner instanceof PoWMiningCoordinator) {
this.epochCalculator = ((PoWMiningCoordinator) miner).getEpochCalculator();
} else {
this.epochCalculator = new EpochCalculator.DefaultEpochCalculator();
}
@ -56,13 +56,13 @@ public class EthGetWork implements JsonRpcMethod {
@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
final Optional<EthHashSolverInputs> solver = miner.getWorkDefinition();
final Optional<PoWSolverInputs> solver = miner.getWorkDefinition();
if (solver.isPresent()) {
final EthHashSolverInputs rawResult = solver.get();
final PoWSolverInputs rawResult = solver.get();
final byte[] dagSeed =
DirectAcyclicGraphSeed.dagSeed(rawResult.getBlockNumber(), epochCalculator);
final String[] result = {
"0x" + BaseEncoding.base16().lowerCase().encode(rawResult.getPrePowHash()),
rawResult.getPrePowHash().toHexString(),
"0x" + BaseEncoding.base16().lowerCase().encode(dagSeed),
rawResult.getTarget().toHexString(),
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.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional;
@ -48,14 +48,14 @@ public class EthSubmitWork implements JsonRpcMethod {
@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
final Optional<EthHashSolverInputs> solver = miner.getWorkDefinition();
final Optional<PoWSolverInputs> solver = miner.getWorkDefinition();
if (solver.isPresent()) {
final EthHashSolution solution =
new EthHashSolution(
final PoWSolution solution =
new PoWSolution(
Bytes.fromHexString(requestContext.getRequiredParameter(0, String.class)).getLong(0),
requestContext.getRequiredParameter(2, Hash.class),
Bytes.fromHexString(requestContext.getRequiredParameter(1, String.class))
.toArrayUnsafe());
null,
Bytes.fromHexString(requestContext.getRequiredParameter(1, String.class)));
final boolean result = miner.submitWork(solution);
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result);
} else {

@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.graphql;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
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.MutableBlockchain;
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));
Mockito.when(synchronizerMock.getSyncStatus()).thenReturn(Optional.of(status));
final EthHashMiningCoordinator miningCoordinatorMock =
Mockito.mock(EthHashMiningCoordinator.class);
final PoWMiningCoordinator miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class);
Mockito.when(miningCoordinatorMock.getMinTransactionGasPrice()).thenReturn(Wei.of(16));
final TransactionPool transactionPoolMock = Mockito.mock(TransactionPool.class);

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

@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.api.graphql;
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.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
@ -71,8 +71,7 @@ public class GraphQLHttpServiceHostWhitelistTest {
final BlockchainQueries blockchainQueries = Mockito.mock(BlockchainQueries.class);
final Synchronizer synchronizer = Mockito.mock(Synchronizer.class);
final EthHashMiningCoordinator miningCoordinatorMock =
Mockito.mock(EthHashMiningCoordinator.class);
final PoWMiningCoordinator miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class);
final GraphQLDataFetcherContextImpl dataFetcherContext =
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.BlockchainQueries;
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.Synchronizer;
import org.hyperledger.besu.ethereum.core.Wei;
@ -70,7 +70,7 @@ public class GraphQLHttpServiceTest {
private static BlockchainQueries blockchainQueries;
private static GraphQL graphQL;
private static GraphQLDataFetcherContextImpl dataFetcherContext;
private static EthHashMiningCoordinator miningCoordinatorMock;
private static PoWMiningCoordinator miningCoordinatorMock;
private final GraphQLTestHelper testHelper = new GraphQLTestHelper();
@ -80,7 +80,7 @@ public class GraphQLHttpServiceTest {
final Synchronizer synchronizer = Mockito.mock(Synchronizer.class);
graphQL = Mockito.mock(GraphQL.class);
miningCoordinatorMock = Mockito.mock(EthHashMiningCoordinator.class);
miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class);
dataFetcherContext = Mockito.mock(GraphQLDataFetcherContextImpl.class);
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.websocket.WebSocketConfiguration;
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.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
@ -117,7 +117,7 @@ public abstract class AbstractJsonRpcHttpServiceTest {
final Synchronizer synchronizerMock = mock(Synchronizer.class);
final P2PNetwork peerDiscoveryMock = mock(P2PNetwork.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)))
.thenReturn(ValidationResult.valid());
// 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.websocket.WebSocketConfiguration;
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.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -108,7 +108,7 @@ public class JsonRpcHttpServiceHostWhitelistTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
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.websocket.WebSocketConfiguration;
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.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -134,7 +134,7 @@ public class JsonRpcHttpServiceLoginTest {
MainnetProtocolSchedule.fromConfig(genesisConfigOptions),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
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.websocket.WebSocketConfiguration;
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.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
@ -205,7 +205,7 @@ public class JsonRpcHttpServiceRpcApisTest {
ProtocolScheduleFixture.MAINNET,
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)),
@ -302,7 +302,7 @@ public class JsonRpcHttpServiceRpcApisTest {
ProtocolScheduleFixture.MAINNET,
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
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.BlockchainQueries;
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.ChainHead;
import org.hyperledger.besu.ethereum.core.Address;
@ -144,7 +144,7 @@ public class JsonRpcHttpServiceTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
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.SelfSignedP12Certificate;
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.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -126,7 +126,7 @@ public class JsonRpcHttpServiceTlsClientAuthTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
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.SelfSignedP12Certificate;
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.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -114,7 +114,7 @@ public class JsonRpcHttpServiceTlsMisconfigurationTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
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.SelfSignedP12Certificate;
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.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -117,7 +117,7 @@ public class JsonRpcHttpServiceTlsTest {
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
mock(PoWMiningCoordinator.class),
new NoOpMetricsSystem(),
supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)),

@ -367,7 +367,8 @@ public class AdminNodeInfoTest {
.atlantis(6)
.agharta(7)
.phoenix(8)
.thanos(9);
.thanos(9)
.ecip1049(10);
final AdminNodeInfo methodClassic =
new AdminNodeInfo(
@ -390,7 +391,8 @@ public class AdminNodeInfoTest {
"atlantisBlock", 6L,
"aghartaBlock", 7L,
"phoenixBlock", 8L,
"thanosBlock", 9L);
"thanosBlock", 9L,
"ecip1049Block", 10L);
final JsonRpcResponse response = methodClassic.response(request);
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.JsonRpcSuccessResponse;
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.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
@ -52,7 +52,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class EthGasPriceTest {
@Mock private EthHashMiningCoordinator miningCoordinator;
@Mock private PoWMiningCoordinator miningCoordinator;
@Mock private Blockchain blockchain;
private EthGasPrice method;
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.fees.TransactionGasBudgetCalculator;
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.ProtocolSpec;
@ -105,7 +106,8 @@ public class EthGetTransactionReceiptTest {
TransactionPriceCalculator.frontier(),
Optional.empty(),
TransactionGasBudgetCalculator.frontier(),
null);
null,
Optional.of(PoWHasher.ETHASH_LIGHT));
private final ProtocolSpec statusTransactionTypeSpec =
new ProtocolSpec(
"status",
@ -130,7 +132,8 @@ public class EthGetTransactionReceiptTest {
TransactionPriceCalculator.frontier(),
Optional.empty(),
TransactionGasBudgetCalculator.frontier(),
null);
null,
Optional.of(PoWHasher.ETHASH_LIGHT));
@SuppressWarnings("unchecked")
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.JsonRpcResponse;
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.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional;
import com.google.common.io.BaseEncoding;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.junit.Before;
import org.junit.Test;
@ -46,7 +47,7 @@ public class EthGetWorkTest {
private final String hexValue =
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
@Mock private EthHashMiningCoordinator miningCoordinator;
@Mock private PoWMiningCoordinator miningCoordinator;
@Before
public void setUp() {
@ -63,9 +64,8 @@ public class EthGetWorkTest {
@Test
public void shouldReturnCorrectResultOnGenesisDAG() {
final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values =
new EthHashSolverInputs(
UInt256.fromHexString(hexValue), BaseEncoding.base16().lowerCase().decode(hexValue), 0);
final PoWSolverInputs values =
new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 0);
final String[] expectedValue = {
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x0000000000000000000000000000000000000000000000000000000000000000",
@ -83,11 +83,8 @@ public class EthGetWorkTest {
@Test
public void shouldReturnCorrectResultOnHighBlockSeed() {
final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values =
new EthHashSolverInputs(
UInt256.fromHexString(hexValue),
BaseEncoding.base16().lowerCase().decode(hexValue),
30000);
final PoWSolverInputs values =
new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 30000);
final String[] expectedValue = {
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -113,11 +110,8 @@ public class EthGetWorkTest {
.thenReturn(new EpochCalculator.Ecip1099EpochCalculator());
method = new EthGetWork(miningCoordinator);
final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values =
new EthHashSolverInputs(
UInt256.fromHexString(hexValue),
BaseEncoding.base16().lowerCase().decode(hexValue),
60000);
final PoWSolverInputs values =
new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 60000);
final String[] expectedValue = {
"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.response.JsonRpcResponse;
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;
@ -34,7 +34,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class EthHashrateTest {
@Mock private EthHashMiningCoordinator miningCoordinator;
@Mock private PoWMiningCoordinator miningCoordinator;
private EthHashrate method;
private final String JSON_RPC_VERSION = "2.0";
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.response.JsonRpcResponse;
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.Test;
@ -34,7 +34,7 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class EthMiningTest {
@Mock private EthHashMiningCoordinator miningCoordinator;
@Mock private PoWMiningCoordinator miningCoordinator;
private EthMining method;
private final String JSON_RPC_VERSION = "2.0";
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.JsonRpcResponse;
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.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional;
import com.google.common.io.BaseEncoding;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.junit.Before;
@ -49,7 +48,7 @@ public class EthSubmitWorkTest {
private final String hexValue =
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
@Mock private EthHashMiningCoordinator miningCoordinator;
@Mock private PoWMiningCoordinator miningCoordinator;
@Before
public void setUp() {
@ -73,9 +72,8 @@ public class EthSubmitWorkTest {
@Test
public void shouldFailIfMissingArguments() {
final JsonRpcRequestContext request = requestWithParams();
final EthHashSolverInputs values =
new EthHashSolverInputs(
UInt256.fromHexString(hexValue), BaseEncoding.base16().lowerCase().decode(hexValue), 0);
final PoWSolverInputs values =
new PoWSolverInputs(UInt256.fromHexString(hexValue), Bytes.fromHexString(hexValue), 0);
when(miningCoordinator.getWorkDefinition()).thenReturn(Optional.of(values));
assertThatThrownBy(
() -> method.response(request), "Missing required json rpc parameter at index 0")
@ -84,21 +82,23 @@ public class EthSubmitWorkTest {
@Test
public void shouldReturnTrueIfGivenCorrectResult() {
final EthHashSolverInputs firstInputs =
new EthHashSolverInputs(
final PoWSolverInputs firstInputs =
new PoWSolverInputs(
UInt256.fromHexString(
"0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"),
new byte[] {
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
},
Bytes.wrap(
new byte[] {
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);
final EthHashSolution expectedFirstOutput =
new EthHashSolution(
final PoWSolution expectedFirstOutput =
new PoWSolution(
-6506032554016940193L,
Hash.fromHexString(
"0xc5e3c33c86d64d0641dd3c86e8ce4628fe0aac0ef7b4c087c5fcaa45d5046d90"),
null,
firstInputs.getPrePowHash());
final JsonRpcRequestContext request =
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.JsonRpcSuccessResponse;
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.Test;
@ -38,7 +38,7 @@ public class MinerStartTest {
private MinerStart method;
@Mock private EthHashMiningCoordinator miningCoordinator;
@Mock private PoWMiningCoordinator miningCoordinator;
@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.response.JsonRpcResponse;
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.Test;
@ -34,7 +34,7 @@ public class MinerStopTest {
private MinerStop method;
@Mock private EthHashMiningCoordinator miningCoordinator;
@Mock private PoWMiningCoordinator miningCoordinator;
@Before
public void before() {

@ -15,8 +15,8 @@
package org.hyperledger.besu.ethereum.blockcreation;
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.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters;
@ -72,7 +72,7 @@ public abstract class AbstractMinerExecutor<M extends BlockMiner<? extends Abstr
public Optional<M> startAsyncMining(
final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers,
final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) {
try {
final M currentRunningMiner = createMiner(observers, ethHashObservers, parentHeader);
@ -98,7 +98,7 @@ public abstract class AbstractMinerExecutor<M extends BlockMiner<? extends Abstr
public abstract M createMiner(
final Subscribers<MinedBlockObserver> subscribers,
final Subscribers<EthHashObserver> ethHashObservers,
final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader);
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.BlockAddedObserver;
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.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
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<EthHashObserver> ethHashObservers = Subscribers.create();
private final Subscribers<PoWObserver> ethHashObservers = Subscribers.create();
private final AbstractMinerExecutor<M> executor;
private final SyncState syncState;
protected final Blockchain blockchain;
@ -189,7 +189,7 @@ public abstract class AbstractMiningCoordinator<
}
@Override
public void addEthHashObserver(final EthHashObserver obs) {
public void addEthHashObserver(final PoWObserver obs) {
ethHashObservers.subscribe(obs);
}

@ -14,14 +14,14 @@
*/
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.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.List;
import java.util.Optional;
@ -71,12 +71,12 @@ public interface MiningCoordinator {
return Optional.empty();
}
default Optional<EthHashSolverInputs> getWorkDefinition() {
default Optional<PoWSolverInputs> getWorkDefinition() {
throw new UnsupportedOperationException(
"Current consensus mechanism prevents querying work definition.");
}
default boolean submitWork(final EthHashSolution solution) {
default boolean submitWork(final PoWSolution solution) {
throw new UnsupportedOperationException(
"Current consensus mechanism prevents submission of work solutions.");
}
@ -105,7 +105,7 @@ public interface MiningCoordinator {
final List<Transaction> transactions,
final List<BlockHeader> ommers);
default void addEthHashObserver(final EthHashObserver observer) {}
default void addEthHashObserver(final PoWObserver observer) {}
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.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.mainnet.EthHash;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolver;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.math.BigInteger;
@ -34,18 +34,18 @@ import java.util.concurrent.ExecutionException;
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 ExtraDataCalculator extraDataCalculator,
final PendingTransactions pendingTransactions,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final GasLimitCalculator gasLimitCalculator,
final EthHashSolver nonceSolver,
final PoWSolver nonceSolver,
final Wei minTransactionGasPrice,
final Double minBlockOccupancyRatio,
final BlockHeader parentHeader) {
@ -66,11 +66,10 @@ public class EthHashBlockCreator extends AbstractBlockCreator {
@Override
protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) {
final EthHashSolverInputs workDefinition = generateNonceSolverInputs(sealableBlockHeader);
final EthHashSolution solution;
final PoWSolverInputs workDefinition = generateNonceSolverInputs(sealableBlockHeader);
final PoWSolution solution;
try {
solution =
nonceSolver.solveFor(EthHashSolver.EthHashSolverJob.createFromInputs(workDefinition));
solution = nonceSolver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(workDefinition));
} catch (final InterruptedException ex) {
throw new CancellationException();
} catch (final ExecutionException ex) {
@ -84,19 +83,18 @@ public class EthHashBlockCreator extends AbstractBlockCreator {
.buildBlockHeader();
}
private EthHashSolverInputs generateNonceSolverInputs(
final SealableBlockHeader sealableBlockHeader) {
private PoWSolverInputs generateNonceSolverInputs(final SealableBlockHeader sealableBlockHeader) {
final BigInteger difficulty = sealableBlockHeader.getDifficulty().toBigInteger();
final UInt256 target =
difficulty.equals(BigInteger.ONE)
? UInt256.MAX_VALUE
: UInt256.valueOf(EthHash.TARGET_UPPER_BOUND.divide(difficulty));
return new EthHashSolverInputs(
return new PoWSolverInputs(
target, EthHash.hashHeader(sealableBlockHeader), sealableBlockHeader.getNumber());
}
public Optional<EthHashSolverInputs> getWorkDefinition() {
public Optional<PoWSolverInputs> getWorkDefinition() {
return nonceSolver.getWorkDefinition();
}
@ -104,7 +102,7 @@ public class EthHashBlockCreator extends AbstractBlockCreator {
return nonceSolver.hashesPerSecond();
}
public boolean submitWork(final EthHashSolution solution) {
public boolean submitWork(final PoWSolution 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.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.util.Subscribers;
@ -26,16 +26,16 @@ import java.util.Optional;
import java.util.function.Function;
/**
* Provides the EthHash specific aspects of the mining operation - i.e. getting the work definition,
* reporting the hashrate of the miner and accepting work submissions.
* Provides the proof-of-work specific aspects of the mining operation - i.e. getting the work
* 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)
* are all conducted by the parent class.
*/
public class EthHashBlockMiner extends BlockMiner<EthHashBlockCreator> {
public class PoWBlockMiner extends BlockMiner<PoWBlockCreator> {
public EthHashBlockMiner(
final Function<BlockHeader, EthHashBlockCreator> blockCreator,
public PoWBlockMiner(
final Function<BlockHeader, PoWBlockCreator> blockCreator,
final ProtocolSchedule protocolSchedule,
final ProtocolContext protocolContext,
final Subscribers<MinedBlockObserver> observers,
@ -44,7 +44,7 @@ public class EthHashBlockMiner extends BlockMiner<EthHashBlockCreator> {
super(blockCreator, protocolSchedule, protocolContext, observers, scheduler, parentHeader);
}
public Optional<EthHashSolverInputs> getWorkDefinition() {
public Optional<PoWSolverInputs> getWorkDefinition() {
return minerBlockCreator.getWorkDefinition();
}
@ -52,7 +52,7 @@ public class EthHashBlockMiner extends BlockMiner<EthHashBlockCreator> {
return minerBlockCreator.getHashesPerSecond();
}
public boolean submitWork(final EthHashSolution solution) {
public boolean submitWork(final PoWSolution solution) {
return minerBlockCreator.submitWork(solution);
}
}

@ -15,29 +15,28 @@
package org.hyperledger.besu.ethereum.blockcreation;
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.PoWObserver;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
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.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.util.Subscribers;
import java.util.Optional;
import java.util.function.Function;
public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMiner> {
public class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
protected volatile Optional<Address> coinbase;
protected boolean stratumMiningEnabled;
protected final Iterable<Long> nonceGenerator;
protected final EpochCalculator epochCalculator;
public EthHashMinerExecutor(
public PoWMinerExecutor(
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final PendingTransactions pendingTransactions,
@ -58,9 +57,9 @@ public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMine
}
@Override
public Optional<EthHashBlockMiner> startAsyncMining(
public Optional<PoWBlockMiner> startAsyncMining(
final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers,
final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) {
if (coinbase.isEmpty()) {
throw new CoinbaseNotSetException("Unable to start mining without a coinbase.");
@ -69,20 +68,20 @@ public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMine
}
@Override
public EthHashBlockMiner createMiner(
public PoWBlockMiner createMiner(
final Subscribers<MinedBlockObserver> observers,
final Subscribers<EthHashObserver> ethHashObservers,
final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) {
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
nonceGenerator,
new EthHasher.Light(),
protocolSchedule.getByBlockNumber(parentHeader.getNumber() + 1).getPoWHasher().get(),
stratumMiningEnabled,
ethHashObservers,
epochCalculator);
final Function<BlockHeader, EthHashBlockCreator> blockCreator =
final Function<BlockHeader, PoWBlockCreator> blockCreator =
(header) ->
new EthHashBlockCreator(
new PoWBlockCreator(
coinbase.get(),
parent -> extraData,
pendingTransactions,
@ -94,7 +93,7 @@ public class EthHashMinerExecutor extends AbstractMinerExecutor<EthHashBlockMine
minBlockOccupancyRatio,
parentHeader);
return new EthHashBlockMiner(
return new PoWBlockMiner(
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.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.Optional;
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
* 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 {
private static final Logger LOG = getLogger();
private final EthHashMinerExecutor executor;
private final PoWMinerExecutor executor;
private final Cache<String, Long> sealerHashRate;
private volatile Optional<Long> cachedHashesPerSecond = Optional.empty();
public EthHashMiningCoordinator(
public PoWMiningCoordinator(
final Blockchain blockchain,
final EthHashMinerExecutor executor,
final PoWMinerExecutor executor,
final SyncState syncState,
final int remoteSealersLimit,
final long remoteSealersTimeToLive) {
@ -96,7 +96,7 @@ public class EthHashMiningCoordinator extends AbstractMiningCoordinator<EthHashB
private Optional<Long> localHashesPerSecond() {
final Optional<Long> currentHashesPerSecond =
currentRunningMiner.flatMap(EthHashBlockMiner::getHashesPerSecond);
currentRunningMiner.flatMap(PoWBlockMiner::getHashesPerSecond);
if (currentHashesPerSecond.isPresent()) {
cachedHashesPerSecond = currentHashesPerSecond;
@ -122,19 +122,19 @@ public class EthHashMiningCoordinator extends AbstractMiningCoordinator<EthHashB
}
@Override
public Optional<EthHashSolverInputs> getWorkDefinition() {
return currentRunningMiner.flatMap(EthHashBlockMiner::getWorkDefinition);
public Optional<PoWSolverInputs> getWorkDefinition() {
return currentRunningMiner.flatMap(PoWBlockMiner::getWorkDefinition);
}
@Override
public boolean submitWork(final EthHashSolution solution) {
public boolean submitWork(final PoWSolution solution) {
synchronized (this) {
return currentRunningMiner.map(miner -> miner.submitWork(solution)).orElse(false);
}
}
@Override
protected void haltMiner(final EthHashBlockMiner miner) {
protected void haltMiner(final PoWBlockMiner miner) {
miner.cancel();
miner.getHashesPerSecond().ifPresent(val -> cachedHashesPerSecond = Optional.of(val));
}

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

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

@ -33,7 +33,7 @@ import org.junit.runners.Parameterized.Parameters;
public class HashRateMiningCoordinatorTest {
private final Blockchain blockchain = mock(Blockchain.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 Long hashRate;
private final Long wantTotalHashrate;
@ -66,8 +66,8 @@ public class HashRateMiningCoordinatorTest {
@Test
public void test() {
final EthHashMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(blockchain, minerExecutor, syncState, 1000, 10);
final PoWMiningCoordinator miningCoordinator =
new PoWMiningCoordinator(blockchain, minerExecutor, syncState, 1000, 10);
for (int i = 0; i < startSealersSize; i++) {
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.TransactionPoolConfiguration;
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.PoWHasher;
import org.hyperledger.besu.ethereum.mainnet.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
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.junit.Test;
public class EthHashBlockCreatorTest {
public class PoWBlockCreatorTest {
private final Address BLOCK_1_COINBASE =
Address.fromHexString("0x05a56e2d52c817161883f50c441c3228cfe54d9f");
@ -79,10 +79,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule())
.build();
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(),
PoWHasher.ETHASH_LIGHT,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator());
@ -97,8 +97,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
final PoWBlockCreator blockCreator =
new PoWBlockCreator(
BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions,
@ -138,10 +138,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule())
.build();
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(),
PoWHasher.ETHASH_LIGHT,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator());
@ -156,8 +156,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
final PoWBlockCreator blockCreator =
new PoWBlockCreator(
BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions,
@ -192,10 +192,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule())
.build();
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(),
PoWHasher.ETHASH_LIGHT,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator());
@ -210,8 +210,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
final PoWBlockCreator blockCreator =
new PoWBlockCreator(
BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions,
@ -262,10 +262,10 @@ public class EthHashBlockCreatorTest {
.createProtocolSchedule())
.build();
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
Lists.newArrayList(BLOCK_1_NONCE),
new EthHasher.Light(),
PoWHasher.ETHASH_LIGHT,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator());
@ -280,8 +280,8 @@ public class EthHashBlockCreatorTest {
executionContextTestFixture.getProtocolContext().getBlockchain()::getChainHeadHeader,
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
final PoWBlockCreator blockCreator =
new PoWBlockCreator(
BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions,

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

@ -24,7 +24,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
import org.hyperledger.besu.ethereum.core.Hash;
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;
@ -32,12 +32,12 @@ import org.apache.tuweni.bytes.Bytes32;
import org.junit.Before;
import org.junit.Test;
public class EthHashMiningCoordinatorTest {
public class PoWMiningCoordinatorTest {
private final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create();
private final SyncState syncState = mock(SyncState.class);
private final EthHashMinerExecutor executor = mock(EthHashMinerExecutor.class);
private final EthHashBlockMiner miner = mock(EthHashBlockMiner.class);
private final PoWMinerExecutor executor = mock(PoWMinerExecutor.class);
private final PoWBlockMiner miner = mock(PoWBlockMiner.class);
@Before
public void setUp() {
@ -46,14 +46,14 @@ public class EthHashMiningCoordinatorTest {
@Test
public void miningCoordinatorIsCreatedDisabledWithNoReportableMiningStatistics() {
final EthHashMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(
final PoWMiningCoordinator miningCoordinator =
new PoWMiningCoordinator(
executionContext.getBlockchain(),
executor,
syncState,
DEFAULT_REMOTE_SEALERS_LIMIT,
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.hashesPerSecond()).isEqualTo(Optional.empty());
@ -72,8 +72,8 @@ public class EthHashMiningCoordinatorTest {
when(executor.startAsyncMining(any(), any(), any())).thenReturn(Optional.of(miner));
final EthHashMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(
final PoWMiningCoordinator miningCoordinator =
new PoWMiningCoordinator(
executionContext.getBlockchain(),
executor,
syncState,

@ -14,20 +14,20 @@
*/
package org.hyperledger.besu.ethereum.chain;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.util.function.Function;
/** Observer of new work for the EthHash PoW algorithm */
public interface EthHashObserver {
/** Observer of new work for the PoW algorithm */
public interface PoWObserver {
/**
* Send a new proof-of-work job to observers
*
* @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.
@ -35,5 +35,5 @@ public interface EthHashObserver {
* @param submitSolutionCallback the callback to set on the observer, consuming a solution and
* 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 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) {
long difficulty = config.getEthashConfigOptions().getFixedDifficulty().getAsLong();
long difficulty =
config
.getEthashConfigOptions()
.getFixedDifficulty()
.orElseGet(() -> config.getKeccak256ConfigOptions().getFixedDifficulty().getAsLong());
return (time, parent, context) -> BigInteger.valueOf(difficulty);
}
}

@ -14,6 +14,9 @@
*/
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.TransactionReceipt;
import org.hyperledger.besu.ethereum.core.Wei;
@ -232,10 +235,10 @@ public class ClassicProtocolSpecs {
quorumCompatibilityMode)
.blockHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createBlockHeaderValidator(
new EpochCalculator.Ecip1099EpochCalculator()))
new EpochCalculator.Ecip1099EpochCalculator(), powHasher(PowAlgorithm.ETHASH)))
.ommerHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createOmmerValidator(
new EpochCalculator.Ecip1099EpochCalculator()))
new EpochCalculator.Ecip1099EpochCalculator(), powHasher(PowAlgorithm.ETHASH)))
.name("Thanos");
}
@ -258,4 +261,28 @@ public class ClassicProtocolSpecs {
return new TransactionReceipt(
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;
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.rlp.BytesValueRLPOutput;
@ -23,10 +24,13 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.DigestException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.function.BiConsumer;
import com.google.common.primitives.Ints;
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;
/** 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
* bytes 32 to 63
*/
public static byte[] hashimotoLight(
final long size, final int[] cache, final byte[] header, final long nonce) {
public static PoWSolution hashimotoLight(
final long size, final int[] cache, final Bytes header, final long nonce) {
return hashimoto(header, size, nonce, (target, ind) -> calcDatasetItem(target, cache, ind));
}
public static byte[] hashimoto(
final byte[] header,
public static PoWSolution hashimoto(
final Bytes header,
final long size,
final long nonce,
final BiConsumer<byte[], Integer> datasetLookup) {
final int n = (int) Long.divideUnsigned(size, MIX_BYTES);
final MessageDigest keccak512 = KECCAK_512.get();
keccak512.update(header);
keccak512.update(header.toArrayUnsafe());
keccak512.update(Longs.toByteArray(Long.reverseBytes(nonce)));
final byte[] seed = keccak512.digest();
final ByteBuffer mixBuffer = ByteBuffer.allocate(MIX_BYTES).order(ByteOrder.LITTLE_ENDIAN);
@ -121,7 +125,12 @@ public final class EthHash {
} catch (final DigestException 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
* @return Truncated BlockHeader hash
*/
public static byte[] hashHeader(final SealableBlockHeader header) {
public static Bytes32 hashHeader(final SealableBlockHeader header) {
final BytesValueRLPOutput out = new BytesValueRLPOutput();
out.startList();
out.writeBytes(header.getParentHash());
@ -184,7 +193,8 @@ public final class EthHash {
out.writeLongScalar(header.getBaseFee().get());
}
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");
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() {
@ -52,7 +56,11 @@ public final class MainnetBlockHeaderValidator {
}
public static BlockHeaderValidator.Builder createClassicValidator() {
return createValidator()
return createClassicValidator(PoWHasher.ETHASH_LIGHT);
}
public static BlockHeaderValidator.Builder createClassicValidator(final PoWHasher hasher) {
return createValidator(hasher)
.addRule(
new ConstantFieldValidationRule<>(
"hash",
@ -69,10 +77,16 @@ public final class MainnetBlockHeaderValidator {
}
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()
.addRule(CalculatedDifficultyValidationRule::new)
.addRule(new AncestryValidationRule())
@ -80,15 +94,19 @@ public final class MainnetBlockHeaderValidator {
.addRule(new GasUsageValidationRule())
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule(epochCalculator));
.addRule(new ProofOfWorkValidationRule(epochCalculator, false, hasher));
}
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(
final EpochCalculator epochCalculator) {
final EpochCalculator epochCalculator, final PoWHasher hasher) {
return new BlockHeaderValidator.Builder()
.addRule(CalculatedDifficultyValidationRule::new)
.addRule(new AncestryValidationRule())
@ -97,7 +115,7 @@ public final class MainnetBlockHeaderValidator {
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S))
.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) {
@ -109,7 +127,9 @@ public final class MainnetBlockHeaderValidator {
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S))
.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)));
}
@ -121,7 +141,9 @@ public final class MainnetBlockHeaderValidator {
.addRule(new GasUsageValidationRule())
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.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)));
}
}

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

@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.ethereum.MainnetBlockValidator;
import org.hyperledger.besu.ethereum.chain.Blockchain;
@ -151,6 +152,21 @@ public abstract class MainnetProtocolSpecs {
.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) {
if (goQuorumMode) {
return GoQuorumBlockValidator::new;

@ -14,35 +14,57 @@
*/
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.
*
* @param buffer At least 64 bytes long buffer to store EthHash result in
* @param nonce Block Nonce
* @param number Block Number
* @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 EthashLight() {}
@Override
public void hash(
final byte[] buffer,
public PoWSolution hash(
final long nonce,
final long number,
final EpochCalculator epochCalc,
final byte[] headerHash) {
final Bytes prePowHash) {
final EthHashCacheFactory.EthHashDescriptor cache =
cacheFactory.ethHashCacheFor(number, epochCalc);
final byte[] hash =
EthHash.hashimotoLight(cache.getDatasetSize(), cache.getCache(), headerHash, nonce);
System.arraycopy(hash, 0, buffer, 0, hash.length);
final PoWSolution solution =
EthHash.hashimotoLight(cache.getDatasetSize(), cache.getCache(), prePowHash, nonce);
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 java.util.Arrays;
import java.util.Objects;
public class EthHashSolution {
import org.apache.tuweni.bytes.Bytes;
public class PoWSolution {
private final long nonce;
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.mixHash = mixHash;
this.solution = solution;
this.powHash = powHash;
}
@ -38,24 +42,27 @@ public class EthHashSolution {
return mixHash;
}
public byte[] getPowHash() {
public Bytes getPowHash() {
return powHash;
}
public Bytes getSolution() {
return solution;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EthHashSolution that = (EthHashSolution) o;
PoWSolution that = (PoWSolution) o;
return nonce == that.nonce
&& Objects.equals(mixHash, that.mixHash)
&& Arrays.equals(powHash, that.powHash);
&& Objects.equals(solution, that.solution)
&& Objects.equals(powHash, that.powHash);
}
@Override
public int hashCode() {
int result = Objects.hash(nonce, mixHash);
result = 31 * result + Arrays.hashCode(powHash);
return result;
return Objects.hash(nonce, mixHash, solution, powHash);
}
}

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

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

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

@ -77,6 +77,8 @@ public class ProtocolSpec {
private final BadBlockManager badBlockManager;
private final Optional<PoWHasher> powHasher;
/**
* 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 gasBudgetCalculator the gas budget calculator to use.
* @param badBlockManager the cache to use to keep invalid blocks
* @param powHasher the proof-of-work hasher
*/
public ProtocolSpec(
final String name,
@ -127,7 +130,8 @@ public class ProtocolSpec {
final TransactionPriceCalculator transactionPriceCalculator,
final Optional<EIP1559> eip1559,
final TransactionGasBudgetCalculator gasBudgetCalculator,
final BadBlockManager badBlockManager) {
final BadBlockManager badBlockManager,
final Optional<PoWHasher> powHasher) {
this.name = name;
this.evm = evm;
this.transactionValidator = transactionValidator;
@ -151,6 +155,7 @@ public class ProtocolSpec {
this.eip1559 = eip1559;
this.gasBudgetCalculator = gasBudgetCalculator;
this.badBlockManager = badBlockManager;
this.powHasher = powHasher;
}
/**
@ -350,4 +355,13 @@ public class ProtocolSpec {
public BadBlockManager getBadBlocksManager() {
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 =
TransactionGasBudgetCalculator.frontier();
private BadBlockManager badBlockManager;
private PoWHasher powHasher = PoWHasher.ETHASH_LIGHT;
public ProtocolSpecBuilder gasCalculator(final Supplier<GasCalculator> gasCalculatorBuilder) {
this.gasCalculatorBuilder = gasCalculatorBuilder;
@ -238,6 +239,11 @@ public class ProtocolSpecBuilder {
return this;
}
public ProtocolSpecBuilder powHasher(final PoWHasher powHasher) {
this.powHasher = powHasher;
return this;
}
public ProtocolSpec build(final ProtocolSchedule protocolSchedule) {
checkNotNull(gasCalculatorBuilder, "Missing gasCalculator");
checkNotNull(evmBuilder, "Missing operation registry");
@ -364,7 +370,8 @@ public class ProtocolSpecBuilder {
transactionPriceCalculator,
eip1559,
gasBudgetCalculator,
badBlockManager);
badBlockManager,
Optional.ofNullable(powHasher));
}
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.mainnet.DetachedBlockHeaderValidationRule;
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 java.math.BigInteger;
import org.apache.logging.log4j.LogManager;
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;
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);
static final EthHasher HASHER = new EthHasher.Light();
private final PoWHasher hasher;
private final EpochCalculator epochCalculator;
private final boolean includeBaseFee;
public ProofOfWorkValidationRule(final EpochCalculator epochCalculator) {
this(epochCalculator, false);
}
public ProofOfWorkValidationRule(
final EpochCalculator epochCalculator, final boolean includeBaseFee) {
final EpochCalculator epochCalculator, final boolean includeBaseFee, final PoWHasher hasher) {
this.epochCalculator = epochCalculator;
this.includeBaseFee = includeBaseFee;
this.hasher = hasher;
}
@Override
@ -63,10 +59,9 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid
}
}
final byte[] hashBuffer = new byte[64];
final Hash headerHash = hashHeader(header);
HASHER.hash(
hashBuffer, header.getNonce(), header.getNumber(), epochCalculator, headerHash.toArray());
PoWSolution solution =
hasher.hash(header.getNonce(), header.getNumber(), epochCalculator, headerHash);
if (header.getDifficulty().isZero()) {
LOG.info("Invalid block header: difficulty is 0");
@ -77,7 +72,7 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid
difficulty.equals(BigInteger.ONE)
? UInt256.MAX_VALUE
: 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) {
LOG.info(
"Invalid block header: the EthHash result {} was greater than the target {}.\n"
@ -88,8 +83,7 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid
return false;
}
final Hash mixedHash =
Hash.wrap(Bytes32.leftPad(Bytes.wrap(hashBuffer).slice(0, Bytes32.SIZE)));
final Hash mixedHash = solution.getMixHash();
if (!header.getMixHash().equals(mixedHash)) {
LOG.info(
"Invalid block header: header mixed hash {} does not equal calculated mixed hash {}.\n"

@ -56,4 +56,36 @@ public class FixedProtocolScheduleTest {
.nextDifficulty(1, parentHeader, null))
.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;
import static org.assertj.core.api.Assertions.assertThat;
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.RLPInput;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import com.google.common.io.Resources;
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.junit.Test;
@ -50,32 +48,28 @@ public final class EthHashTest {
final long epoch = epochCalculator.cacheEpoch(blockNumber);
final long datasetSize = EthHash.datasetSize(epoch);
final long cacheSize = EthHash.cacheSize(epoch);
Assertions.assertThat(datasetSize).isEqualTo(1157627776);
Assertions.assertThat(cacheSize).isEqualTo(18087488);
assertThat(datasetSize).isEqualTo(1157627776);
assertThat(cacheSize).isEqualTo(18087488);
final int[] cache = EthHash.mkCache((int) cacheSize, blockNumber, epochCalculator);
Assertions.assertThat(
Hash.wrap(
Bytes32.wrap(
Arrays.copyOf(
EthHash.hashimotoLight(
datasetSize, cache, EthHash.hashHeader(header), header.getNonce()),
32))))
.isEqualTo(header.getMixHash());
PoWSolution solution =
EthHash.hashimotoLight(datasetSize, cache, EthHash.hashHeader(header), header.getNonce());
assertThat(solution.getMixHash()).isEqualTo(header.getMixHash());
}
@Test
public void hashimotoLightExample() {
final int[] cache = EthHash.mkCache(1024, 1L, new EpochCalculator.DefaultEpochCalculator());
Assertions.assertThat(
Hex.toHexString(
EthHash.hashimotoLight(
32 * 1024,
cache,
Hex.decode("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f"),
0L)))
.isEqualTo(
"e4073cffaef931d37117cefd9afd27ea0f1cad6a981dd2605c4a1ac97c519800"
+ "d3539235ee2e6f8db665c0a72169f55b7f6c605712330b778ec3944f0eb5a557");
PoWSolution solution =
EthHash.hashimotoLight(
32 * 1024,
cache,
Bytes.fromHexString("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f"),
0L);
assertThat(solution.getSolution().toHexString())
.isEqualTo("0xd3539235ee2e6f8db665c0a72169f55b7f6c605712330b778ec3944f0eb5a557");
assertThat(solution.getMixHash().toHexString())
.isEqualTo("0xe4073cffaef931d37117cefd9afd27ea0f1cad6a981dd2605c4a1ac97c519800");
}
@Test
@ -86,7 +80,7 @@ public final class EthHashTest {
for (final int i : cache) {
buffer.putInt(i);
}
Assertions.assertThat(Hex.toHexString(buffer.array()))
assertThat(Hex.toHexString(buffer.array()))
.isEqualTo(
new StringBuilder()
.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
public void validHeaderFrontier() throws Exception {
final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create()
MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.build();
assertThat(
@ -45,7 +45,7 @@ public final class MainnetBlockHeaderValidatorTest {
@Test
public void validHeaderHomestead() throws Exception {
final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create()
MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
.build();
assertThat(
@ -60,7 +60,7 @@ public final class MainnetBlockHeaderValidatorTest {
@Test
public void invalidParentHash() throws Exception {
final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create()
MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.build();
assertThat(
@ -75,7 +75,7 @@ public final class MainnetBlockHeaderValidatorTest {
@Test
public void validHeaderByzantium() throws Exception {
final BlockHeaderValidator headerValidator =
MainnetBlockHeaderValidator.create()
MainnetBlockHeaderValidator.create(PoWHasher.ETHASH_LIGHT)
.difficultyCalculator(MainnetDifficultyCalculators.BYZANTIUM)
.build();
assertThat(

@ -31,18 +31,20 @@ import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch;
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.junit.Test;
public class EthHashSolverTest {
public class PoWSolverTest {
@Test
public void emptyHashRateAndWorkDefinitionIsReportedPriorToSolverStarting() {
final List<Long> noncesToTry = Arrays.asList(1L, 1L, 1L, 1L, 1L, 1L, 0L);
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
noncesToTry,
new EthHasher.Light(),
PoWHasher.ETHASH_LIGHT,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator());
@ -55,20 +57,25 @@ public class EthHashSolverTest {
public void hashRateIsProducedSuccessfully() throws InterruptedException, ExecutionException {
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(
invocation -> {
final Object[] args = invocation.getArguments();
final byte[] headerHash = ((byte[]) args[0]);
final long nonce = ((long) args[1]);
headerHash[32] = (byte) (nonce & 0xFF);
return null;
final long nonce = ((long) args[0]);
final Bytes prePow = (Bytes) args[3];
PoWSolution solution =
new PoWSolution(
nonce,
Hash.wrap(Bytes32.leftPad(Bytes.EMPTY)),
Bytes32.rightPad(Bytes.of((byte) (nonce & 0xFF))),
prePow);
return solution;
})
.when(hasher)
.hash(any(), anyLong(), anyLong(), any(), any());
.hash(anyLong(), anyLong(), any(), any());
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
noncesToTry,
hasher,
false,
@ -76,8 +83,8 @@ public class EthHashSolverTest {
new EpochCalculator.DefaultEpochCalculator());
final Stopwatch operationTimer = Stopwatch.createStarted();
final EthHashSolverInputs inputs = new EthHashSolverInputs(UInt256.ONE, new byte[0], 5);
solver.solveFor(EthHashSolver.EthHashSolverJob.createFromInputs(inputs));
final PoWSolverInputs inputs = new PoWSolverInputs(UInt256.ONE, Bytes.EMPTY, 5);
solver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(inputs));
final double runtimeSeconds = operationTimer.elapsed(TimeUnit.NANOSECONDS) / 1e9;
final long worstCaseHashesPerSecond = (long) (noncesToTry.size() / runtimeSeconds);
@ -93,54 +100,57 @@ public class EthHashSolverTest {
public void ifInvokedTwiceProducesCorrectAnswerForSecondInvocation()
throws InterruptedException, ExecutionException {
final EthHashSolverInputs firstInputs =
new EthHashSolverInputs(
final PoWSolverInputs firstInputs =
new PoWSolverInputs(
UInt256.fromHexString(
"0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"),
new byte[] {
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
},
Bytes.wrap(
new byte[] {
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);
final EthHashSolution expectedFirstOutput =
new EthHashSolution(
final PoWSolution expectedFirstOutput =
new PoWSolution(
-6506032554016940193L,
Hash.fromHexString(
"0xc5e3c33c86d64d0641dd3c86e8ce4628fe0aac0ef7b4c087c5fcaa45d5046d90"),
null,
firstInputs.getPrePowHash());
final EthHashSolverInputs secondInputs =
new EthHashSolverInputs(
final PoWSolverInputs secondInputs =
new PoWSolverInputs(
UInt256.fromHexString(
"0x0083126e978d4fdf3b645a1cac083126e978d4fdf3b645a1cac083126e978d4f"),
new byte[] {
-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,
},
Bytes.wrap(
new byte[] {
-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);
final EthHashSolution expectedSecondOutput =
new EthHashSolution(
final PoWSolution expectedSecondOutput =
new PoWSolution(
8855952212886464488L,
Hash.fromHexString(
"0x2adb0f375dd2d528689cb9e00473c3c9692737109d547130feafbefb2c6c5244"),
null,
firstInputs.getPrePowHash());
// Nonces need to have a 0L inserted, as it is a "wasted" nonce in the solver.
final EthHashSolver solver =
new EthHashSolver(
final PoWSolver solver =
new PoWSolver(
Lists.newArrayList(expectedFirstOutput.getNonce(), 0L, expectedSecondOutput.getNonce()),
new EthHasher.Light(),
PoWHasher.ETHASH_LIGHT,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator());
EthHashSolution soln =
solver.solveFor(EthHashSolver.EthHashSolverJob.createFromInputs(firstInputs));
PoWSolution soln = solver.solveFor(PoWSolver.PoWSolverJob.createFromInputs(firstInputs));
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());
}
}

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

@ -81,7 +81,8 @@ public class NoRewardProtocolScheduleWrapper implements ProtocolSchedule {
original.getTransactionPriceCalculator(),
original.getEip1559(),
original.getGasBudgetCalculator(),
original.getBadBlocksManager());
original.getBadBlocksManager(),
Optional.empty());
}
@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.TransactionPoolFactory;
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.MainnetBlockHeaderFunctions;
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.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
@ -72,12 +72,9 @@ import org.apache.tuweni.bytes.Bytes;
public class RetestethContext {
private static final Logger LOG = LogManager.getLogger();
private static final EthHasher NO_WORK_HASHER =
(final byte[] buffer,
final long nonce,
final long number,
EpochCalculator epochCalc,
final byte[] headerHash) -> {};
private static final PoWHasher NO_WORK_HASHER =
(final long nonce, final long number, EpochCalculator epochCalc, final Bytes headerHash) ->
null;
private final ReentrantLock contextLock = new ReentrantLock();
private Address coinbase;
@ -93,7 +90,7 @@ public class RetestethContext {
private TransactionPool transactionPool;
private EthScheduler ethScheduler;
private EthHashSolver ethHashSolver;
private PoWSolver poWSolver;
public boolean resetContext(
final String genesisConfigString, final String sealEngine, final Optional<Long> clockTime) {
@ -161,17 +158,17 @@ public class RetestethContext {
: HeaderValidationMode.FULL;
final Iterable<Long> nonceGenerator = new IncrementingNonceGenerator(0);
ethHashSolver =
poWSolver =
("NoProof".equals(sealengine) || "NoReward".equals(sealEngine))
? new EthHashSolver(
? new PoWSolver(
nonceGenerator,
NO_WORK_HASHER,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator())
: new EthHashSolver(
: new PoWSolver(
nonceGenerator,
new EthHasher.Light(),
PoWHasher.ETHASH_LIGHT,
false,
Subscribers.none(),
new EpochCalculator.DefaultEpochCalculator());
@ -288,7 +285,7 @@ public class RetestethContext {
return retestethClock;
}
public EthHashSolver getEthHashSolver() {
return ethHashSolver;
public PoWSolver getEthHashSolver() {
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.response.JsonRpcResponse;
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.PoWBlockCreator;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockImporter;
@ -60,8 +60,8 @@ public class TestMineBlocks implements JsonRpcMethod {
final ProtocolContext protocolContext = context.getProtocolContext();
final MutableBlockchain blockchain = context.getBlockchain();
final HeaderValidationMode headerValidationMode = context.getHeaderValidationMode();
final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
final PoWBlockCreator blockCreator =
new PoWBlockCreator(
context.getCoinbase(),
header -> context.getExtraData(),
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.internal.JsonRpcRequest;
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.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.io.IOException;
import java.util.Arrays;
import java.util.function.Function;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -49,18 +48,18 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
private static final JsonMapper mapper = new JsonMapper();
private final MiningCoordinator miningCoordinator;
private EthHashSolverInputs currentInput;
private Function<EthHashSolution, Boolean> submitCallback;
private PoWSolverInputs currentInput;
private Function<PoWSolution, Boolean> submitCallback;
private final EpochCalculator epochCalculator;
public Stratum1EthProxyProtocol(final MiningCoordinator miningCoordinator) {
if (!(miningCoordinator instanceof EthHashMiningCoordinator)) {
if (!(miningCoordinator instanceof PoWMiningCoordinator)) {
throw new IllegalArgumentException(
"Stratum1 Proxies require an EthHashMiningCoordinator not "
"Stratum1 Proxies require an PoWMiningCoordinator not "
+ ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName()));
}
this.miningCoordinator = miningCoordinator;
this.epochCalculator = ((EthHashMiningCoordinator) miningCoordinator).getEpochCalculator();
this.epochCalculator = ((PoWMiningCoordinator) miningCoordinator).getEpochCalculator();
}
@Override
@ -91,7 +90,7 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
private void sendNewWork(final StratumConnection conn, final Object id) {
byte[] dagSeed = DirectAcyclicGraphSeed.dagSeed(currentInput.getBlockNumber(), epochCalculator);
final String[] result = {
"0x" + BaseEncoding.base16().lowerCase().encode(currentInput.getPrePowHash()),
currentInput.getPrePowHash().toHexString(),
"0x" + BaseEncoding.base16().lowerCase().encode(dagSeed),
currentInput.getTarget().toHexString()
};
@ -127,12 +126,13 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
throws IOException {
LOG.debug("Miner submitted solution {}", req);
boolean result = false;
final EthHashSolution solution =
new EthHashSolution(
final PoWSolution solution =
new PoWSolution(
Bytes.fromHexString(req.getRequiredParameter(0, String.class)).getLong(0),
req.getRequiredParameter(2, Hash.class),
Bytes.fromHexString(req.getRequiredParameter(1, String.class)).toArrayUnsafe());
if (Arrays.equals(currentInput.getPrePowHash(), solution.getPowHash())) {
null,
Bytes.fromHexString(req.getRequiredParameter(1, String.class)));
if (currentInput.getPrePowHash().equals(solution.getPowHash())) {
result = submitCallback.apply(solution);
}
@ -141,12 +141,12 @@ public class Stratum1EthProxyProtocol implements StratumProtocol {
}
@Override
public void setCurrentWorkTask(final EthHashSolverInputs input) {
public void setCurrentWorkTask(final PoWSolverInputs input) {
this.currentInput = input;
}
@Override
public void setSubmitCallback(final Function<EthHashSolution, Boolean> submitSolutionCallback) {
public void setSubmitCallback(final Function<PoWSolution, Boolean> 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.internal.JsonRpcRequest;
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.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.DirectAcyclicGraphSeed;
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
@ -60,8 +59,8 @@ public class Stratum1Protocol implements StratumProtocol {
private final MiningCoordinator miningCoordinator;
private final String extranonce;
private EthHashSolverInputs currentInput;
private Function<EthHashSolution, Boolean> submitCallback;
private PoWSolverInputs currentInput;
private Function<PoWSolution, Boolean> submitCallback;
private final Supplier<String> jobIdSupplier;
private final Supplier<String> subscriptionIdCreator;
private final List<StratumConnection> activeConnections = new ArrayList<>();
@ -83,16 +82,16 @@ public class Stratum1Protocol implements StratumProtocol {
final MiningCoordinator miningCoordinator,
final Supplier<String> jobIdSupplier,
final Supplier<String> subscriptionIdCreator) {
if (!(miningCoordinator instanceof EthHashMiningCoordinator)) {
if (!(miningCoordinator instanceof PoWMiningCoordinator)) {
throw new IllegalArgumentException(
"Stratum1 requires an EthHashMiningCoordinator not "
"Stratum1 requires an PoWMiningCoordinator not "
+ ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName()));
}
this.extranonce = extranonce;
this.miningCoordinator = miningCoordinator;
this.jobIdSupplier = jobIdSupplier;
this.subscriptionIdCreator = subscriptionIdCreator;
this.epochCalculator = ((EthHashMiningCoordinator) miningCoordinator).getEpochCalculator();
this.epochCalculator = ((PoWMiningCoordinator) miningCoordinator).getEpochCalculator();
}
@Override
@ -180,12 +179,13 @@ public class Stratum1Protocol implements StratumProtocol {
throws IOException {
LOG.debug("Miner submitted solution {}", message);
boolean result = false;
final EthHashSolution solution =
new EthHashSolution(
final PoWSolution solution =
new PoWSolution(
Bytes.fromHexString(message.getRequiredParameter(2, String.class)).getLong(0),
Hash.fromHexString(message.getRequiredParameter(4, String.class)),
Bytes.fromHexString(message.getRequiredParameter(3, String.class)).toArrayUnsafe());
if (Arrays.equals(currentInput.getPrePowHash(), solution.getPowHash())) {
null,
Bytes.fromHexString(message.getRequiredParameter(3, String.class)));
if (currentInput.getPrePowHash().equals(solution.getPowHash())) {
result = submitCallback.apply(solution);
}
@ -205,7 +205,7 @@ public class Stratum1Protocol implements StratumProtocol {
}
@Override
public void setCurrentWorkTask(final EthHashSolverInputs input) {
public void setCurrentWorkTask(final PoWSolverInputs input) {
this.currentInput = input;
LOG.debug("Sending new work to miners: {}", input);
for (StratumConnection conn : activeConnections) {
@ -214,7 +214,7 @@ public class Stratum1Protocol implements StratumProtocol {
}
@Override
public void setSubmitCallback(final Function<EthHashSolution, Boolean> submitSolutionCallback) {
public void setSubmitCallback(final Function<PoWSolution, Boolean> 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.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolution;
import org.hyperledger.besu.ethereum.mainnet.EthHashSolverInputs;
import org.hyperledger.besu.ethereum.mainnet.PoWSolution;
import org.hyperledger.besu.ethereum.mainnet.PoWSolverInputs;
import java.io.IOException;
import java.util.function.Function;
@ -63,9 +63,9 @@ public interface StratumProtocol {
*
* @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(
final JsonMapper mapper,

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

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

Loading…
Cancel
Save