Skip to content

Commit

Permalink
Keccak256 mining (hyperledger#1882)
Browse files Browse the repository at this point in the history
* Decouple PoW from ethash

Signed-off-by: Antoine Toulme <[email protected]>

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

Signed-off-by: Antoine Toulme <[email protected]>

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

Signed-off-by: Antoine Toulme <[email protected]>

* Make the PoWHasher hash function a bit easier to understand

Signed-off-by: Antoine Toulme <[email protected]>

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

Signed-off-by: Antoine Toulme <[email protected]>

* support fixed difficulty for keccak mining

Signed-off-by: Antoine Toulme <[email protected]>

* Fix the dev network config

Signed-off-by: Antoine Toulme <[email protected]>

* Add comment to KeccakHasher

Signed-off-by: Antoine Toulme <[email protected]>

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

Signed-off-by: Antoine Toulme <[email protected]>

* spotless

Signed-off-by: Antoine Toulme <[email protected]>

* fix test expectations

Signed-off-by: Antoine Toulme <[email protected]>

* Fix javadoc issue

Signed-off-by: Antoine Toulme <[email protected]>

* add acceptance test using keccak mining

Signed-off-by: Antoine Toulme <[email protected]>

* add changelog entry

Signed-off-by: Antoine Toulme <[email protected]>

* Address code review comments

Signed-off-by: Antoine Toulme <[email protected]>
Signed-off-by: Richard Hart <[email protected]>
  • Loading branch information
atoulme authored and RichardH92 committed Mar 29, 2021
1 parent f09babb commit 15d37a2
Show file tree
Hide file tree
Showing 91 changed files with 1,147 additions and 492 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
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;
Expand Down Expand Up @@ -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;
Expand All @@ -123,6 +125,7 @@ public BesuNode(
final Optional<PermissioningConfiguration> permissioningConfiguration,
final Optional<String> keyfilePath,
final boolean devMode,
final NetworkName network,
final GenesisConfigurationProvider genesisConfigProvider,
final boolean p2pEnabled,
final NetworkingConfiguration networkingConfiguration,
Expand Down Expand Up @@ -156,6 +159,7 @@ public BesuNode(
this.permissioningConfiguration = permissioningConfiguration;
this.genesisConfigProvider = genesisConfigProvider;
this.devMode = devMode;
this.network = network;
this.p2pEnabled = p2pEnabled;
this.networkingConfiguration = networkingConfiguration;
this.discoveryEnabled = discoveryEnabled;
Expand Down Expand Up @@ -579,6 +583,10 @@ public boolean isDevMode() {
return devMode;
}

public NetworkName getNetwork() {
return network;
}

public boolean isSecp256k1Native() {
return secp256k1Native;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ public void startNode(final BesuNode node) {
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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -193,4 +197,8 @@ public Optional<PrivacyParameters> getPrivacyParameters() {
public List<String> getRunCommand() {
return runCommand;
}

public NetworkName getNetwork() {
return network;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
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;
Expand Down Expand Up @@ -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<>();
Expand Down Expand Up @@ -165,6 +167,11 @@ public BesuNodeConfigurationBuilder metricsConfiguration(
return this;
}

public BesuNodeConfigurationBuilder network(final NetworkName network) {
this.network = network;
return this;
}

public BesuNodeConfigurationBuilder webSocketEnabled() {
final WebSocketConfiguration config = WebSocketConfiguration.createDefault();
config.setEnabled(true);
Expand Down Expand Up @@ -295,6 +302,7 @@ public BesuNodeConfiguration build() {
permissioningConfiguration,
Optional.ofNullable(keyFilePath),
devMode,
network,
genesisConfigProvider,
p2pEnabled,
networkingConfiguration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public BesuNode create(final BesuNodeConfiguration config) throws IOException {
config.getPermissioningConfiguration(),
config.getKeyFilePath(),
config.isDevMode(),
config.getNetwork(),
config.getGenesisConfigProvider(),
config.isP2pEnabled(),
config.getNetworkingConfiguration(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public PrivacyNode(final PrivacyNodeConfiguration privacyConfiguration, final Ve
besuConfig.getPermissioningConfiguration(),
besuConfig.getKeyFilePath(),
besuConfig.isDevMode(),
besuConfig.getNetwork(),
besuConfig.getGenesisConfigProvider(),
besuConfig.isP2pEnabled(),
besuConfig.getNetworkingConfiguration(),
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
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;
Expand Down Expand Up @@ -119,9 +120,9 @@ private void setOptionalFields(
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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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";
Expand Down Expand Up @@ -154,6 +156,9 @@ public static EthNetworkConfig getNetworkConfig(final NetworkName networkName) {
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);
Expand Down Expand Up @@ -194,6 +199,8 @@ public static String jsonConfig(final NetworkName network) {
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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ public enum NetworkName {
CLASSIC,
KOTTI,
MORDOR,
YOLO_V3
YOLO_V3,
ECIP1049_DEV
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
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;
Expand Down Expand Up @@ -191,7 +192,7 @@ BesuControllerBuilder fromGenesisConfig(
genesisConfig.getConfigOptions(genesisConfigOverrides);
final BesuControllerBuilder builder;

if (configOptions.isEthHash()) {
if (configOptions.getPowAlgorithm() != PowAlgorithm.UNSUPPORTED) {
builder = new MainnetBesuControllerBuilder();
} else if (configOptions.isIbft2()) {
builder = new IbftBesuControllerBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

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;
Expand All @@ -42,8 +42,9 @@ protected MiningCoordinator createMiningCoordinator(
final MiningParameters miningParameters,
final SyncState syncState,
final EthProtocolManager ethProtocolManager) {
final EthHashMinerExecutor executor =
new EthHashMinerExecutor(

final PoWMinerExecutor executor =
new PoWMinerExecutor(
protocolContext,
protocolSchedule,
transactionPool.getPendingTransactions(),
Expand All @@ -55,8 +56,8 @@ protected MiningCoordinator createMiningCoordinator(
gasLimitCalculator,
epochCalculator);

final EthHashMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(
final PoWMiningCoordinator miningCoordinator =
new PoWMiningCoordinator(
protocolContext.getBlockchain(),
executor,
syncState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -95,6 +97,8 @@ public void setup() {
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()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ public static GenesisConfigFile development() {
}
}

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));
}
Expand Down
Loading

0 comments on commit 15d37a2

Please sign in to comment.