Skip to content
Permalink
Browse files

Treat block version 5

  • Loading branch information...
wo01 committed Sep 14, 2018
1 parent 47c888e commit 73bcec72d700c7e48e2a892d57ba7d4bda5ab273
Showing with 79 additions and 25 deletions.
  1. +57 −16 cpu-miner.c
  2. +3 −2 miner.h
  3. +14 −2 util.c
  4. +2 −2 yescrypt.c
  5. +3 −3 yespower.c
@@ -259,7 +259,7 @@ static struct option const options[] = {
};

struct work {
uint32_t data[32];
uint32_t data[40];
uint32_t target[8];

int height;
@@ -269,6 +269,8 @@ struct work {
char *job_id;
size_t xnonce2_len;
unsigned char *xnonce2;

bool sapling;
};

static struct work g_work;
@@ -357,12 +359,14 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
int tx_count, tx_size;
unsigned char txc_vi[9];
unsigned char (*merkle_tree)[32] = NULL;
uint32_t final_sapling_hash[8];
bool coinbase_append = false;
bool submit_coinbase = false;
bool version_force = false;
bool version_reduce = false;
json_t *tmp, *txa;
bool rc = false;
bool sapling = false;

tmp = json_object_get(val, "mutable");
if (tmp && json_is_array(tmp)) {
@@ -395,7 +399,9 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
goto out;
}
version = json_integer_value(tmp);
if (version > 4) {
if (version == 5) {
sapling = true;
} else if (version > 4) {
if (version_reduce) {
version = 4;
} else if (!version_force) {
@@ -421,6 +427,13 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
goto out;
}

if (sapling) {
if (unlikely(!jobj_binary(val, "finalsaplingroothash", final_sapling_hash, sizeof(final_sapling_hash)))) {
applog(LOG_ERR, "JSON invalid finalsaplingroothash");
goto out;
}
}

/* find count and size of transactions */
txa = json_object_get(val, "transactions");
if (!txa || !json_is_array(txa)) {
@@ -576,9 +589,20 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i);
work->data[17] = swab32(curtime);
work->data[18] = le32dec(&bits);
memset(work->data + 19, 0x00, 52);
work->data[20] = 0x80000000;
work->data[31] = 0x00000280;
if (sapling) {
work->sapling = true;
memset(work->data + 28, 0x00, 48);
for (i = 0; i < 8; i++)
work->data[27 - i] = le32dec(final_sapling_hash + i);
work->data[19] = 0;
work->data[28] = 0x80000000;
work->data[39] = 0x00000280;
} else {
work->sapling = false;
memset(work->data + 19, 0x00, 52);
work->data[20] = 0x80000000;
work->data[31] = 0x00000280;
}

if (unlikely(!jobj_binary(val, "target", target, sizeof(target)))) {
applog(LOG_ERR, "JSON invalid target");
@@ -692,23 +716,27 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
}
} else if (work->txs) {
char *req;
int datasize = 80;
if (work->sapling) {
datasize = 112;
}

for (i = 0; i < ARRAY_SIZE(work->data); i++)
be32enc(work->data + i, work->data[i]);
bin2hex(data_str, (unsigned char *)work->data, 80);
bin2hex(data_str, (unsigned char *)work->data, datasize);
if (work->workid) {
char *params;
val = json_object();
json_object_set_new(val, "workid", json_string(work->workid));
params = json_dumps(val, 0);
json_decref(val);
req = malloc(128 + 2*80 + strlen(work->txs) + strlen(params));
req = malloc(128 + 2*datasize + strlen(work->txs) + strlen(params));
sprintf(req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":1}\r\n",
data_str, work->txs, params);
free(params);
} else {
req = malloc(128 + 2*80 + strlen(work->txs));
req = malloc(128 + 2*datasize + strlen(work->txs));
sprintf(req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":1}\r\n",
data_str, work->txs);
@@ -959,9 +987,9 @@ static bool get_work(struct thr_info *thr, struct work *work)
if (opt_benchmark) {
memset(work->data, 0x55, 76);
work->data[17] = swab32(time(NULL));
memset(work->data + 19, 0x00, 52);
work->data[20] = 0x80000000;
work->data[31] = 0x00000280;
memset(work->data + 27, 0x00, 52);
work->data[28] = 0x80000000;
work->data[39] = 0x00000280;
memset(work->target, 0x00, sizeof(work->target));
return true;
}
@@ -1044,16 +1072,26 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
for (i = 0; i < sctx->xnonce2_size && !++sctx->job.xnonce2[i]; i++);

/* Assemble block header */
memset(work->data, 0, 128);
memset(work->data, 0, 160);
work->data[0] = le32dec(sctx->job.version);
work->sapling = work->data[0] == 5 ? true : false;
for (i = 0; i < 8; i++)
work->data[1 + i] = le32dec((uint32_t *)sctx->job.prevhash + i);
if (work->sapling) {
for (i = 0; i < 8; i++)
work->data[27 + i] = le32dec((uint32_t *)sctx->job.finalsaplinghash + i);
}
for (i = 0; i < 8; i++)
work->data[9 + i] = be32dec((uint32_t *)merkle_root + i);
work->data[17] = le32dec(sctx->job.ntime);
work->data[18] = le32dec(sctx->job.nbits);
work->data[20] = 0x80000000;
work->data[31] = 0x00000280;
if (work->sapling) {
work->data[28] = 0x80000000;
work->data[39] = 0x00000280;
} else {
work->data[20] = 0x80000000;
work->data[31] = 0x00000280;
}

pthread_mutex_unlock(&sctx->work_lock);

@@ -1103,6 +1141,7 @@ static void *miner_thread(void *userdata)
unsigned long hashes_done;
struct timeval tv_start, tv_end, diff;
int64_t max64;
int perslen = 80;
int rc;

if (have_stratum) {
@@ -1164,14 +1203,16 @@ static void *miner_thread(void *userdata)
gettimeofday(&tv_start, NULL);

/* scan nonces for a proof-of-work hash */
if (work.sapling)
perslen = 112;
switch (opt_algo) {
case ALGO_YESCRYPT:
rc = scanhash_yescrypt(thr_id, work.data, work.target,
max_nonce, &hashes_done);
max_nonce, &hashes_done, perslen);
break;
case ALGO_YESPOWER:
rc = scanhash_yespower(thr_id, work.data, work.target,
max_nonce, &hashes_done);
max_nonce, &hashes_done, perslen);
break;
default:
/* should never happen */
@@ -155,10 +155,10 @@ extern int scanhash_sha256d(int thr_id, uint32_t *pdata,
const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done);

extern int scanhash_yescrypt(int thr_id, uint32_t *pdata,
const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done);
const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done, int perslen);

extern int scanhash_yespower(int thr_id, uint32_t *pdata,
const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done);
const uint32_t *ptarget, uint32_t max_nonce, unsigned long *hashes_done, int perslen);

extern unsigned char *scrypt_buffer_alloc(int N);
extern int scanhash_scrypt(int thr_id, uint32_t *pdata,
@@ -216,6 +216,7 @@ extern void diff_to_target(uint32_t *target, double diff);
struct stratum_job {
char *job_id;
unsigned char prevhash[32];
unsigned char finalsaplinghash[32];
size_t coinbase_size;
unsigned char *coinbase;
unsigned char *xnonce2;
16 util.c
@@ -1175,12 +1175,13 @@ bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *p

static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
{
const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime;
const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime, *finalsaplinghash;
size_t coinb1_size, coinb2_size;
bool clean, ret = false;
int merkle_count, i;
json_t *merkle_arr;
unsigned char **merkle;
int ver;

job_id = json_string_value(json_array_get(params, 0));
prevhash = json_string_value(json_array_get(params, 1));
@@ -1201,6 +1202,15 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
applog(LOG_ERR, "Stratum notify: invalid parameters");
goto out;
}
hex2bin(sctx->job.version, version, 4);
ver = le32dec(sctx->job.version);
if (ver == 5) {
finalsaplinghash = json_string_value(json_array_get(params, 9));
if (!finalsaplinghash || strlen(finalsaplinghash) != 64) {
applog(LOG_ERR, "Stratum notify: invalid parameters");
goto out;
}
}
merkle = malloc(merkle_count * sizeof(char *));
for (i = 0; i < merkle_count; i++) {
const char *s = json_string_value(json_array_get(merkle_arr, i));
@@ -1232,14 +1242,16 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
free(sctx->job.job_id);
sctx->job.job_id = strdup(job_id);
hex2bin(sctx->job.prevhash, prevhash, 32);
if (ver == 5) {
hex2bin(sctx->job.finalsaplinghash, finalsaplinghash, 32);
}

for (i = 0; i < sctx->job.merkle_count; i++)
free(sctx->job.merkle[i]);
free(sctx->job.merkle);
sctx->job.merkle = merkle;
sctx->job.merkle_count = merkle_count;

hex2bin(sctx->job.version, version, 4);
hex2bin(sctx->job.nbits, nbits, 4);
hex2bin(sctx->job.ntime, ntime, 4);
sctx->job.clean = clean;
@@ -12,7 +12,7 @@
#include "sha256_Y.c"

int scanhash_yescrypt(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, unsigned long *hashes_done)
uint32_t max_nonce, unsigned long *hashes_done, int perslen)
{
uint32_t n = pdata[19] - 1;
const uint32_t first_nonce = pdata[19];
@@ -38,7 +38,7 @@ int scanhash_yescrypt(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
if (opt_debug) {
bin2hex(hash_str, (unsigned char *)hash64, 32);
bin2hex(target_str, (unsigned char *)ptarget, 32);
bin2hex(data_str, (unsigned char *)endiandata, 80);
bin2hex(data_str, (unsigned char *)endiandata, perslen);
applog(LOG_DEBUG, "DEBUG: [%d thread] Found share!\ndata %s\nhash %s\ntarget %s", thr_id,
data_str,
hash_str,
@@ -28,7 +28,7 @@
#include "yespower.h"

int scanhash_yespower(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, unsigned long *hashes_done)
uint32_t max_nonce, unsigned long *hashes_done, int perslen)
{
uint32_t n = pdata[19] - 1;
const uint32_t first_nonce = pdata[19];
@@ -40,7 +40,7 @@ int scanhash_yespower(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
.N = 2048,
.r = 8,
.pers = (const uint8_t *)endiandata,
.perslen = 80
.perslen = perslen
};
//we need bigendian data...
int kk=0;
@@ -52,7 +52,7 @@ int scanhash_yespower(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
do {
pdata[19] = ++n;
be32enc(&endiandata[19], n);
if (yespower_tls((unsigned char *)endiandata, 80, &params, (yespower_binary_t *)hash64)) {
if (yespower_tls((unsigned char *)endiandata, perslen, &params, (yespower_binary_t *)hash64)) {
puts("FAILED");
return -1;
}

2 comments on commit 73bcec7

@solardiz

This comment has been minimized.

Copy link

replied Dec 1, 2018

FWIW, the value 0x00000280 was probably the block header size in bits (80*8). If so, should it really stay the same for Sapling's larger block headers? If things are working fine with Sapling despite this value staying the same, was/is it possibly unused?

@solardiz

This comment has been minimized.

Copy link

replied Dec 1, 2018

Answering my own question: this value was first introduced in ee7b535 "Add Stratum support" and this commit includes use of a function sha256d_80, which apparently assumes pre-applied SHA-256 padding (where this value would indeed be the input size in bits). This is confirmed in pooler's answer in pooler#82. So this value/field is probably unused for PoW schemes other than Bitcoin's double-SHA-256. Ditto about the many zeroes and 0x80000000. It's unclean to be doing this padding for other PoW schemes and with the wrong bit size, but it shouldn't hurt.

Please sign in to comment.
You can’t perform that action at this time.