mirror of
https://github.com/GOSTSec/ccminer
synced 2025-01-10 14:57:53 +00:00
sia: support for nanopool http protocol
-o http://xxxx:port -u <addr> -p <worker> Signed-off-by: Tanguy Pruvot <tanguy.pruvot@gmail.com>
This commit is contained in:
parent
b31fb5316b
commit
d8e518ac3d
220
ccminer.cpp
220
ccminer.cpp
@ -710,11 +710,178 @@ static bool work_decode(const json_t *val, struct work *work)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- SIA LONGPOLL --------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct data_buffer {
|
||||||
|
void *buf;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t sia_data_cb(const void *ptr, size_t size, size_t nmemb,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct data_buffer *db = (struct data_buffer *)user_data;
|
||||||
|
size_t len = size * nmemb;
|
||||||
|
size_t oldlen, newlen;
|
||||||
|
void *newmem;
|
||||||
|
static const uchar zero = 0;
|
||||||
|
|
||||||
|
oldlen = db->len;
|
||||||
|
newlen = oldlen + len;
|
||||||
|
|
||||||
|
newmem = realloc(db->buf, newlen + 1);
|
||||||
|
if (!newmem)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
db->buf = newmem;
|
||||||
|
db->len = newlen;
|
||||||
|
memcpy((char*)db->buf + oldlen, ptr, len);
|
||||||
|
memcpy((char*)db->buf + newlen, &zero, 1); /* null terminate */
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* sia_getheader(CURL *curl, struct pool_infos *pool)
|
||||||
|
{
|
||||||
|
char curl_err_str[CURL_ERROR_SIZE] = { 0 };
|
||||||
|
struct data_buffer all_data = { 0 };
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
char data[256] = { 0 };
|
||||||
|
char url[512];
|
||||||
|
|
||||||
|
// nanopool
|
||||||
|
snprintf(url, 512, "%s/miner/header?address=%s&worker=%s", //&longpoll
|
||||||
|
pool->url, pool->user, pool->pass);
|
||||||
|
|
||||||
|
if (opt_protocol)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, opt_timeout);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, sia_data_cb);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
|
||||||
|
|
||||||
|
headers = curl_slist_append(headers, "Accept: application/octet-stream");
|
||||||
|
headers = curl_slist_append(headers, "Expect:"); // disable Expect hdr
|
||||||
|
headers = curl_slist_append(headers, "User-Agent: Sia-Agent"); // required for now
|
||||||
|
// headers = curl_slist_append(headers, "User-Agent: " USER_AGENT);
|
||||||
|
// headers = curl_slist_append(headers, "X-Mining-Extensions: longpoll");
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
int rc = curl_easy_perform(curl);
|
||||||
|
if (rc && strlen(curl_err_str)) {
|
||||||
|
applog(LOG_WARNING, "%s", curl_err_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_data.len >= 112)
|
||||||
|
cbin2hex(data, (const char*) all_data.buf, 112);
|
||||||
|
if (opt_protocol || all_data.len != 112)
|
||||||
|
applog(LOG_DEBUG, "received %d bytes: %s", (int) all_data.len, data);
|
||||||
|
|
||||||
|
curl_slist_free_all(headers);
|
||||||
|
|
||||||
|
return rc == 0 && all_data.len ? strdup(data) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sia_work_decode(const char *hexdata, struct work *work)
|
||||||
|
{
|
||||||
|
uint8_t target[32];
|
||||||
|
if (!work) return false;
|
||||||
|
|
||||||
|
hex2bin((uchar*)target, &hexdata[0], 32);
|
||||||
|
swab256(work->target, target);
|
||||||
|
work->targetdiff = target_to_diff(work->target);
|
||||||
|
|
||||||
|
hex2bin((uchar*)work->data, &hexdata[64], 80);
|
||||||
|
// high 16 bits of the 64 bits nonce
|
||||||
|
work->data[9] = rand() << 16;
|
||||||
|
|
||||||
|
// use work ntime as job id
|
||||||
|
cbin2hex(work->job_id, (const char*)&work->data[10], 4);
|
||||||
|
calc_network_diff(work);
|
||||||
|
|
||||||
|
if (stratum_diff != work->targetdiff) {
|
||||||
|
stratum_diff = work->targetdiff;
|
||||||
|
applog(LOG_WARNING, "Pool diff set to %g", stratum_diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int share_result(int result, int pooln, double sharediff, const char *reason);
|
||||||
|
|
||||||
|
bool sia_submit(CURL *curl, struct pool_infos *pool, struct work *work)
|
||||||
|
{
|
||||||
|
char curl_err_str[CURL_ERROR_SIZE] = { 0 };
|
||||||
|
struct data_buffer all_data = { 0 };
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
char buf[256] = { 0 };
|
||||||
|
char url[512];
|
||||||
|
|
||||||
|
if (opt_protocol)
|
||||||
|
applog_hex(work->data, 80);
|
||||||
|
//applog_hex(&work->data[8], 16);
|
||||||
|
//applog_hex(&work->data[10], 4);
|
||||||
|
|
||||||
|
// nanopool
|
||||||
|
snprintf(url, 512, "%s/miner/header?address=%s&worker=%s",
|
||||||
|
pool->url, pool->user, pool->pass);
|
||||||
|
|
||||||
|
if (opt_protocol)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, sia_data_cb);
|
||||||
|
|
||||||
|
memcpy(buf, work->data, 80);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 80);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*) buf);
|
||||||
|
|
||||||
|
// headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
|
||||||
|
// headers = curl_slist_append(headers, "Content-Length: 80");
|
||||||
|
headers = curl_slist_append(headers, "Accept:"); // disable Accept hdr
|
||||||
|
headers = curl_slist_append(headers, "Expect:"); // disable Expect hdr
|
||||||
|
headers = curl_slist_append(headers, "User-Agent: Sia-Agent");
|
||||||
|
// headers = curl_slist_append(headers, "User-Agent: " USER_AGENT);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
int res = curl_easy_perform(curl) == 0;
|
||||||
|
long errcode;
|
||||||
|
CURLcode c = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &errcode);
|
||||||
|
if (errcode != 204) {
|
||||||
|
if (strlen(curl_err_str))
|
||||||
|
applog(LOG_ERR, "submit err %ld %s", errcode, curl_err_str);
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
share_result(res, work->pooln, work->sharediff, res ? NULL : (char*) all_data.buf);
|
||||||
|
|
||||||
|
curl_slist_free_all(headers);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- END SIA LONGPOLL ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define YES "yes!"
|
#define YES "yes!"
|
||||||
#define YAY "yay!!!"
|
#define YAY "yay!!!"
|
||||||
#define BOO "booooo"
|
#define BOO "booooo"
|
||||||
|
|
||||||
static int share_result(int result, int pooln, double sharediff, const char *reason)
|
int share_result(int result, int pooln, double sharediff, const char *reason)
|
||||||
{
|
{
|
||||||
const char *flag;
|
const char *flag;
|
||||||
char suppl[32] = { 0 };
|
char suppl[32] = { 0 };
|
||||||
@ -935,6 +1102,9 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
|
|||||||
else if (opt_algo == ALGO_DECRED) {
|
else if (opt_algo == ALGO_DECRED) {
|
||||||
data_size = 192; adata_sz = 180/4;
|
data_size = 192; adata_sz = 180/4;
|
||||||
}
|
}
|
||||||
|
else if (opt_algo == ALGO_SIA) {
|
||||||
|
return sia_submit(curl, pool, work);
|
||||||
|
}
|
||||||
|
|
||||||
if (opt_algo != ALGO_HEAVY && opt_algo != ALGO_MJOLLNIR) {
|
if (opt_algo != ALGO_HEAVY && opt_algo != ALGO_MJOLLNIR) {
|
||||||
for (int i = 0; i < adata_sz; i++)
|
for (int i = 0; i < adata_sz; i++)
|
||||||
@ -1097,21 +1267,36 @@ static bool get_mininginfo(CURL *curl, struct work *work)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *rpc_req =
|
static const char *json_rpc_getwork =
|
||||||
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
|
"{\"method\":\"getwork\",\"params\":[],\"id\":0}\r\n";
|
||||||
|
|
||||||
static bool get_upstream_work(CURL *curl, struct work *work)
|
static bool get_upstream_work(CURL *curl, struct work *work)
|
||||||
{
|
{
|
||||||
bool rc;
|
bool rc = false;
|
||||||
struct timeval tv_start, tv_end, diff;
|
struct timeval tv_start, tv_end, diff;
|
||||||
struct pool_infos *pool = &pools[work->pooln];
|
struct pool_infos *pool = &pools[work->pooln];
|
||||||
|
const char *rpc_req = json_rpc_getwork;
|
||||||
json_t *val;
|
json_t *val;
|
||||||
|
|
||||||
|
gettimeofday(&tv_start, NULL);
|
||||||
|
|
||||||
|
if (opt_algo == ALGO_SIA) {
|
||||||
|
char *sia_header = sia_getheader(curl, pool);
|
||||||
|
if (sia_header) {
|
||||||
|
rc = sia_work_decode(sia_header, work);
|
||||||
|
free(sia_header);
|
||||||
|
}
|
||||||
|
gettimeofday(&tv_end, NULL);
|
||||||
|
if (have_stratum || unlikely(work->pooln != cur_pooln)) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (opt_debug_threads)
|
if (opt_debug_threads)
|
||||||
applog(LOG_DEBUG, "%s: want_longpoll=%d have_longpoll=%d",
|
applog(LOG_DEBUG, "%s: want_longpoll=%d have_longpoll=%d",
|
||||||
__func__, want_longpoll, have_longpoll);
|
__func__, want_longpoll, have_longpoll);
|
||||||
|
|
||||||
gettimeofday(&tv_start, NULL);
|
|
||||||
/* want_longpoll/have_longpoll required here to init/unlock the lp thread */
|
/* want_longpoll/have_longpoll required here to init/unlock the lp thread */
|
||||||
val = json_rpc_call_pool(curl, pool, rpc_req, want_longpoll, have_longpoll, NULL);
|
val = json_rpc_call_pool(curl, pool, rpc_req, want_longpoll, have_longpoll, NULL);
|
||||||
gettimeofday(&tv_end, NULL);
|
gettimeofday(&tv_end, NULL);
|
||||||
@ -1730,7 +1915,7 @@ static void *miner_thread(void *userdata)
|
|||||||
|
|
||||||
regen = (nonceptr[0] >= end_nonce);
|
regen = (nonceptr[0] >= end_nonce);
|
||||||
if (opt_algo == ALGO_SIA) {
|
if (opt_algo == ALGO_SIA) {
|
||||||
regen = (nonceptr[1] & 0xFF00 >= 0xF000);
|
regen = ((nonceptr[1] & 0xFF00) >= 0xF000);
|
||||||
}
|
}
|
||||||
regen = regen || extrajob;
|
regen = regen || extrajob;
|
||||||
|
|
||||||
@ -1813,8 +1998,7 @@ static void *miner_thread(void *userdata)
|
|||||||
|
|
||||||
} else if (opt_algo == ALGO_SIA) {
|
} else if (opt_algo == ALGO_SIA) {
|
||||||
// suprnova job_id check without data/target/height change...
|
// suprnova job_id check without data/target/height change...
|
||||||
check_stratum_jobs = true;
|
if (have_stratum && strcmp(work.job_id, g_work.job_id)) {
|
||||||
if (check_stratum_jobs && strcmp(work.job_id, g_work.job_id)) {
|
|
||||||
pthread_mutex_unlock(&g_work_lock);
|
pthread_mutex_unlock(&g_work_lock);
|
||||||
work_done = true;
|
work_done = true;
|
||||||
continue;
|
continue;
|
||||||
@ -2344,6 +2528,7 @@ static void *longpoll_thread(void *userdata)
|
|||||||
struct pool_infos *pool;
|
struct pool_infos *pool;
|
||||||
CURL *curl = NULL;
|
CURL *curl = NULL;
|
||||||
char *hdr_path = NULL, *lp_url = NULL;
|
char *hdr_path = NULL, *lp_url = NULL;
|
||||||
|
const char *rpc_req = json_rpc_getwork;
|
||||||
bool need_slash = false;
|
bool need_slash = false;
|
||||||
int pooln, switchn;
|
int pooln, switchn;
|
||||||
|
|
||||||
@ -2369,8 +2554,12 @@ wait_lp_url:
|
|||||||
// to detect pool switch during loop
|
// to detect pool switch during loop
|
||||||
switchn = pool_switch_count;
|
switchn = pool_switch_count;
|
||||||
|
|
||||||
|
if (opt_algo == ALGO_SIA) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* full URL */
|
/* full URL */
|
||||||
if (strstr(hdr_path, "://")) {
|
else if (strstr(hdr_path, "://")) {
|
||||||
lp_url = hdr_path;
|
lp_url = hdr_path;
|
||||||
hdr_path = NULL;
|
hdr_path = NULL;
|
||||||
}
|
}
|
||||||
@ -2408,6 +2597,19 @@ longpoll_retry:
|
|||||||
if (switchn != pool_switch_count)
|
if (switchn != pool_switch_count)
|
||||||
goto need_reinit;
|
goto need_reinit;
|
||||||
|
|
||||||
|
if (opt_algo == ALGO_SIA) {
|
||||||
|
char *sia_header = sia_getheader(curl, pool);
|
||||||
|
if (sia_header) {
|
||||||
|
pthread_mutex_lock(&g_work_lock);
|
||||||
|
if (sia_work_decode(sia_header, &g_work)) {
|
||||||
|
g_work_time = time(NULL);
|
||||||
|
pthread_mutex_unlock(&g_work_lock);
|
||||||
|
}
|
||||||
|
free(sia_header);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
val = json_rpc_longpoll(curl, lp_url, pool, rpc_req, &err);
|
val = json_rpc_longpoll(curl, lp_url, pool, rpc_req, &err);
|
||||||
if (have_stratum || switchn != pool_switch_count) {
|
if (have_stratum || switchn != pool_switch_count) {
|
||||||
if (val)
|
if (val)
|
||||||
|
3
miner.h
3
miner.h
@ -662,7 +662,6 @@ struct work {
|
|||||||
#define POK_BOOL_MASK 0x00008000
|
#define POK_BOOL_MASK 0x00008000
|
||||||
#define POK_DATA_MASK 0xFFFF0000
|
#define POK_DATA_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
|
||||||
#define MAX_POOLS 8
|
#define MAX_POOLS 8
|
||||||
struct pool_infos {
|
struct pool_infos {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
@ -681,7 +680,7 @@ struct pool_infos {
|
|||||||
// credentials
|
// credentials
|
||||||
char url[512];
|
char url[512];
|
||||||
char short_url[64];
|
char short_url[64];
|
||||||
char user[64];
|
char user[128];
|
||||||
char pass[384];
|
char pass[384];
|
||||||
// config options
|
// config options
|
||||||
double max_diff;
|
double max_diff;
|
||||||
|
Loading…
Reference in New Issue
Block a user