stratum: improve and add new methods for pool benchmark/stats
will allow to submit some device benchmark data to compute algo power usage and profitability. Introduce two new methods mining.get_algo and mining_get_stats These methods will be used with yiimp stratum with a special benchmark option Note: only the first card is handled for the moment. also add stratum mining.ping support (like cgminer 4.7.1+) and prevent disconnect on unknown methods, reply it is unsupported.
This commit is contained in:
parent
81051dd75f
commit
dcbcf6ba7e
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
ccMiner release 1.7.6 (May 2016) "Under dev..."
|
ccMiner release 1.7.6 (May 2016) "DCR vote & pool device stats"
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
|
|
||||||
***************************************************************
|
***************************************************************
|
||||||
@ -238,10 +238,11 @@ features.
|
|||||||
|
|
||||||
>>> RELEASE HISTORY <<<
|
>>> RELEASE HISTORY <<<
|
||||||
|
|
||||||
May XXth 2016 v1.7.6
|
May 15th 2016 v1.7.6
|
||||||
Decred vote support
|
Decred vote support
|
||||||
X17 cleanup and improvement
|
X17 cleanup and improvement
|
||||||
...
|
Add mining.ping stratum method and handle unknown methods
|
||||||
|
Implement a pool stats/benchmark mode (-p stats on yiimp)
|
||||||
|
|
||||||
Mar. 13th 2016 v1.7.5
|
Mar. 13th 2016 v1.7.5
|
||||||
Blake2S Algo (NEVA/OXEN)
|
Blake2S Algo (NEVA/OXEN)
|
||||||
|
2
api.cpp
2
api.cpp
@ -101,8 +101,6 @@ extern struct stratum_ctx stratum;
|
|||||||
extern int num_cpus;
|
extern int num_cpus;
|
||||||
extern float cpu_temp(int);
|
extern float cpu_temp(int);
|
||||||
extern uint32_t cpu_clock(int);
|
extern uint32_t cpu_clock(int);
|
||||||
// cuda.cpp
|
|
||||||
extern int cuda_gpu_clocks(struct cgpu_info *gpu);
|
|
||||||
|
|
||||||
char driver_version[32] = { 0 };
|
char driver_version[32] = { 0 };
|
||||||
|
|
||||||
|
@ -204,6 +204,8 @@ char *opt_api_allow = strdup("127.0.0.1"); /* 0.0.0.0 for all ips */
|
|||||||
int opt_api_remote = 0;
|
int opt_api_remote = 0;
|
||||||
int opt_api_listen = 4068; /* 0 to disable */
|
int opt_api_listen = 4068; /* 0 to disable */
|
||||||
|
|
||||||
|
bool opt_stratum_stats = false;
|
||||||
|
|
||||||
static char const usage[] = "\
|
static char const usage[] = "\
|
||||||
Usage: " PROGRAM_NAME " [OPTIONS]\n\
|
Usage: " PROGRAM_NAME " [OPTIONS]\n\
|
||||||
Options:\n\
|
Options:\n\
|
||||||
|
5
cuda.cpp
5
cuda.cpp
@ -52,6 +52,11 @@ int cuda_num_devices()
|
|||||||
return GPU_N;
|
return GPU_N;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cuda_version()
|
||||||
|
{
|
||||||
|
return (int) CUDART_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
void cuda_devicenames()
|
void cuda_devicenames()
|
||||||
{
|
{
|
||||||
cudaError_t err;
|
cudaError_t err;
|
||||||
|
3
miner.h
3
miner.h
@ -459,6 +459,7 @@ extern bool want_longpoll;
|
|||||||
extern bool have_longpoll;
|
extern bool have_longpoll;
|
||||||
extern bool want_stratum;
|
extern bool want_stratum;
|
||||||
extern bool have_stratum;
|
extern bool have_stratum;
|
||||||
|
extern bool opt_stratum_stats;
|
||||||
extern char *opt_cert;
|
extern char *opt_cert;
|
||||||
extern char *opt_proxy;
|
extern char *opt_proxy;
|
||||||
extern long opt_proxy_type;
|
extern long opt_proxy_type;
|
||||||
@ -493,7 +494,9 @@ void cuda_devicenames();
|
|||||||
void cuda_reset_device(int thr_id, bool *init);
|
void cuda_reset_device(int thr_id, bool *init);
|
||||||
void cuda_shutdown();
|
void cuda_shutdown();
|
||||||
int cuda_finddevice(char *name);
|
int cuda_finddevice(char *name);
|
||||||
|
int cuda_version();
|
||||||
void cuda_print_devices();
|
void cuda_print_devices();
|
||||||
|
int cuda_gpu_clocks(struct cgpu_info *gpu);
|
||||||
int cuda_available_memory(int thr_id);
|
int cuda_available_memory(int thr_id);
|
||||||
|
|
||||||
uint32_t cuda_default_throughput(int thr_id, uint32_t defcount);
|
uint32_t cuda_default_throughput(int thr_id, uint32_t defcount);
|
||||||
|
@ -196,6 +196,9 @@ bool pool_switch(int thr_id, int pooln)
|
|||||||
|
|
||||||
want_stratum = have_stratum = (p->type & POOL_STRATUM) != 0;
|
want_stratum = have_stratum = (p->type & POOL_STRATUM) != 0;
|
||||||
|
|
||||||
|
// yiimp stats reporting
|
||||||
|
opt_stratum_stats = (strstr(p->pass, "stats") != NULL) || (strcmp(p->user, "test") == 0);
|
||||||
|
|
||||||
pthread_mutex_unlock(&stratum_work_lock);
|
pthread_mutex_unlock(&stratum_work_lock);
|
||||||
|
|
||||||
// algo "blind" switch without free, not proper
|
// algo "blind" switch without free, not proper
|
||||||
|
205
util.cpp
205
util.cpp
@ -104,10 +104,10 @@ void applog(int prio, const char *fmt, ...)
|
|||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
const char* color = "";
|
const char* color = "";
|
||||||
|
const time_t now = time(NULL);
|
||||||
char *f;
|
char *f;
|
||||||
int len;
|
int len;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
time_t now = time(NULL);
|
|
||||||
|
|
||||||
localtime_r(&now, &tm);
|
localtime_r(&now, &tm);
|
||||||
|
|
||||||
@ -1561,19 +1561,134 @@ static bool stratum_reconnect(struct stratum_ctx *sctx, json_t *params)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id)
|
static bool stratum_pong(struct stratum_ctx *sctx, json_t *id)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (!id || json_is_null(id))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
sprintf(buf, "{\"id\":%d,\"result\":\"pong\",\"error\":null}",
|
||||||
|
(int) json_integer_value(id));
|
||||||
|
ret = stratum_send_line(sctx, buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool stratum_get_algo(struct stratum_ctx *sctx, json_t *id, json_t *params)
|
||||||
|
{
|
||||||
|
char algo[64] = { 0 };
|
||||||
|
char *s;
|
||||||
|
json_t *val;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (!id || json_is_null(id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
get_currentalgo(algo, sizeof(algo));
|
||||||
|
|
||||||
|
val = json_object();
|
||||||
|
json_object_set(val, "id", id);
|
||||||
|
json_object_set_new(val, "error", json_null());
|
||||||
|
json_object_set_new(val, "result", json_string(algo));
|
||||||
|
|
||||||
|
s = json_dumps(val, 0);
|
||||||
|
ret = stratum_send_line(sctx, s);
|
||||||
|
json_decref(val);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "nvml.h"
|
||||||
|
extern char driver_version[32];
|
||||||
|
|
||||||
|
static bool json_object_set_error(json_t *result, int code, const char *msg)
|
||||||
|
{
|
||||||
|
json_t *val = json_object();
|
||||||
|
json_object_set_new(val, "code", json_integer(code));
|
||||||
|
json_object_set_new(val, "message", json_string(msg));
|
||||||
|
return json_object_set_new(result, "error", val) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow to report algo/device perf to the pool for algo stats */
|
||||||
|
static bool stratum_benchdata(json_t *result, json_t *params, int thr_id)
|
||||||
|
{
|
||||||
|
char algo[64] = { 0 };
|
||||||
|
char vid[32], arch[8], driver[32];
|
||||||
|
char *card;
|
||||||
|
char os[8];
|
||||||
|
int dev_id = device_map[thr_id];
|
||||||
|
int cuda_ver = cuda_version();
|
||||||
|
struct cgpu_info *cgpu = &thr_info[thr_id].gpu;
|
||||||
|
json_t *val;
|
||||||
|
|
||||||
|
if (!cgpu) return false;
|
||||||
|
|
||||||
|
#if defined(WIN32) && (defined(_M_X64) || defined(__x86_64__))
|
||||||
|
strcpy(os, "win64");
|
||||||
|
#else
|
||||||
|
strcpy(os, is_windows() ? "win32" : "linux");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WRAPNVML
|
||||||
|
cgpu->has_monitoring = true;
|
||||||
|
cgpu->gpu_power = gpu_power(cgpu); // Watts
|
||||||
|
gpu_info(cgpu);
|
||||||
|
#endif
|
||||||
|
cuda_gpu_clocks(cgpu);
|
||||||
|
get_currentalgo(algo, sizeof(algo));
|
||||||
|
|
||||||
|
card = device_name[dev_id];
|
||||||
|
cgpu->khashes = stats_get_speed(thr_id, 0.0) / 1000.0;
|
||||||
|
|
||||||
|
sprintf(vid, "%04hx:%04hx", cgpu->gpu_vid, cgpu->gpu_pid);
|
||||||
|
sprintf(arch, "%d", (int) cgpu->gpu_arch);
|
||||||
|
snprintf(driver, 32, "CUDA %d.%d %s", cuda_ver/1000, (cuda_ver%1000) / 10, driver_version);
|
||||||
|
driver[31] = '\0';
|
||||||
|
|
||||||
|
val = json_object();
|
||||||
|
json_object_set_new(val, "algo", json_string(algo));
|
||||||
|
json_object_set_new(val, "type", json_string("gpu"));
|
||||||
|
json_object_set_new(val, "device", json_string(card));
|
||||||
|
json_object_set_new(val, "vendorid", json_string(vid));
|
||||||
|
json_object_set_new(val, "arch", json_string(arch));
|
||||||
|
json_object_set_new(val, "freq", json_integer(cgpu->gpu_clock/1000));
|
||||||
|
json_object_set_new(val, "memf", json_integer(cgpu->gpu_memclock/1000));
|
||||||
|
json_object_set_new(val, "power", json_integer(cgpu->gpu_power/1000));
|
||||||
|
json_object_set_new(val, "khashes", json_real(cgpu->khashes));
|
||||||
|
json_object_set_new(val, "intensity", json_integer(cgpu->intensity));
|
||||||
|
json_object_set_new(val, "throughput", json_integer(cgpu->throughput));
|
||||||
|
json_object_set_new(val, "client", json_string(PACKAGE_NAME "/" PACKAGE_VERSION));
|
||||||
|
json_object_set_new(val, "os", json_string(os));
|
||||||
|
json_object_set_new(val, "driver", json_string(driver));
|
||||||
|
|
||||||
|
json_object_set_new(result, "result", val);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool stratum_get_stats(struct stratum_ctx *sctx, json_t *id, json_t *params)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
json_t *val;
|
json_t *val;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
if (!id || json_is_null(id))
|
if (!id || json_is_null(id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
val = json_object();
|
val = json_object();
|
||||||
json_object_set(val, "id", id);
|
json_object_set(val, "id", id);
|
||||||
json_object_set_new(val, "error", json_null());
|
|
||||||
json_object_set_new(val, "result", json_string(USER_AGENT));
|
ret = stratum_benchdata(val, params, 0);
|
||||||
|
|
||||||
|
if (!opt_stratum_stats || !ret) {
|
||||||
|
json_object_set_error(val, 1, "disabled"); //EPERM
|
||||||
|
} else {
|
||||||
|
json_object_set_new(val, "error", json_null());
|
||||||
|
}
|
||||||
|
|
||||||
s = json_dumps(val, 0);
|
s = json_dumps(val, 0);
|
||||||
ret = stratum_send_line(sctx, s);
|
ret = stratum_send_line(sctx, s);
|
||||||
json_decref(val);
|
json_decref(val);
|
||||||
@ -1582,6 +1697,36 @@ static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id, json_t *params)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
json_t *val;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (!id || json_is_null(id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
val = json_object();
|
||||||
|
json_object_set(val, "id", id);
|
||||||
|
|
||||||
|
if (opt_stratum_stats && params) {
|
||||||
|
// linked here as transition, miners without get_stats method could fail
|
||||||
|
ret = stratum_benchdata(val, params, 0);
|
||||||
|
if (!ret) json_object_set_error(val, 1, "disabled"); // EPERM
|
||||||
|
} else {
|
||||||
|
json_object_set_new(val, "result", json_string(USER_AGENT));
|
||||||
|
}
|
||||||
|
if (ret) json_object_set_new(val, "error", json_null());
|
||||||
|
|
||||||
|
s = json_dumps(val, 0);
|
||||||
|
ret = stratum_send_line(sctx, s);
|
||||||
|
|
||||||
|
json_decref(val);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *params)
|
static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *params)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
@ -1607,6 +1752,28 @@ static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *p
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool stratum_unknown_method(struct stratum_ctx *sctx, json_t *id)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
json_t *val;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (!id || json_is_null(id))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = json_object();
|
||||||
|
json_object_set(val, "id", id);
|
||||||
|
json_object_set_new(val, "result", json_false());
|
||||||
|
json_object_set_error(val, 38, "unknown method"); // ENOSYS
|
||||||
|
|
||||||
|
s = json_dumps(val, 0);
|
||||||
|
ret = stratum_send_line(sctx, s);
|
||||||
|
json_decref(val);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
|
bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
|
||||||
{
|
{
|
||||||
json_t *val, *id, *params;
|
json_t *val, *id, *params;
|
||||||
@ -1630,6 +1797,11 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
|
|||||||
ret = stratum_notify(sctx, params);
|
ret = stratum_notify(sctx, params);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (!strcasecmp(method, "mining.ping")) { // cgminer 4.7.1+
|
||||||
|
if (opt_debug) applog(LOG_DEBUG, "Pool ping");
|
||||||
|
ret = stratum_pong(sctx, id);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (!strcasecmp(method, "mining.set_difficulty")) {
|
if (!strcasecmp(method, "mining.set_difficulty")) {
|
||||||
ret = stratum_set_difficulty(sctx, params);
|
ret = stratum_set_difficulty(sctx, params);
|
||||||
goto out;
|
goto out;
|
||||||
@ -1642,15 +1814,32 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
|
|||||||
ret = stratum_reconnect(sctx, params);
|
ret = stratum_reconnect(sctx, params);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!strcasecmp(method, "client.get_version")) {
|
if (!strcasecmp(method, "client.get_algo")) { // ccminer only yet!
|
||||||
ret = stratum_get_version(sctx, id);
|
// will prevent wrong algo parameters on a pool, will be used as test on rejects
|
||||||
|
if (!opt_quiet) applog(LOG_NOTICE, "Pool asked your algo parameter");
|
||||||
|
ret = stratum_get_algo(sctx, id, params);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!strcasecmp(method, "client.show_message")) {
|
if (!strcasecmp(method, "client.get_stats")) { // ccminer/yiimp only yet!
|
||||||
|
// optional to fill device benchmarks
|
||||||
|
ret = stratum_get_stats(sctx, id, params);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!strcasecmp(method, "client.get_version")) { // common
|
||||||
|
ret = stratum_get_version(sctx, id, params);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!strcasecmp(method, "client.show_message")) { // common
|
||||||
ret = stratum_show_message(sctx, id, params);
|
ret = stratum_show_message(sctx, id, params);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
// don't fail = disconnect stratum on unknown (and optional?) methods
|
||||||
|
if (opt_debug) applog(LOG_WARNING, "unknown stratum method %s!", method);
|
||||||
|
ret = stratum_unknown_method(sctx, id);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (val)
|
if (val)
|
||||||
json_decref(val);
|
json_decref(val);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user