multipool: Squashed commit (v2)
commit a9d3c1ffdb71d2a4985749acba3d424161154ab4 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Thu May 21 05:39:24 2015 +0200 multipool: last changes before squashed merge and fix net diff on wallets.. was longpoll specific commit a63f0024f3f1fb52d2c4369518bf87c33a9e16ae Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Thu May 21 05:02:27 2015 +0200 update api sample for the protocol 1.5 commit adda14b22edde6485932be56550166478f6f00dd Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Thu May 21 04:43:25 2015 +0200 stats: store pool number in scanlog commit e1a0274b01c29409ce16f9096b9985a35cf78ba7 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Thu May 21 03:36:15 2015 +0200 api: switchpool and new pool stats variables (API v1.5) add accepted/rej by pool, wait time on conditional, net diff and rate also add scantime per pool config option and do some pool cleanup.. commit 1a30450ad2a5e068983531b9d2a96629b970c1e8 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Wed May 20 06:39:09 2015 +0200 prevent concurrent pool switching and limit condtionnal wait messages to the first thread/device commit e3922c7a331a3ad2730bc83082fcd6b2547542f5 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Wed May 20 05:39:45 2015 +0200 add some pool rotate options, like pool time-limit update sample pools.conf for time rotation commit 312bd905412d49fd5a9f9e7ff2bc72b23edf38ed Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Wed May 20 04:31:19 2015 +0200 do not try to restart threads from threads Start inconditionally the stratum and longpoll threads, these threads are just waiting a tq_push() if unused... so add some checks to know if vars are set for the right pool commit d4a9428fefdd9e9d70c3c8231f10961e7cd41760 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Wed May 20 01:06:31 2015 +0200 pools: add name and removed attributes also increase max defined pools to 8 to be tested on windows.. commit d840d683ecb2cc4767f0a0612b8359c52d4bad29 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Tue May 19 22:33:11 2015 +0200 parse json config file pools array commit d6c29b1f7f6b786c56e1f0cb8a90305f06cc7aec Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Tue May 19 03:29:30 2015 +0200 multi-pools: prepare storage/switch of credentials for the moment: - allow the storage of multiple -o params (and user/pass) - allow a failover pool on connection failed - switch to the next pool with the "seturl" api remote command - longpoll to stratum switch (reverse to check...) todo: mix stratum/getwork, new api commands, json config... commit 2d6b3fddf6631d7df1ac6ca74eee91c33a3c09ee Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Fri May 22 08:26:40 2015 +0200 multipool: increase stability, but not 100% perfect several problems fixed: - submit to the pool set in work (source pool) - longpoll curl timeout could be too high and could lock the switch - mutexes cant be copied on windows (stratum global var to fully remove later) I linked the -T timeout option to curl and tried to remove all fixed timeout values commit 6fd935c369cf33949dab98c8b09b2ca8cab3e7ea Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Fri May 22 11:23:07 2015 +0200 stratum: remove last rpc_ vars in stratum thread commit ee9c821525be303282e5dab512ffd2ae81ad524f Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Sat May 23 03:53:50 2015 +0200 stratum: do not alloc empty merkle tree commit 69852a2874bd18c4ed1daa9180a10d12976424dc Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Sat May 23 04:25:12 2015 +0200 stratum: properly free jobs on disconnect Signed-off-by: Tanguy Pruvot <tanguy.pruvot@gmail.com>
This commit is contained in:
parent
298573b45d
commit
bbd2c704f9
107
api.cpp
107
api.cpp
@ -8,7 +8,7 @@
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version. See COPYING for more details.
|
||||
*/
|
||||
#define APIVERSION "1.4"
|
||||
#define APIVERSION "1.5"
|
||||
|
||||
#ifdef WIN32
|
||||
# define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
@ -92,13 +92,12 @@ static int bye = 0;
|
||||
extern char *opt_api_allow;
|
||||
extern int opt_api_listen; /* port */
|
||||
extern int opt_api_remote;
|
||||
extern uint32_t accepted_count;
|
||||
extern uint32_t rejected_count;
|
||||
extern int num_cpus;
|
||||
|
||||
// current stratum...
|
||||
extern struct stratum_ctx stratum;
|
||||
extern char* rpc_user;
|
||||
|
||||
// sysinfos.cpp
|
||||
extern int num_cpus;
|
||||
extern float cpu_temp(int);
|
||||
extern uint32_t cpu_clock(int);
|
||||
// cuda.cpp
|
||||
@ -111,6 +110,8 @@ char driver_version[32] = { 0 };
|
||||
|
||||
static void gpustatus(int thr_id)
|
||||
{
|
||||
struct pool_infos *p = &pools[cur_pooln];
|
||||
|
||||
if (thr_id >= 0 && thr_id < opt_n_threads) {
|
||||
struct cgpu_info *cgpu = &thr_info[thr_id].gpu;
|
||||
int gpuid = cgpu->gpu_id;
|
||||
@ -127,8 +128,8 @@ static void gpustatus(int thr_id)
|
||||
cuda_gpu_clocks(cgpu);
|
||||
|
||||
// todo: per gpu
|
||||
cgpu->accepted = accepted_count;
|
||||
cgpu->rejected = rejected_count;
|
||||
cgpu->accepted = p->accepted_count;
|
||||
cgpu->rejected = p->rejected_count;
|
||||
|
||||
cgpu->khashes = stats_get_speed(thr_id, 0.0) / 1000.0;
|
||||
|
||||
@ -165,19 +166,27 @@ static char *getsummary(char *params)
|
||||
{
|
||||
char algo[64]; *algo = '\0';
|
||||
time_t ts = time(NULL);
|
||||
double uptime = difftime(ts, startup);
|
||||
double accps = (60.0 * accepted_count) / (uptime ? uptime : 1.0);
|
||||
double accps, uptime = difftime(ts, startup);
|
||||
uint32_t wait_time = 0, accepted_count = 0, rejected_count = 0;
|
||||
for (int p = 0; p < num_pools; p++) {
|
||||
wait_time += pools[cur_pooln].wait_time;
|
||||
accepted_count += pools[cur_pooln].accepted_count;
|
||||
rejected_count += pools[cur_pooln].rejected_count;
|
||||
}
|
||||
accps = (60.0 * accepted_count) / (uptime ? uptime : 1.0);
|
||||
|
||||
get_currentalgo(algo, sizeof(algo));
|
||||
|
||||
*buffer = '\0';
|
||||
sprintf(buffer, "NAME=%s;VER=%s;API=%s;"
|
||||
"ALGO=%s;GPUS=%d;KHS=%.2f;ACC=%d;REJ=%d;"
|
||||
"ACCMN=%.3f;DIFF=%.6f;UPTIME=%.0f;TS=%u|",
|
||||
"ACCMN=%.3f;DIFF=%.6f;NETKHS=%.2f;"
|
||||
"POOLS=%u;WAIT=%u;UPTIME=%.0f;TS=%u|",
|
||||
PACKAGE_NAME, PACKAGE_VERSION, APIVERSION,
|
||||
algo, active_gpus, (double)global_hashrate / 1000.0,
|
||||
algo, active_gpus, (double)global_hashrate / 1000.,
|
||||
accepted_count, rejected_count,
|
||||
accps, net_diff > 0. ? net_diff : stratum_diff, uptime, (uint32_t) ts);
|
||||
accps, net_diff > 0. ? net_diff : stratum_diff, (double)net_hashrate / 1000.,
|
||||
num_pools, wait_time, uptime, (uint32_t) ts);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -186,31 +195,30 @@ static char *getsummary(char *params)
|
||||
*/
|
||||
static char *getpoolnfo(char *params)
|
||||
{
|
||||
char *p = buffer;
|
||||
char *s = buffer;
|
||||
char jobid[128] = { 0 };
|
||||
char nonce[128] = { 0 };
|
||||
*p = '\0';
|
||||
struct pool_infos *p = &pools[cur_pooln];
|
||||
|
||||
if (!stratum.url) {
|
||||
sprintf(p, "|");
|
||||
return p;
|
||||
}
|
||||
*s = '\0';
|
||||
|
||||
if (stratum.job.job_id)
|
||||
strncpy(jobid, stratum.job.job_id, sizeof(stratum.job.job_id));
|
||||
|
||||
if (stratum.job.xnonce2) {
|
||||
/* used temporary to be sure all is ok */
|
||||
cbin2hex(nonce, (const char*) stratum.job.xnonce2, stratum.xnonce2_size);
|
||||
sprintf(nonce, "0x");
|
||||
cbin2hex(&nonce[2], (const char*) stratum.job.xnonce2, stratum.xnonce2_size);
|
||||
}
|
||||
|
||||
snprintf(p, MYBUFSIZ, "URL=%s;USER=%s;H=%u;JOB=%s;DIFF=%.6f;N2SZ=%d;N2=0x%s;PING=%u;DISCO=%u;UPTIME=%u|",
|
||||
stratum.url, rpc_user ? rpc_user : "",
|
||||
stratum.job.height, jobid, stratum.job.diff,
|
||||
snprintf(s, MYBUFSIZ, "URL=%s;USER=%s;ACC=%d;REJ=%d;H=%u;JOB=%s;DIFF=%.6f;"
|
||||
"N2SZ=%d;N2=%s;PING=%u;DISCO=%u;WAIT=%u;UPTIME=%u|",
|
||||
p->url, p->type & POOL_STRATUM ? p->user : "",
|
||||
p->accepted_count, p->rejected_count,
|
||||
stratum.job.height, jobid, stratum_diff,
|
||||
(int) stratum.xnonce2_size, nonce, stratum.answer_msec,
|
||||
stratum.disconnects, (uint32_t) (time(NULL) - stratum.tm_connected));
|
||||
p->disconnects, p->wait_time, p->work_time);
|
||||
|
||||
return p;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -342,9 +350,9 @@ static char *getscanlog(char *params)
|
||||
*buffer = '\0';
|
||||
for (int i = 0; i < records; i++) {
|
||||
time_t ts = data[i].tm_upd;
|
||||
p += sprintf(p, "H=%u;JOB=%u;N=%u;FROM=0x%x;SCANTO=0x%x;"
|
||||
p += sprintf(p, "H=%u;P=%u;JOB=%u;N=%u;FROM=0x%x;SCANTO=0x%x;"
|
||||
"COUNT=0x%x;FOUND=%u;TS=%u|",
|
||||
data[i].height, data[i].njobid, data[i].nonce, data[i].scanned_from, data[i].scanned_to,
|
||||
data[i].height, data[i].npool, data[i].njobid, data[i].nonce, data[i].scanned_from, data[i].scanned_to,
|
||||
(data[i].scanned_to - data[i].scanned_from), data[i].tm_sent ? 1 : 0, (uint32_t)ts);
|
||||
}
|
||||
return buffer;
|
||||
@ -381,18 +389,46 @@ static bool check_remote_access(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* Change pool url (see --url parameter)
|
||||
* seturl|stratum+tcp://Danila.1:X@pool.ipominer.com:3335|
|
||||
* Set pool by index (pools array in json config)
|
||||
* switchpool|1|
|
||||
*/
|
||||
extern bool stratum_need_reset;
|
||||
static char *remote_seturl(char *params)
|
||||
static char *remote_switchpool(char *params)
|
||||
{
|
||||
bool ret = false;
|
||||
*buffer = '\0';
|
||||
if (!check_remote_access())
|
||||
return buffer;
|
||||
parse_arg('o', params);
|
||||
stratum_need_reset = true;
|
||||
sprintf(buffer, "%s", "ok|");
|
||||
if (!params || strlen(params) == 0) {
|
||||
// rotate pool test
|
||||
ret = pool_switch_next();
|
||||
} else {
|
||||
int n = atoi(params);
|
||||
if (n == cur_pooln)
|
||||
ret = true;
|
||||
else if (n < num_pools)
|
||||
ret = pool_switch(n);
|
||||
}
|
||||
sprintf(buffer, "%s|", ret ? "ok" : "fail");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change pool url (see --url parameter)
|
||||
* seturl|stratum+tcp://<user>:<pass>@mine.xpool.ca:1131|
|
||||
*/
|
||||
static char *remote_seturl(char *params)
|
||||
{
|
||||
bool ret;
|
||||
*buffer = '\0';
|
||||
if (!check_remote_access())
|
||||
return buffer;
|
||||
if (!params || strlen(params) == 0) {
|
||||
// rotate pool test
|
||||
ret = pool_switch_next();
|
||||
} else {
|
||||
ret = pool_switch_url(params);
|
||||
}
|
||||
sprintf(buffer, "%s|", ret ? "ok" : "fail");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -425,7 +461,8 @@ struct CMDS {
|
||||
{ "scanlog", getscanlog },
|
||||
|
||||
/* remote functions */
|
||||
{ "seturl", remote_seturl },
|
||||
{ "seturl", remote_seturl }, /* prefer switchpool, deprecated */
|
||||
{ "switchpool", remote_switchpool },
|
||||
{ "quit", remote_quit },
|
||||
|
||||
/* keep it the last */
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/* ccminer API sample UI */
|
||||
/* ccminer API sample UI (API 1.5) */
|
||||
|
||||
$host = 'http://localhost/api/'; // 'http://'.$_SERVER['SERVER_NAME'].'/api/';
|
||||
$configs = array(
|
||||
@ -27,7 +27,7 @@ function getdataFromPeers()
|
||||
function ignoreField($key)
|
||||
{
|
||||
$ignored = array(
|
||||
'API','VER','GPU','BUS',
|
||||
'API','VER','GPU','BUS','POOLS',
|
||||
'CARD','GPUS','CPU','TS',
|
||||
);
|
||||
return in_array($key, $ignored);
|
||||
@ -47,13 +47,17 @@ function translateField($key)
|
||||
$intl['ACCMN'] = 'Accepted / mn';
|
||||
$intl['REJ'] = 'Rejected';
|
||||
$intl['DIFF'] = 'Difficulty';
|
||||
$intl['NETKHS'] = 'Net Rate';
|
||||
$intl['UPTIME'] = 'Miner up time';
|
||||
$intl['TS'] = 'Last update';
|
||||
$intl['THR'] = 'Throughput';
|
||||
$intl['WAIT'] = 'Wait time';
|
||||
|
||||
|
||||
$intl['H'] = 'Bloc height';
|
||||
$intl['I'] = 'Intensity';
|
||||
$intl['HWF'] = 'Failures';
|
||||
$intl['POOLS'] = 'Pools';
|
||||
|
||||
$intl['TEMP'] = 'T°c';
|
||||
$intl['FAN'] = 'Fan %';
|
||||
@ -76,6 +80,7 @@ function translateValue($key,$val,$data=array())
|
||||
{
|
||||
switch ($key) {
|
||||
case 'UPTIME':
|
||||
case 'WAIT':
|
||||
$min = floor(intval($val) / 60);
|
||||
$sec = intval($val) % 60;
|
||||
$val = "${min}mn${sec}s";
|
||||
@ -95,6 +100,7 @@ function translateValue($key,$val,$data=array())
|
||||
$val = strftime("%H:%M:%S", (int) $val);
|
||||
break;
|
||||
case 'KHS':
|
||||
case 'NETKHS':
|
||||
$val = '<span class="bold">'.$val.'</span> kH/s';
|
||||
break;
|
||||
case 'NAME':
|
||||
@ -246,7 +252,7 @@ span.elipsis { display: inline-block; max-width: 130px; overflow: hidden; }
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
<p>© 2014 <a href="http://github.com/tpruvot/ccminer">tpruvot@github</a></p>
|
||||
<p>© 2014-2015 <a href="http://github.com/tpruvot/ccminer">tpruvot@github</a></p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
824
ccminer.cpp
824
ccminer.cpp
File diff suppressed because it is too large
Load Diff
@ -18,13 +18,17 @@
|
||||
|
||||
/* from miner.h
|
||||
struct hashlog_data {
|
||||
uint32_t tm_sent;
|
||||
uint8_t npool;
|
||||
uint8_t pool_type;
|
||||
uint32_t height;
|
||||
uint32_t njobid;
|
||||
uint32_t nonce;
|
||||
uint32_t scanned_from;
|
||||
uint32_t scanned_to;
|
||||
uint32_t last_from;
|
||||
uint32_t tm_add;
|
||||
uint32_t tm_upd;
|
||||
uint32_t tm_sent;
|
||||
};
|
||||
*/
|
||||
|
||||
@ -75,6 +79,8 @@ void hashlog_remember_submit(struct work* work, uint32_t nonce)
|
||||
data.height = work->height;
|
||||
data.njobid = (uint32_t) njobid;
|
||||
data.tm_add = data.tm_upd = data.tm_sent = (uint32_t) time(NULL);
|
||||
data.npool = (uint8_t) cur_pooln;
|
||||
data.pool_type = pools[cur_pooln].type;
|
||||
tlastshares[key] = data;
|
||||
}
|
||||
|
||||
|
76
miner.h
76
miner.h
@ -423,16 +423,25 @@ struct stats_data {
|
||||
uint32_t tm_stat;
|
||||
uint32_t hashcount;
|
||||
uint32_t height;
|
||||
|
||||
double difficulty;
|
||||
double hashrate;
|
||||
|
||||
uint8_t thr_id;
|
||||
uint8_t gpu_id;
|
||||
uint8_t hashfound;
|
||||
uint8_t ignored;
|
||||
|
||||
uint8_t npool;
|
||||
uint8_t pool_type;
|
||||
uint16_t align;
|
||||
};
|
||||
|
||||
struct hashlog_data {
|
||||
uint32_t tm_sent;
|
||||
uint8_t npool;
|
||||
uint8_t pool_type;
|
||||
uint16_t align;
|
||||
|
||||
uint32_t height;
|
||||
uint32_t njobid;
|
||||
uint32_t nonce;
|
||||
@ -441,6 +450,7 @@ struct hashlog_data {
|
||||
uint32_t last_from;
|
||||
uint32_t tm_add;
|
||||
uint32_t tm_upd;
|
||||
uint32_t tm_sent;
|
||||
};
|
||||
|
||||
/* end of api */
|
||||
@ -529,8 +539,6 @@ extern uint32_t gpus_intensity[MAX_GPUS];
|
||||
extern void format_hashrate(double hashrate, char *output);
|
||||
extern void applog(int prio, const char *fmt, ...);
|
||||
void get_defconfig_path(char *out, size_t bufsize, char *argv0);
|
||||
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
||||
const char *rpc_req, bool, bool, int *);
|
||||
extern void cbin2hex(char *out, const char *in, size_t len);
|
||||
extern char *bin2hex(const unsigned char *in, size_t len);
|
||||
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
||||
@ -567,7 +575,6 @@ struct stratum_ctx {
|
||||
curl_socket_t sock;
|
||||
size_t sockbuf_size;
|
||||
char *sockbuf;
|
||||
pthread_mutex_t sock_lock;
|
||||
|
||||
double next_diff;
|
||||
|
||||
@ -576,11 +583,10 @@ struct stratum_ctx {
|
||||
unsigned char *xnonce1;
|
||||
size_t xnonce2_size;
|
||||
struct stratum_job job;
|
||||
pthread_mutex_t work_lock;
|
||||
|
||||
struct timeval tv_submit;
|
||||
uint32_t answer_msec;
|
||||
uint32_t disconnects;
|
||||
int pooln;
|
||||
time_t tm_connected;
|
||||
|
||||
int srvtime_diff;
|
||||
@ -602,11 +608,68 @@ struct work {
|
||||
|
||||
double difficulty;
|
||||
uint32_t height;
|
||||
uint8_t pooln;
|
||||
|
||||
uint32_t scanned_from;
|
||||
uint32_t scanned_to;
|
||||
};
|
||||
|
||||
#define MAX_POOLS 8
|
||||
struct pool_infos {
|
||||
uint8_t id;
|
||||
#define POOL_UNUSED 0
|
||||
#define POOL_GETWORK 1
|
||||
#define POOL_STRATUM 2
|
||||
#define POOL_LONGPOLL 4
|
||||
uint8_t type;
|
||||
#define POOL_ST_DEFINED 1
|
||||
#define POOL_ST_VALID 2
|
||||
#define POOL_ST_DISABLED 4
|
||||
#define POOL_ST_REMOVED 8
|
||||
uint16_t status;
|
||||
char name[64];
|
||||
// credentials
|
||||
char url[256];
|
||||
char short_url[64];
|
||||
char user[64];
|
||||
char pass[64];
|
||||
// config options
|
||||
double max_diff;
|
||||
double max_rate;
|
||||
int time_limit;
|
||||
int scantime;
|
||||
// connection
|
||||
struct stratum_ctx stratum;
|
||||
uint8_t allow_gbt;
|
||||
uint8_t allow_mininginfo;
|
||||
uint16_t check_dups; // 16_t for align
|
||||
int retries;
|
||||
int fail_pause;
|
||||
int timeout;
|
||||
// stats
|
||||
uint32_t work_time;
|
||||
uint32_t wait_time;
|
||||
uint32_t accepted_count;
|
||||
uint32_t rejected_count;
|
||||
uint32_t disconnects;
|
||||
};
|
||||
|
||||
extern struct pool_infos pools[MAX_POOLS];
|
||||
extern int num_pools;
|
||||
extern volatile int cur_pooln;
|
||||
|
||||
int pool_get_first_valid(int startfrom);
|
||||
void pool_set_creds(int pooln);
|
||||
void pool_set_attr(int pooln, const char* key, char* arg);
|
||||
bool pool_switch_url(char *params);
|
||||
bool pool_switch(int pooln);
|
||||
bool pool_switch_next(void);
|
||||
|
||||
json_t * json_rpc_call_pool(CURL *curl, struct pool_infos*,
|
||||
const char *req, bool lp_scan, bool lp, int *err);
|
||||
json_t * json_rpc_longpoll(CURL *curl, char *lp_url, struct pool_infos*,
|
||||
const char *req, int *err);
|
||||
|
||||
bool stratum_socket_full(struct stratum_ctx *sctx, int timeout);
|
||||
bool stratum_send_line(struct stratum_ctx *sctx, char *s);
|
||||
char *stratum_recv_line(struct stratum_ctx *sctx);
|
||||
@ -615,6 +678,7 @@ void stratum_disconnect(struct stratum_ctx *sctx);
|
||||
bool stratum_subscribe(struct stratum_ctx *sctx);
|
||||
bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass);
|
||||
bool stratum_handle_method(struct stratum_ctx *sctx, const char *s);
|
||||
void stratum_free_job(struct stratum_ctx *sctx);
|
||||
|
||||
void hashlog_remember_submit(struct work* work, uint32_t nonce);
|
||||
void hashlog_remember_scan_range(struct work* work);
|
||||
|
27
pools.conf
Normal file
27
pools.conf
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"_note": "Sample rotation of 2 pools",
|
||||
|
||||
"pools":[{
|
||||
"name": "Longpoll sample",
|
||||
"url": "http://ziftr.suprnova.cc:9991",
|
||||
"user": "tpruvot.win",
|
||||
"pass": "x",
|
||||
"max-diff": 0.0,
|
||||
"time-limit": 180,
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "Stratum sample",
|
||||
"url": "stratum+tcp://zrc-stratum.suprnova.cc:2257",
|
||||
"user": "tpruvot.elite",
|
||||
"pass": "x",
|
||||
"time-limit": 300
|
||||
}],
|
||||
|
||||
"algo" : "zr5",
|
||||
|
||||
"api-bind" : "0.0.0.0",
|
||||
"api-remote" : true,
|
||||
|
||||
"no-gbt": true
|
||||
}
|
@ -41,6 +41,8 @@ void stats_remember_speed(int thr_id, uint32_t hashcount, double hashrate, uint8
|
||||
data.thr_id = (uint8_t) thr_id;
|
||||
data.tm_stat = (uint32_t) time(NULL);
|
||||
data.height = height;
|
||||
data.npool = (uint8_t) cur_pooln;
|
||||
data.pool_type = pools[cur_pooln].type;
|
||||
data.hashcount = hashcount;
|
||||
data.hashfound = found;
|
||||
data.hashrate = hashrate;
|
||||
|
124
util.cpp
124
util.cpp
@ -36,6 +36,9 @@
|
||||
#include "miner.h"
|
||||
#include "elist.h"
|
||||
|
||||
extern pthread_mutex_t stratum_sock_lock;
|
||||
extern pthread_mutex_t stratum_work_lock;
|
||||
|
||||
bool opt_tracegpu = false;
|
||||
|
||||
struct data_buffer {
|
||||
@ -385,9 +388,12 @@ static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd,
|
||||
}
|
||||
#endif
|
||||
|
||||
json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
/* For getwork (longpoll or wallet) - not stratum pools!
|
||||
* DO NOT USE DIRECTLY
|
||||
*/
|
||||
static json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
const char *userpass, const char *rpc_req,
|
||||
bool longpoll_scan, bool longpoll, int *curl_err)
|
||||
bool longpoll_scan, bool longpoll, bool keepalive, int *curl_err)
|
||||
{
|
||||
json_t *val, *err_val, *res_val;
|
||||
int rc;
|
||||
@ -395,10 +401,10 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
struct upload_buffer upload_data;
|
||||
json_error_t err;
|
||||
struct curl_slist *headers = NULL;
|
||||
char* httpdata;
|
||||
char *httpdata;
|
||||
char len_hdr[64], hashrate_hdr[64];
|
||||
char curl_err_str[CURL_ERROR_SIZE] = { 0 };
|
||||
long timeout = longpoll ? opt_timeout : 30;
|
||||
long timeout = longpoll ? opt_timeout*2 : opt_timeout;
|
||||
struct header_info hi = { 0 };
|
||||
bool lp_scanning = longpoll_scan && !have_longpoll;
|
||||
|
||||
@ -435,7 +441,7 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||
}
|
||||
#if LIBCURL_VERSION_NUM >= 0x070f06
|
||||
if (longpoll)
|
||||
if (keepalive)
|
||||
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
|
||||
#endif
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
@ -486,7 +492,8 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
}
|
||||
|
||||
if (!all_data.buf || !all_data.len) {
|
||||
applog(LOG_ERR, "Empty data received in json_rpc_call.");
|
||||
if (!have_longpoll) // seems normal on longpoll timeout
|
||||
applog(LOG_ERR, "Empty data received in json_rpc_call.");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
@ -571,6 +578,31 @@ err_out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* getwork calls with pool pointer (wallet/longpoll pools) */
|
||||
json_t *json_rpc_call_pool(CURL *curl, struct pool_infos *pool, const char *req,
|
||||
bool longpoll_scan, bool longpoll, int *curl_err)
|
||||
{
|
||||
char userpass[256];
|
||||
// todo, malloc and store that in pool array
|
||||
snprintf(userpass, sizeof(userpass), "%s%c%s", pool->user,
|
||||
strlen(pool->pass)?':':'\0', pool->pass);
|
||||
|
||||
return json_rpc_call(curl, pool->url, userpass, req, longpoll_scan, false, false, curl_err);
|
||||
}
|
||||
|
||||
/* called only from longpoll thread */
|
||||
json_t *json_rpc_longpoll(CURL *curl, char *lp_url, struct pool_infos *pool, const char *req, int *curl_err)
|
||||
{
|
||||
char userpass[256];
|
||||
snprintf(userpass, sizeof(userpass), "%s%c%s", pool->user,
|
||||
strlen(pool->pass)?':':'\0', pool->pass);
|
||||
|
||||
// on pool rotate by time-limit, this keepalive can be a problem
|
||||
bool keepalive = pool->time_limit == 0 || pool->time_limit > opt_timeout*4;
|
||||
|
||||
return json_rpc_call(curl, lp_url, userpass, req, want_longpoll, have_longpoll, keepalive, curl_err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike malloc, calloc set the memory to zero
|
||||
*/
|
||||
@ -774,9 +806,9 @@ bool stratum_send_line(struct stratum_ctx *sctx, char *s)
|
||||
if (opt_protocol)
|
||||
applog(LOG_DEBUG, "> %s", s);
|
||||
|
||||
pthread_mutex_lock(&sctx->sock_lock);
|
||||
pthread_mutex_lock(&stratum_sock_lock);
|
||||
ret = send_line(sctx->sock, s);
|
||||
pthread_mutex_unlock(&sctx->sock_lock);
|
||||
pthread_mutex_unlock(&stratum_sock_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -797,6 +829,7 @@ static bool socket_full(curl_socket_t sock, int timeout)
|
||||
|
||||
bool stratum_socket_full(struct stratum_ctx *sctx, int timeout)
|
||||
{
|
||||
if (!sctx->sockbuf) return false;
|
||||
return strlen(sctx->sockbuf) || socket_full(sctx->sock, timeout);
|
||||
}
|
||||
|
||||
@ -821,10 +854,13 @@ char *stratum_recv_line(struct stratum_ctx *sctx)
|
||||
ssize_t len, buflen;
|
||||
char *tok, *sret = NULL;
|
||||
|
||||
if (!sctx->sockbuf)
|
||||
return NULL;
|
||||
|
||||
if (!strstr(sctx->sockbuf, "\n")) {
|
||||
bool ret = true;
|
||||
time_t rstart = time(NULL);
|
||||
if (!socket_full(sctx->sock, 60)) {
|
||||
if (!socket_full(sctx->sock, opt_timeout)) {
|
||||
applog(LOG_ERR, "stratum_recv_line timed out");
|
||||
goto out;
|
||||
}
|
||||
@ -845,7 +881,7 @@ char *stratum_recv_line(struct stratum_ctx *sctx)
|
||||
}
|
||||
} else
|
||||
stratum_buffer_append(sctx, s);
|
||||
} while (time(NULL) - rstart < 60 && !strstr(sctx->sockbuf, "\n"));
|
||||
} while (time(NULL) - rstart < opt_timeout && !strstr(sctx->sockbuf, "\n"));
|
||||
|
||||
if (!ret) {
|
||||
applog(LOG_ERR, "stratum_recv_line failed");
|
||||
@ -888,13 +924,13 @@ bool stratum_connect(struct stratum_ctx *sctx, const char *url)
|
||||
CURL *curl;
|
||||
int rc;
|
||||
|
||||
pthread_mutex_lock(&sctx->sock_lock);
|
||||
pthread_mutex_lock(&stratum_sock_lock);
|
||||
if (sctx->curl)
|
||||
curl_easy_cleanup(sctx->curl);
|
||||
sctx->curl = curl_easy_init();
|
||||
if (!sctx->curl) {
|
||||
applog(LOG_ERR, "CURL initialization failed");
|
||||
pthread_mutex_unlock(&sctx->sock_lock);
|
||||
pthread_mutex_unlock(&stratum_sock_lock);
|
||||
return false;
|
||||
}
|
||||
curl = sctx->curl;
|
||||
@ -903,21 +939,21 @@ bool stratum_connect(struct stratum_ctx *sctx, const char *url)
|
||||
sctx->sockbuf_size = RBUFSIZE;
|
||||
}
|
||||
sctx->sockbuf[0] = '\0';
|
||||
pthread_mutex_unlock(&sctx->sock_lock);
|
||||
pthread_mutex_unlock(&stratum_sock_lock);
|
||||
|
||||
if (url != sctx->url) {
|
||||
free(sctx->url);
|
||||
sctx->url = strdup(url);
|
||||
}
|
||||
free(sctx->curl_url);
|
||||
sctx->curl_url = (char*)malloc(strlen(url));
|
||||
sctx->curl_url = (char*)malloc(strlen(url)+1);
|
||||
sprintf(sctx->curl_url, "http%s", strstr(url, "://"));
|
||||
|
||||
if (opt_protocol)
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, sctx->curl_url);
|
||||
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, opt_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, sctx->curl_err_str);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
|
||||
@ -957,16 +993,41 @@ bool stratum_connect(struct stratum_ctx *sctx, const char *url)
|
||||
return true;
|
||||
}
|
||||
|
||||
void stratum_free_job(struct stratum_ctx *sctx)
|
||||
{
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
if (sctx->job.job_id) {
|
||||
free(sctx->job.job_id);
|
||||
}
|
||||
if (sctx->job.merkle_count) {
|
||||
for (int i = 0; i < sctx->job.merkle_count; i++) {
|
||||
free(sctx->job.merkle[i]);
|
||||
sctx->job.merkle[i] = NULL;
|
||||
}
|
||||
free(sctx->job.merkle);
|
||||
}
|
||||
free(sctx->job.coinbase);
|
||||
// note: xnonce2 is not allocated
|
||||
memset(&(sctx->job.job_id), 0, sizeof(struct stratum_job));
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
}
|
||||
|
||||
void stratum_disconnect(struct stratum_ctx *sctx)
|
||||
{
|
||||
pthread_mutex_lock(&sctx->sock_lock);
|
||||
pthread_mutex_lock(&stratum_sock_lock);
|
||||
if (sctx->curl) {
|
||||
sctx->disconnects++;
|
||||
pools[sctx->pooln].disconnects++;
|
||||
curl_easy_cleanup(sctx->curl);
|
||||
sctx->curl = NULL;
|
||||
sctx->sockbuf[0] = '\0';
|
||||
if (sctx->sockbuf)
|
||||
sctx->sockbuf[0] = '\0';
|
||||
// free(sctx->sockbuf);
|
||||
// sctx->sockbuf = NULL;
|
||||
}
|
||||
pthread_mutex_unlock(&sctx->sock_lock);
|
||||
if (sctx->job.job_id) {
|
||||
stratum_free_job(sctx);
|
||||
}
|
||||
pthread_mutex_unlock(&stratum_sock_lock);
|
||||
}
|
||||
|
||||
static const char *get_stratum_session_id(json_t *val)
|
||||
@ -1012,19 +1073,19 @@ static bool stratum_parse_extranonce(struct stratum_ctx *sctx, json_t *params, i
|
||||
goto out;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&sctx->work_lock);
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
if (sctx->xnonce1)
|
||||
free(sctx->xnonce1);
|
||||
sctx->xnonce1_size = strlen(xnonce1) / 2;
|
||||
sctx->xnonce1 = (uchar*) calloc(1, sctx->xnonce1_size);
|
||||
if (unlikely(!sctx->xnonce1)) {
|
||||
applog(LOG_ERR, "Failed to alloc xnonce1");
|
||||
pthread_mutex_unlock(&sctx->work_lock);
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
goto out;
|
||||
}
|
||||
hex2bin(sctx->xnonce1, xnonce1, sctx->xnonce1_size);
|
||||
sctx->xnonce2_size = xn2_size;
|
||||
pthread_mutex_unlock(&sctx->work_lock);
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
|
||||
if (pndx == 0 && opt_debug) /* pool dynamic change */
|
||||
applog(LOG_DEBUG, "Stratum set nonce %s with extranonce2 size=%d",
|
||||
@ -1103,12 +1164,12 @@ start:
|
||||
if (opt_debug && sid)
|
||||
applog(LOG_DEBUG, "Stratum session id: %s", sid);
|
||||
|
||||
pthread_mutex_lock(&sctx->work_lock);
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
if (sctx->session_id)
|
||||
free(sctx->session_id);
|
||||
sctx->session_id = sid ? strdup(sid) : NULL;
|
||||
sctx->next_diff = 1.0;
|
||||
pthread_mutex_unlock(&sctx->work_lock);
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
|
||||
out:
|
||||
free(s);
|
||||
@ -1253,8 +1314,8 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
|
||||
bool clean, ret = false;
|
||||
int merkle_count, i;
|
||||
json_t *merkle_arr;
|
||||
uchar **merkle;
|
||||
uchar(*merkle_tree)[32] = NULL;
|
||||
uchar **merkle = NULL;
|
||||
// uchar(*merkle_tree)[32] = { 0 };
|
||||
int ntime;
|
||||
|
||||
job_id = json_string_value(json_array_get(params, 0));
|
||||
@ -1287,7 +1348,8 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
|
||||
applog(LOG_DEBUG, "stratum time is at least %ds in the future", ntime);
|
||||
}
|
||||
|
||||
merkle = (uchar**) malloc(merkle_count * sizeof(char *));
|
||||
if (merkle_count)
|
||||
merkle = (uchar**) malloc(merkle_count * sizeof(char *));
|
||||
for (i = 0; i < merkle_count; i++) {
|
||||
const char *s = json_string_value(json_array_get(merkle_arr, i));
|
||||
if (!s || strlen(s) != 64) {
|
||||
@ -1301,7 +1363,7 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
|
||||
hex2bin(merkle[i], s, 32);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&sctx->work_lock);
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
|
||||
coinb1_size = strlen(coinb1) / 2;
|
||||
coinb2_size = strlen(coinb2) / 2;
|
||||
@ -1341,7 +1403,7 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
|
||||
|
||||
sctx->job.diff = sctx->next_diff;
|
||||
|
||||
pthread_mutex_unlock(&sctx->work_lock);
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
|
||||
ret = true;
|
||||
|
||||
@ -1358,9 +1420,9 @@ static bool stratum_set_difficulty(struct stratum_ctx *sctx, json_t *params)
|
||||
if (diff <= 0.0)
|
||||
return false;
|
||||
|
||||
pthread_mutex_lock(&sctx->work_lock);
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
sctx->next_diff = diff;
|
||||
pthread_mutex_unlock(&sctx->work_lock);
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
|
||||
/* store for api stats */
|
||||
if (diff != stratum_diff) {
|
||||
|
Loading…
Reference in New Issue
Block a user