restored default segwit on, worked on stratum support of lbry

This commit is contained in:
Brannon King 2019-10-14 09:40:05 -06:00
parent 897f30df0f
commit b8ffcc1d4b
4 changed files with 131 additions and 128 deletions

View file

@ -1,17 +1,16 @@
# #
# Dockerfile for cpuminer # Dockerfile for cpuminer
# usage: docker run creack/cpuminer --url xxxx --user xxxx --pass xxxx # usage: docker run lbry/cpuminer --url xxxx --user xxxx --pass xxxx
# ex: docker run creack/cpuminer --url stratum+tcp://ltc.pool.com:80 --user creack.worker1 --pass abcdef # ex: docker run lbry/cpuminer --url stratum+tcp://lbc.pool.com:80 --user worker1 --pass abcdef
# #
# #
FROM ubuntu:16.04 FROM ubuntu:18.04
MAINTAINER Guillaume J. Charmes <guillaume@charmes.net>
RUN apt-get update -qq && \ RUN apt-get update -qq && \
apt-get install -qqy automake libcurl4-openssl-dev git make gcc apt-get install -qqy automake libcurl4-openssl-dev git make gcc
RUN git clone https://github.com/pooler/cpuminer RUN git clone https://github.com/lbryio/cpuminer
RUN cd cpuminer && \ RUN cd cpuminer && \
./autogen.sh && \ ./autogen.sh && \

View file

@ -102,14 +102,14 @@ struct workio_cmd {
enum algos { enum algos {
ALGO_LBRY, /* lbry */ ALGO_LBRY, /* lbry */
ALGO_SCRYPT, /* scrypt(1024,1,1) */ ALGO_SCRYPT, /* scrypt(1024,1,1) */
ALGO_SHA256D, /* SHA-256d */ ALGO_SHA256D, /* SHA-256d */
}; };
static const char *algo_names[] = { static const char *algo_names[] = {
[ALGO_LBRY] = "lbry", [ALGO_LBRY] = "lbry",
[ALGO_SCRYPT] = "scrypt", [ALGO_SCRYPT] = "scrypt",
[ALGO_SHA256D] = "sha256d", [ALGO_SHA256D] = "sha256d",
}; };
bool opt_debug = false; bool opt_debug = false;
@ -122,7 +122,6 @@ bool have_gbt = true;
bool allow_getwork = false; bool allow_getwork = false;
bool want_stratum = false; bool want_stratum = false;
bool have_stratum = false; bool have_stratum = false;
bool want_segwit = false;
bool use_syslog = false; bool use_syslog = false;
static bool opt_background = false; static bool opt_background = false;
static bool opt_quiet = false; static bool opt_quiet = false;
@ -186,7 +185,7 @@ Options:\n\
-r, --retries=N number of times to retry if a network call fails\n\ -r, --retries=N number of times to retry if a network call fails\n\
(default: retry indefinitely)\n\ (default: retry indefinitely)\n\
-R, --retry-pause=N time to pause between retries, in seconds (default: 30)\n\ -R, --retry-pause=N time to pause between retries, in seconds (default: 30)\n\
-T, --timeout=N timeout for long polling, in seconds (default: none)\n\ -T, --timeout=N timeout for long polling, in seconds (default: 70sec)\n\
-s, --scantime=N upper bound on time spent scanning current work when\n\ -s, --scantime=N upper bound on time spent scanning current work when\n\
long polling is unavailable, in seconds (default: 5)\n\ long polling is unavailable, in seconds (default: 5)\n\
--coinbase-addr=ADDR payout address for solo mining\n\ --coinbase-addr=ADDR payout address for solo mining\n\
@ -198,8 +197,7 @@ Options:\n\
--no-redirect ignore requests to change the URL of the mining server\n\ --no-redirect ignore requests to change the URL of the mining server\n\
-q, --quiet disable per-thread hashmeter output\n\ -q, --quiet disable per-thread hashmeter output\n\
-D, --debug enable debug output\n\ -D, --debug enable debug output\n\
-P, --protocol-dump verbose dump of protocol-level activities\n\ -P, --protocol-dump verbose dump of protocol-level activities\n"
--segwit include Segwit transactions in the mined data\n"
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
"\ "\
-S, --syslog use system log for output messages\n" -S, --syslog use system log for output messages\n"
@ -248,7 +246,6 @@ static struct option const options[] = {
{ "retries", 1, NULL, 'r' }, { "retries", 1, NULL, 'r' },
{ "retry-pause", 1, NULL, 'R' }, { "retry-pause", 1, NULL, 'R' },
{ "scantime", 1, NULL, 's' }, { "scantime", 1, NULL, 's' },
{ "segwit", 0, NULL, 1016 },
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
{ "syslog", 0, NULL, 'S' }, { "syslog", 0, NULL, 'S' },
#endif #endif
@ -327,26 +324,26 @@ static bool jobj_binary(const json_t *obj, const char *key,
static bool work_decode(const json_t *val, struct work *work) static bool work_decode(const json_t *val, struct work *work)
{ {
int i; int i;
if (unlikely(!jobj_binary(val, "data", work->data, sizeof(work->data)))) { if (unlikely(!jobj_binary(val, "data", work->data, sizeof(work->data)))) {
applog(LOG_ERR, "JSON invalid data"); applog(LOG_ERR, "JSON invalid data");
goto err_out; goto err_out;
} }
if (unlikely(!jobj_binary(val, "target", work->target, sizeof(work->target)))) { if (unlikely(!jobj_binary(val, "target", work->target, sizeof(work->target)))) {
applog(LOG_ERR, "JSON invalid target"); applog(LOG_ERR, "JSON invalid target");
goto err_out; goto err_out;
} }
for (i = 0; i < ARRAY_SIZE(work->data); i++) for (i = 0; i < ARRAY_SIZE(work->data); i++)
work->data[i] = le32dec(work->data + i); work->data[i] = le32dec(work->data + i);
for (i = 0; i < ARRAY_SIZE(work->target); i++) for (i = 0; i < ARRAY_SIZE(work->target); i++)
work->target[i] = le32dec(work->target + i); work->target[i] = le32dec(work->target + i);
return true; return true;
err_out: err_out:
return false; return false;
} }
static bool gbt_work_decode(const json_t *val, struct work *work) static bool gbt_work_decode(const json_t *val, struct work *work)
@ -450,7 +447,6 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
/* build coinbase transaction */ /* build coinbase transaction */
tmp = json_object_get(val, "coinbasetxn"); tmp = json_object_get(val, "coinbasetxn");
if (tmp) { if (tmp) {
const char *cbtx_hex = json_string_value(json_object_get(tmp, "data")); const char *cbtx_hex = json_string_value(json_object_get(tmp, "data"));
cbtx_size = cbtx_hex ? strlen(cbtx_hex) / 2 : 0; cbtx_size = cbtx_hex ? strlen(cbtx_hex) / 2 : 0;
@ -460,22 +456,22 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
goto out; goto out;
} }
bool hasWitness = *(uint16_t*)(cbtx + 4) == 256; bool hasWitness = *(uint16_t*)(cbtx + 4) == 256;
if (hasWitness && coinbase_append) { if (hasWitness && coinbase_append) {
// TODO: make this work by using index 43 instead of 41 in the coinbase_append handler below // TODO: make this work by using index 43 instead of 41 in the coinbase_append handler below
// and then would we pass it in as one of our supported capabilities? Sure. // and then would we pass it in as one of our supported capabilities? Sure.
applog(LOG_ERR, "This tool cannot append onto segwit transactions"); applog(LOG_ERR, "This tool cannot append onto segwit transactions");
goto out; goto out;
} }
if (hasWitness) { if (hasWitness) {
cbtx_hex = json_string_value(json_object_get(tmp, "txid")); cbtx_hex = json_string_value(json_object_get(tmp, "txid"));
size_t txid_size = strlen(cbtx_hex) / 2; size_t txid_size = strlen(cbtx_hex) / 2;
cbtx_txid = malloc(txid_size + 1); cbtx_txid = malloc(txid_size + 1);
if (txid_size != 32 || !hex2bin(cbtx_txid, cbtx_hex, txid_size)) { if (txid_size != 32 || !hex2bin(cbtx_txid, cbtx_hex, txid_size)) {
applog(LOG_ERR, "Invalid txid on coinbase"); applog(LOG_ERR, "Invalid txid on coinbase");
goto out; goto out;
} }
memrev(cbtx_txid, 32); memrev(cbtx_txid, 32);
} }
} else { } else {
int64_t cbvalue; int64_t cbvalue;
if (!pk_script_size) { if (!pk_script_size) {
@ -592,7 +588,7 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
if (xsig_len) { if (xsig_len) {
unsigned char *ssig_end = cbtx + 42 + cbtx[41]; unsigned char *ssig_end = cbtx + 42 + cbtx[41];
int push_len = cbtx[41] + xsig_len < 76 ? 1 : int push_len = cbtx[41] + xsig_len < 76 ? 1 :
cbtx[41] + 2 + xsig_len > 100 ? 0 : 2; cbtx[41] + 2 + xsig_len > 100 ? 0 : 2;
n = xsig_len + push_len; n = xsig_len + push_len;
memmove(ssig_end + n, ssig_end, cbtx_size - 42 - cbtx[41]); memmove(ssig_end + n, ssig_end, cbtx_size - 42 - cbtx[41]);
cbtx[41] += n; cbtx[41] += n;
@ -616,9 +612,9 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
size_t tx_buf_size = 32 * 1024; size_t tx_buf_size = 32 * 1024;
tx = malloc(tx_buf_size); tx = malloc(tx_buf_size);
if (cbtx_txid) if (cbtx_txid)
memcpy(merkle_tree[0], cbtx_txid, 32); memcpy(merkle_tree[0], cbtx_txid, 32);
else else
sha256d(merkle_tree[0], cbtx, cbtx_size); sha256d(merkle_tree[0], cbtx, cbtx_size);
for (i = 0; i < tx_count; i++) { for (i = 0; i < tx_count; i++) {
tmp = json_array_get(txa, i); tmp = json_array_get(txa, i);
const char *tx_hex = json_string_value(json_object_get(tmp, "data")); const char *tx_hex = json_string_value(json_object_get(tmp, "data"));
@ -668,17 +664,17 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i); work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i);
int offset = 0; int offset = 0;
if (opt_algo == ALGO_LBRY) { if (opt_algo == ALGO_LBRY) {
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
work->data[24 - i] = le32dec(claimtrie + i); work->data[24 - i] = le32dec(claimtrie + i);
offset = 8; offset = 8;
} }
work->data[17 + offset] = swab32(curtime); work->data[17 + offset] = swab32(curtime);
work->data[18 + offset] = le32dec(&bits); work->data[18 + offset] = le32dec(&bits);
memset(work->data + 19 + offset, 0x00, 52); memset(work->data + 19 + offset, 0x00, 52);
work->data[20 + offset] = 0x80000000; work->data[20 + offset] = 0x80000000;
work->data[31 + offset] = 0x00000280; work->data[31 + offset] = 0x00000280;
if (unlikely(!jobj_binary(val, "target", target, sizeof(target)))) { if (unlikely(!jobj_binary(val, "target", target, sizeof(target)))) {
applog(LOG_ERR, "JSON invalid target"); applog(LOG_ERR, "JSON invalid target");
goto out; goto out;
} }
@ -762,8 +758,9 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
uint32_t ntime, nonce; uint32_t ntime, nonce;
char ntimestr[9], noncestr[9], *xnonce2str, *req; char ntimestr[9], noncestr[9], *xnonce2str, *req;
le32enc(&ntime, work->data[17]); int offset = opt_algo == ALGO_LBRY ? 8 : 0;
le32enc(&nonce, work->data[19]); le32enc(&ntime, work->data[17 + offset]);
le32enc(&nonce, work->data[19 + offset]);
bin2hex(ntimestr, (const unsigned char *)(&ntime), 4); bin2hex(ntimestr, (const unsigned char *)(&ntime), 4);
bin2hex(noncestr, (const unsigned char *)(&nonce), 4); bin2hex(noncestr, (const unsigned char *)(&nonce), 4);
xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len); xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len);
@ -865,14 +862,13 @@ static const char *getwork_req =
#define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]" #define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]"
#define GBT_RULES "[\"segwit\"]" #define GBT_RULES "[\"segwit\"]"
#define GBT_NO_RULES "[]"
static const char *gbt_req = static const char *gbt_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES ", \"rules\": " GBT_NO_RULES "}], \"id\":0}\r\n"; GBT_CAPABILITIES ", \"rules\": " GBT_RULES "}], \"id\":0}\r\n";
static const char *gbt_lp_req = static const char *gbt_lp_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": " "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES ", \"rules\": %s, \"longpollid\": \"%s\"}], \"id\":0}\r\n"; GBT_CAPABILITIES ", \"rules\": " GBT_RULES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
static bool get_upstream_work(CURL *curl, struct work *work) static bool get_upstream_work(CURL *curl, struct work *work)
{ {
@ -884,8 +880,8 @@ static bool get_upstream_work(CURL *curl, struct work *work)
start: start:
gettimeofday(&tv_start, NULL); gettimeofday(&tv_start, NULL);
val = json_rpc_call(curl, rpc_url, rpc_userpass, val = json_rpc_call(curl, rpc_url, rpc_userpass,
have_gbt ? gbt_req : getwork_req, have_gbt ? gbt_req : getwork_req,
&err, have_gbt ? JSON_RPC_QUIET_404 : 0); &err, have_gbt ? JSON_RPC_QUIET_404 : 0);
gettimeofday(&tv_end, NULL); gettimeofday(&tv_end, NULL);
if (have_stratum) { if (have_stratum) {
@ -922,7 +918,7 @@ start:
if (opt_debug && rc) { if (opt_debug && rc) {
timeval_subtract(&diff, &tv_end, &tv_start); timeval_subtract(&diff, &tv_end, &tv_start);
applog(LOG_DEBUG, "DEBUG: got new work in %d ms", applog(LOG_DEBUG, "DEBUG: got new work in %d ms",
diff.tv_sec * 1000 + diff.tv_usec / 1000); diff.tv_sec * 1000 + diff.tv_usec / 1000);
} }
json_decref(val); json_decref(val);
@ -1115,7 +1111,7 @@ err_out:
static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work) static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
{ {
unsigned char merkle_root[64]; unsigned char merkle_root[64];
int i; int i, offset = 0;
pthread_mutex_lock(&sctx->work_lock); pthread_mutex_lock(&sctx->work_lock);
@ -1136,23 +1132,29 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
for (i = 0; i < sctx->xnonce2_size && !++sctx->job.xnonce2[i]; i++); for (i = 0; i < sctx->xnonce2_size && !++sctx->job.xnonce2[i]; i++);
/* Assemble block header */ /* Assemble block header */
memset(work->data, 0, 128); memset(work->data, 0, sizeof(work->data));
work->data[0] = le32dec(sctx->job.version); work->data[0] = le32dec(sctx->job.version);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
work->data[1 + i] = le32dec((uint32_t *)sctx->job.prevhash + i); work->data[1 + i] = le32dec((uint32_t *)sctx->job.prevhash + i);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
work->data[9 + i] = be32dec((uint32_t *)merkle_root + i); work->data[9 + i] = be32dec((uint32_t *)merkle_root + i);
work->data[17] = le32dec(sctx->job.ntime);
work->data[18] = le32dec(sctx->job.nbits); if (sctx->job.needs_claimhash) {
work->data[20] = 0x80000000; offset = 8;
work->data[31] = 0x00000280; for (i = 0; i < 8; i++)
work->data[24 - i] = le32dec((uint32_t *)sctx->job.claimhash + i);
}
work->data[17 + offset] = le32dec(sctx->job.ntime);
work->data[18 + offset] = le32dec(sctx->job.nbits);
work->data[20 + offset] = 0x80000000;
work->data[31 + offset] = 0x00000280;
pthread_mutex_unlock(&sctx->work_lock); pthread_mutex_unlock(&sctx->work_lock);
if (opt_debug) { if (opt_debug) {
char *xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len); char *xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len);
applog(LOG_DEBUG, "DEBUG: job_id='%s' extranonce2=%s ntime=%08x", applog(LOG_DEBUG, "DEBUG: job_id='%s' extranonce2=%s ntime=%08x",
work->job_id, xnonce2str, swab32(work->data[17])); work->job_id, xnonce2str, swab32(work->data[17 + offset]));
free(xnonce2str); free(xnonce2str);
} }
@ -1163,7 +1165,7 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
} }
extern int scanhash_lbry(int thr_id, uint32_t *pdata, const uint32_t *ptarget, extern int scanhash_lbry(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done); uint32_t max_nonce, uint64_t *hashes_done);
static void *miner_thread(void *userdata) static void *miner_thread(void *userdata)
{ {
@ -1189,7 +1191,7 @@ static void *miner_thread(void *userdata)
if (num_processors > 1 && opt_n_threads % num_processors == 0) { if (num_processors > 1 && opt_n_threads % num_processors == 0) {
if (!opt_quiet) if (!opt_quiet)
applog(LOG_INFO, "Binding thread %d to cpu %d", applog(LOG_INFO, "Binding thread %d to cpu %d",
thr_id, thr_id % num_processors); thr_id, thr_id % num_processors);
affine_to_cpu(thr_id, thr_id % num_processors); affine_to_cpu(thr_id, thr_id % num_processors);
} }
@ -1221,8 +1223,8 @@ static void *miner_thread(void *userdata)
/* obtain new work from internal workio thread */ /* obtain new work from internal workio thread */
pthread_mutex_lock(&g_work_lock); pthread_mutex_lock(&g_work_lock);
if (!have_stratum && if (!have_stratum &&
(time(NULL) - g_work_time >= min_scantime || (time(NULL) - g_work_time >= min_scantime ||
work.data[19 + offset] >= end_nonce)) { work.data[19 + offset] >= end_nonce)) {
work_free(&g_work); work_free(&g_work);
if (unlikely(!get_work(mythr, &g_work))) { if (unlikely(!get_work(mythr, &g_work))) {
applog(LOG_ERR, "work retrieval failed, exiting " applog(LOG_ERR, "work retrieval failed, exiting "
@ -1251,25 +1253,23 @@ static void *miner_thread(void *userdata)
max64 = LP_SCANTIME; max64 = LP_SCANTIME;
else else
max64 = g_work_time + (have_longpoll ? LP_SCANTIME : opt_scantime) max64 = g_work_time + (have_longpoll ? LP_SCANTIME : opt_scantime)
- time(NULL); - time(NULL);
max64 *= thr_hashrates[thr_id]; max64 *= thr_hashrates[thr_id];
if (max64 <= 0) { if (max64 <= 0) {
switch (opt_algo) { switch (opt_algo) {
case ALGO_LBRY: case ALGO_SCRYPT:
max64 = 0x1fffff; max64 = opt_scrypt_n < 16 ? 0x3ffff : 0x3fffff / opt_scrypt_n;
break; break;
case ALGO_SCRYPT: case ALGO_LBRY:
max64 = opt_scrypt_n < 16 ? 0x3ffff : 0x3fffff / opt_scrypt_n; case ALGO_SHA256D:
break; max64 = 0x1fffff;
case ALGO_SHA256D: break;
max64 = 0x1fffff; }
break;
}
} }
if (work.data[19] + max64 > end_nonce) if (work.data[19 + offset] + max64 > end_nonce)
max_nonce = end_nonce; max_nonce = end_nonce;
else else
max_nonce = work.data[19] + max64; max_nonce = work.data[19 + offset] + max64;
hashes_done = 0; hashes_done = 0;
gettimeofday(&tv_start, NULL); gettimeofday(&tv_start, NULL);
@ -1278,18 +1278,18 @@ static void *miner_thread(void *userdata)
switch (opt_algo) { switch (opt_algo) {
case ALGO_LBRY: case ALGO_LBRY:
rc = scanhash_lbry(thr_id, work.data, work.target, rc = scanhash_lbry(thr_id, work.data, work.target,
max_nonce, &hashes_done); max_nonce, &hashes_done);
break;
case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &hashes_done, opt_scrypt_n);
break; break;
case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &hashes_done, opt_scrypt_n);
break;
case ALGO_SHA256D: case ALGO_SHA256D:
rc = scanhash_sha256d(thr_id, work.data, work.target, rc = scanhash_sha256d(thr_id, work.data, work.target,
max_nonce, &hashes_done); max_nonce, &hashes_done);
break; break;
default: default:
/* should never happen */ /* should never happen */
goto out; goto out;
} }
@ -1383,12 +1383,12 @@ start:
int err; int err;
if (have_gbt) { if (have_gbt) {
req = malloc(strlen(gbt_lp_req) + strlen(lp_id) + 1 + strlen(GBT_RULES)); req = malloc(strlen(gbt_lp_req) + strlen(lp_id) + 1);
sprintf(req, gbt_lp_req, want_segwit ? GBT_RULES : GBT_NO_RULES, lp_id); sprintf(req, gbt_lp_req, lp_id);
} }
val = json_rpc_call(curl, lp_url, rpc_userpass, val = json_rpc_call(curl, lp_url, rpc_userpass,
req ? req : getwork_req, &err, req ? req : getwork_req, &err,
JSON_RPC_LONGPOLL); JSON_RPC_LONGPOLL);
free(req); free(req);
if (have_stratum) { if (have_stratum) {
if (val) if (val)
@ -1490,8 +1490,8 @@ static void *stratum_thread(void *userdata)
restart_threads(); restart_threads();
if (!stratum_connect(&stratum, stratum.url) || if (!stratum_connect(&stratum, stratum.url) ||
!stratum_subscribe(&stratum) || !stratum_subscribe(&stratum) ||
!stratum_authorize(&stratum, rpc_user, rpc_pass)) { !stratum_authorize(&stratum, rpc_user, rpc_pass)) {
stratum_disconnect(&stratum); stratum_disconnect(&stratum);
if (opt_retries >= 0 && ++failures > opt_retries) { if (opt_retries >= 0 && ++failures > opt_retries) {
applog(LOG_ERR, "...terminating workio thread"); applog(LOG_ERR, "...terminating workio thread");
@ -1504,7 +1504,7 @@ static void *stratum_thread(void *userdata)
} }
if (stratum.job.job_id && if (stratum.job.job_id &&
(!g_work_time || strcmp(stratum.job.job_id, g_work.job_id))) { (!g_work_time || strcmp(stratum.job.job_id, g_work.job_id))) {
pthread_mutex_lock(&g_work_lock); pthread_mutex_lock(&g_work_lock);
stratum_gen_work(&stratum, &g_work); stratum_gen_work(&stratum, &g_work);
time(&g_work_time); time(&g_work_time);
@ -1731,9 +1731,9 @@ static void parse_arg(int key, char *arg, char *pname)
hp = ap; hp = ap;
if (ap != arg) { if (ap != arg) {
if (strncasecmp(arg, "http://", 7) && if (strncasecmp(arg, "http://", 7) &&
strncasecmp(arg, "https://", 8) && strncasecmp(arg, "https://", 8) &&
strncasecmp(arg, "stratum+tcp://", 14) && strncasecmp(arg, "stratum+tcp://", 14) &&
strncasecmp(arg, "stratum+tcps://", 15)) { strncasecmp(arg, "stratum+tcps://", 15)) {
fprintf(stderr, "%s: unknown protocol -- '%s'\n", fprintf(stderr, "%s: unknown protocol -- '%s'\n",
pname, arg); pname, arg);
show_usage_and_exit(1); show_usage_and_exit(1);
@ -1826,9 +1826,6 @@ static void parse_arg(int key, char *arg, char *pname)
} }
strcpy(coinbase_sig, arg); strcpy(coinbase_sig, arg);
break; break;
case 1016:
want_segwit = true;
break;
case 'S': case 'S':
use_syslog = true; use_syslog = true;
break; break;
@ -1948,9 +1945,9 @@ int main(int argc, char *argv[])
pthread_mutex_init(&stratum.work_lock, NULL); pthread_mutex_init(&stratum.work_lock, NULL);
flags = opt_benchmark || (strncasecmp(rpc_url, "https://", 8) && flags = opt_benchmark || (strncasecmp(rpc_url, "https://", 8) &&
strncasecmp(rpc_url, "stratum+tcps://", 15)) strncasecmp(rpc_url, "stratum+tcps://", 15))
? (CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL) ? (CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL)
: CURL_GLOBAL_ALL; : CURL_GLOBAL_ALL;
if (curl_global_init(flags)) { if (curl_global_init(flags)) {
applog(LOG_ERR, "CURL initialization failed"); applog(LOG_ERR, "CURL initialization failed");
return 1; return 1;
@ -2039,6 +2036,7 @@ int main(int argc, char *argv[])
} }
if (want_stratum) { if (want_stratum) {
/* init stratum thread info */ /* init stratum thread info */
stratum.job.needs_claimhash = opt_algo == ALGO_LBRY;
stratum_thr_id = opt_n_threads + 2; stratum_thr_id = opt_n_threads + 2;
thr = &thr_info[stratum_thr_id]; thr = &thr_info[stratum_thr_id];
thr->id = stratum_thr_id; thr->id = stratum_thr_id;

View file

@ -228,6 +228,8 @@ struct stratum_job {
unsigned char ntime[4]; unsigned char ntime[4];
bool clean; bool clean;
double diff; double diff;
unsigned char claimhash[32];
bool needs_claimhash;
}; };
struct stratum_ctx { struct stratum_ctx {

30
util.c
View file

@ -346,7 +346,7 @@ json_t *json_rpc_call(CURL *curl, const char *url,
json_error_t err; json_error_t err;
struct curl_slist *headers = NULL; struct curl_slist *headers = NULL;
char curl_err_str[CURL_ERROR_SIZE]; char curl_err_str[CURL_ERROR_SIZE];
long timeout = (flags & JSON_RPC_LONGPOLL) ? opt_timeout : 30; long timeout = (flags & JSON_RPC_LONGPOLL) ? opt_timeout : 70;
struct header_info hi = {0}; struct header_info hi = {0};
all_data.headers = &hi; all_data.headers = &hi;
@ -787,7 +787,7 @@ size_t address_to_script(unsigned char *out, size_t outsz, const char *addr)
if (addrver < 0) if (addrver < 0)
return 0; return 0;
switch (addrver) { switch (addrver) {
case 5: /* Bitcoin script hash */ case 0x7a: /* LBRY mainnet script hash */
case 196: /* Testnet script hash */ case 196: /* Testnet script hash */
if (outsz < (rv = 23)) if (outsz < (rv = 23))
return rv; return rv;
@ -1321,25 +1321,27 @@ out:
static bool stratum_notify(struct stratum_ctx *sctx, json_t *params) static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
{ {
const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime; const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime, *claimhash;
size_t coinb1_size, coinb2_size; size_t coinb1_size, coinb2_size;
bool clean, ret = false; bool clean, ret = false;
int merkle_count, i; int merkle_count, i, idx = 0;
json_t *merkle_arr; json_t *merkle_arr;
unsigned char **merkle; unsigned char **merkle;
job_id = json_string_value(json_array_get(params, 0)); job_id = json_string_value(json_array_get(params, idx++));
prevhash = json_string_value(json_array_get(params, 1)); prevhash = json_string_value(json_array_get(params, idx++));
coinb1 = json_string_value(json_array_get(params, 2)); if (sctx->job.needs_claimhash)
coinb2 = json_string_value(json_array_get(params, 3)); claimhash = json_string_value(json_array_get(params, idx++));
merkle_arr = json_array_get(params, 4); coinb1 = json_string_value(json_array_get(params, idx++));
coinb2 = json_string_value(json_array_get(params, idx++));
merkle_arr = json_array_get(params, idx++);
if (!merkle_arr || !json_is_array(merkle_arr)) if (!merkle_arr || !json_is_array(merkle_arr))
goto out; goto out;
merkle_count = json_array_size(merkle_arr); merkle_count = json_array_size(merkle_arr);
version = json_string_value(json_array_get(params, 5)); version = json_string_value(json_array_get(params, idx++));
nbits = json_string_value(json_array_get(params, 6)); nbits = json_string_value(json_array_get(params, idx++));
ntime = json_string_value(json_array_get(params, 7)); ntime = json_string_value(json_array_get(params, idx++));
clean = json_is_true(json_array_get(params, 8)); clean = json_is_true(json_array_get(params, idx++));
if (!job_id || !prevhash || !coinb1 || !coinb2 || !version || !nbits || !ntime || if (!job_id || !prevhash || !coinb1 || !coinb2 || !version || !nbits || !ntime ||
strlen(prevhash) != 64 || strlen(version) != 8 || strlen(prevhash) != 64 || strlen(version) != 8 ||
@ -1378,6 +1380,8 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
free(sctx->job.job_id); free(sctx->job.job_id);
sctx->job.job_id = strdup(job_id); sctx->job.job_id = strdup(job_id);
hex2bin(sctx->job.prevhash, prevhash, 32); hex2bin(sctx->job.prevhash, prevhash, 32);
if (sctx->job.needs_claimhash)
hex2bin(sctx->job.claimhash, claimhash, 32);
for (i = 0; i < sctx->job.merkle_count; i++) for (i = 0; i < sctx->job.merkle_count; i++)
free(sctx->job.merkle[i]); free(sctx->job.merkle[i]);