Generate gbt solo work emulating stratum work construction.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
diff --git a/cgminer.c b/cgminer.c
index 6783293..ff44c21 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -6408,8 +6408,6 @@ static bool setup_gbt_solo(CURL *curl, struct pool *pool)
free(cb);
}
- exit(0);
-
out:
return ret;
}
@@ -6805,7 +6803,7 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
/* Copy the data template from header_bin */
memcpy(work->data, pool->header_bin, 112);
- memcpy(work->data + pool->merkle_offset, merkle_root, 32);
+ memcpy(work->data + 36, merkle_root, 32);
/* Store the stratum work diff to check it still matches the pool's
* stratum diff when submitting shares */
@@ -6848,6 +6846,81 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
cgtime(&work->tv_staged);
}
+static void gen_solo_work(struct pool *pool, struct work *work)
+{
+ unsigned char merkle_root[32], merkle_sha[64];
+ uint32_t *data32, *swap32;
+ uint64_t nonce2le;
+ int i;
+
+ cg_wlock(&pool->gbt_lock);
+
+ /* Update coinbase. Always use an LE encoded nonce2 to fill in values
+ * from left to right and prevent overflow errors with small n2sizes */
+ nonce2le = htole64(pool->nonce2);
+ memcpy(pool->coinbase + pool->nonce2_offset, &nonce2le, pool->n2size);
+ work->nonce2 = pool->nonce2++;
+ work->nonce2_len = pool->n2size;
+
+ /* Downgrade to a read lock to read off the pool variables */
+ cg_dwlock(&pool->gbt_lock);
+
+ /* Generate merkle root */
+ gen_hash(pool->coinbase, merkle_root, pool->coinbase_len);
+ memcpy(merkle_sha, merkle_root, 32);
+ for (i = 0; i < pool->merkles; i++) {
+ unsigned char *merkle_bin;
+
+ merkle_bin = pool->merklebin + (i * 32);
+ memcpy(merkle_sha + 32, merkle_bin, 32);
+ gen_hash(merkle_sha, merkle_root, 64);
+ memcpy(merkle_sha, merkle_root, 32);
+ }
+ data32 = (uint32_t *)merkle_sha;
+ swap32 = (uint32_t *)merkle_root;
+ flip32(swap32, data32);
+
+ /* Copy the data template from header_bin */
+ memcpy(work->data, pool->header_bin, 112);
+ memcpy(work->data + 36, merkle_root, 32);
+
+ work->sdiff = pool->sdiff;
+
+ /* Copy parameters required for share submission */
+ work->ntime = strdup(pool->ntime);
+ memcpy(work->target, pool->gbt_target, 32);
+ cg_runlock(&pool->gbt_lock);
+
+ if (opt_debug) {
+ char *header, *merkle_hash;
+
+ header = bin2hex(work->data, 112);
+ merkle_hash = bin2hex((const unsigned char *)merkle_root, 32);
+ applog(LOG_DEBUG, "Generated GBT solo merkle %s", merkle_hash);
+ applog(LOG_DEBUG, "Generated GBT solo header %s", header);
+ applog(LOG_DEBUG, "Work nonce2 %"PRIu64" ntime %s", work->nonce2,
+ work->ntime);
+ free(header);
+ free(merkle_hash);
+ }
+
+ calc_midstate(work);
+
+ local_work++;
+ work->pool = pool;
+ work->stratum = true;
+ work->nonce = 0;
+ work->id = total_work++;
+ work->longpoll = false;
+ work->getwork_mode = GETWORK_MODE_SOLO;
+ work->work_block = work_block;
+ /* Nominally allow a driver to ntime roll 60 seconds */
+ work->drv_rolllimit = 60;
+ calc_diff(work, work->sdiff);
+
+ cgtime(&work->tv_staged);
+}
+
/* The time difference in seconds between when this device last got work via
* get_work() and generated a valid share. */
int share_work_tdiff(struct cgpu_info *cgpu)
@@ -9434,6 +9507,22 @@ retry:
#ifdef HAVE_LIBCURL
struct curl_ent *ce;
+ if (pool->gbt_solo) {
+ while (pool->idle) {
+ struct pool *altpool = select_pool(true);
+
+ cgsleep_ms(5000);
+ if (altpool != pool) {
+ pool = altpool;
+ goto retry;
+ }
+ }
+ gen_solo_work(pool, work);
+ applog(LOG_DEBUG, "Generated GBT SOLO work!");
+ stage_work(work);
+ continue;
+ }
+
if (pool->has_gbt) {
while (pool->idle) {
struct pool *altpool = select_pool(true);
diff --git a/miner.h b/miner.h
index 2fdc828..281e743 100644
--- a/miner.h
+++ b/miner.h
@@ -1262,7 +1262,6 @@ struct pool {
int nonce2_offset;
unsigned char header_bin[128];
int merkles;
- int merkle_offset;
char prev_hash[68];
char bbversion[12];
char nbit[12];
@@ -1278,6 +1277,7 @@ struct pool {
#define GETWORK_MODE_BENCHMARK 'B'
#define GETWORK_MODE_STRATUM 'S'
#define GETWORK_MODE_GBT 'G'
+#define GETWORK_MODE_SOLO 'C'
struct work {
unsigned char data[128];
diff --git a/util.c b/util.c
index 2143641..54dc10a 100644
--- a/util.c
+++ b/util.c
@@ -1670,7 +1670,6 @@ static bool parse_notify(struct pool *pool, json_t *val)
pool->merkles = merkles;
if (clean)
pool->nonce2 = 0;
- pool->merkle_offset = 36;
#if 0
header_len = strlen(pool->bbversion) +
strlen(pool->prev_hash);