diff --git a/src/stratifier.c b/src/stratifier.c index 31b58397..58348f03 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -253,6 +253,11 @@ static inline void json_set_double(json_t *val, const char *key, double real) json_object_set_new_nocheck(val, key, json_real(real)); } +static inline void json_set_bool(json_t *val, const char *key, bool boolean) +{ + json_object_set_new_nocheck(val, key, json_boolean(boolean)); +} + static void generate_coinbase(ckpool_t *ckp, workbase_t *wb) { char header[228]; @@ -863,6 +868,12 @@ static void add_submit(stratum_instance_t *client, int diff, bool valid) int optimal; tv_t now_t; + if (valid) { + if (unlikely(!client->absolute_shares++)) + tv_time(&client->first_share); + client->diff_shares += diff; + } + tv_time(&now_t); tdiff = tvdiff(&now_t, &client->last_share); copy_tv(&client->last_share, &now_t); @@ -936,72 +947,6 @@ static void add_submit(stratum_instance_t *client, int diff, bool valid) stratum_send_diff(client); } -static void add_submit_success(stratum_instance_t *client, const char *logdir, - const char *idstring, const char *nonce2, - const uint32_t ntime, const int diff, - double sdiff, const char *hash) -{ - char *fname, *s; - json_t *val; - FILE *fp; - int len; - - if (unlikely(!client->absolute_shares++)) - tv_time(&client->first_share); - client->diff_shares += diff; - add_submit(client, diff, true); - len = strlen(logdir) + strlen(client->workername) + 12; - fname = alloca(len); - - /* First write to the user's sharelog */ - sprintf(fname, "%s/%s.sharelog", logdir, client->workername); - fp = fopen(fname, "a"); - if (unlikely(!fp < 0)) { - LOGERR("Failed to fopen %s", fname); - return; - } - - val = json_object(); - json_set_string(val, "wbid", idstring); - json_set_string(val, "nonce2", nonce2); - json_set_int(val, "ntime", ntime); - json_set_int(val, "diff", diff); - json_set_double(val, "sdiff", sdiff); - json_set_string(val, "hash", hash); - s = json_dumps(val, 0); - len = strlen(s); - len = fprintf(fp, "%s\n", s); - free(s); - fclose(fp); - if (unlikely(len < 0)) - LOGERR("Failed to fwrite to %s", fname); - - /* Now write to the pool's sharelog, adding workername to json */ - sprintf(fname, "%s.sharelog", logdir); - fp = fopen(fname, "a"); - if (unlikely(!fp < 0)) { - LOGERR("Failed to fopen %s", fname); - return; - } - json_set_string(val, "worker", client->workername); - s = json_dumps(val, 0); - len = strlen(s); - len = fprintf(fp, "%s\n", s); - free(s); - fclose(fp); - if (unlikely(len < 0)) - LOGERR("Failed to fwrite to %s", fname); - - json_decref(val); -} - -static void add_submit_fail(stratum_instance_t *client, int diff, bool share) -{ - /* FIXME Do something else here? */ - if (share) - add_submit(client, diff, false); -} - /* We should already be holding the workbase_lock */ static void test_blocksolve(workbase_t *wb, const uchar *data, double diff, const char *coinbase, int cblen) @@ -1126,16 +1071,21 @@ out_unlock: static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, json_t *params_val, json_t **err_val) { + bool share = false, result = false, invalid = true; const char *user, *job_id, *nonce2, *ntime, *nonce; - char hexhash[68], sharehash[32], *logdir = NULL; - bool share = false, ret = false; - uint64_t wb_id = 0, id; + char hexhash[68], sharehash[32], *logdir; double sdiff = -1; char idstring[20]; uint32_t ntime32; + char *fname, *s; workbase_t *wb; uchar hash[32]; - int diff; + int len, diff; + uint64_t id; + json_t *val; + FILE *fp; + + memset(hexhash, 0, 68); if (unlikely(!json_is_array(params_val))) { *err_val = json_string("params not an array"); @@ -1177,16 +1127,22 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, sscanf(job_id, "%lx", &id); sscanf(ntime, "%x", &ntime32); - /* Decide whether this submit request should count towards share diff - * management or not. */ share = true; ck_rlock(&workbase_lock); HASH_FIND_INT(workbases, &id, wb); if (unlikely(!wb)) { json_object_set_nocheck(json_msg, "reject-reason", json_string("Invalid JobID")); + strcpy(idstring, job_id); + logdir = current_workbase->logdir; goto out_unlock; } + strcpy(idstring, wb->idstring); + logdir = strdupa(wb->logdir); + sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash); + bswap_256(sharehash, hash); + __bin2hex(hexhash, sharehash, 32); + if (id < blockchange_id) { json_object_set_nocheck(json_msg, "reject-reason", json_string("Stale")); goto out_unlock; @@ -1200,10 +1156,7 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, json_object_set_nocheck(json_msg, "reject-reason", json_string("Ntime out of range")); goto out_unlock; } - sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash); - wb_id = wb->id; - strcpy(idstring, wb->idstring); - logdir = strdupa(wb->logdir); + invalid = false; out_unlock: ck_runlock(&workbase_lock); @@ -1212,30 +1165,72 @@ out_unlock: diff = client->old_diff; else diff = client->diff; - if (sdiff >= diff) { - bswap_256(sharehash, hash); - __bin2hex(hexhash, sharehash, 32); - if (new_share(hash, wb_id)) { - LOGINFO("Accepted client %d share diff %.1f/%d: %s", client->id, sdiff, diff, hexhash); - add_submit_success(client, logdir, idstring, nonce2, ntime32, diff, sdiff, hexhash); - ret = true; + if (!invalid) { + if (sdiff >= diff) { + if (new_share(hash, id)) { + LOGINFO("Accepted client %d share diff %.1f/%d: %s", client->id, sdiff, diff, hexhash); + result = true; + } else { + json_object_set_nocheck(json_msg, "reject-reason", json_string("Duplicate")); + LOGINFO("Rejected client %d dupe diff %.1f/%d: %s", client->id, sdiff, diff, hexhash); + } } else { - add_submit_fail(client, diff, share); - json_object_set_nocheck(json_msg, "reject-reason", json_string("Duplicate")); - LOGINFO("Rejected client %d dupe diff %.1f/%d: %s", client->id, sdiff, diff, hexhash); - } - } else { - add_submit_fail(client, diff, share); - if (sdiff >= 0) { - bswap_256(sharehash, hash); - __bin2hex(hexhash, sharehash, 32); LOGINFO("Rejected client %d high diff %.1f/%d: %s", client->id, sdiff, diff, hexhash); json_object_set_nocheck(json_msg, "reject-reason", json_string("Above target")); - } else - LOGINFO("Rejected client %d invalid share", client->id); + } + } else + LOGINFO("Rejected client %d invalid share", client->id); + add_submit(client, diff, result); + + /* Log shares here */ + len = strlen(logdir) + strlen(client->workername) + 12; + fname = alloca(len); + + /* First write to the user's sharelog */ + sprintf(fname, "%s/%s.sharelog", logdir, client->workername); + fp = fopen(fname, "a"); + if (unlikely(!fp)) { + LOGERR("Failed to fopen %s", fname); + goto out; } + + val = json_object(); + json_set_string(val, "wbid", idstring); + json_set_string(val, "nonce2", nonce2); + json_set_int(val, "ntime", ntime32); + json_set_int(val, "diff", diff); + json_set_double(val, "sdiff", sdiff); + json_set_string(val, "hash", hexhash); + json_set_bool(val, "result", result); + json_object_set(val, "reject-reason", json_object_get(json_msg, "reject-reason")); + json_object_set(val, "error", *err_val); + s = json_dumps(val, 0); + len = strlen(s); + len = fprintf(fp, "%s\n", s); + free(s); + fclose(fp); + if (unlikely(len < 0)) + LOGERR("Failed to fwrite to %s", fname); + + /* Now write to the pool's sharelog, adding workername to json */ + sprintf(fname, "%s.sharelog", logdir); + fp = fopen(fname, "a"); + if (likely(fp)) { + json_set_string(val, "worker", client->workername); + s = json_dumps(val, 0); + len = strlen(s); + len = fprintf(fp, "%s\n", s); + free(s); + fclose(fp); + if (unlikely(len < 0)) + LOGERR("Failed to fwrite to %s", fname); + } else + LOGERR("Failed to fopen %s", fname); + json_decref(val); out: - return json_boolean(ret); + if (!share) + LOGINFO("Invalid share from client %d: %s", client->id, client->workername); + return json_boolean(result); } /* We should have already determined all the values passed to this are valid