Browse Source

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.
2upstream
Tanguy Pruvot 9 years ago
parent
commit
dcbcf6ba7e
  1. 7
      README.txt
  2. 2
      api.cpp
  3. 1
      bench.cpp
  4. 2
      ccminer.cpp
  5. 5
      cuda.cpp
  6. 3
      miner.h
  7. 3
      pools.cpp
  8. 203
      util.cpp

7
README.txt

@ -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

@ -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 };

1
bench.cpp

@ -200,4 +200,3 @@ void bench_display_results()
} }
} }
} }

2
ccminer.cpp

@ -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

@ -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

@ -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);

3
pools.cpp

@ -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

203
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,21 +1561,166 @@ 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; char *s;
json_t *val; json_t *val;
bool ret; bool ret = true;
if (!id || json_is_null(id)) if (!id || json_is_null(id))
return false; return false;
get_currentalgo(algo, sizeof(algo));
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, "error", json_null());
json_object_set_new(val, "result", json_string(USER_AGENT)); 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;
json_t *val;
bool ret;
if (!id || json_is_null(id))
return false;
val = json_object();
json_object_set(val, "id", id);
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);
ret = stratum_send_line(sctx, s);
json_decref(val);
free(s);
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); s = json_dumps(val, 0);
ret = stratum_send_line(sctx, s); ret = stratum_send_line(sctx, s);
json_decref(val); json_decref(val);
free(s); free(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…
Cancel
Save