Skip to content
This repository has been archived by the owner on Nov 30, 2023. It is now read-only.

Commit

Permalink
JSON-RPC API (ethereum-mining#253)
Browse files Browse the repository at this point in the history
Adding claymore compatible json-rpc api. supporting miner_getstat1 and miner_restart  commands
  • Loading branch information
smurfy authored Sep 5, 2017
1 parent f0ab0f6 commit 94c60e5
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ before_install:
- if [ "$TRAVIS_OS_NAME" = linux ]; then scripts/install_cmake.sh; fi
- pip install requests
script:
- cmake -DHUNTER_JOBS_NUMBER=4 -DETHASHCUDA=$CUDA -DETHASHCL=ON -H. -Bbuild
- cmake -DHUNTER_JOBS_NUMBER=4 -DETHASHCUDA=$CUDA -DETHASHCL=ON -DAPICORE=ON -H. -Bbuild
- cmake --build build -- -j4
- build/ethminer/ethminer --list-devices -G
- build/ethminer/ethminer --list-devices -U
Expand Down
13 changes: 10 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ set(HUNTER_CONFIGURATION_TYPES Release)
set(HUNTER_CACHE_SERVERS "https://github.com/ethereum/hunter-cache")
include(HunterGate)
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.19.49.tar.gz"
SHA1 "dd8a16d1beeede2159c58f4cd478ac010545686b"
URL "https://github.com/ruslo/hunter/archive/v0.19.86.tar.gz"
SHA1 "aafb99b93d466f963d53a39271f20d5074996cb0"
LOCAL
)

Expand Down Expand Up @@ -59,7 +59,7 @@ option(ETHASHCL "Build with OpenCL mining" ON)
option(ETHASHCUDA "Build with CUDA mining" OFF)
option(ETHSTRATUM "Build with Stratum protocol support" ON)
option(ETHDBUS "Build with D-Bus support" OFF)

option(APICORE "Build with API Server support" ON)

# propagates CMake configuration options to the compiler
function(configureProject)
Expand All @@ -75,6 +75,9 @@ function(configureProject)
if (ETHDBUS)
add_definitions(-DETH_DBUS)
endif()
if (APICORE)
add_definitions(-DAPI_CORE)
endif()
endfunction()

function(createBuildInfo)
Expand Down Expand Up @@ -132,6 +135,7 @@ message("-- ETHASHCL Build OpenCL components ${ETHASHCL
message("-- ETHASHCUDA Build CUDA components ${ETHASHCUDA}")
message("-- ETHSTRATUM Build Stratum components ${ETHSTRATUM}")
message("-- ETHDBUS Build D-Bus components ${ETHDBUS}")
message("-- APICORE Build API Server components ${APICORE}")
message("------------------------------------------------------------------------")
message("")

Expand All @@ -150,6 +154,9 @@ endif ()
if(ETHSTRATUM)
add_subdirectory(libstratum)
endif()
if (APICORE)
add_subdirectory(libapicore)
endif()
add_subdirectory(libethcore)
add_subdirectory(ethminer)

Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ install: |
nvcc -V
pip install requests
before_build:
- cmake -G "Visual Studio 14 2015 Win64" -H. -Bbuild -DETHASHCUDA=ON
- cmake -G "Visual Studio 14 2015 Win64" -H. -Bbuild -DETHASHCUDA=ON -DAPICORE=ON
build_script:
- cmake --build build --config %CONFIGURATION%
after_build:
Expand Down
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- run: scripts/install_cmake.sh --prefix /usr
- restore_cache:
key: hunter
- run: cmake -DHUNTER_JOBS_NUMBER=4 -DETHASHCUDA=ON -H. -Bbuild
- run: cmake -DHUNTER_JOBS_NUMBER=4 -DETHASHCUDA=ON -DAPICORE=ON -H. -Bbuild
- save_cache:
key: hunter
paths:
Expand Down
3 changes: 2 additions & 1 deletion cmake/Hunter/config.cmake
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
hunter_config(CURL VERSION ${HUNTER_CURL_VERSION} CMAKE_ARGS HTTP_ONLY=ON CMAKE_USE_OPENSSL=OFF CMAKE_USE_LIBSSH2=OFF)
hunter_config(CURL VERSION ${HUNTER_CURL_VERSION} CMAKE_ARGS HTTP_ONLY=ON CMAKE_USE_OPENSSL=OFF CMAKE_USE_LIBSSH2=OFF)
hunter_config(libjson-rpc-cpp VERSION ${HUNTER_libjson-rpc-cpp_VERSION} CMAKE_ARGS TCP_SOCKET_SERVER=ON)
3 changes: 3 additions & 0 deletions ethminer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ if(ETHDBUS)
target_link_libraries(${EXECUTABLE} ${DBUS_LIBRARIES})
endif()

if(APICORE)
target_link_libraries(${EXECUTABLE} apicore)
endif()

if(ETHSTRATUM)
target_link_libraries(${EXECUTABLE} ethstratum)
Expand Down
32 changes: 31 additions & 1 deletion ethminer/MinerAux.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
#if ETH_DBUS
#include "DBusInt.h"
#endif
#if API_CORE
#include <libapicore/Api.h>
#endif

using namespace std;
using namespace dev;
Expand Down Expand Up @@ -243,6 +246,12 @@ class MinerCLI
}

#endif
#if API_CORE
else if ((arg == "--api-port") && i + 1 < argc)
{
m_api_port = atoi(argv[++i]);
}
#endif
#if ETH_ETHASHCL
else if (arg == "--opencl-platform" && i + 1 < argc)
try {
Expand Down Expand Up @@ -588,6 +597,9 @@ class MinerCLI
<< " sync - Instruct CUDA to block the CPU thread on a synchronization primitive when waiting for the results from the device." << endl
<< " --cuda-devices <0 1 ..n> Select which CUDA GPUs to mine on. Default is to use all" << endl
<< " --cuda-parallel-hash <1 2 ..8> Define how many hashes to calculate in a kernel, can be scaled to achieve better performance. Default=4" << endl
#endif
#if API_CORE
<< " --api-port Set the api port, the miner should listen to. Use 0 to disable. Default=0, use negative numbers to run in readonly mode. for example -3333." << endl
#endif
;
}
Expand Down Expand Up @@ -758,6 +770,11 @@ class MinerCLI

h256 id = h256::random();
Farm f;

#if API_CORE
Api api(this->m_api_port, f);
#endif

f.setSealers(sealers);
if (_m == MinerType::CL)
f.start("opencl", false);
Expand Down Expand Up @@ -890,7 +907,11 @@ class MinerCLI
m_farmRecheckPeriod = m_defaultStratumFarmRecheckPeriod;

Farm f;


#if API_CORE
Api api(this->m_api_port, f);
#endif

// this is very ugly, but if Stratum Client V2 tunrs out to be a success, V1 will be completely removed anyway
if (m_stratumClientVersion == 1) {
EthStratumClient client(&f, m_minerType, m_farmURL, m_port, m_user, m_pass, m_maxFarmRetries, m_worktimeout, m_stratumProtocol, m_email);
Expand All @@ -917,6 +938,9 @@ class MinerCLI
}
return false;
});
f.onMinerRestart([&](){
client.reconnect();
});

while (client.isRunning())
{
Expand Down Expand Up @@ -964,6 +988,9 @@ class MinerCLI
client.submit(sol);
return false;
});
f.onMinerRestart([&](){
client.reconnect();
});

while (client.isRunning())
{
Expand Down Expand Up @@ -1040,6 +1067,9 @@ class MinerCLI
unsigned m_defaultStratumFarmRecheckPeriod = 2000;
bool m_farmRecheckSet = false;
int m_worktimeout = 180;
#if API_CORE
int m_api_port = 0;
#endif

#if ETH_STRATUM
bool m_report_stratum_hashrate = false;
Expand Down
20 changes: 20 additions & 0 deletions libapicore/Api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "Api.h"

Api::Api(const int &port, Farm &farm): m_farm(farm)
{
int portNumber = port;
bool readonly = true;

// > 0 = rw, < 0 = ro, 0 = disabled
if (portNumber > 0) {
readonly = false;
} else if(portNumber < 0) {
portNumber = -portNumber;
}

if (portNumber > 0) {
TcpSocketServer *conn = new TcpSocketServer("0.0.0.0", portNumber);
this->m_server = new ApiServer(conn, JSONRPC_SERVER_V2, this->m_farm, readonly);
this->m_server->StartListening();
}
}
22 changes: 22 additions & 0 deletions libapicore/Api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef _API_H_
#define _API_H_

#include "ApiServer.h"
#include <libethcore/Farm.h>
#include <libethcore/Miner.h>
#include <jsonrpccpp/server/connectors/tcpsocketserver.h>

using namespace jsonrpc;
using namespace dev;
using namespace dev::eth;

class Api
{
public:
Api(const int &port, Farm &farm);
private:
ApiServer *m_server;
Farm &m_farm;
};

#endif //_API_H_
69 changes: 69 additions & 0 deletions libapicore/ApiServer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "ApiServer.h"
#include "BuildInfo.h"

ApiServer::ApiServer(AbstractServerConnector *conn, serverVersion_t type, Farm &farm, bool &readonly) : AbstractServer(*conn, type), m_farm(farm)
{
this->bindAndAddMethod(Procedure("miner_getstat1", PARAMS_BY_NAME, JSON_OBJECT, NULL), &ApiServer::getMinerStat1);
if (!readonly) {
this->bindAndAddMethod(Procedure("miner_restart", PARAMS_BY_NAME, JSON_OBJECT, NULL), &ApiServer::doMinerRestart);
this->bindAndAddMethod(Procedure("miner_reboot", PARAMS_BY_NAME, JSON_OBJECT, NULL), &ApiServer::doMinerReboot);
}
}

void ApiServer::getMinerStat1(const Json::Value& request, Json::Value& response)
{
(void) request; // unused

auto runningTime = std::chrono::duration_cast<std::chrono::minutes>(steady_clock::now() - this->m_started);

SolutionStats s = this->m_farm.getSolutionStats();
WorkingProgress p = this->m_farm.miningProgress();

ostringstream totalMhEth;
ostringstream totalMhDcr;
ostringstream detailedMhEth;
ostringstream detailedMhDcr;
ostringstream tempAndFans;
ostringstream invalidStats;

totalMhEth << std::fixed << std::setprecision(0) << (p.rate() / 1000.0f) << ";" << s.getAccepts() << ";" << s.getRejects();
totalMhDcr << "0;0;0"; // DualMining not supported
invalidStats << s.getFailures() << ";0"; // Invalid + Pool switches
invalidStats << ";0;0"; // DualMining not supported

int gpuIndex = 0;
int numGpus = p.minersHashes.size();
for (auto const& i: p.minersHashes)
{
detailedMhEth << std::fixed << std::setprecision(0) << (p.minerRate(i) / 1000.0f) << (((numGpus -1) > gpuIndex) ? ";" : "");
detailedMhDcr << "off" << (((numGpus -1) > gpuIndex) ? ";" : ""); // DualMining not supported
tempAndFans << "50;50" <<(((numGpus -1) > gpuIndex) ? ";" : ""); // Fetching Temp and Fans not supported
gpuIndex++;
}

response[0] = ETH_PROJECT_VERSION; //miner version.
response[1] = toString(runningTime.count()); // running time, in minutes.
response[2] = totalMhEth.str(); // total ETH hashrate in MH/s, number of ETH shares, number of ETH rejected shares.
response[3] = detailedMhEth.str(); // detailed ETH hashrate for all GPUs.
response[4] = totalMhDcr.str(); // total DCR hashrate in MH/s, number of DCR shares, number of DCR rejected shares.
response[5] = detailedMhDcr.str(); // detailed DCR hashrate for all GPUs.
response[6] = tempAndFans.str(); // Temperature and Fan speed(%) pairs for all GPUs.
response[7] = ""; // current mining pool. For dual mode, there will be two pools here.
response[8] = invalidStats.str(); // number of ETH invalid shares, number of ETH pool switches, number of DCR invalid shares, number of DCR pool switches.
}

void ApiServer::doMinerRestart(const Json::Value& request, Json::Value& response)
{
(void) request; // unused
(void) response; // unused

this->m_farm.restart();
}

void ApiServer::doMinerReboot(const Json::Value& request, Json::Value& response)
{
(void) request; // unused
(void) response; // unused

// Not supported
}
25 changes: 25 additions & 0 deletions libapicore/ApiServer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef _APISERVER_H_
#define _APISERVER_H_

#include <libethcore/Farm.h>
#include <libethcore/Miner.h>
#include <jsonrpccpp/server.h>

using namespace jsonrpc;
using namespace dev;
using namespace dev::eth;
using namespace std::chrono;

class ApiServer : public AbstractServer<ApiServer>
{
public:
ApiServer(AbstractServerConnector *conn, serverVersion_t type, Farm &farm, bool &readonly);
private:
steady_clock::time_point m_started = steady_clock::now();
Farm &m_farm;
void getMinerStat1(const Json::Value& request, Json::Value& response);
void doMinerRestart(const Json::Value& request, Json::Value& response);
void doMinerReboot(const Json::Value& request, Json::Value& response);
};

#endif //_APISERVER_H_
8 changes: 8 additions & 0 deletions libapicore/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
set(SOURCES
Api.h Api.cpp
ApiServer.h ApiServer.cpp
)

add_library(apicore ${SOURCES})
target_link_libraries(apicore devcore libjson-rpc-cpp::server)
target_include_directories(apicore PRIVATE ..)
18 changes: 18 additions & 0 deletions libethcore/Farm.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class Farm: public FarmFace
}
m_isMining = true;
m_lastSealer = _sealer;
b_lastMixed = mixed;
resetTimer();
return true;
}
Expand All @@ -122,6 +123,19 @@ class Farm: public FarmFace
m_isMining = false;
}

/**
* @brief Stop all mining activities and Starts them again
*/
void restart()
{
stop();
start(m_lastSealer, b_lastMixed);

if (m_onMinerRestart) {
m_onMinerRestart();
}
}

bool isMining() const
{
return m_isMining;
Expand Down Expand Up @@ -191,13 +205,15 @@ class Farm: public FarmFace
}

using SolutionFound = std::function<bool(Solution const&)>;
using MinerRestart = std::function<void()>;

/**
* @brief Provides a valid header based upon that received previously with setWork().
* @param _bi The now-valid header.
* @return true if the header was good and that the Farm should pause until more work is submitted.
*/
void onSolutionFound(SolutionFound const& _handler) { m_onSolutionFound = _handler; }
void onMinerRestart(MinerRestart const& _handler) { m_onMinerRestart = _handler; }

WorkPackage work() const { Guard l(x_minerWork); return m_work; }

Expand Down Expand Up @@ -230,9 +246,11 @@ class Farm: public FarmFace
std::chrono::steady_clock::time_point m_lastStart;

SolutionFound m_onSolutionFound;
MinerRestart m_onMinerRestart;

std::map<std::string, SealerDescriptor> m_sealers;
std::string m_lastSealer;
bool b_lastMixed = false;

mutable SolutionStats m_solutionStats;

Expand Down

0 comments on commit 94c60e5

Please sign in to comment.