Add block detection via getblockcount polling in gbt solo and update gbt template every 60 seconds.
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 160 161 162 163 164 165 166 167 168 169 170 171 172 173
diff --git a/cgminer.c b/cgminer.c
index ac34418..ee28fce 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -2166,7 +2166,6 @@ static void gbt_merkle_bins(struct pool *pool, json_t *transaction_arr)
txn = json_string_value(json_object_get(arr_val, "data"));
len = strlen(txn);
memcpy(pool->txn_data + ofs, txn, len);
- pool->txn_data = realloc_strcat(pool->txn_data, (char *)txn);
if (!hash) {
unsigned char *txn_bin;
int txn_len;
@@ -2282,6 +2281,7 @@ static bool gbt_solo_decode(struct pool *pool, json_t *res_val)
pool->nValue = coinbasevalue;
hex2bin((unsigned char *)&pool->gbt_bits, bits, 4);
gbt_merkle_bins(pool, transaction_arr);
+ pool->height = height;
memset(pool->scriptsig_base, 0, 42);
pool->scriptsig_base[ofs++] = 49; // Template is 49 bytes
@@ -2371,15 +2371,15 @@ static bool work_decode(struct pool *pool, struct work *work, json_t *val)
goto out;
}
- if (pool->has_gbt) {
- if (unlikely(!gbt_decode(pool, res_val)))
+ if (pool->gbt_solo) {
+ if (unlikely(!gbt_solo_decode(pool, res_val)))
goto out;
- work->gbt = true;
ret = true;
goto out;
- } else if (pool->gbt_solo) {
- if (unlikely(!gbt_solo_decode(pool, res_val)))
+ } else if (pool->has_gbt) {
+ if (unlikely(!gbt_decode(pool, res_val)))
goto out;
+ work->gbt = true;
ret = true;
goto out;
} else if (unlikely(!getwork_decode(res_val, work)))
@@ -6556,6 +6556,9 @@ retry_stratum:
if (rc) {
if (pool->gbt_solo) {
ret = setup_gbt_solo(curl, pool);
+ pool->lp_started = true;
+ if (unlikely(pthread_create(&pool->longpoll_thread, NULL, longpoll_thread, (void *)pool)))
+ quit(1, "Failed to create pool longpoll thread");
goto out;
}
applog(LOG_DEBUG, "Successfully retrieved and deciphered work from pool %u %s",
@@ -6871,6 +6874,27 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
cgtime(&work->tv_staged);
}
+static void update_gbt_solo(struct pool *pool)
+{
+ struct work *work = make_work();
+ struct curl_ent *ce;
+ int rolltime;
+ json_t *val;
+
+ ce = pop_curl_entry(pool);
+ val = json_rpc_call(ce->curl, pool->rpc_url, pool->rpc_userpass, pool->rpc_req,
+ true, false, &rolltime, pool, false);
+
+ if (likely(val)) {
+ bool rc = work_decode(pool, work, val);
+
+ if (rc)
+ setup_gbt_solo(ce->curl, pool);
+ free_work(work);
+ }
+ push_curl_entry(ce, pool);
+}
+
static void gen_solo_work(struct pool *pool, struct work *work)
{
unsigned char merkle_root[32], merkle_sha[64];
@@ -6880,22 +6904,8 @@ static void gen_solo_work(struct pool *pool, struct work *work)
int i;
cgtime(&now);
- if (now.tv_sec - pool->tv_lastwork.tv_sec > 5) {
- struct curl_ent *ce;
- int rolltime;
- json_t *val;
-
- ce = pop_curl_entry(pool);
- val = json_rpc_call(ce->curl, pool->rpc_url, pool->rpc_userpass, pool->rpc_req,
- true, false, &rolltime, pool, false);
-
- if (likely(val)) {
- bool rc = work_decode(pool, work, val);
- if (rc)
- setup_gbt_solo(ce->curl, pool);
- }
- push_curl_entry(ce, pool);
- }
+ if (now.tv_sec - pool->tv_lastwork.tv_sec > 60)
+ update_gbt_solo(pool);
cg_wlock(&pool->gbt_lock);
@@ -7788,7 +7798,7 @@ static struct pool *select_longpoll_pool(struct pool *cp)
{
int i;
- if (cp->hdr_path || cp->has_gbt)
+ if (cp->hdr_path || cp->has_gbt || cp->gbt_solo)
return cp;
for (i = 0; i < total_pools; i++) {
struct pool *pool = pools[i];
@@ -7857,6 +7867,41 @@ retry_pool:
/* Any longpoll from any pool is enough for this to be true */
have_longpoll = true;
+ if (pool->gbt_solo) {
+ applog(LOG_WARNING, "Block change for %s detection via getblockcount polling",
+ cp->rpc_url);
+ while (42) {
+ json_t *val, *res_val = NULL;
+
+ cgtime(&start);
+ wait_lpcurrent(cp);
+ sprintf(lpreq, "{\"id\": 0, \"method\": \"getblockcount\"}\n");
+ val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, lpreq, true,
+ false, &rolltime, pool, false);
+ if (likely(val))
+ res_val = json_object_get(val, "result");
+ if (likely(res_val)) {
+ int height = json_integer_value(res_val);
+
+ failures = 0;
+ json_decref(val);
+ if (height >= cp->height) {
+ applog(LOG_WARNING, "Block height change to %d detected on pool %d",
+ height, cp->pool_no);
+ update_gbt_solo(pool);
+ } else
+ cgsleep_ms(500);
+ } else {
+ cgtime(&end);
+ if (end.tv_sec - start.tv_sec > 30)
+ continue;
+ if (failures == 1)
+ applog(LOG_WARNING, "longpoll failed for %s, retrying every 30s", lp_url);
+ cgsleep_ms(30000);
+ }
+ }
+ }
+
wait_lpcurrent(cp);
if (pool->has_gbt) {
diff --git a/miner.h b/miner.h
index 5cf450e..e47efc8 100644
--- a/miner.h
+++ b/miner.h
@@ -1247,11 +1247,12 @@ struct pool {
uint32_t gbt_bits;
unsigned char *txn_hashes;
int gbt_txns;
+ int height;
bool gbt_solo;
unsigned char merklebin[16 * 32];
int transactions;
- unsigned char *txn_data;
+ char *txn_data;
unsigned char scriptsig_base[42 + 2];
unsigned char script_pubkey[25 + 3];
int nValue;