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.
master
Tanguy Pruvot 8 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. 205
      util.cpp

7
README.txt

@ -1,5 +1,5 @@ @@ -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. @@ -238,10 +238,11 @@ features.
>>> RELEASE HISTORY <<<
May XXth 2016 v1.7.6
May 15th 2016 v1.7.6
Decred vote support
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
Blake2S Algo (NEVA/OXEN)

2
api.cpp

@ -101,8 +101,6 @@ extern struct stratum_ctx stratum; @@ -101,8 +101,6 @@ extern struct stratum_ctx stratum;
extern int num_cpus;
extern float cpu_temp(int);
extern uint32_t cpu_clock(int);
// cuda.cpp
extern int cuda_gpu_clocks(struct cgpu_info *gpu);
char driver_version[32] = { 0 };

1
bench.cpp

@ -200,4 +200,3 @@ void bench_display_results() @@ -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 */ @@ -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_listen = 4068; /* 0 to disable */
bool opt_stratum_stats = false;
static char const usage[] = "\
Usage: " PROGRAM_NAME " [OPTIONS]\n\
Options:\n\

5
cuda.cpp

@ -52,6 +52,11 @@ int cuda_num_devices() @@ -52,6 +52,11 @@ int cuda_num_devices()
return GPU_N;
}
int cuda_version()
{
return (int) CUDART_VERSION;
}
void cuda_devicenames()
{
cudaError_t err;

3
miner.h

@ -459,6 +459,7 @@ extern bool want_longpoll; @@ -459,6 +459,7 @@ extern bool want_longpoll;
extern bool have_longpoll;
extern bool want_stratum;
extern bool have_stratum;
extern bool opt_stratum_stats;
extern char *opt_cert;
extern char *opt_proxy;
extern long opt_proxy_type;
@ -493,7 +494,9 @@ void cuda_devicenames(); @@ -493,7 +494,9 @@ void cuda_devicenames();
void cuda_reset_device(int thr_id, bool *init);
void cuda_shutdown();
int cuda_finddevice(char *name);
int cuda_version();
void cuda_print_devices();
int cuda_gpu_clocks(struct cgpu_info *gpu);
int cuda_available_memory(int thr_id);
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) @@ -196,6 +196,9 @@ bool pool_switch(int thr_id, int pooln)
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);
// algo "blind" switch without free, not proper

205
util.cpp

@ -104,10 +104,10 @@ void applog(int prio, const char *fmt, ...) @@ -104,10 +104,10 @@ void applog(int prio, const char *fmt, ...)
#endif
else {
const char* color = "";
const time_t now = time(NULL);
char *f;
int len;
struct tm tm;
time_t now = time(NULL);
localtime_r(&now, &tm);
@ -1561,19 +1561,134 @@ static bool stratum_reconnect(struct stratum_ctx *sctx, json_t *params) @@ -1561,19 +1561,134 @@ static bool stratum_reconnect(struct stratum_ctx *sctx, json_t *params)
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;
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(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);
@ -1582,6 +1697,36 @@ static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id) @@ -1582,6 +1697,36 @@ static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id)
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)
{
char *s;
@ -1607,6 +1752,28 @@ static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *p @@ -1607,6 +1752,28 @@ static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *p
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)
{
json_t *val, *id, *params;
@ -1630,6 +1797,11 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s) @@ -1630,6 +1797,11 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
ret = stratum_notify(sctx, params);
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")) {
ret = stratum_set_difficulty(sctx, params);
goto out;
@ -1642,15 +1814,32 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s) @@ -1642,15 +1814,32 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
ret = stratum_reconnect(sctx, params);
goto out;
}
if (!strcasecmp(method, "client.get_version")) {
ret = stratum_get_version(sctx, id);
if (!strcasecmp(method, "client.get_algo")) { // ccminer only yet!
// 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;
}
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);
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:
if (val)
json_decref(val);

Loading…
Cancel
Save