Skip to content

Commit

Permalink
Initial JSON-RPC 2 tcp support
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasjones committed May 23, 2014
1 parent 834d79c commit 5e287fa
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 64 deletions.
109 changes: 68 additions & 41 deletions cpu-miner.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ static bool opt_background = false;
static bool opt_quiet = false;
static int opt_retries = -1;
static int opt_fail_pause = 10;
static int jsonrpc_2 = false;
bool jsonrpc_2 = false;
int opt_timeout = 0;
static int opt_scantime = 5;
static json_t *opt_config;
Expand Down Expand Up @@ -274,15 +274,6 @@ static struct option const options[] = {
{ 0, 0, 0, 0 }
};

struct work {
uint32_t data[32];
uint32_t target[8];

char *job_id;
size_t xnonce2_len;
unsigned char *xnonce2;
};

static struct work g_work;
static time_t g_work_time;
static pthread_mutex_t g_work_lock;
Expand Down Expand Up @@ -386,7 +377,7 @@ static bool jobj_binary(const json_t *obj, const char *key, void *buf,
return true;
}

static bool rpc2_job_decode(const json_t *job, struct work *work) {
bool rpc2_job_decode(const json_t *job, struct work *work) {
if (!jsonrpc_2) {
applog(LOG_ERR, "Tried to decode job without JSON-RPC 2.0");
return false;
Expand Down Expand Up @@ -489,7 +480,7 @@ static bool work_decode(const json_t *val, struct work *work) {
err_out: return false;
}

static bool login_decode(const json_t *val) {
bool rpc2_login_decode(const json_t *val) {
const char *id;
const char *s;

Expand Down Expand Up @@ -531,12 +522,6 @@ static bool login_decode(const json_t *val) {
return false;
}

json_t *job = json_object_get(res, "job");

if(!rpc2_job_decode(job, &g_work)) {
return false;
}

return true;

err_out: return false;
Expand Down Expand Up @@ -593,17 +578,32 @@ static bool submit_upstream_work(CURL *curl, struct work *work) {
uint32_t ntime, nonce;
char *ntimestr, *noncestr, *xnonce2str;

le32enc(&ntime, work->data[17]);
le32enc(&nonce, work->data[19]);
ntimestr = bin2hex((const unsigned char *) (&ntime), 4);
noncestr = bin2hex((const unsigned char *) (&nonce), 4);
xnonce2str = bin2hex(work->xnonce2, work->xnonce2_len);
snprintf(s, JSON_BUF_LEN,
"{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}",
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr);
free(ntimestr);
if (jsonrpc_2) {
noncestr = bin2hex(((const unsigned char*)work->data) + 39, 4);
char hash[32];
switch(opt_algo) {
case ALGO_CRYPTONIGHT:
default:
cryptonight_hash(hash, work->data, 76);
}
char *hashhex = bin2hex(hash, 32);
snprintf(s, JSON_BUF_LEN,
"{\"method\": \"submit\", \"params\": {\"id\": \"%s\", \"job_id\": \"%s\", \"nonce\": \"%s\", \"result\": \"%s\"}, \"id\":1}\r\n",
rpc2_id, work->job_id, noncestr, hashhex);
free(hashhex);
} else {
le32enc(&ntime, work->data[17]);
le32enc(&nonce, work->data[19]);
ntimestr = bin2hex((const unsigned char *) (&ntime), 4);
noncestr = bin2hex((const unsigned char *) (&nonce), 4);
xnonce2str = bin2hex(work->xnonce2, work->xnonce2_len);
snprintf(s, JSON_BUF_LEN,
"{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}",
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr);
free(ntimestr);
free(xnonce2str);
}
free(noncestr);
free(xnonce2str);

if (unlikely(!stratum_send_line(&stratum, s))) {
applog(LOG_ERR, "submit_upstream_work stratum_send_line failed");
Expand Down Expand Up @@ -732,7 +732,13 @@ static bool rpc2_login(CURL *curl) {

// applog(LOG_DEBUG, "JSON value: %s", json_dumps(val, 0));

rc = login_decode(val);
rc = rpc2_login_decode(val);

json_t *job = json_object_get(val, "job");

if(!rpc2_job_decode(job, &g_work)) {
return false;
}

if (opt_debug && rc) {
timeval_subtract(&diff, &tv_end, &tv_start);
Expand Down Expand Up @@ -844,10 +850,6 @@ static void *workio_thread(void *userdata) {
return NULL ;
}

if(jsonrpc_2) {
ok = workio_login(curl);
}

while (ok) {
struct workio_cmd *wc;

Expand Down Expand Up @@ -1321,6 +1323,7 @@ static bool stratum_handle_response(char *buf) {
json_t *val, *err_val, *res_val, *id_val;
json_error_t err;
bool ret = false;
bool valid = false;

val = JSON_LOADS(buf, &err);
if (!val) {
Expand All @@ -1335,7 +1338,17 @@ static bool stratum_handle_response(char *buf) {
if (!id_val || json_is_null(id_val) || !res_val)
goto out;

share_result(json_is_true(res_val), NULL,
if(jsonrpc_2) {
json_t *status = json_object_get(res_val, "status");
if(status) {
char *s = json_string_value(status);
valid = !strcmp(s, "OK");
}
} else {
valid = json_is_true(res_val);
}

share_result(valid, NULL,
err_val ? json_string_value(json_array_get(err_val, 1)) : NULL );

ret = true;
Expand Down Expand Up @@ -1377,16 +1390,30 @@ static void *stratum_thread(void *userdata) {
}
}

if (stratum.job.job_id
&& (!g_work_time || strcmp(stratum.job.job_id, g_work.job_id))) {
pthread_mutex_lock(&g_work_lock);
stratum_gen_work(&stratum, &g_work);
time(&g_work_time);
pthread_mutex_unlock(&g_work_lock);
if (stratum.job.clean) {
if (jsonrpc_2) {
if (stratum.work.job_id
&& (!g_work_time
|| strcmp(stratum.work.job_id, g_work.job_id))) {
pthread_mutex_lock(&g_work_lock);
memcpy(&g_work, &stratum.work, sizeof(struct work));
time(&g_work_time);
pthread_mutex_unlock(&g_work_lock);
applog(LOG_INFO, "Stratum detected new block");
restart_threads();
}
} else {
if (stratum.job.job_id
&& (!g_work_time
|| strcmp(stratum.job.job_id, g_work.job_id))) {
pthread_mutex_lock(&g_work_lock);
stratum_gen_work(&stratum, &g_work);
time(&g_work_time);
pthread_mutex_unlock(&g_work_lock);
if (stratum.job.clean) {
applog(LOG_INFO, "Stratum detected new block");
restart_threads();
}
}
}

if (!stratum_socket_full(&stratum, 120)) {
Expand Down
14 changes: 14 additions & 0 deletions miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ extern struct thr_info *thr_info;
extern int longpoll_thr_id;
extern int stratum_thr_id;
extern struct work_restart *work_restart;
extern bool jsonrpc_2;

#define JSON_RPC_LONGPOLL (1 << 0)
#define JSON_RPC_QUIET_404 (1 << 1)
Expand All @@ -229,6 +230,15 @@ extern int timeval_subtract(struct timeval *result, struct timeval *x,
extern bool fulltest(const uint32_t *hash, const uint32_t *target);
extern void diff_to_target(uint32_t *target, double diff);

struct work {
uint32_t data[32];
uint32_t target[8];

char *job_id;
size_t xnonce2_len;
unsigned char *xnonce2;
};

struct stratum_job {
char *job_id;
unsigned char prevhash[32];
Expand Down Expand Up @@ -262,6 +272,7 @@ struct stratum_ctx {
unsigned char *xnonce1;
size_t xnonce2_size;
struct stratum_job job;
struct work work;
pthread_mutex_t work_lock;
};

Expand All @@ -274,6 +285,9 @@ 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);

extern bool rpc2_job_decode(const json_t *job, struct work *work);
extern bool rpc2_login_decode(const json_t *val);

struct thread_q;

extern struct thread_q *tq_new(void);
Expand Down
84 changes: 61 additions & 23 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ static const char *get_stratum_session_id(json_t *val)

bool stratum_subscribe(struct stratum_ctx *sctx)
{
if(jsonrpc_2) return true;
char *s, *sret = NULL;
const char *sid, *xnonce1;
int xn2_size;
Expand Down Expand Up @@ -933,9 +934,15 @@ bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *p
json_error_t err;
bool ret = false;

s = malloc(80 + strlen(user) + strlen(pass));
sprintf(s, "{\"id\": 2, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}",
user, pass);
if(jsonrpc_2) {
s = malloc(300 + strlen(user) + strlen(pass));
sprintf(s, "{\"method\": \"login\", \"params\": {\"login\": \"%s\", \"pass\": \"%s\", \"agent\": \"cpuminer-multi/0.1\"}, \"id\": 1}",
user, pass);
} else {
s = malloc(80 + strlen(user) + strlen(pass));
sprintf(s, "{\"id\": 2, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}",
user, pass);
}

if (!stratum_send_line(sctx, s))
goto out;
Expand Down Expand Up @@ -965,6 +972,14 @@ bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *p
goto out;
}

if(jsonrpc_2) {
rpc2_login_decode(val);
json_t *job_val = json_object_get(res_val, "job");
pthread_mutex_lock(&sctx->work_lock);
if(job_val) rpc2_job_decode(job_val, &sctx->work);
pthread_mutex_unlock(&sctx->work_lock);
}

ret = true;

out:
Expand All @@ -975,6 +990,22 @@ bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *p
return ret;
}

static bool stratum_2_job(struct stratum_ctx *sctx, json_t *params)
{
bool ret = false;

json_t *job = json_object_get(params, "job");
if(!job) goto out;

pthread_mutex_lock(&sctx->work_lock);
ret = rpc2_job_decode(job, &sctx->work);
pthread_mutex_unlock(&sctx->work_lock);

out:

return ret;
}

static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
{
const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime;
Expand Down Expand Up @@ -1173,26 +1204,33 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
id = json_object_get(val, "id");
params = json_object_get(val, "params");

if (!strcasecmp(method, "mining.notify")) {
ret = stratum_notify(sctx, params);
goto out;
}
if (!strcasecmp(method, "mining.set_difficulty")) {
ret = stratum_set_difficulty(sctx, params);
goto out;
}
if (!strcasecmp(method, "client.reconnect")) {
ret = stratum_reconnect(sctx, params);
goto out;
}
if (!strcasecmp(method, "client.get_version")) {
ret = stratum_get_version(sctx, id);
goto out;
}
if (!strcasecmp(method, "client.show_message")) {
ret = stratum_show_message(sctx, id, params);
goto out;
}
if (jsonrpc_2) {
if (!strcasecmp(method, "job")) {
ret = stratum_2_job(sctx, params);
goto out;
}
} else {
if (!strcasecmp(method, "mining.notify")) {
ret = stratum_notify(sctx, params);
goto out;
}
if (!strcasecmp(method, "mining.set_difficulty")) {
ret = stratum_set_difficulty(sctx, params);
goto out;
}
if (!strcasecmp(method, "client.reconnect")) {
ret = stratum_reconnect(sctx, params);
goto out;
}
if (!strcasecmp(method, "client.get_version")) {
ret = stratum_get_version(sctx, id);
goto out;
}
if (!strcasecmp(method, "client.show_message")) {
ret = stratum_show_message(sctx, id, params);
goto out;
}
}

out:
if (val)
Expand Down

0 comments on commit 5e287fa

Please sign in to comment.