|
|
|
@ -1862,7 +1862,8 @@ static void add_node_base(ckpool_t *ckp, json_t *val, bool trusted, int64_t clie
|
|
|
|
|
/* Calculate share diff and fill in hash and swap. Need to hold workbase read count */ |
|
|
|
|
static double |
|
|
|
|
share_diff(char *coinbase, const uchar *enonce1bin, const workbase_t *wb, const char *nonce2, |
|
|
|
|
const uint32_t ntime32, const char *nonce, uchar *hash, uchar *swap, int *cblen) |
|
|
|
|
const uint32_t ntime32, const uint32_t version_mask, const char *nonce, |
|
|
|
|
uchar *hash, uchar *swap, int *cblen) |
|
|
|
|
{ |
|
|
|
|
unsigned char merkle_root[32], merkle_sha[64]; |
|
|
|
|
uint32_t *data32, *swap32, benonce32; |
|
|
|
@ -1894,6 +1895,17 @@ share_diff(char *coinbase, const uchar *enonce1bin, const workbase_t *wb, const
|
|
|
|
|
memcpy(data, wb->headerbin, 80); |
|
|
|
|
memcpy(data + 36, merkle_root, 32); |
|
|
|
|
|
|
|
|
|
/* Update nVersion when version_mask is in use */ |
|
|
|
|
if (version_mask) { |
|
|
|
|
uint32_t version; |
|
|
|
|
|
|
|
|
|
data32 = (uint32_t *)data; |
|
|
|
|
version = be32toh(*data32); |
|
|
|
|
version |= version_mask; |
|
|
|
|
LOGDEBUG("Vmask %u version changed to %08x", version_mask, version); |
|
|
|
|
*data32 = htobe32(version); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Insert the nonce value into the data */ |
|
|
|
|
hex2bin(&benonce32, nonce, 4); |
|
|
|
|
data32 = (uint32_t *)(data + 64 + 12); |
|
|
|
@ -1972,8 +1984,8 @@ static void send_nodes_block(sdata_t *sdata, const json_t *block_val, const int6
|
|
|
|
|
|
|
|
|
|
/* Entered with workbase readcount. */ |
|
|
|
|
static void send_node_block(ckpool_t *ckp, sdata_t *sdata, const char *enonce1, const char *nonce, |
|
|
|
|
const char *nonce2, const uint32_t ntime32, const int64_t jobid, |
|
|
|
|
const double diff, const int64_t client_id, |
|
|
|
|
const char *nonce2, const uint32_t ntime32, const uint32_t version_mask, |
|
|
|
|
const int64_t jobid, const double diff, const int64_t client_id, |
|
|
|
|
const char *coinbase, const int cblen, const uchar *data) |
|
|
|
|
{ |
|
|
|
|
if (sdata->node_instances) { |
|
|
|
@ -1983,6 +1995,7 @@ static void send_node_block(ckpool_t *ckp, sdata_t *sdata, const char *enonce1,
|
|
|
|
|
json_set_string(val, "nonce", nonce); |
|
|
|
|
json_set_string(val, "nonce2", nonce2); |
|
|
|
|
json_set_uint32(val, "ntime32", ntime32); |
|
|
|
|
json_set_uint32(val, "version_mask", version_mask); |
|
|
|
|
json_set_int64(val, "jobid", jobid); |
|
|
|
|
json_set_double(val, "diff", diff); |
|
|
|
|
add_remote_blockdata(ckp, val, cblen, coinbase, data); |
|
|
|
@ -2110,11 +2123,11 @@ static void submit_node_block(ckpool_t *ckp, sdata_t *sdata, json_t *val)
|
|
|
|
|
char *coinbase = NULL, *enonce1 = NULL, *nonce = NULL, *nonce2 = NULL, *gbt_block, |
|
|
|
|
*coinbasehex, *swaphex; |
|
|
|
|
uchar *enonce1bin = NULL, hash[32], swap[80], flip32[32]; |
|
|
|
|
uint32_t ntime32, version_mask = 0; |
|
|
|
|
char blockhash[68], cdfield[64]; |
|
|
|
|
json_t *bval, *bval_copy; |
|
|
|
|
int enonce1len, cblen; |
|
|
|
|
workbase_t *wb = NULL; |
|
|
|
|
uint32_t ntime32; |
|
|
|
|
double diff; |
|
|
|
|
ts_t ts_now; |
|
|
|
|
int64_t id; |
|
|
|
@ -2145,6 +2158,11 @@ static void submit_node_block(ckpool_t *ckp, sdata_t *sdata, json_t *val)
|
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!json_get_uint32(&version_mask, val, "version_mask")) { |
|
|
|
|
/* No version mask is not fatal, assume it to be zero */ |
|
|
|
|
LOGINFO("No version mask in node method block"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LOGWARNING("Possible upstream block solve diff %lf !", diff); |
|
|
|
|
|
|
|
|
|
ts_realtime(&ts_now); |
|
|
|
@ -2176,20 +2194,21 @@ static void submit_node_block(ckpool_t *ckp, sdata_t *sdata, json_t *val)
|
|
|
|
|
hex2bin(enonce1bin, enonce1, enonce1len); |
|
|
|
|
coinbase = alloca(wb->coinb1len + wb->enonce1constlen + wb->enonce1varlen + wb->enonce2varlen + wb->coinb2len); |
|
|
|
|
/* Fill in the hashes */ |
|
|
|
|
share_diff(coinbase, enonce1bin, wb, nonce2, ntime32, nonce, hash, swap, &cblen); |
|
|
|
|
share_diff(coinbase, enonce1bin, wb, nonce2, ntime32, version_mask, nonce, hash, swap, &cblen); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Now we have enough to assemble a block */ |
|
|
|
|
gbt_block = process_block(wb, coinbase, cblen, swap, hash, flip32, blockhash); |
|
|
|
|
ret = local_block_submit(ckp, gbt_block, flip32, wb->height); |
|
|
|
|
|
|
|
|
|
JSON_CPACK(bval, "{si,ss,ss,sI,ss,ss,ss,sI,sf,ss,ss,ss,ss}", |
|
|
|
|
JSON_CPACK(bval, "{si,ss,ss,sI,ss,ss,si,ss,sI,sf,ss,ss,ss,ss}", |
|
|
|
|
"height", wb->height, |
|
|
|
|
"blockhash", blockhash, |
|
|
|
|
"confirmed", "n", |
|
|
|
|
"workinfoid", wb->id, |
|
|
|
|
"enonce1", enonce1, |
|
|
|
|
"nonce2", nonce2, |
|
|
|
|
"version_mask", version_mask, |
|
|
|
|
"nonce", nonce, |
|
|
|
|
"reward", wb->coinbasevalue, |
|
|
|
|
"diff", diff, |
|
|
|
@ -5691,6 +5710,18 @@ static void stratum_send_diff(sdata_t *sdata, const stratum_instance_t *client)
|
|
|
|
|
stratum_add_send(sdata, json_msg, client->id, SM_DIFF); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Needs to be entered with client holding a ref count. */ |
|
|
|
|
static void stratum_send_version_mask(sdata_t *sdata, const stratum_instance_t *client) |
|
|
|
|
{ |
|
|
|
|
char version_str[12]; |
|
|
|
|
json_t *json_msg; |
|
|
|
|
|
|
|
|
|
sprintf(version_str, "%08x", client->ckp->version_mask); |
|
|
|
|
JSON_CPACK(json_msg, "{s[s]soss}", "params", version_str, "id", json_null(), |
|
|
|
|
"method", "mining.set_version_mask"); |
|
|
|
|
stratum_add_send(sdata, json_msg, client->id, SM_VERSIONMASK); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Needs to be entered with client holding a ref count. */ |
|
|
|
|
static void stratum_send_message(sdata_t *sdata, const stratum_instance_t *client, const char *msg) |
|
|
|
|
{ |
|
|
|
@ -5864,7 +5895,8 @@ downstream_block(ckpool_t *ckp, sdata_t *sdata, const json_t *val, const int cbl
|
|
|
|
|
static void |
|
|
|
|
test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uchar *data, |
|
|
|
|
const uchar *hash, const double diff, const char *coinbase, int cblen, |
|
|
|
|
const char *nonce2, const char *nonce, const uint32_t ntime32, const bool stale) |
|
|
|
|
const char *nonce2, const char *nonce, const uint32_t ntime32, const uint32_t version_mask, |
|
|
|
|
const bool stale) |
|
|
|
|
{ |
|
|
|
|
char blockhash[68], cdfield[64], *gbt_block; |
|
|
|
|
sdata_t *sdata = client->sdata; |
|
|
|
@ -5887,8 +5919,8 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
|
|
|
|
|
sprintf(cdfield, "%lu,%lu", ts_now.tv_sec, ts_now.tv_nsec); |
|
|
|
|
|
|
|
|
|
gbt_block = process_block(wb, coinbase, cblen, data, hash, flip32, blockhash); |
|
|
|
|
send_node_block(ckp, sdata, client->enonce1, nonce, nonce2, ntime32, wb->id, |
|
|
|
|
diff, client->id, coinbase, cblen, data); |
|
|
|
|
send_node_block(ckp, sdata, client->enonce1, nonce, nonce2, ntime32, version_mask, |
|
|
|
|
wb->id, diff, client->id, coinbase, cblen, data); |
|
|
|
|
|
|
|
|
|
val = json_object(); |
|
|
|
|
json_set_int(val, "height", wb->height); |
|
|
|
@ -5905,6 +5937,7 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
|
|
|
|
|
json_set_string(val, "nonce2", nonce2); |
|
|
|
|
json_set_string(val, "nonce", nonce); |
|
|
|
|
json_set_uint32(val, "ntime32", ntime32); |
|
|
|
|
json_set_uint32(val, "version_mask", version_mask); |
|
|
|
|
json_set_int64(val, "reward", wb->coinbasevalue); |
|
|
|
|
json_set_double(val, "diff", diff); |
|
|
|
|
json_set_string(val, "createdate", cdfield); |
|
|
|
@ -5934,7 +5967,8 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
|
|
|
|
|
|
|
|
|
|
/* Needs to be entered with workbase readcount and client holding a ref count. */ |
|
|
|
|
static double submission_diff(const stratum_instance_t *client, const workbase_t *wb, const char *nonce2, |
|
|
|
|
const uint32_t ntime32, const char *nonce, uchar *hash, const bool stale) |
|
|
|
|
const uint32_t ntime32, const uint32_t version_mask, |
|
|
|
|
const char *nonce, uchar *hash, const bool stale) |
|
|
|
|
{ |
|
|
|
|
char *coinbase; |
|
|
|
|
uchar swap[80]; |
|
|
|
@ -5944,10 +5978,10 @@ static double submission_diff(const stratum_instance_t *client, const workbase_t
|
|
|
|
|
coinbase = ckalloc(wb->coinb1len + wb->enonce1constlen + wb->enonce1varlen + wb->enonce2varlen + wb->coinb2len); |
|
|
|
|
|
|
|
|
|
/* Calculate the diff of the share here */ |
|
|
|
|
ret = share_diff(coinbase, client->enonce1bin, wb, nonce2, ntime32, nonce, hash, swap, &cblen); |
|
|
|
|
ret = share_diff(coinbase, client->enonce1bin, wb, nonce2, ntime32, version_mask, nonce, hash, swap, &cblen); |
|
|
|
|
|
|
|
|
|
/* Test we haven't solved a block regardless of share status */ |
|
|
|
|
test_blocksolve(client, wb, swap, hash, ret, coinbase, cblen, nonce2, nonce, ntime32, stale); |
|
|
|
|
test_blocksolve(client, wb, swap, hash, ret, coinbase, cblen, nonce2, nonce, ntime32, version_mask, stale); |
|
|
|
|
|
|
|
|
|
free(coinbase); |
|
|
|
|
|
|
|
|
@ -6022,17 +6056,17 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg,
|
|
|
|
|
const json_t *params_val, json_t **err_val) |
|
|
|
|
{ |
|
|
|
|
bool share = false, result = false, invalid = true, submit = false, stale = false; |
|
|
|
|
const char *workername, *job_id, *ntime, *nonce, *version_mask; |
|
|
|
|
double diff = client->diff, wdiff = 0, sdiff = -1; |
|
|
|
|
char hexhash[68] = {}, sharehash[32], cdfield[64]; |
|
|
|
|
const char *workername, *job_id, *ntime, *nonce; |
|
|
|
|
user_instance_t *user = client->user_instance; |
|
|
|
|
uint32_t ntime32, version_mask32 = 0; |
|
|
|
|
char *fname = NULL, *s, *nonce2; |
|
|
|
|
sdata_t *sdata = client->sdata; |
|
|
|
|
enum share_err err = SE_NONE; |
|
|
|
|
ckpool_t *ckp = client->ckp; |
|
|
|
|
char idstring[20] = {}; |
|
|
|
|
workbase_t *wb = NULL; |
|
|
|
|
uint32_t ntime32; |
|
|
|
|
uchar hash[32]; |
|
|
|
|
int nlen, len; |
|
|
|
|
time_t now_t; |
|
|
|
@ -6085,6 +6119,18 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg,
|
|
|
|
|
*err_val = JSON_ERR(err); |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
version_mask = json_string_value(json_array_get(params_val, 5)); |
|
|
|
|
if (version_mask && strlen(version_mask) && validhex(version_mask)) { |
|
|
|
|
sscanf(version_mask, "%x", &version_mask32); |
|
|
|
|
// check version mask
|
|
|
|
|
if (version_mask32 && ((~ckp->version_mask) & version_mask32) != 0) { |
|
|
|
|
// means client changed some bits which server doesn't allow to change
|
|
|
|
|
err = SE_INVALID_VERSION_MASK; |
|
|
|
|
*err_val = JSON_ERR(err); |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (safecmp(workername, client->workername)) { |
|
|
|
|
err = SE_WORKER_MISMATCH; |
|
|
|
|
*err_val = JSON_ERR(err); |
|
|
|
@ -6126,7 +6172,7 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg,
|
|
|
|
|
} |
|
|
|
|
if (id < sdata->blockchange_id) |
|
|
|
|
stale = true; |
|
|
|
|
sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash, stale); |
|
|
|
|
sdiff = submission_diff(client, wb, nonce2, ntime32, version_mask32, nonce, hash, stale); |
|
|
|
|
if (sdiff > client->best_diff) { |
|
|
|
|
worker_instance_t *worker = client->worker_instance; |
|
|
|
|
|
|
|
|
@ -7680,13 +7726,17 @@ static void sauth_process(ckpool_t *ckp, json_params_t *jp)
|
|
|
|
|
mindiff = client->suggest_diff; |
|
|
|
|
else |
|
|
|
|
mindiff = client->worker_instance->mindiff; |
|
|
|
|
if (!mindiff) |
|
|
|
|
goto out; |
|
|
|
|
mindiff = MAX(ckp->mindiff, mindiff); |
|
|
|
|
if (mindiff != client->diff) { |
|
|
|
|
client->diff = mindiff; |
|
|
|
|
stratum_send_diff(sdata, client); |
|
|
|
|
if (mindiff) { |
|
|
|
|
mindiff = MAX(ckp->mindiff, mindiff); |
|
|
|
|
if (mindiff != client->diff) { |
|
|
|
|
client->diff = mindiff; |
|
|
|
|
stratum_send_diff(sdata, client); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Set block version mask if needed */ |
|
|
|
|
if (ckp->version_mask) |
|
|
|
|
stratum_send_version_mask(sdata, client); |
|
|
|
|
out: |
|
|
|
|
dec_instance_ref(sdata, client); |
|
|
|
|
out_noclient: |
|
|
|
|