Browse Source

Support virtual mask changing of the version bits by clients according to a hex config parameter version_mask.

master
Con Kolivas 7 years ago
parent
commit
f642c515df
  1. 4
      README
  2. 1
      ckpool.conf
  3. 5
      src/ckpool.c
  4. 3
      src/ckpool.h
  5. 6
      src/libckpool.h
  6. 92
      src/stratifier.c

4
README

@ -286,6 +286,10 @@ from 2 to 8. Default 8
miners and is set to 30 seconds by default to help perpetuate transactions for
the health of the bitcoin network.
"version_mask" : This is a mask of which bits in the version number it is valid
for a client to alter and is expressed as an hex string. Eg "7FFFFFFB"
Default is "00000000".
"serverurl" : This is the IP(s) to try to bind ckpool uniquely to, otherwise it
will attempt to bind to all interfaces in port 3333 by default in pool mode
and 3334 in proxy mode. Multiple entries can be specified as an array by

1
ckpool.conf

@ -20,6 +20,7 @@
"nonce1length" : 4,
"nonce2length" : 8,
"update_interval" : 30,
"version_mask" : "00000000",
"serverurl" : [
"ckpool.org:3333",
"node.ckpool.org:3333",

5
src/ckpool.c

@ -1444,8 +1444,8 @@ static void parse_config(ckpool_t *ckp)
{
json_t *json_conf, *arr_val;
json_error_t err_val;
char *url, *vmask;
int arr_size;
char *url;
json_conf = json_load_file(ckp->config, JSON_DISABLE_EOF_CHECK, &err_val);
if (!json_conf) {
@ -1469,6 +1469,9 @@ static void parse_config(ckpool_t *ckp)
json_get_int(&ckp->nonce1length, json_conf, "nonce1length");
json_get_int(&ckp->nonce2length, json_conf, "nonce2length");
json_get_int(&ckp->update_interval, json_conf, "update_interval");
json_get_string(&vmask, json_conf, "version_mask");
if (vmask && strlen(vmask) && validhex(vmask))
sscanf(vmask, "%x", &ckp->version_mask);
/* Look for an array first and then a single entry */
arr_val = json_object_get(json_conf, "serverurl");
if (!parse_serverurls(ckp, arr_val)) {

3
src/ckpool.h

@ -255,6 +255,8 @@ struct ckpool_instance {
int update_interval; // Seconds between stratum updates
uint32_t version_mask; // Bits which set to true means allow miner to modify those bits
/* Proxy options */
int proxies;
char **proxyurl;
@ -295,6 +297,7 @@ enum stratum_msgtype {
SM_SHAREERR,
SM_WORKERSTATS,
SM_REQTXNS,
SM_VERSIONMASK,
SM_NONE
};

6
src/libckpool.h

@ -267,7 +267,8 @@ enum share_err {
SE_STALE,
SE_NTIME_INVALID,
SE_DUPE,
SE_HIGH_DIFF
SE_HIGH_DIFF,
SE_INVALID_VERSION_MASK
};
static const char __maybe_unused *share_errs[] = {
@ -285,7 +286,8 @@ static const char __maybe_unused *share_errs[] = {
"Stale",
"Ntime out of range",
"Duplicate",
"Above target"
"Above target",
"Invalid version mask"
};
#define SHARE_ERR(x) share_errs[((x) + 9)]

92
src/stratifier.c

@ -1862,7 +1862,8 @@ static void add_node_base(ckpool_t *ckp, json_t *val, bool trusted, int64_t clie
/* Calculate share diff and fill in hash and swap. Need to hold workbase read count */
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)
const uint32_t ntime32, const uint32_t version_mask, const char *nonce,
uchar *hash, uchar *swap, int *cblen)
{
unsigned char merkle_root[32], merkle_sha[64];
uint32_t *data32, *swap32, benonce32;
@ -1894,6 +1895,17 @@ share_diff(char *coinbase, const uchar *enonce1bin, const workbase_t *wb, const
memcpy(data, wb->headerbin, 80);
memcpy(data + 36, merkle_root, 32);
/* Update nVersion when version_mask is in use */
if (version_mask) {
uint32_t version;
data32 = (uint32_t *)data;
version = be32toh(*data32);
version |= version_mask;
LOGDEBUG("Vmask %u version changed to %08x", version_mask, version);
*data32 = htobe32(version);
}
/* Insert the nonce value into the data */
hex2bin(&benonce32, nonce, 4);
data32 = (uint32_t *)(data + 64 + 12);
@ -1972,8 +1984,8 @@ static void send_nodes_block(sdata_t *sdata, const json_t *block_val, const int6
/* Entered with workbase readcount. */
static void send_node_block(ckpool_t *ckp, sdata_t *sdata, const char *enonce1, const char *nonce,
const char *nonce2, const uint32_t ntime32, const int64_t jobid,
const double diff, const int64_t client_id,
const char *nonce2, const uint32_t ntime32, const uint32_t version_mask,
const int64_t jobid, const double diff, const int64_t client_id,
const char *coinbase, const int cblen, const uchar *data)
{
if (sdata->node_instances) {
@ -1983,6 +1995,7 @@ static void send_node_block(ckpool_t *ckp, sdata_t *sdata, const char *enonce1,
json_set_string(val, "nonce", nonce);
json_set_string(val, "nonce2", nonce2);
json_set_uint32(val, "ntime32", ntime32);
json_set_uint32(val, "version_mask", version_mask);
json_set_int64(val, "jobid", jobid);
json_set_double(val, "diff", diff);
add_remote_blockdata(ckp, val, cblen, coinbase, data);
@ -2110,11 +2123,11 @@ static void submit_node_block(ckpool_t *ckp, sdata_t *sdata, json_t *val)
char *coinbase = NULL, *enonce1 = NULL, *nonce = NULL, *nonce2 = NULL, *gbt_block,
*coinbasehex, *swaphex;
uchar *enonce1bin = NULL, hash[32], swap[80], flip32[32];
uint32_t ntime32, version_mask = 0;
char blockhash[68], cdfield[64];
json_t *bval, *bval_copy;
int enonce1len, cblen;
workbase_t *wb = NULL;
uint32_t ntime32;
double diff;
ts_t ts_now;
int64_t id;
@ -2145,6 +2158,11 @@ static void submit_node_block(ckpool_t *ckp, sdata_t *sdata, json_t *val)
goto out;
}
if (!json_get_uint32(&version_mask, val, "version_mask")) {
/* No version mask is not fatal, assume it to be zero */
LOGINFO("No version mask in node method block");
}
LOGWARNING("Possible upstream block solve diff %lf !", diff);
ts_realtime(&ts_now);
@ -2176,20 +2194,21 @@ static void submit_node_block(ckpool_t *ckp, sdata_t *sdata, json_t *val)
hex2bin(enonce1bin, enonce1, enonce1len);
coinbase = alloca(wb->coinb1len + wb->enonce1constlen + wb->enonce1varlen + wb->enonce2varlen + wb->coinb2len);
/* Fill in the hashes */
share_diff(coinbase, enonce1bin, wb, nonce2, ntime32, nonce, hash, swap, &cblen);
share_diff(coinbase, enonce1bin, wb, nonce2, ntime32, version_mask, nonce, hash, swap, &cblen);
}
/* Now we have enough to assemble a block */
gbt_block = process_block(wb, coinbase, cblen, swap, hash, flip32, blockhash);
ret = local_block_submit(ckp, gbt_block, flip32, wb->height);
JSON_CPACK(bval, "{si,ss,ss,sI,ss,ss,ss,sI,sf,ss,ss,ss,ss}",
JSON_CPACK(bval, "{si,ss,ss,sI,ss,ss,si,ss,sI,sf,ss,ss,ss,ss}",
"height", wb->height,
"blockhash", blockhash,
"confirmed", "n",
"workinfoid", wb->id,
"enonce1", enonce1,
"nonce2", nonce2,
"version_mask", version_mask,
"nonce", nonce,
"reward", wb->coinbasevalue,
"diff", diff,
@ -5691,6 +5710,18 @@ static void stratum_send_diff(sdata_t *sdata, const stratum_instance_t *client)
stratum_add_send(sdata, json_msg, client->id, SM_DIFF);
}
/* Needs to be entered with client holding a ref count. */
static void stratum_send_version_mask(sdata_t *sdata, const stratum_instance_t *client)
{
char version_str[12];
json_t *json_msg;
sprintf(version_str, "%08x", client->ckp->version_mask);
JSON_CPACK(json_msg, "{s[s]soss}", "params", version_str, "id", json_null(),
"method", "mining.set_version_mask");
stratum_add_send(sdata, json_msg, client->id, SM_VERSIONMASK);
}
/* Needs to be entered with client holding a ref count. */
static void stratum_send_message(sdata_t *sdata, const stratum_instance_t *client, const char *msg)
{
@ -5864,7 +5895,8 @@ downstream_block(ckpool_t *ckp, sdata_t *sdata, const json_t *val, const int cbl
static void
test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uchar *data,
const uchar *hash, const double diff, const char *coinbase, int cblen,
const char *nonce2, const char *nonce, const uint32_t ntime32, const bool stale)
const char *nonce2, const char *nonce, const uint32_t ntime32, const uint32_t version_mask,
const bool stale)
{
char blockhash[68], cdfield[64], *gbt_block;
sdata_t *sdata = client->sdata;
@ -5887,8 +5919,8 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
sprintf(cdfield, "%lu,%lu", ts_now.tv_sec, ts_now.tv_nsec);
gbt_block = process_block(wb, coinbase, cblen, data, hash, flip32, blockhash);
send_node_block(ckp, sdata, client->enonce1, nonce, nonce2, ntime32, wb->id,
diff, client->id, coinbase, cblen, data);
send_node_block(ckp, sdata, client->enonce1, nonce, nonce2, ntime32, version_mask,
wb->id, diff, client->id, coinbase, cblen, data);
val = json_object();
json_set_int(val, "height", wb->height);
@ -5905,6 +5937,7 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
json_set_string(val, "nonce2", nonce2);
json_set_string(val, "nonce", nonce);
json_set_uint32(val, "ntime32", ntime32);
json_set_uint32(val, "version_mask", version_mask);
json_set_int64(val, "reward", wb->coinbasevalue);
json_set_double(val, "diff", diff);
json_set_string(val, "createdate", cdfield);
@ -5934,7 +5967,8 @@ test_blocksolve(const stratum_instance_t *client, const workbase_t *wb, const uc
/* Needs to be entered with workbase readcount and 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, const bool stale)
const uint32_t ntime32, const uint32_t version_mask,
const char *nonce, uchar *hash, const bool stale)
{
char *coinbase;
uchar swap[80];
@ -5944,10 +5978,10 @@ static double submission_diff(const stratum_instance_t *client, const workbase_t
coinbase = ckalloc(wb->coinb1len + wb->enonce1constlen + wb->enonce1varlen + wb->enonce2varlen + wb->coinb2len);
/* Calculate the diff of the share here */
ret = share_diff(coinbase, client->enonce1bin, wb, nonce2, ntime32, nonce, hash, swap, &cblen);
ret = share_diff(coinbase, client->enonce1bin, wb, nonce2, ntime32, version_mask, nonce, hash, swap, &cblen);
/* Test we haven't solved a block regardless of share status */
test_blocksolve(client, wb, swap, hash, ret, coinbase, cblen, nonce2, nonce, ntime32, stale);
test_blocksolve(client, wb, swap, hash, ret, coinbase, cblen, nonce2, nonce, ntime32, version_mask, stale);
free(coinbase);
@ -6022,17 +6056,17 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg,
const json_t *params_val, json_t **err_val)
{
bool share = false, result = false, invalid = true, submit = false, stale = false;
const char *workername, *job_id, *ntime, *nonce, *version_mask;
double diff = client->diff, wdiff = 0, sdiff = -1;
char hexhash[68] = {}, sharehash[32], cdfield[64];
const char *workername, *job_id, *ntime, *nonce;
user_instance_t *user = client->user_instance;
uint32_t ntime32, version_mask32 = 0;
char *fname = NULL, *s, *nonce2;
sdata_t *sdata = client->sdata;
enum share_err err = SE_NONE;
ckpool_t *ckp = client->ckp;
char idstring[20] = {};
workbase_t *wb = NULL;
uint32_t ntime32;
uchar hash[32];
int nlen, len;
time_t now_t;
@ -6085,6 +6119,18 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg,
*err_val = JSON_ERR(err);
goto out;
}
version_mask = json_string_value(json_array_get(params_val, 5));
if (version_mask && strlen(version_mask) && validhex(version_mask)) {
sscanf(version_mask, "%x", &version_mask32);
// check version mask
if (version_mask32 && ((~ckp->version_mask) & version_mask32) != 0) {
// means client changed some bits which server doesn't allow to change
err = SE_INVALID_VERSION_MASK;
*err_val = JSON_ERR(err);
goto out;
}
}
if (safecmp(workername, client->workername)) {
err = SE_WORKER_MISMATCH;
*err_val = JSON_ERR(err);
@ -6126,7 +6172,7 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg,
}
if (id < sdata->blockchange_id)
stale = true;
sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash, stale);
sdiff = submission_diff(client, wb, nonce2, ntime32, version_mask32, nonce, hash, stale);
if (sdiff > client->best_diff) {
worker_instance_t *worker = client->worker_instance;
@ -7680,13 +7726,17 @@ static void sauth_process(ckpool_t *ckp, json_params_t *jp)
mindiff = client->suggest_diff;
else
mindiff = client->worker_instance->mindiff;
if (!mindiff)
goto out;
mindiff = MAX(ckp->mindiff, mindiff);
if (mindiff != client->diff) {
client->diff = mindiff;
stratum_send_diff(sdata, client);
if (mindiff) {
mindiff = MAX(ckp->mindiff, mindiff);
if (mindiff != client->diff) {
client->diff = mindiff;
stratum_send_diff(sdata, client);
}
}
/* Set block version mask if needed */
if (ckp->version_mask)
stratum_send_version_mask(sdata, client);
out:
dec_instance_ref(sdata, client);
out_noclient:

Loading…
Cancel
Save