diff --git a/README.md b/README.md index 43f0ef54..1be5aaff 100644 --- a/README.md +++ b/README.md @@ -114,10 +114,6 @@ For Arch: sudo pacman -Syu base-devel cmake pkgconf curl jansson libsodium libmicrohttpd psmisc -For Clear Linux: - - sudo swupd bundle-add c-basic cmake pkgconf devpkg-curl devpkg-jansson devpkg-libsodium devpkg-libmicrohttpd psmisc - For FreeBSD: sudo pkg install cmake pkgconf curl jansson libsodium libmicrohttpd argp-standalone libepoll-shim diff --git a/src/datum_api.c b/src/datum_api.c index 7904f04f..ba54565c 100644 --- a/src/datum_api.c +++ b/src/datum_api.c @@ -1485,6 +1485,7 @@ int datum_api_config_post(struct MHD_Connection * const connection, char * const const char * const checkboxes = json_string_value(j_checkboxes); const size_t checkboxes_len = json_string_length(j_checkboxes); const char *p = checkboxes; + if (!p) p = ""; char buf[0x100]; while (p[0] != '\0') { const char *p2 = strchr(p, ' '); diff --git a/src/datum_blocktemplates.c b/src/datum_blocktemplates.c index 7b2813a7..1b9faf40 100644 --- a/src/datum_blocktemplates.c +++ b/src/datum_blocktemplates.c @@ -500,7 +500,7 @@ void *datum_gateway_template_thread(void *args) { if (t && !datum_blocktemplates_abw_ready(t, datum_protocol_is_active(), datum_protocol_abw_required())) { - DLOG_DEBUG("Retaining current work until a BLAKE2b anti-withholding assignment is active"); + DLOG_DEBUG("Retaining current work until an anti-withholding assignment is active"); t = NULL; } diff --git a/src/datum_coinbaser.c b/src/datum_coinbaser.c index 9ff4f019..a2d7bee1 100644 --- a/src/datum_coinbaser.c +++ b/src/datum_coinbaser.c @@ -783,6 +783,7 @@ int datum_coinbaser_v2_parse(T_DATUM_STRATUM_JOB *s, unsigned char *coinbaser, i // 0 outputs possible DLOG_WARN("Coinbaser length is invalid (too short). Using default/empty"); s->available_coinbase_outputs_count = 0; + if (must_free) free(coinbaser); return 0; } @@ -794,10 +795,11 @@ int datum_coinbaser_v2_parse(T_DATUM_STRATUM_JOB *s, unsigned char *coinbaser, i if (cidx + 8 + 1 > cblen) { DLOG_ERROR("Coinbaser length is invalid (mid-parsing). Using default/empty"); s->available_coinbase_outputs_count = 0; + if (must_free) free(coinbaser); return 0; } outval = upk_u64le(coinbaser, cidx); cidx+=8; - if ((outval + tally) > s->coinbase_value) { + if (outval > s->coinbase_value - tally) { // we can't include this value, since it would put us over our total available! // this shouldn't happen, however... break; @@ -806,6 +808,7 @@ int datum_coinbaser_v2_parse(T_DATUM_STRATUM_JOB *s, unsigned char *coinbaser, i if (slen < 2 || slen > 64 || cidx + slen > cblen) { DLOG_ERROR("Script length (%d) is invalid. Using default/empty", slen); s->available_coinbase_outputs_count = 0; + if (must_free) free(coinbaser); return 0; } diff --git a/src/datum_coinbaser_tests.c b/src/datum_coinbaser_tests.c index d6b1dbcb..c0bc11f3 100644 --- a/src/datum_coinbaser_tests.c +++ b/src/datum_coinbaser_tests.c @@ -75,7 +75,21 @@ static void datum_blake2b_coinbase_limit_tests(void) { datum_test(datum_stratum_coinbase_fit_to_template(1000, 0, &job) == 866); } +static void datum_coinbaser_value_overflow_tests(void) { + T_DATUM_STRATUM_JOB job = {.coinbase_value = UINT64_C(5000000000)}; + unsigned char response[] = { + 1, + 1, 0, 0, 0, 0, 0, 0, 0, 2, 0x51, 0x51, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2, 0x51, 0x51, + }; + + datum_test(datum_coinbaser_v2_parse(&job, response, sizeof(response), false) == 1); + datum_test(job.available_coinbase_outputs_count == 1); + datum_test(job.available_coinbase_outputs[0].value_sats == 1); +} + void datum_coinbaser_tests(void) { datum_prime_id_64bit_tests(); datum_blake2b_coinbase_limit_tests(); + datum_coinbaser_value_overflow_tests(); } diff --git a/src/datum_protocol.c b/src/datum_protocol.c index ff069ba1..2cb89d98 100644 --- a/src/datum_protocol.c +++ b/src/datum_protocol.c @@ -1006,7 +1006,7 @@ static bool datum_protocol_abw_mark_handled_exact( int datum_protocol_abw_candidate_receipt(int len, unsigned char *data) { if (len != 35 || data[0] != DATUM_ABW_DRAFT_REVISION || data[1] >= DATUM_ABW_ASSIGNMENT_SLOTS || data[34] != 0xFE) { - DLOG_ERROR("Invalid BLAKE2b anti-withholding candidate receipt"); + DLOG_ERROR("Invalid anti-withholding candidate receipt"); return 0; } const uint8_t assignment_id = data[1] + 1; @@ -1024,7 +1024,7 @@ int datum_protocol_abw_candidate_receipt(int len, unsigned char *data) { int datum_protocol_abw_candidate_release(int len, unsigned char *data) { if (len != 35 || data[0] != DATUM_ABW_DRAFT_REVISION || data[1] >= DATUM_ABW_ASSIGNMENT_SLOTS || data[34] != 0xFE) { - DLOG_ERROR("Invalid BLAKE2b anti-withholding candidate release"); + DLOG_ERROR("Invalid anti-withholding candidate release"); return 0; } if (!datum_config.mining_abw_verify_all_shares_on_disclosure) { @@ -1036,7 +1036,7 @@ int datum_protocol_abw_candidate_release(int len, unsigned char *data) { int datum_protocol_abw_activation(int len, unsigned char *data) { if (len != 3 || data[0] != DATUM_ABW_DRAFT_REVISION || data[1] >= DATUM_ABW_ASSIGNMENT_SLOTS || data[2] != 0xFE) { - DLOG_ERROR("Invalid BLAKE2b anti-withholding activation"); + DLOG_ERROR("Invalid anti-withholding activation"); return 0; } const uint8_t assignment_id = data[1] + 1; @@ -1059,7 +1059,7 @@ int datum_protocol_abw_assignment_notice(int len, unsigned char *data) { if (len != 36 || data[0] != DATUM_ABW_DRAFT_REVISION || (data[1] & ~DATUM_ABW_ASSIGNMENT_ACTIVE) || data[2] >= DATUM_ABW_ASSIGNMENT_SLOTS || data[35] != 0xFE) { - DLOG_ERROR("Invalid BLAKE2b anti-withholding assignment notice"); + DLOG_ERROR("Invalid anti-withholding assignment notice"); return 0; } const uint8_t assignment_id = data[2] + 1; @@ -1072,7 +1072,7 @@ int datum_protocol_abw_assignment_notice(int len, unsigned char *data) { } pthread_mutex_unlock(&datum_abw_mutex); if (!installed) { - DLOG_ERROR("Could not retain BLAKE2b anti-withholding assignment"); + DLOG_ERROR("Could not retain anti-withholding assignment"); } if (installed && (data[1] & DATUM_ABW_ASSIGNMENT_ACTIVE)) { datum_blocktemplates_notifynew(NULL, 0); @@ -1147,7 +1147,7 @@ int datum_protocol_abw_reveal(int len, unsigned char *data) { if (len != 19 || data[0] != DATUM_ABW_DRAFT_REVISION || data[18] != 0xFE || data[1] >= DATUM_ABW_ASSIGNMENT_SLOTS || !datum_blake2b_xor_key_hash(key_hash, data + 2)) { - DLOG_ERROR("Invalid BLAKE2b anti-withholding reveal"); + DLOG_ERROR("Invalid anti-withholding reveal"); return 0; } const uint8_t assignment_id = data[1] + 1; @@ -1165,7 +1165,7 @@ int datum_protocol_abw_reveal(int len, unsigned char *data) { } pthread_mutex_unlock(&datum_abw_mutex); if (has_pending) { - DLOG_ERROR("BLAKE2b anti-withholding reveal has proofs without a commitment"); + DLOG_ERROR("Anti-withholding reveal has proofs without a commitment"); return 0; } DLOG_DEBUG("Ignored disclosure for an ABW slot not held by this session"); @@ -1177,7 +1177,7 @@ int datum_protocol_abw_reveal(int len, unsigned char *data) { assignment_id, key_hash); pthread_mutex_unlock(&datum_abw_mutex); if (!commitment_matched) { - DLOG_ERROR("BLAKE2b anti-withholding reveal did not match its commitment"); + DLOG_ERROR("Anti-withholding reveal did not match its commitment"); return 0; } size_t submitted = 0; @@ -1201,15 +1201,15 @@ int datum_protocol_abw_reveal(int len, unsigned char *data) { } if (!datum_submitblock_trigger_owned(block_request, block_hash)) { free(block_request); - DLOG_ERROR("Could not queue a revealed BLAKE2b block for local submission"); + DLOG_ERROR("Could not queue a revealed block for local submission"); continue; } submitted++; - DLOG_WARN("DATUM server revealed a verified BLAKE2b block key for candidate %s", + DLOG_WARN("DATUM server revealed a verified block key for candidate %s", block_hash); } if (!submitted) { - DLOG_INFO("DATUM server retired BLAKE2b assignment slot %u", + DLOG_INFO("DATUM server retired ABW assignment slot %u", (unsigned)(assignment_id - 1)); } if (retired_active) datum_blocktemplates_notifynew(NULL, 0); @@ -2670,7 +2670,7 @@ int datum_protocol_pow_submit( } if (pow.abw_assignment_id && !datum_protocol_abw_cache_candidate( &pow, full_cb_tx, full_cb_tx_size, raw_pow_hash)) { - DLOG_ERROR("BLAKE2b anti-withholding candidate cache is full"); + DLOG_ERROR("Anti-withholding candidate cache is full"); return -1; } diff --git a/src/datum_stratum.c b/src/datum_stratum.c index a1818faf..89b4654f 100644 --- a/src/datum_stratum.c +++ b/src/datum_stratum.c @@ -918,6 +918,75 @@ void stratum_update_miner_stats_accepted(T_DATUM_CLIENT_DATA *c, uint64_t diff_a } } +bool stratum_get_job(const T_DATUM_MINER_DATA * const m, const json_t * const job_id, T_DATUM_STRATUM_JOB ** const out_job, uint16_t * const out_job_index, bool * const out_quickdiff, bool * const out_empty_work, uint64_t * const out_job_diff, const uint8_t ** const out_job_target, unsigned char * const out_coinbase_index) { + *out_quickdiff = *out_empty_work = false; + *out_job_diff = m->last_sent_diff; + + // see if this is a real job + if (!job_id) { + return false; + } + + const char *job_id_s = json_string_value(job_id); + if (!job_id_s) { + return false; + } + + if (strlen(job_id_s) != 16) { + if ((strlen(job_id_s) == 17) && (job_id_s[0] == 'Q')) { + // was a quick diff change job. discard the Q at the front + job_id_s++; + *out_quickdiff = true; + *out_job_diff = m->quickdiff_value; + *out_job_target = m->quickdiff_target; + } else if ((strlen(job_id_s) == 17) && (job_id_s[0] == 'N')) { + // new block empty work. means we use coinbase 0 and we have no merkle leafs + job_id_s++; + *out_empty_work = true; + } else { + return false; + } + } + + // jobID is + // 4 bytes time (who cares) + // 1 byte raw index kinda (useless) + // 2 bytes global ptr index + // 1 byte coinbase index used + // 6625a3d53cc0e500 + // 0123456789ABCDEF + *out_job_index = (hex2bin_uchar(&job_id_s[0xA]) << 8) | hex2bin_uchar(&job_id_s[0xC]); + *out_job_index ^= STRATUM_JOB_INDEX_XOR; + if (*out_job_index >= MAX_STRATUM_JOBS) { + return false; + } + + *out_job = global_cur_stratum_jobs[*out_job_index]; + + if (!*out_job) { + return false; + } + + if (upk_u64le((*out_job)->job_id, 0) != upk_u64le(job_id_s, 0)) { + //LOG_PRINTF("DEBUG: Job ID for index %u doesn't match expected in RAM. (%s vs %s)", *out_job_index, job->job_id, job_id_s); + return false; + } + + if (!*out_quickdiff) { + *out_job_diff = m->stratum_job_diffs[*out_job_index]; + *out_job_target = m->stratum_job_targets[*out_job_index]; + } + + *out_coinbase_index = hex2bin_uchar(&job_id_s[0xE]); + if (*out_coinbase_index >= MAX_COINBASE_TYPES) { + if (!(*out_empty_work && *out_coinbase_index == DATUM_COINBASE_ID_EMPTY)) { + return false; + } + } + + return true; +} + // CAUTION: modname MUST be part of username_s following a tilde const char *datum_stratum_mod_username(const char *username_s, char * const username_buf, const size_t username_buf_sz, const uint16_t share_rnd, const char * const modname, const size_t modname_len) { struct datum_username_mod * const umod = datum_username_mods_find(datum_config.stratum_username_mod, modname, modname_len); @@ -975,14 +1044,12 @@ int client_mining_submit(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_obj // 4 = nonce json_t *username; - json_t *job_id; json_t *extranonce2; json_t *ntime; json_t *nonce; T_DATUM_STRATUM_JOB *job = NULL; - const char *job_id_s; const char *username_s; char username_buf[0x100]; const char *extranonce2_s; @@ -1011,73 +1078,19 @@ int client_mining_submit(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_obj unsigned char full_cb_txn[MAX_COINBASE_TXN_SIZE_BYTES]; T_DATUM_MINER_DATA * const m = c->app_client_data; int i; - bool quickdiff = false; - bool empty_work = false; + bool quickdiff; + bool empty_work; bool was_block = false; char new_notify_blockhash[65]; - // see if this is a real job - job_id = json_array_get(params_obj, 1); - if (!job_id) { - send_unknown_work_error(c,id); - stratum_note_share(m, false, m->last_sent_diff); // guestimate here - return 0; - } - - job_id_s = json_string_value(job_id); - if (!job_id_s) { - send_unknown_work_error(c,id); - stratum_note_share(m, false, m->last_sent_diff); // guestimate here - return 0; - } - - if (strlen(job_id_s) != 16) { - if ((strlen(job_id_s) == 17) && (job_id_s[0] == 'Q')) { - // was a quick diff change job. discard the Q at the front - job_id_s++; - quickdiff = true; - } else if ((strlen(job_id_s) == 17) && (job_id_s[0] == 'N')) { - // new block empty work. means we use coinbase 0 and we have no merkle leafs - job_id_s++; - empty_work = true; - } else { - send_unknown_work_error(c,id); - stratum_note_share(m, false, m->last_sent_diff); // guestimate here - return 0; - } - } - - // jobID is - // 4 bytes time (who cares) - // 1 byte raw index kinda (useless) - // 2 bytes global ptr index - // 1 byte coinbase index used - // 6625a3d53cc0e500 - // 0123456789ABCDEF - g_job_index = (hex2bin_uchar(&job_id_s[0xA])<<8) | hex2bin_uchar(&job_id_s[0xC]); - g_job_index ^= STRATUM_JOB_INDEX_XOR; - if (g_job_index >= MAX_STRATUM_JOBS) { - send_unknown_work_error(c,id); - stratum_note_share(m, false, m->last_sent_diff); // guestimate here - return 0; - } - - job = global_cur_stratum_jobs[g_job_index]; - - if (!job) { - send_unknown_work_error(c,id); - stratum_note_share(m, false, m->last_sent_diff); // guestimate here - return 0; - } - - if (upk_u64le(job->job_id, 0) != upk_u64le(job_id_s, 0)) { - //LOG_PRINTF("DEBUG: Job ID for index %u doesn't match expected in RAM. (%s vs %s)", g_job_index, job->job_id, job_id_s); - send_unknown_work_error(c,id); - stratum_note_share(m, false, m->last_sent_diff); // guestimate here + uint64_t job_diff; + const uint8_t *work_target; + if (!stratum_get_job(m, json_array_get(params_obj, 1), &job, &g_job_index, &quickdiff, &empty_work, &job_diff, &work_target, &coinbase_index)) { + send_unknown_work_error(c, id); + stratum_note_share(m, false, job_diff); return 0; } - const uint64_t job_diff = quickdiff ? m->quickdiff_value : m->stratum_job_diffs[g_job_index]; // construct block header bver = job->version_uint; @@ -1085,36 +1098,17 @@ int client_mining_submit(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_obj // need to get the extranonce together pk_u32le(extranonce_bin, 0, m->sid_inv); extranonce2 = json_array_get(params_obj, 2); - if (!extranonce2) { + if (json_string_length(extranonce2) != 16) { send_unknown_work_error(c, id); stratum_note_share(m, false, job_diff); return 0; } extranonce2_s = json_string_value(extranonce2); - if (!extranonce2_s) { - send_unknown_work_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } - if (strlen(extranonce2_s) != 16) { - send_unknown_work_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } for(i=0;i<8;i++) { extranonce_bin[i+4] = hex2bin_uchar(&extranonce2_s[i<<1]); } // need to build the full coinbase txn - coinbase_index = hex2bin_uchar(&job_id_s[0xE]); - if (coinbase_index >= MAX_COINBASE_TYPES) { - if (!(empty_work && coinbase_index == DATUM_COINBASE_ID_EMPTY)) { - send_unknown_work_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } - } - if (empty_work) { cb = &job->subsidy_only_coinbase; } else { @@ -1143,31 +1137,17 @@ int client_mining_submit(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_obj // we must encode the current diff directly into the PoW. This allows remote DATUM servers to accept // our variable difficulty work (subject to the DATUM server provided global minimum) - if (quickdiff) { - full_cb_txn[job->target_pot_index] = floorPoT(m->quickdiff_value); - } else { - full_cb_txn[job->target_pot_index] = floorPoT(m->stratum_job_diffs[g_job_index]); - } + full_cb_txn[job->target_pot_index] = floorPoT(job_diff); // time offset ntime = json_array_get(params_obj, 3); - if (!ntime) { - send_unknown_work_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } - ntime_s = json_string_value(ntime); - if (!ntime_s) { - send_unknown_work_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } - ntime_len = strlen(ntime_s); + ntime_len = json_string_length(ntime); if (ntime_len != 8 && ntime_len != 16) { send_unknown_work_error(c, id); stratum_note_share(m, false, job_diff); return 0; } + ntime_s = json_string_value(ntime); if (ntime_len == 8) { ntime_val = (uint32_t)strtoul(ntime_s, NULL, 16); pk_u32le(ntime8, 0, ntime_val); @@ -1179,23 +1159,13 @@ int client_mining_submit(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_obj // nonce nonce = json_array_get(params_obj, 4); - if (!nonce) { - send_unknown_work_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } - nonce_s = json_string_value(nonce); - if (!nonce_s) { - send_unknown_work_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } - nonce_len = strlen(nonce_s); + nonce_len = json_string_length(nonce); if (nonce_len != 8 && nonce_len != 16) { send_unknown_work_error(c, id); stratum_note_share(m, false, job_diff); return 0; } + nonce_s = json_string_value(nonce); if (nonce_len == 8) { nonce_val = (uint32_t)strtoul(nonce_s, NULL, 16); pk_u32le(nonce8, 0, nonce_val); @@ -1304,22 +1274,11 @@ int client_mining_submit(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_obj } // check if share beats miner's work target - if (!quickdiff) { - // check against job+connection target - if (compare_hashes(share_hash, m->stratum_job_targets[g_job_index]) > 0) { - // bad target diff - send_rejected_high_hash_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } - } else { - // check against quickdiff target instead - if (compare_hashes(share_hash, m->quickdiff_target) > 0) { - // bad target diff - send_rejected_high_hash_error(c, id); - stratum_note_share(m, false, job_diff); - return 0; - } + if (compare_hashes(share_hash, work_target) > 0) { + // bad target diff + send_rejected_high_hash_error(c, id); + stratum_note_share(m, false, job_diff); + return 0; } // check if stale @@ -1620,68 +1579,7 @@ int send_mining_set_difficulty(T_DATUM_CLIENT_DATA *c) { } void datum_stratum_fingerprint_by_UA(T_DATUM_MINER_DATA *m) { - // TODO: Make this a little more efficient. perhaps move to a loadable definitions file of some kind. - - if (strstr(m->useragent, "Antminer A3") == m->useragent) { - m->coinbase_selection = 0; - return; - } - - // S21 tested to handle 2.25KB coinbase work on all versions released - // UA starts with: Antminer S21/ - // S21 Pro NOT confirmed to work this way (yet)... so keep the / - if (strstr(m->useragent, "Antminer S21/") == m->useragent) { - m->coinbase_selection = 5; // ANTMAIN2 - return; - } - - // the ePIC control boards can handle almost any size coinbase - // UA starts with: PowerPlay-BM/ - if (strstr(m->useragent, "PowerPlay-BM/") == m->useragent) { - m->coinbase_selection = 4; // YUGE - return; - } - - // "vinsh" reports as xminer - // Tested to handle up to 16KB - if (strstr(m->useragent, "xminer-1.") == m->useragent) { - m->coinbase_selection = 4; // YUGE - return; - } - - // whatsminer works fine with about a 6.5 KB coinbase - // UA starts with: whatsminer/v1 - if (strstr(m->useragent, "whatsminer/v1") == m->useragent) { - m->coinbase_selection = 3; // RESPECTABLE - return; - } - - // Braiins firmware - // Appears to handle arbitrary coinbase sizes, however not extensively tested on all firmware versions - // feed the S21-like coinbase for now, which is at least moderately sized - // UA contains: bosminer-plus-tuner - if (strstr(m->useragent, "bosminer-plus-tuner") != NULL) { // match anywhere in string, not just beginning - m->coinbase_selection = 5; // ANTMAIN2 - return; - } - - // Nicehash, sadly needs a smaller coinbase than even antminer s19s - // they also need a high minimum difficulty - if (strstr(m->useragent, "NiceHash/") == m->useragent) { - m->current_diff=524288; - m->forced_high_min_diff=524288; - m->coinbase_selection = 1; // TINY - return; - } - - // The Bitaxe is tested to work with a large coinbase - // However, it does slow work changes slightly when they're YUGE, so we'll go with - // the whatsminer tested size as a compromise. also should save some bandwidth, which - // is probably not a bad plan, given the low odds of a bitaxe finding a block. - if (strstr(m->useragent, "bitaxe") == m->useragent) { - m->coinbase_selection = 3; // RESPECTABLE - return; - } + // TODO: Stub for now } int client_mining_subscribe(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_obj) { @@ -1704,9 +1602,9 @@ int client_mining_subscribe(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_ // set default diff m->current_diff = datum_config.stratum_v1_vardiff_min; - // default to the antminer workaround, which appears to be universally compatible - // except for NiceHash. - m->coinbase_selection = 2; + // Sv1 is blind to the generation transaction now, so go as large as we want + // TODO: We may want to shrink based on block free space in the future + m->coinbase_selection = COINBASE_TYPE_YUGE; m->useragent[0] = 0; if (params_obj) { @@ -1746,15 +1644,13 @@ int client_mining_subscribe(T_DATUM_CLIENT_DATA *c, uint64_t id, json_t *params_ // mark them as subscribed so that notifies actually work m->subscribed = true; + // begin vardiff sampling before the first notify can evaluate it + reset_vardiff_stats(c); + m->subscribe_tsms = m->sdata->loop_tsms; + // clean work on connect, not quickdiff, doesn't matter if new block or not (don't need empty work speedup on connect) send_mining_notify(c,true,false,false); - // reset vardiff tallies - m->share_count_since_snap = 0; - m->share_diff_since_snap = 0; - m->share_snap_tsms = m->sdata->loop_tsms; - m->subscribe_tsms = m->sdata->loop_tsms; - return 0; } @@ -2068,7 +1964,7 @@ void datum_stratum_job_refresh_blake2b(T_DATUM_STRATUM_JOB *s) { // commitment, notify and DATUM submission all read it from there. // time_on_wire already holds curtime: the helper only writes on // success. - DLOG_ERROR("Could not derive the BLAKE2b wire time from curtime %llu; mining this template without the time offset", + DLOG_ERROR("Could not derive the wire time from curtime %llu; mining this template without the time offset", (unsigned long long)block_template->curtime); s->blake2b_flags &= ~DATUM_BLAKE2B_USE_TIME_OFFSET; }