Browse Source

Add mechanism for parsing received block messages from the main pool at remote nodes to submit them locally

master
Con Kolivas 10 years ago
parent
commit
7b887e9ac6
  1. 20
      src/ckpool.c
  2. 3
      src/ckpool.h
  3. 286
      src/stratifier.c

20
src/ckpool.c

@ -1274,6 +1274,26 @@ out:
return ret;
}
bool json_get_uint32(uint32_t *store, const json_t *val, const char *res)
{
json_t *entry = json_object_get(val, res);
bool ret = false;
if (!entry) {
LOGDEBUG("Json did not find entry %s", res);
goto out;
}
if (!json_is_integer(entry)) {
LOGWARNING("Json entry %s is not an integer", res);
goto out;
}
*store = json_integer_value(entry);
LOGDEBUG("Json found entry %s: %u", res, *store);
ret = true;
out:
return ret;
}
bool json_get_bool(bool *store, const json_t *val, const char *res)
{
json_t *entry = json_object_get(val, res);

3
src/ckpool.h

@ -267,6 +267,7 @@ enum stratum_msgtype {
SM_PING,
SM_WORKINFO,
SM_SUGGESTDIFF,
SM_BLOCK,
SM_NONE
};
@ -287,6 +288,7 @@ static const char __maybe_unused *stratum_msgs[] = {
"ping",
"workinfo",
"suggestdiff",
"block",
""
};
@ -331,6 +333,7 @@ bool json_get_string(char **store, const json_t *val, const char *res);
bool json_get_int64(int64_t *store, const json_t *val, const char *res);
bool json_get_int(int *store, const json_t *val, const char *res);
bool json_get_double(double *store, const json_t *val, const char *res);
bool json_get_uint32(uint32_t *store, const json_t *val, const char *res);
bool json_get_bool(bool *store, const json_t *val, const char *res);
bool json_getdel_int(int *store, json_t *val, const char *res);
bool json_getdel_int64(int64_t *store, json_t *val, const char *res);

286
src/stratifier.c

@ -1202,6 +1202,193 @@ static void add_node_base(ckpool_t *ckp, json_t *val)
LOGNOTICE("Block hash changed to %s", sdata->lastswaphash);
}
/* Calculate share diff and fill in hash and swap */
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)
{
unsigned char merkle_root[32], merkle_sha[64];
uint32_t *data32, *swap32, benonce32;
uchar hash1[32];
char data[80];
int i;
memcpy(coinbase, wb->coinb1bin, wb->coinb1len);
*cblen = wb->coinb1len;
memcpy(coinbase + *cblen, enonce1bin, wb->enonce1constlen + wb->enonce1varlen);
*cblen += wb->enonce1constlen + wb->enonce1varlen;
hex2bin(coinbase + *cblen, nonce2, wb->enonce2varlen);
*cblen += wb->enonce2varlen;
memcpy(coinbase + *cblen, wb->coinb2bin, wb->coinb2len);
*cblen += wb->coinb2len;
gen_hash((uchar *)coinbase, merkle_root, *cblen);
memcpy(merkle_sha, merkle_root, 32);
for (i = 0; i < wb->merkles; i++) {
memcpy(merkle_sha + 32, &wb->merklebin[i], 32);
gen_hash(merkle_sha, merkle_root, 64);
memcpy(merkle_sha, merkle_root, 32);
}
data32 = (uint32_t *)merkle_sha;
swap32 = (uint32_t *)merkle_root;
flip_32(swap32, data32);
/* Copy the cached header binary and insert the merkle root */
memcpy(data, wb->headerbin, 80);
memcpy(data + 36, merkle_root, 32);
/* Insert the nonce value into the data */
hex2bin(&benonce32, nonce, 4);
data32 = (uint32_t *)(data + 64 + 12);
*data32 = benonce32;
/* Insert the ntime value into the data */
data32 = (uint32_t *)(data + 68);
*data32 = htobe32(ntime32);
/* Hash the share */
data32 = (uint32_t *)data;
swap32 = (uint32_t *)swap;
flip_80(swap32, data32);
sha256(swap, 80, hash1);
sha256(hash1, 32, hash);
/* Calculate the diff of the share here */
return diff_from_target(hash);
}
static void
process_block(ckpool_t *ckp, const workbase_t *wb, const char *coinbase, const int cblen,
const uchar *data, const uchar *hash, uchar *swap32, char *blockhash)
{
int transactions = wb->transactions + 1;
char *gbt_block, varint[12];
char hexcoinbase[1024];
gbt_block = ckalloc(1024);
flip_32(swap32, hash);
__bin2hex(blockhash, swap32, 32);
/* Message format: "submitblock:hash,data" */
sprintf(gbt_block, "submitblock:%s,", blockhash);
__bin2hex(gbt_block + 12 + 64 + 1, data, 80);
if (transactions < 0xfd) {
uint8_t val8 = transactions;
__bin2hex(varint, (const unsigned char *)&val8, 1);
} else if (transactions <= 0xffff) {
uint16_t val16 = htole16(transactions);
strcat(gbt_block, "fd");
__bin2hex(varint, (const unsigned char *)&val16, 2);
} else {
uint32_t val32 = htole32(transactions);
strcat(gbt_block, "fe");
__bin2hex(varint, (const unsigned char *)&val32, 4);
}
strcat(gbt_block, varint);
__bin2hex(hexcoinbase, coinbase, cblen);
strcat(gbt_block, hexcoinbase);
if (wb->transactions)
realloc_strcat(&gbt_block, wb->txn_data);
send_generator(ckp, gbt_block, GEN_PRIORITY);
free(gbt_block);
}
static void submit_node_block(ckpool_t *ckp, sdata_t *sdata, json_t *val)
{
char *coinbase = NULL, *enonce1 = NULL, *nonce = NULL, *nonce2 = NULL;
uchar *enonce1bin = NULL, hash[32], swap[80], swap32[32];
char blockhash[68], cdfield[64];
int enonce1len, cblen;
ckmsg_t *block_ckmsg;
json_t *bval = NULL;
uint32_t ntime32;
workbase_t *wb;
double diff;
ts_t ts_now;
int64_t id;
if (unlikely(!json_get_string(&enonce1, val, "enonce1"))) {
LOGWARNING("Failed to get enonce1 from node method block");
goto out;
}
if (unlikely(!json_get_string(&nonce, val, "nonce"))) {
LOGWARNING("Failed to get nonce from node method block");
goto out;
}
if (unlikely(!json_get_string(&nonce2, val, "nonce2"))) {
LOGWARNING("Failed to get nonce2 from node method block");
goto out;
}
if (unlikely(!json_get_uint32(&ntime32, val, "ntime32"))) {
LOGWARNING("Failed to get ntime32 from node method block");
goto out;
}
if (unlikely(!json_get_int64(&id, val, "jobid"))) {
LOGWARNING("Failed to get jobid from node method block");
goto out;
}
if (unlikely(!json_get_double(&diff, val, "diff"))) {
LOGWARNING("Failed to get diff from node method block");
goto out;
}
ts_realtime(&ts_now);
sprintf(cdfield, "%lu,%lu", ts_now.tv_sec, ts_now.tv_nsec);
ck_rlock(&sdata->workbase_lock);
HASH_FIND_I64(sdata->workbases, &id, wb);
if (unlikely(!wb))
goto out_unlock;
/* Now we have enough to assemble a block */
coinbase = ckalloc(wb->coinb1len + wb->enonce1constlen + wb->enonce1varlen + wb->enonce2varlen + wb->coinb2len);
enonce1len = wb->enonce1constlen + wb->enonce1varlen;
enonce1bin = ckalloc(enonce1len);
hex2bin(enonce1bin, enonce1, enonce1len);
/* Fill in the hashes */
share_diff(coinbase, enonce1bin, wb, nonce2, ntime32, nonce, hash, swap, &cblen);
process_block(ckp, wb, coinbase, cblen, swap, hash, swap32, blockhash);
JSON_CPACK(bval, "{si,ss,ss,sI,ss,ss,ss,sI,sf,ss,ss,ss,ss}",
"height", wb->height,
"blockhash", blockhash,
"confirmed", "n",
"workinfoid", wb->id,
"enonce1", enonce1,
"nonce2", nonce2,
"nonce", nonce,
"reward", wb->coinbasevalue,
"diff", diff,
"createdate", cdfield,
"createby", "code",
"createcode", __func__,
"createinet", ckp->serverurl[0]);
out_unlock:
ck_runlock(&sdata->workbase_lock);
if (unlikely(!wb))
LOGWARNING("Failed to find workbase with jobid %"PRId64" in node method block", id);
else {
block_ckmsg = ckalloc(sizeof(ckmsg_t));
block_ckmsg->data = bval;
mutex_lock(&sdata->block_lock);
DL_APPEND(sdata->block_solves, block_ckmsg);
mutex_unlock(&sdata->block_lock);
ckdbq_add(ckp, ID_BLOCK, bval);
}
out:
free(enonce1bin);
free(coinbase);
free(nonce2);
free(nonce);
free(enonce1);
}
static void update_base(ckpool_t *ckp, const int prio)
{
struct update_req *ur = ckalloc(sizeof(struct update_req));
@ -4621,15 +4808,12 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
const uchar *hash, const double diff, const char *coinbase, int cblen,
const char *nonce2, const char *nonce)
{
int transactions = wb->transactions + 1;
char hexcoinbase[1024], blockhash[68];
char blockhash[68], cdfield[64];
sdata_t *sdata = client->sdata;
json_t *val = NULL, *val_copy;
char *gbt_block, varint[12];
ckpool_t *ckp = wb->ckp;
ckmsg_t *block_ckmsg;
char cdfield[64];
uchar swap[32];
uchar swap32[32];
ts_t ts_now;
/* Submit anything over 99.9% of the diff in case of rounding errors */
@ -4644,35 +4828,7 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
ts_realtime(&ts_now);
sprintf(cdfield, "%lu,%lu", ts_now.tv_sec, ts_now.tv_nsec);
gbt_block = ckalloc(1024);
flip_32(swap, hash);
__bin2hex(blockhash, swap, 32);
/* Message format: "submitblock:hash,data" */
sprintf(gbt_block, "submitblock:%s,", blockhash);
__bin2hex(gbt_block + 12 + 64 + 1, data, 80);
if (transactions < 0xfd) {
uint8_t val8 = transactions;
__bin2hex(varint, (const unsigned char *)&val8, 1);
} else if (transactions <= 0xffff) {
uint16_t val16 = htole16(transactions);
strcat(gbt_block, "fd");
__bin2hex(varint, (const unsigned char *)&val16, 2);
} else {
uint32_t val32 = htole32(transactions);
strcat(gbt_block, "fe");
__bin2hex(varint, (const unsigned char *)&val32, 4);
}
strcat(gbt_block, varint);
__bin2hex(hexcoinbase, coinbase, cblen);
strcat(gbt_block, hexcoinbase);
if (wb->transactions)
realloc_strcat(&gbt_block, wb->txn_data);
send_generator(ckp, gbt_block, GEN_PRIORITY);
free(gbt_block);
process_block(ckp, wb, coinbase, cblen, data, hash, swap32, blockhash);
JSON_CPACK(val, "{si,ss,ss,sI,ss,ss,sI,ss,ss,ss,sI,ss,ss,ss,ss}",
"height", wb->height,
@ -4702,61 +4858,6 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
ckdbq_add(ckp, ID_BLOCK, val);
}
/* Calculate share diff and fill in hash and swap */
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)
{
unsigned char merkle_root[32], merkle_sha[64];
uint32_t *data32, *swap32, benonce32;
uchar hash1[32];
char data[80];
int i;
memcpy(coinbase, wb->coinb1bin, wb->coinb1len);
*cblen = wb->coinb1len;
memcpy(coinbase + *cblen, enonce1bin, wb->enonce1constlen + wb->enonce1varlen);
*cblen += wb->enonce1constlen + wb->enonce1varlen;
hex2bin(coinbase + *cblen, nonce2, wb->enonce2varlen);
*cblen += wb->enonce2varlen;
memcpy(coinbase + *cblen, wb->coinb2bin, wb->coinb2len);
*cblen += wb->coinb2len;
gen_hash((uchar *)coinbase, merkle_root, *cblen);
memcpy(merkle_sha, merkle_root, 32);
for (i = 0; i < wb->merkles; i++) {
memcpy(merkle_sha + 32, &wb->merklebin[i], 32);
gen_hash(merkle_sha, merkle_root, 64);
memcpy(merkle_sha, merkle_root, 32);
}
data32 = (uint32_t *)merkle_sha;
swap32 = (uint32_t *)merkle_root;
flip_32(swap32, data32);
/* Copy the cached header binary and insert the merkle root */
memcpy(data, wb->headerbin, 80);
memcpy(data + 36, merkle_root, 32);
/* Insert the nonce value into the data */
hex2bin(&benonce32, nonce, 4);
data32 = (uint32_t *)(data + 64 + 12);
*data32 = benonce32;
/* Insert the ntime value into the data */
data32 = (uint32_t *)(data + 68);
*data32 = htobe32(ntime32);
/* Hash the share */
data32 = (uint32_t *)data;
swap32 = (uint32_t *)swap;
flip_80(swap32, data32);
sha256(swap, 80, hash1);
sha256(hash1, 32, hash);
/* Calculate the diff of the share here */
return diff_from_target(hash);
}
/* Needs to be entered with 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)
@ -5711,7 +5812,7 @@ static void node_client_msg(ckpool_t *ckp, json_t *val, const char *buf, stratum
}
}
static void parse_node_msg(ckpool_t *ckp, json_t *val, const char *buf)
static void parse_node_msg(ckpool_t *ckp, sdata_t *sdata, json_t *val, const char *buf)
{
int msg_type = node_msg_type(val);
@ -5724,6 +5825,9 @@ static void parse_node_msg(ckpool_t *ckp, json_t *val, const char *buf)
case SM_WORKINFO:
add_node_base(ckp, val);
break;
case SM_BLOCK:
submit_node_block(ckp, sdata, val);
break;
default:
break;
}
@ -5804,7 +5908,7 @@ static void srecv_process(ckpool_t *ckp, char *buf)
val = json_object_get(msg->json_msg, "client_id");
if (unlikely(!val)) {
if (ckp->node)
parse_node_msg(ckp, msg->json_msg, buf);
parse_node_msg(ckp, sdata, msg->json_msg, buf);
else
LOGWARNING("Failed to extract client_id from connector json smsg %s", buf);
json_decref(msg->json_msg);

Loading…
Cancel
Save