Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

[WIP] Adds GPU Mining to Pantheon #1946

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions GPU-MINING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Pantheon Ethereum Client

## Mining Software

EthMiner is recommended. You can [download EthMiner from Github](https://github.com/ethereum-mining/ethminer), available for Windows, Linux, and MacOS.

## GPU Mining with Pantheon

To mine with EthMiner, start Pantheon with HTTP RPC enabled, setting cors to the IP of the miners you want mining from Pantheon.

If running in a development environment, the starting flags would be the following:

```
./bin/pantheon --network=dev --gpu-mining-enabled --rpc-http-enabled --rpc-http-cors-origins=all
```

This starts Pantheon in a developer network with JSON RPC available at localhost:8545, with cors set to all IPs.

Once initiated, you must wait until work is available before starting EthMiner. Once work is availabe, start EthMiner pointing to the JSON RPC endpoint. From the directory containing EthMiner:

```
<EthMiner> -P http://<Your Ethereum Address>@<Host>:<Port>
```

An example on Windows would look like the following:

```
ethminer.exe -P http://[email protected]:8545
```

Other computers can mine to this Pantheon node if cors allows it, by setting the host to the IP of the computer/server running Pantheon, or the hostname of the server running Pantheon.

You can test when work is available using CURL in a command line:

```
curl -X POST --data "{"jsonrpc":"2.0","method":"eth_getWork","params":[],"id":73}" localhost:8545
```

From Windows Command Prompt, qoutes are special characters.

```
curl -X POST --data "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getWork\",\"params\":[],\"id\":73}" localhost:8545
```

If work is available for mining, you should see a response similar to the following:

```
{"jsonrpc":"2.0","id":73,"result":["0xc9a815cfff9186b3b1ebb286ff71156b2605c4ca45e2413418c8054688011706","0x0000000000000000000000000000000000000000000000000000000000000000","0x028f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f"]}
```

If EthMiner disappears after building or downloading, check with your anti-virus software, allow EthMiner to run, and redownload.
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ private String serialise(final JsonRpcResponse response) {
return EMPTY_RESPONSE;
}

return Json.encodePrettily(response);
return Json.encode(response);
}

@SuppressWarnings("rawtypes")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.EthSendTransaction;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.EthSyncing;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.EthUninstallFilter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.EthSubmitLogin;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.NetEnode;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.NetListening;
Expand Down Expand Up @@ -260,6 +261,7 @@ public Map<String, JsonRpcMethod> methods(
new EthProtocolVersion(supportedCapabilities),
new EthGasPrice(miningCoordinator),
new EthGetWork(miningCoordinator),
new EthSubmitLogin(),
new EthHashrate(miningCoordinator),
new EthChainId(protocolSchedule.getChainId()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public enum RpcMethod {
ETH_SEND_RAW_TRANSACTION("eth_sendRawTransaction"),
ETH_SEND_TRANSACTION("eth_sendTransaction"),
ETH_SUBSCRIBE("eth_subscribe"),
ETH_SUBMIT_LOGIN("eth_submitLogin"),
ETH_SYNCING("eth_syncing"),
ETH_UNINSTALL_FILTER("eth_uninstallFilter"),
ETH_UNSUBSCRIBE("eth_unsubscribe"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class EthGetWork implements JsonRpcMethod {

private final MiningCoordinator miner;
private static final Logger LOG = getLogger();
private Boolean solverWasPresent = false;
private String[] storedResult;

public EthGetWork(final MiningCoordinator miner) {
this.miner = miner;
Expand All @@ -54,7 +56,11 @@ public JsonRpcResponse response(final JsonRpcRequest req) {
"0x" + BaseEncoding.base16().lowerCase().encode(dagSeed),
rawResult.getTarget().toHexString()
};
solverWasPresent = true;
storedResult = result;
return new JsonRpcSuccessResponse(req.getId(), result);
} else if (solverWasPresent) {
return new JsonRpcSuccessResponse(req.getId(), storedResult);
} else {
LOG.trace("Mining is not operational, eth_getWork request cannot be processed");
return new JsonRpcErrorResponse(req.getId(), JsonRpcError.NO_MINING_WORK_FOUND);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2018 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.
*/
package tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods;

import tech.pegasys.pantheon.ethereum.jsonrpc.RpcMethod;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;

public class EthSubmitLogin implements JsonRpcMethod {

@Override
public String getName() {
return RpcMethod.ETH_SUBMIT_LOGIN.getMethodName();
}

@Override
public JsonRpcResponse response(final JsonRpcRequest req) {
// Confirm login request
boolean result = true;
return new JsonRpcSuccessResponse(req.getId(), result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,11 @@ void setBannedNodeIds(final List<String> values) {
description = "Set if node will perform mining (default: ${DEFAULT-VALUE})")
private final Boolean isMiningEnabled = false;

@Option(
names = {"--gpu-mining-enabled"},
description = "Set if node supports GPU mining software (default: ${DEFAULT-VALUE})")
private final Boolean isGpuMiningEnabled = false;

@Option(
names = {"--miner-coinbase"},
description =
Expand Down Expand Up @@ -846,6 +851,13 @@ private PantheonCommand checkOptions() {
!isMiningEnabled,
asList("--miner-coinbase", "--min-gas-price", "--miner-extra-data"));

checkOptionDependencies(
logger,
commandLine,
"--gpu-mining-enabled",
!isGpuMiningEnabled,
asList("--rpc-http-cors-origins", "--rpc-http-enabled"));

checkOptionDependencies(
logger,
commandLine,
Expand All @@ -867,6 +879,12 @@ private PantheonCommand checkOptions() {
"Unable to mine without a valid coinbase. Either disable mining (remove --miner-enabled)"
+ "or specify the beneficiary of mining (via --miner-coinbase <Address>)");
}
// noinspection ConstantConditions
if (isGpuMiningEnabled && isRpcHttpEnabled == null) {
throw new ParameterException(
this.commandLine,
"GPU mining requires RPC to be enabled, and CORS to be set to allow your miner's IP address");
}
return this;
}

Expand Down Expand Up @@ -929,22 +947,41 @@ public PantheonController<?> buildController() {

public PantheonControllerBuilder<?> getControllerBuilder() {
try {
return controllerBuilderFactory
.fromEthNetworkConfig(updateNetworkConfig(getNetwork()))
.synchronizerConfiguration(buildSyncConfig())
.ethProtocolConfiguration(ethProtocolOptions.toDomainObject())
.rocksDbConfiguration(buildRocksDbConfiguration())
.dataDirectory(dataDir())
.miningParameters(
new MiningParameters(coinbase, minTransactionGasPrice, extraData, isMiningEnabled))
.transactionPoolConfiguration(buildTransactionPoolConfiguration())
.nodePrivateKeyFile(nodePrivateKeyFile())
.metricsSystem(metricsSystem.get())
.privacyParameters(privacyParameters())
.clock(Clock.systemUTC())
.isRevertReasonEnabled(isRevertReasonEnabled)
.isPruningEnabled(isPruningEnabled)
.pruningConfiguration(buildPruningConfiguration());
if (isGpuMiningEnabled) {
return controllerBuilderFactory
.fromEthNetworkConfig(updateNetworkConfig(getNetwork()))
.synchronizerConfiguration(buildSyncConfig())
.ethProtocolConfiguration(ethProtocolOptions.toDomainObject())
.rocksDbConfiguration(buildRocksDbConfiguration())
.dataDirectory(dataDir())
.miningParameters(
new MiningParameters(Address.ZERO, minTransactionGasPrice, extraData, isGpuMiningEnabled))
.transactionPoolConfiguration(buildTransactionPoolConfiguration())
.nodePrivateKeyFile(nodePrivateKeyFile())
.metricsSystem(metricsSystem.get())
.privacyParameters(privacyParameters())
.clock(Clock.systemUTC())
.isRevertReasonEnabled(isRevertReasonEnabled)
.isPruningEnabled(isPruningEnabled)
.pruningConfiguration(buildPruningConfiguration());
} else {
return controllerBuilderFactory
.fromEthNetworkConfig(updateNetworkConfig(getNetwork()))
.synchronizerConfiguration(buildSyncConfig())
.ethProtocolConfiguration(ethProtocolOptions.toDomainObject())
.rocksDbConfiguration(buildRocksDbConfiguration())
.dataDirectory(dataDir())
.miningParameters(
new MiningParameters(coinbase, minTransactionGasPrice, extraData, isMiningEnabled))
.transactionPoolConfiguration(buildTransactionPoolConfiguration())
.nodePrivateKeyFile(nodePrivateKeyFile())
.metricsSystem(metricsSystem.get())
.privacyParameters(privacyParameters())
.clock(Clock.systemUTC())
.isRevertReasonEnabled(isRevertReasonEnabled)
.isPruningEnabled(isPruningEnabled)
.pruningConfiguration(buildPruningConfiguration());
}
} catch (final IOException e) {
throw new ExecutionException(this.commandLine, "Invalid path", e);
}
Expand Down