mirror of
https://github.com/LBRYFoundation/pool.git
synced 2025-08-23 09:27:25 +00:00
commit c59abe5d203fabdabcca81ff5f9c6ff133cfae3b Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Tue Nov 28 11:13:52 2017 +0100 segwit: show a segwit icon on blocks history + remove some inline styles... commit b4a8639370e6837ebc5a2047e7c334e9f931abfc Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Tue Nov 28 09:55:40 2017 +0100 segwit: cleanup + masternode case tested ok with BSD (block 400996), and with real BTX segwit txs (block 90958) also ok on VTC and GRS commit 926dbd11757ebff7f7d4930266de9b9061c8ab16 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Sat Nov 25 18:41:01 2017 +0100 sql: add segwit fields, and ui config and fill block segwit field if it contains segwit txs, an icon is added in the dashboard "last blocks" for these blocks commit 0b13bf55e9dd1d2229d188f0f8382b27642b20da Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Sat Nov 25 13:47:20 2017 +0100 segwit: include commitment in coinbase + .conf toggle tested ok on BTX, GRS and VTC with normal txs, but the commitment merkle hash maybe need some more love... so, to prevent useless bigger blocks, only generate segwit commitment if a segwit tx is present in mempool to check with real segwit txs... not seen any yet.. commit b508bc87943d9e426cda994c2f53c16c11e8d4c3 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Thu Mar 2 11:18:34 2017 +0100 segwit: prepare the witness data, but disabled need more test, may affect the coinbase merkle and the miners... commit 19bd3a83b9ddddd8b5ed4b7a1bdf8cf8c233e346 Author: Tanguy Pruvot <tanguy.pruvot@gmail.com> Date: Thu Mar 2 10:30:29 2017 +0100 stratum: handle and auto toggle segwit if supported
532 lines
17 KiB
C++
532 lines
17 KiB
C++
|
|
#include "stratum.h"
|
|
|
|
uint64_t lyra2z_height = 0;
|
|
|
|
//#define MERKLE_DEBUGLOG
|
|
//#define HASH_DEBUGLOG_
|
|
//#define DONTSUBMIT
|
|
|
|
void build_submit_values(YAAMP_JOB_VALUES *submitvalues, YAAMP_JOB_TEMPLATE *templ,
|
|
const char *nonce1, const char *nonce2, const char *ntime, const char *nonce)
|
|
{
|
|
sprintf(submitvalues->coinbase, "%s%s%s%s", templ->coinb1, nonce1, nonce2, templ->coinb2);
|
|
int coinbase_len = strlen(submitvalues->coinbase);
|
|
|
|
unsigned char coinbase_bin[1024];
|
|
memset(coinbase_bin, 0, 1024);
|
|
binlify(coinbase_bin, submitvalues->coinbase);
|
|
|
|
char doublehash[128];
|
|
memset(doublehash, 0, 128);
|
|
|
|
// some (old) wallet/algos need a simple SHA256 (blakecoin, whirlcoin, groestlcoin...)
|
|
YAAMP_HASH_FUNCTION merkle_hash = sha256_double_hash_hex;
|
|
if (g_current_algo->merkle_func)
|
|
merkle_hash = g_current_algo->merkle_func;
|
|
merkle_hash((char *)coinbase_bin, doublehash, coinbase_len/2);
|
|
|
|
string merkleroot = merkle_with_first(templ->txsteps, doublehash);
|
|
ser_string_be(merkleroot.c_str(), submitvalues->merkleroot_be, 8);
|
|
|
|
#ifdef MERKLE_DEBUGLOG
|
|
printf("merkle root %s\n", merkleroot.c_str());
|
|
#endif
|
|
if (!strcmp(g_current_algo->name, "lbry")) {
|
|
sprintf(submitvalues->header, "%s%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be,
|
|
templ->claim_be, ntime, templ->nbits, nonce);
|
|
ser_string_be(submitvalues->header, submitvalues->header_be, 32 + 20);
|
|
} else {
|
|
sprintf(submitvalues->header, "%s%s%s%s%s%s", templ->version, templ->prevhash_be, submitvalues->merkleroot_be,
|
|
ntime, templ->nbits, nonce);
|
|
ser_string_be(submitvalues->header, submitvalues->header_be, 20);
|
|
}
|
|
|
|
binlify(submitvalues->header_bin, submitvalues->header_be);
|
|
|
|
// printf("%s\n", submitvalues->header_be);
|
|
int header_len = strlen(submitvalues->header)/2;
|
|
g_current_algo->hash_function((char *)submitvalues->header_bin, (char *)submitvalues->hash_bin, header_len);
|
|
|
|
hexlify(submitvalues->hash_hex, submitvalues->hash_bin, 32);
|
|
string_be(submitvalues->hash_hex, submitvalues->hash_be);
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
static void create_decred_header(YAAMP_JOB_TEMPLATE *templ, YAAMP_JOB_VALUES *out,
|
|
const char *ntime, const char *nonce, const char *nonce2, const char *vote, bool usegetwork)
|
|
{
|
|
struct __attribute__((__packed__)) {
|
|
uint32_t version;
|
|
char prevblock[32];
|
|
char merkleroot[32];
|
|
char stakeroot[32];
|
|
uint16_t votebits;
|
|
char finalstate[6];
|
|
uint16_t voters;
|
|
uint8_t freshstake;
|
|
uint8_t revoc;
|
|
uint32_t poolsize;
|
|
uint32_t nbits;
|
|
uint64_t sbits;
|
|
uint32_t height;
|
|
uint32_t size;
|
|
uint32_t ntime;
|
|
uint32_t nonce;
|
|
unsigned char extra[32];
|
|
uint32_t stakever;
|
|
uint32_t hashtag[3];
|
|
} header;
|
|
|
|
memcpy(&header, templ->header, sizeof(header));
|
|
|
|
memset(header.extra, 0, 32);
|
|
sscanf(nonce, "%08x", &header.nonce);
|
|
|
|
if (strcmp(vote, "")) {
|
|
uint16_t votebits = 0;
|
|
sscanf(vote, "%04hx", &votebits);
|
|
header.votebits = (header.votebits & 1) | (votebits & 0xfffe);
|
|
}
|
|
|
|
binlify(header.extra, nonce2);
|
|
|
|
hexlify(out->header, (const unsigned char*) &header, 180);
|
|
memcpy(out->header_bin, &header, sizeof(header));
|
|
}
|
|
|
|
static void build_submit_values_decred(YAAMP_JOB_VALUES *submitvalues, YAAMP_JOB_TEMPLATE *templ,
|
|
const char *nonce1, const char *nonce2, const char *ntime, const char *nonce, const char *vote, bool usegetwork)
|
|
{
|
|
if (!usegetwork) {
|
|
// not used yet
|
|
char doublehash[128] = { 0 };
|
|
|
|
sprintf(submitvalues->coinbase, "%s%s%s%s", templ->coinb1, nonce1, nonce2, templ->coinb2);
|
|
int coinbase_len = strlen(submitvalues->coinbase);
|
|
|
|
unsigned char coinbase_bin[1024];
|
|
memset(coinbase_bin, 0, 1024);
|
|
binlify(coinbase_bin, submitvalues->coinbase);
|
|
|
|
YAAMP_HASH_FUNCTION merkle_hash = sha256_double_hash_hex;
|
|
if (g_current_algo->merkle_func)
|
|
merkle_hash = g_current_algo->merkle_func;
|
|
merkle_hash((char *)coinbase_bin, doublehash, coinbase_len/2);
|
|
|
|
string merkleroot = merkle_with_first(templ->txsteps, doublehash);
|
|
ser_string_be(merkleroot.c_str(), submitvalues->merkleroot_be, 8);
|
|
|
|
#ifdef MERKLE_DEBUGLOG
|
|
printf("merkle root %s\n", merkleroot.c_str());
|
|
#endif
|
|
}
|
|
create_decred_header(templ, submitvalues, ntime, nonce, nonce2, vote, usegetwork);
|
|
|
|
int header_len = strlen(submitvalues->header)/2;
|
|
g_current_algo->hash_function((char *)submitvalues->header_bin, (char *)submitvalues->hash_bin, header_len);
|
|
|
|
hexlify(submitvalues->hash_hex, submitvalues->hash_bin, 32);
|
|
string_be(submitvalues->hash_hex, submitvalues->hash_be);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void client_do_submit(YAAMP_CLIENT *client, YAAMP_JOB *job, YAAMP_JOB_VALUES *submitvalues,
|
|
char *extranonce2, char *ntime, char *nonce, char *vote)
|
|
{
|
|
YAAMP_COIND *coind = job->coind;
|
|
YAAMP_JOB_TEMPLATE *templ = job->templ;
|
|
|
|
if(job->block_found) return;
|
|
if(job->deleted) return;
|
|
|
|
uint64_t hash_int = get_hash_difficulty(submitvalues->hash_bin);
|
|
uint64_t coin_target = decode_compact(templ->nbits);
|
|
if (templ->nbits && !coin_target) coin_target = 0xFFFF000000000000ULL;
|
|
|
|
int block_size = YAAMP_SMALLBUFSIZE;
|
|
vector<string>::const_iterator i;
|
|
|
|
for(i = templ->txdata.begin(); i != templ->txdata.end(); ++i)
|
|
block_size += strlen((*i).c_str());
|
|
|
|
char *block_hex = (char *)malloc(block_size);
|
|
if(!block_hex) return;
|
|
|
|
// do aux first
|
|
for(int i=0; i<templ->auxs_size; i++)
|
|
{
|
|
if(!templ->auxs[i]) continue;
|
|
YAAMP_COIND *coind_aux = templ->auxs[i]->coind;
|
|
|
|
if(!coind_aux || !strcmp(coind->symbol, coind_aux->symbol2))
|
|
continue;
|
|
|
|
unsigned char target_aux[1024];
|
|
binlify(target_aux, coind_aux->aux.target);
|
|
|
|
uint64_t coin_target_aux = get_hash_difficulty(target_aux);
|
|
if(hash_int <= coin_target_aux)
|
|
{
|
|
memset(block_hex, 0, block_size);
|
|
|
|
strcat(block_hex, submitvalues->coinbase); // parent coinbase
|
|
strcat(block_hex, submitvalues->hash_be); // parent hash
|
|
|
|
////////////////////////////////////////////////// parent merkle steps
|
|
|
|
sprintf(block_hex+strlen(block_hex), "%02x", (unsigned char)templ->txsteps.size());
|
|
|
|
vector<string>::const_iterator i;
|
|
for(i = templ->txsteps.begin(); i != templ->txsteps.end(); ++i)
|
|
sprintf(block_hex + strlen(block_hex), "%s", (*i).c_str());
|
|
|
|
strcat(block_hex, "00000000");
|
|
|
|
////////////////////////////////////////////////// auxs merkle steps
|
|
|
|
vector<string> lresult = coind_aux_merkle_branch(templ->auxs, templ->auxs_size, coind_aux->aux.index);
|
|
sprintf(block_hex+strlen(block_hex), "%02x", (unsigned char)lresult.size());
|
|
|
|
for(i = lresult.begin(); i != lresult.end(); ++i)
|
|
sprintf(block_hex+strlen(block_hex), "%s", (*i).c_str());
|
|
|
|
sprintf(block_hex+strlen(block_hex), "%02x000000", (unsigned char)coind_aux->aux.index);
|
|
|
|
////////////////////////////////////////////////// parent header
|
|
|
|
strcat(block_hex, submitvalues->header_be);
|
|
|
|
bool b = coind_submitgetauxblock(coind_aux, coind_aux->aux.hash, block_hex);
|
|
if(b)
|
|
{
|
|
debuglog("*** ACCEPTED %s %d (+1)\n", coind_aux->name, coind_aux->height);
|
|
|
|
block_add(client->userid, client->workerid, coind_aux->id, coind_aux->height, target_to_diff(coin_target_aux),
|
|
target_to_diff(hash_int), coind_aux->aux.hash, "", 0);
|
|
}
|
|
|
|
else
|
|
debuglog("%s %d REJECTED\n", coind_aux->name, coind_aux->height);
|
|
}
|
|
}
|
|
|
|
if(hash_int <= coin_target)
|
|
{
|
|
memset(block_hex, 0, block_size);
|
|
sprintf(block_hex, "%s%02x%s", submitvalues->header_be, (unsigned char)templ->txcount, submitvalues->coinbase);
|
|
|
|
if (g_current_algo->name && !strcmp("jha", g_current_algo->name)) {
|
|
// block header of 88 bytes
|
|
sprintf(block_hex, "%s8400000008000000%02x%s", submitvalues->header_be, (unsigned char)templ->txcount, submitvalues->coinbase);
|
|
}
|
|
|
|
vector<string>::const_iterator i;
|
|
for(i = templ->txdata.begin(); i != templ->txdata.end(); ++i)
|
|
sprintf(block_hex+strlen(block_hex), "%s", (*i).c_str());
|
|
|
|
// POS coins need a zero byte appended to block, the daemon replaces it with the signature
|
|
if(coind->pos)
|
|
strcat(block_hex, "00");
|
|
|
|
if(!strcmp("DCR", coind->rpcencoding)) {
|
|
// submit the regenerated block header
|
|
char hex[384];
|
|
hexlify(hex, submitvalues->header_bin, 180);
|
|
if (coind->usegetwork)
|
|
snprintf(block_hex, block_size, "%s8000000100000000000005a0", hex);
|
|
else
|
|
snprintf(block_hex, block_size, "%s", hex);
|
|
}
|
|
|
|
bool b = coind_submit(coind, block_hex);
|
|
if(b)
|
|
{
|
|
debuglog("*** ACCEPTED %s %d (diff %g) by %s (id: %d)\n", coind->name, templ->height,
|
|
target_to_diff(hash_int), client->sock->ip, client->userid);
|
|
|
|
job->block_found = true;
|
|
|
|
char doublehash2[128];
|
|
memset(doublehash2, 0, 128);
|
|
|
|
YAAMP_HASH_FUNCTION merkle_hash = sha256_double_hash_hex;
|
|
//if (g_current_algo->merkle_func)
|
|
// merkle_hash = g_current_algo->merkle_func;
|
|
|
|
merkle_hash((char *)submitvalues->header_bin, doublehash2, strlen(submitvalues->header_be)/2);
|
|
|
|
char hash1[1024];
|
|
memset(hash1, 0, 1024);
|
|
|
|
string_be(doublehash2, hash1);
|
|
|
|
if(coind->usegetwork && !strcmp("DCR", coind->rpcencoding)) {
|
|
// no merkle stuff
|
|
strcpy(hash1, submitvalues->hash_hex);
|
|
}
|
|
|
|
block_add(client->userid, client->workerid, coind->id, templ->height,
|
|
target_to_diff(coin_target), target_to_diff(hash_int),
|
|
hash1, submitvalues->hash_be, templ->has_segwit_txs);
|
|
|
|
if(coind->noblocknotify) {
|
|
// DCR go wallet doesnt handle blocknotify= config (yet)
|
|
// required to store the user id and the user diff
|
|
sleep(1);
|
|
block_confirm(coind->id, submitvalues->hash_be);
|
|
}
|
|
|
|
#ifdef HASH_DEBUGLOG_
|
|
debuglog("--------------------------------------------------------------\n");
|
|
debuglog("hash1 %s\n", hash1);
|
|
debuglog("hash2 %s\n", submitvalues->hash_be);
|
|
#endif
|
|
}
|
|
|
|
else {
|
|
debuglog("*** REJECTED :( %s block %d %d txs\n", coind->name, templ->height, templ->txcount);
|
|
rejectlog("REJECTED %s block %d\n", coind->symbol, templ->height);
|
|
#ifdef HASH_DEBUGLOG_
|
|
//debuglog("block %s\n", block_hex);
|
|
debuglog("--------------------------------------------------------------\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
free(block_hex);
|
|
}
|
|
|
|
bool dump_submit_debug(const char *title, YAAMP_CLIENT *client, YAAMP_JOB *job, char *extranonce2, char *ntime, char *nonce)
|
|
{
|
|
debuglog("ERROR %s, %s subs %d, job %x, %s, id %x, %d, %s, %s %s\n",
|
|
title, client->sock->ip, client->extranonce_subscribe, job? job->id: 0, client->extranonce1,
|
|
client->extranonce1_id, client->extranonce2size, extranonce2, ntime, nonce);
|
|
}
|
|
|
|
void client_submit_error(YAAMP_CLIENT *client, YAAMP_JOB *job, int id, const char *message, char *extranonce2, char *ntime, char *nonce)
|
|
{
|
|
// if(job->templ->created+2 > time(NULL))
|
|
if(job && job->deleted)
|
|
client_send_result(client, "true");
|
|
|
|
else
|
|
{
|
|
client_send_error(client, id, message);
|
|
share_add(client, job, false, extranonce2, ntime, nonce, 0, id);
|
|
|
|
client->submit_bad++;
|
|
#ifdef HASH_DEBUGLOG_
|
|
dump_submit_debug(message, client, job, extranonce2, ntime, nonce);
|
|
#endif
|
|
}
|
|
|
|
object_unlock(job);
|
|
}
|
|
|
|
static bool ntime_valid_range(const char ntimehex[])
|
|
{
|
|
time_t rawtime = 0;
|
|
uint32_t ntime = 0;
|
|
if (strlen(ntimehex) != 8) return false;
|
|
sscanf(ntimehex, "%8x", &ntime);
|
|
if (ntime < 0x57000000 || ntime > 0x60000000) // 14 Jan 2021
|
|
ntime = bswap32(ntime); // just in case...
|
|
time(&rawtime);
|
|
return ((rawtime - ntime) < (23 * 60 * 60));
|
|
}
|
|
|
|
bool client_submit(YAAMP_CLIENT *client, json_value *json_params)
|
|
{
|
|
// submit(worker_name, jobid, extranonce2, ntime, nonce):
|
|
if(json_params->u.array.length<5)
|
|
{
|
|
debuglog("%s - %s bad message\n", client->username, client->sock->ip);
|
|
client->submit_bad++;
|
|
return false;
|
|
}
|
|
|
|
char extranonce2[32];
|
|
char ntime[32];
|
|
char nonce[32];
|
|
char vote[8];
|
|
|
|
memset(extranonce2, 0, 32);
|
|
memset(ntime, 0, 32);
|
|
memset(nonce, 0, 32);
|
|
memset(vote, 0, 8);
|
|
|
|
if (!json_params->u.array.values[1]->u.string.ptr || strlen(json_params->u.array.values[1]->u.string.ptr) > 32) {
|
|
clientlog(client, "bad json, wrong jobid len");
|
|
client->submit_bad++;
|
|
return false;
|
|
}
|
|
int jobid = htoi(json_params->u.array.values[1]->u.string.ptr);
|
|
|
|
strncpy(extranonce2, json_params->u.array.values[2]->u.string.ptr, 31);
|
|
strncpy(ntime, json_params->u.array.values[3]->u.string.ptr, 31);
|
|
strncpy(nonce, json_params->u.array.values[4]->u.string.ptr, 31);
|
|
if (json_params->u.array.length == 6)
|
|
strncpy(vote, json_params->u.array.values[5]->u.string.ptr, 7);
|
|
|
|
#ifdef HASH_DEBUGLOG_
|
|
debuglog("submit %s (uid %d) %d, %s, %s, %s\n", client->sock->ip, client->userid, jobid, extranonce2, ntime, nonce);
|
|
#endif
|
|
|
|
string_lower(extranonce2);
|
|
string_lower(ntime);
|
|
string_lower(nonce);
|
|
string_lower(vote);
|
|
|
|
YAAMP_JOB *job = (YAAMP_JOB *)object_find(&g_list_job, jobid, true);
|
|
if(!job)
|
|
{
|
|
client_submit_error(client, NULL, 21, "Invalid job id", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
|
|
if(job->deleted)
|
|
{
|
|
client_send_result(client, "true");
|
|
object_unlock(job);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool is_decred = job->coind && !strcmp("DCR", job->coind->rpcencoding);
|
|
|
|
YAAMP_JOB_TEMPLATE *templ = job->templ;
|
|
|
|
if(strlen(nonce) != YAAMP_NONCE_SIZE*2)
|
|
{
|
|
client_submit_error(client, job, 20, "Invalid nonce size", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
|
|
if(strcmp(ntime, templ->ntime))
|
|
{
|
|
if (!ntime_valid_range(ntime)) {
|
|
client_submit_error(client, job, 23, "Invalid time rolling", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
// dont allow algos permutations change over time (can lead to different speeds)
|
|
if (!g_allow_rolltime) {
|
|
client_submit_error(client, job, 23, "Invalid ntime (rolling not allowed)", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
YAAMP_SHARE *share = share_find(job->id, extranonce2, ntime, nonce, client->extranonce1);
|
|
if(share)
|
|
{
|
|
client_submit_error(client, job, 22, "Duplicate share", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
|
|
if(strlen(extranonce2) != client->extranonce2size*2)
|
|
{
|
|
client_submit_error(client, job, 24, "Invalid extranonce2 size", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
|
|
// check if the submitted extranonce is valid
|
|
if(is_decred && client->extranonce2size > 4) {
|
|
char extra1_id[16], extra2_id[16];
|
|
int cmpoft = client->extranonce2size*2 - 8;
|
|
strcpy(extra1_id, &client->extranonce1[cmpoft]);
|
|
strcpy(extra2_id, &extranonce2[cmpoft]);
|
|
int extradiff = (int) strcmp(extra2_id, extra1_id);
|
|
int extranull = (int) !strcmp(extra2_id, "00000000");
|
|
if (extranull && client->extranonce2size > 8)
|
|
extranull = (int) !strcmp(&extranonce2[8], "00000000" "00000000");
|
|
if (extranull) {
|
|
debuglog("extranonce %s is empty!, should be %s - %s\n", extranonce2, extra1_id, client->sock->ip);
|
|
client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce);
|
|
client->submit_bad++;
|
|
return true;
|
|
}
|
|
if (extradiff) {
|
|
// some ccminer pre-release doesn't fill correctly the extranonce
|
|
client_submit_error(client, job, 27, "Invalid extranonce2 suffix", extranonce2, ntime, nonce);
|
|
client->submit_bad++;
|
|
socket_send(client->sock, "{\"id\":null,\"method\":\"mining.set_extranonce\",\"params\":[\"%s\",%d]}\n",
|
|
client->extranonce1, client->extranonce2size);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
YAAMP_JOB_VALUES submitvalues;
|
|
memset(&submitvalues, 0, sizeof(submitvalues));
|
|
|
|
if(is_decred)
|
|
build_submit_values_decred(&submitvalues, templ, client->extranonce1, extranonce2, ntime, nonce, vote, true);
|
|
else
|
|
build_submit_values(&submitvalues, templ, client->extranonce1, extranonce2, ntime, nonce);
|
|
|
|
if (templ->height && !strcmp(g_current_algo->name,"lyra2z")) {
|
|
lyra2z_height = templ->height;
|
|
}
|
|
|
|
// minimum hash diff begins with 0000, for all...
|
|
uint8_t pfx = submitvalues.hash_bin[30] | submitvalues.hash_bin[31];
|
|
if(pfx) {
|
|
#ifdef HASH_DEBUGLOG_
|
|
debuglog("Possible %s error, hash starts with %02x%02x%02x%02x\n", g_current_algo->name,
|
|
(int) submitvalues.hash_bin[31], (int) submitvalues.hash_bin[30],
|
|
(int) submitvalues.hash_bin[29], (int) submitvalues.hash_bin[28]);
|
|
#endif
|
|
client_submit_error(client, job, 25, "Invalid share", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
|
|
uint64_t hash_int = get_hash_difficulty(submitvalues.hash_bin);
|
|
uint64_t user_target = diff_to_target(client->difficulty_actual);
|
|
uint64_t coin_target = decode_compact(templ->nbits);
|
|
if (templ->nbits && !coin_target) coin_target = 0xFFFF000000000000ULL;
|
|
|
|
#ifdef HASH_DEBUGLOG_
|
|
debuglog("%016llx actual\n", hash_int);
|
|
debuglog("%016llx target\n", user_target);
|
|
debuglog("%016llx coin\n", coin_target);
|
|
#endif
|
|
if(hash_int > user_target && hash_int > coin_target)
|
|
{
|
|
client_submit_error(client, job, 26, "Low difficulty share", extranonce2, ntime, nonce);
|
|
return true;
|
|
}
|
|
|
|
if(job->coind)
|
|
client_do_submit(client, job, &submitvalues, extranonce2, ntime, nonce, vote);
|
|
else
|
|
remote_submit(client, job, &submitvalues, extranonce2, ntime, nonce);
|
|
|
|
client_send_result(client, "true");
|
|
client_record_difficulty(client);
|
|
client->submit_bad = 0;
|
|
client->shares++;
|
|
if (client->shares <= 200 && (client->shares % 50) == 0) {
|
|
// 4 records are enough per miner
|
|
if (!client_ask_stats(client)) client->stats = false;
|
|
}
|
|
|
|
double share_diff = diff_to_target(hash_int);
|
|
// if (g_current_algo->diff_multiplier != 0) {
|
|
// share_diff = share_diff / g_current_algo->diff_multiplier;
|
|
// }
|
|
|
|
#ifndef HASH_DEBUGLOG_
|
|
// only log a few...
|
|
if (share_diff > (client->difficulty_actual * 16))
|
|
debuglog("submit %s (uid %d) %d, %s, %s, %s, %.3f/%.3f\n", client->sock->ip, client->userid,
|
|
jobid, extranonce2, ntime, nonce, share_diff, client->difficulty_actual);
|
|
#endif
|
|
|
|
share_add(client, job, true, extranonce2, ntime, nonce, share_diff, 0);
|
|
object_unlock(job);
|
|
|
|
return true;
|
|
}
|