Skip to content

Commit

Permalink
SSM: Implement mining.capabilities including proxying mining.set_goal
Browse files Browse the repository at this point in the history
  • Loading branch information
luke-jr committed Nov 1, 2014
1 parent 91de01e commit 20ababc
Showing 1 changed file with 96 additions and 22 deletions.
118 changes: 96 additions & 22 deletions driver-stratum.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@

#define _ssm_client_octets work2d_xnonce1sz
#define _ssm_client_xnonce2sz work2d_xnonce2sz
static char *_ssm_notify;
static int _ssm_notify_sz;
static char *_ssm_notify, *_ssm_setgoal;
static int _ssm_notify_sz, _ssm_setgoal_sz;
static struct stratumsrv_job *_ssm_last_ssj;
static struct event *ev_notify;
static notifier_t _ssm_update_notifier;
Expand Down Expand Up @@ -66,8 +66,16 @@ struct stratumsrv_conn_userlist {
struct stratumsrv_conn_userlist *next;
};

enum stratumsrv_conn_capability {
SCC_NOTIFY = 1 << 0,
SCC_SET_DIFF = 1 << 1,
SCC_SET_GOAL = 1 << 2,
};
typedef uint8_t stratumsrv_conn_capabilities_t;

struct stratumsrv_conn {
struct bufferevent *bev;
stratumsrv_conn_capabilities_t capabilities;
uint32_t xnonce1_le;
struct timeval tv_hashes_done;
bool hashes_done_ext;
Expand Down Expand Up @@ -156,6 +164,10 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
bin2hex(ntime, &ntime_n, 4);
p += sprintf(p, "],\"%s\",\"%s\",\"%s\",%s],\"method\":\"mining.notify\",\"id\":null}\n", version, nbits, ntime, clean ? "true" : "false");

const size_t setgoalbufsz = 49 + strlen(pool->goal->name) + (pool->goalname ? (1 + strlen(pool->goalname)) : 0) + 4 + 1;
char * const setgoalbuf = malloc(setgoalbufsz);
snprintf(setgoalbuf, setgoalbufsz, "{\"method\":\"mining.set_goal\",\"id\":null,\"params\":[\"%s%s%s\"]}\n", pool->goal->name, pool->goalname ? "/" : "", pool->goalname ?: "");

ssj = malloc(sizeof(*ssj));
*ssj = (struct stratumsrv_job){
.my_job_id = strdup(my_job_id),
Expand All @@ -176,6 +188,15 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
assert(_ssm_notify_sz <= bufsz);
free(_ssm_notify);
_ssm_notify = buf;
const bool setgoal_changed = _ssm_setgoal ? strcmp(setgoalbuf, _ssm_setgoal) : true;
if (setgoal_changed)
{
free(_ssm_setgoal);
_ssm_setgoal = setgoalbuf;
_ssm_setgoal_sz = setgoalbufsz - 1;
}
else
free(setgoalbuf);
_ssm_last_ssj = ssj;

float pdiff = target_diff(ssj->swork.target);
Expand All @@ -185,13 +206,19 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
{
if (unlikely(!conn->xnonce1_le))
continue;
float conn_pdiff = stratumsrv_choose_share_pdiff(conn, malgo);
if (pdiff < conn_pdiff)
conn_pdiff = pdiff;
ssj->job_pdiff[conn->xnonce1_le] = conn_pdiff;
if (conn_pdiff != conn->current_share_pdiff)
stratumsrv_send_set_difficulty(conn, conn_pdiff);
bufferevent_write(conn->bev, _ssm_notify, _ssm_notify_sz);
if (setgoal_changed && (conn->capabilities & SCC_SET_GOAL))
bufferevent_write(conn->bev, setgoalbuf, setgoalbufsz);
if (likely(conn->capabilities & SCC_SET_DIFF))
{
float conn_pdiff = stratumsrv_choose_share_pdiff(conn, malgo);
if (pdiff < conn_pdiff)
conn_pdiff = pdiff;
ssj->job_pdiff[conn->xnonce1_le] = conn_pdiff;
if (conn_pdiff != conn->current_share_pdiff)
stratumsrv_send_set_difficulty(conn, conn_pdiff);
}
if (likely(conn->capabilities & SCC_NOTIFY))
bufferevent_write(conn->bev, _ssm_notify, _ssm_notify_sz);
}

return true;
Expand Down Expand Up @@ -388,18 +415,55 @@ void _stratumsrv_failure(struct bufferevent * const bev, const char * const idst
}while(0)

static
void _stratumsrv_success(struct bufferevent * const bev, const char * const idstr)
void stratumsrv_success2(struct bufferevent * const bev, const char * const idstr, const char * const resultstr)
{
if (!idstr)
return;

size_t bufsz = 36 + strlen(idstr);
size_t bufsz = 32 + strlen(resultstr) + strlen(idstr);
char buf[bufsz];

bufsz = sprintf(buf, "{\"result\":true,\"id\":%s,\"error\":null}\n", idstr);
bufsz = sprintf(buf, "{\"result\":%s,\"id\":%s,\"error\":null}\n", resultstr, idstr);
bufferevent_write(bev, buf, bufsz);
}

static inline
void _stratumsrv_success(struct bufferevent * const bev, const char * const idstr)
{
stratumsrv_success2(bev, idstr, "true");
}

static
void stratumsrv_mining_capabilities(struct bufferevent * const bev, json_t * const params, const char * const idstr, struct stratumsrv_conn * const conn)
{
if (json_is_null(params) || (!json_is_array(params)))
return_stratumsrv_failure(20, "Bad params");

conn->capabilities = 0;

json_t * const caps = (json_array_size(params) < 1) ? NULL : json_array_get(params, 0);
if (caps && (!json_is_null(caps)) && json_is_array(caps))
{
for (size_t i = json_array_size(caps); i-- > 0; )
{
json_t * const j = json_array_get(caps, i);
if (!json_is_string(j))
continue;
const char * const s = json_string_value(j);
if (!strcasecmp(s, "notify"))
conn->capabilities |= SCC_NOTIFY;
else
if (!strcasecmp(s, "set_difficulty"))
conn->capabilities |= SCC_SET_DIFF;
else
if (!strcasecmp(s, "set_goal"))
conn->capabilities |= SCC_SET_GOAL;
}
}

stratumsrv_success2(bev, idstr, "null");
}

static
void stratumsrv_mining_subscribe(struct bufferevent * const bev, json_t * const params, const char * const idstr, struct stratumsrv_conn * const conn)
{
Expand All @@ -426,16 +490,22 @@ void stratumsrv_mining_subscribe(struct bufferevent * const bev, json_t * const
bufsz = sprintf(buf, "{\"id\":%s,\"result\":[[[\"mining.set_difficulty\",\"x\"],[\"mining.notify\",\"%s\"]],\"%s\",%d],\"error\":null}\n", idstr, xnonce1x, xnonce1x, _ssm_client_xnonce2sz);
bufferevent_write(bev, buf, bufsz);

const struct pool * const pool = _ssm_last_ssj->swork.pool;
const struct mining_goal_info * const goal = pool->goal;
const struct mining_algorithm * const malgo = goal->malgo;
float pdiff = target_diff(_ssm_last_ssj->swork.target);
const float conn_pdiff = stratumsrv_choose_share_pdiff(conn, malgo);
if (pdiff > conn_pdiff)
pdiff = conn_pdiff;
_ssm_last_ssj->job_pdiff[*xnonce1_p] = pdiff;
stratumsrv_send_set_difficulty(conn, pdiff);
bufferevent_write(bev, _ssm_notify, _ssm_notify_sz);
if (conn->capabilities & SCC_SET_GOAL)
bufferevent_write(conn->bev, _ssm_setgoal, _ssm_setgoal_sz);
if (likely(conn->capabilities & SCC_SET_DIFF))
{
const struct pool * const pool = _ssm_last_ssj->swork.pool;
const struct mining_goal_info * const goal = pool->goal;
const struct mining_algorithm * const malgo = goal->malgo;
float pdiff = target_diff(_ssm_last_ssj->swork.target);
const float conn_pdiff = stratumsrv_choose_share_pdiff(conn, malgo);
if (pdiff > conn_pdiff)
pdiff = conn_pdiff;
_ssm_last_ssj->job_pdiff[*xnonce1_p] = pdiff;
stratumsrv_send_set_difficulty(conn, pdiff);
}
if (likely(conn->capabilities & SCC_NOTIFY))
bufferevent_write(bev, _ssm_notify, _ssm_notify_sz);
}

static
Expand Down Expand Up @@ -619,6 +689,9 @@ bool stratumsrv_process_line(struct bufferevent * const bev, const char * const
else
if (!strcasecmp(method, "mining.subscribe"))
stratumsrv_mining_subscribe(bev, params, idstr, conn);
else
if (!strcasecmp(method, "mining.capabilities"))
stratumsrv_mining_capabilities(bev, params, idstr, conn);
else
_stratumsrv_failure(bev, idstr, -3, "Method not supported");

Expand Down Expand Up @@ -709,6 +782,7 @@ void stratumlistener(struct evconnlistener *listener, evutil_socket_t sock, stru
conn = malloc(sizeof(*conn));
*conn = (struct stratumsrv_conn){
.bev = bev,
.capabilities = SCC_NOTIFY | SCC_SET_DIFF,
.desired_share_pdiff = FLT_MAX,
.desired_default_share_pdiff = true,
};
Expand Down

0 comments on commit 20ababc

Please sign in to comment.