Skip to content

Instantly share code, notes, and snippets.

@wo01
Last active November 13, 2018 08:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wo01/fefedf586610680ad44fa32078149536 to your computer and use it in GitHub Desktop.
Save wo01/fefedf586610680ad44fa32078149536 to your computer and use it in GitHub Desktop.
Diff cpuminer for Koto Sapling
diff --git a/configure.ac b/configure.ac
index eb48278..32c2f1e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([cpuminer], [2.5])
+AC_INIT([cpuminer], [3.0])
AC_PREREQ([2.59c])
AC_CANONICAL_SYSTEM
diff --git a/cpu-miner.c b/cpu-miner.c
index b84fd0d..a1c4a87 100644
--- a/cpu-miner.c
+++ b/cpu-miner.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,7 +1072,8 @@ 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->sapling = be32dec(sctx->job.version) == 5 ? true : false;
work->data[0] = le32dec(sctx->job.version);
for (i = 0; i < 8; i++)
work->data[1 + i] = le32dec((uint32_t *)sctx->job.prevhash + i);
@@ -1052,8 +1081,15 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
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) {
+ for (i = 0; i < 8; i++)
+ work->data[20 + i] = le32dec((uint32_t *)sctx->job.finalsaplinghash + i);
+ 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 +1139,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 +1201,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 */
diff --git a/miner.h b/miner.h
index 440bc9a..3d867bc 100644
--- a/miner.h
+++ b/miner.h
@@ -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;
diff --git a/util.c b/util.c
index 32a79e6..24e31c4 100644
--- a/util.c
+++ b/util.c
@@ -1175,12 +1175,13 @@ out:
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 = be32dec(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,6 +1242,9 @@ 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]);
@@ -1239,7 +1252,6 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
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;
diff --git a/winbuild-cross.sh b/winbuild-cross.sh
index fac9c76..33257eb 100755
--- a/winbuild-cross.sh
+++ b/winbuild-cross.sh
@@ -19,6 +19,7 @@ CFLAGS="-Wall -O3 -fomit-frame-pointer"
mkdir release
cp README.txt release/
#cp /usr/i686-w64-mingw32/lib/libwinpthread-1.dll release/
+#cp /usr/lib/gcc/i686-w64-mingw32/5.3-win32/libgcc_s_sjlj-1.dll release/
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll release/
cp curl/lib/.libs/libcurl-4.dll release/
diff --git a/yescrypt.c b/yescrypt.c
index 35e3277..19392f9 100644
--- a/yescrypt.c
+++ b/yescrypt.c
@@ -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,
diff --git a/yespower.c b/yespower.c
index f0f06f4..b4fd427 100644
--- a/yespower.c
+++ b/yespower.c
@@ -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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment