diff --git a/src/generator.c b/src/generator.c index 79a30681..6b1f1198 100644 --- a/src/generator.c +++ b/src/generator.c @@ -347,9 +347,14 @@ retry: } } } else if (cmdmatch(buf, "submitblock:")) { + char blockmsg[80]; + bool ret; + LOGNOTICE("Submitting block data!"); - if (submit_block(cs, buf + 12)) - send_proc(ckp->stratifier, "block"); + ret = submit_block(cs, buf + 12 + 64 + 1); + memset(buf + 12 + 64, 0, 1); + sprintf(blockmsg, "%sblock:%s", ret ? "" : "no", buf + 12); + send_proc(ckp->stratifier, blockmsg); } else if (cmdmatch(buf, "checkaddr:")) { if (validate_address(cs, buf + 10)) send_unix_msg(sockd, "true"); diff --git a/src/stratifier.c b/src/stratifier.c index ccff94e1..0741fb6e 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -318,6 +318,12 @@ static share_t *shares; static cklock_t share_lock; +/* Linked list of block solves, added to during submission, removed on + * accept/reject. It is likely we only ever have one solve on here but you + * never know... */ +static pthread_mutex_t block_lock; +static ckmsg_t *block_solves; + static int gen_priority; /* Priority levels for generator messages */ @@ -1149,48 +1155,96 @@ static void reconnect_clients(void) stratum_broadcast(json_msg); } -static void block_solve(ckpool_t *ckp) +static void block_solve(ckpool_t *ckp, const char *blockhash) { + ckmsg_t *block, *tmp, *found = NULL; char cdfield[64]; + int height = 0; ts_t ts_now; json_t *val; char *msg; + update_base(ckp, GEN_PRIORITY); + ts_realtime(&ts_now); sprintf(cdfield, "%lu,%lu", ts_now.tv_sec, ts_now.tv_nsec); - ck_rlock(&workbase_lock); - ASPRINTF(&msg, "Block %d solved by %s!", current_workbase->height, ckp->name); - /* We send blank settings to ckdb with only the matching data from what we submitted - * to say the block has been confirmed. */ - JSON_CPACK(val, "{si,ss,sI,ss,ss,si,ss,ss,ss,sI,ss,ss,ss,ss}", - "height", current_workbase->height, - "confirmed", "1", - "workinfoid", current_workbase->id, - "username", "", - "workername", "", - "clientid", 0, - "enonce1", "", - "nonce2", "", - "nonce", "", - "reward", current_workbase->coinbasevalue, - "createdate", cdfield, - "createby", "code", - "createcode", __func__, - "createinet", ckp->serverurl); - ck_runlock(&workbase_lock); + mutex_lock(&block_lock); + DL_FOREACH_SAFE(block_solves, block, tmp) { + val = block->data; + char *solvehash; - update_base(ckp, GEN_PRIORITY); + json_get_string(&solvehash, val, "blockhash"); + if (unlikely(!solvehash)) { + LOGERR("Failed to find blockhash in block_solve json!"); + continue; + } + if (!strcmp(solvehash, blockhash)) { + dealloc(solvehash); + found = block; + DL_DELETE(block_solves, block); + break; + } + dealloc(solvehash); + } + mutex_unlock(&block_lock); - ck_rlock(&workbase_lock); - json_set_string(val, "blockhash", current_workbase->prevhash); - ck_runlock(&workbase_lock); + if (unlikely(!found)) { + LOGERR("Failed to find blockhash %s in block_solve!", blockhash); + return; + } + val = found->data; + json_set_string(val, "confirmed", "1"); + json_set_string(val, "createdate", cdfield); + json_set_string(val, "createcode", __func__); + json_get_int(&height, val, "height"); ckdbq_add(ckp, ID_BLOCK, val); + free(found); + ASPRINTF(&msg, "Block %d solved by %s!", height, ckp->name); stratum_broadcast_message(msg); free(msg); + LOGWARNING("Solved and confirmed block %d", height); +} + +static void block_reject(const char *blockhash) +{ + ckmsg_t *block, *tmp, *found = NULL; + int height = 0; + json_t *val; + + mutex_lock(&block_lock); + DL_FOREACH_SAFE(block_solves, block, tmp) { + val = block->data; + char *solvehash; + + json_get_string(&solvehash, val, "blockhash"); + if (unlikely(!solvehash)) { + LOGERR("Failed to find blockhash in block_reject json!"); + continue; + } + if (!strcmp(solvehash, blockhash)) { + dealloc(solvehash); + found = block; + DL_DELETE(block_solves, block); + break; + } + dealloc(solvehash); + } + mutex_unlock(&block_lock); + + if (unlikely(!found)) { + LOGERR("Failed to find blockhash %s in block_reject!", blockhash); + return; + } + val = found->data; + json_get_int(&height, val, "height"); + json_decref(val); + free(found); + + LOGWARNING("Submitted, but rejected block %d", height); } /* Some upstream pools (like p2pool) don't update stratum often enough and @@ -1291,7 +1345,9 @@ retry: } else if (cmdmatch(buf, "dropall")) { drop_allclients(ckp); } else if (cmdmatch(buf, "block")) { - block_solve(ckp); + block_solve(ckp, buf + 6); + } else if (cmdmatch(buf, "noblock")) { + block_reject(buf + 8); } else if (cmdmatch(buf, "reconnect")) { reconnect_clients(); } else if (cmdmatch(buf, "loglevel")) { @@ -1907,8 +1963,9 @@ test_blocksolve(stratum_instance_t *client, workbase_t *wb, const uchar *data, c { int transactions = wb->transactions + 1; char hexcoinbase[1024], blockhash[68]; + json_t *val = NULL, *val_copy; char *gbt_block, varint[12]; - json_t *val = NULL; + ckmsg_t *block_ckmsg; char cdfield[64]; uchar swap[32]; ckpool_t *ckp; @@ -1927,8 +1984,12 @@ test_blocksolve(stratum_instance_t *client, workbase_t *wb, const uchar *data, c sprintf(cdfield, "%lu,%lu", ts_now.tv_sec, ts_now.tv_nsec); gbt_block = ckalloc(1024); - sprintf(gbt_block, "submitblock:"); - __bin2hex(gbt_block + 12, data, 80); + 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; @@ -1953,8 +2014,6 @@ test_blocksolve(stratum_instance_t *client, workbase_t *wb, const uchar *data, c send_generator(ckp, gbt_block, GEN_PRIORITY); free(gbt_block); - flip_32(swap, hash); - __bin2hex(blockhash, swap, 32); JSON_CPACK(val, "{si,ss,ss,sI,ss,ss,sI,ss,ss,ss,sI,ss,ss,ss,ss}", "height", wb->height, "blockhash", blockhash, @@ -1971,6 +2030,14 @@ test_blocksolve(stratum_instance_t *client, workbase_t *wb, const uchar *data, c "createby", "code", "createcode", __func__, "createinet", ckp->serverurl); + val_copy = json_deep_copy(val); + block_ckmsg = ckalloc(sizeof(ckmsg_t)); + block_ckmsg->data = val_copy; + + mutex_lock(&block_lock); + DL_APPEND(block_solves, block_ckmsg); + mutex_unlock(&block_lock); + ckdbq_add(ckp, ID_BLOCK, val); } @@ -3343,6 +3410,7 @@ int stratifier(proc_instance_t *pi) create_pthread(&pth_statsupdate, statsupdate, ckp); cklock_init(&share_lock); + mutex_init(&block_lock); LOGWARNING("%s stratifier ready", ckp->name);