diff --git a/src/stratifier.c b/src/stratifier.c index 36673a6a..ecc92702 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -459,6 +459,9 @@ struct stratifier_data { int workbases_generated; txntable_t *txns; + /* Is this a node and unable to rebuild workinfos due to lack of txns */ + bool wbincomplete; + /* Semaphore to serialise calls to add_base */ sem_t update_sem; /* Time we last sent out a stratum update */ @@ -955,7 +958,8 @@ static void send_workinfo(ckpool_t *ckp, sdata_t *sdata, const workbase_t *wb) "createcode", __func__, "createinet", ckp->serverurl[0]); ckdbq_add(ckp, ID_WORKINFO, val); - send_node_workinfo(sdata, wb); + if (!ckp->proxy) + send_node_workinfo(sdata, wb); } static void send_ageworkinfo(ckpool_t *ckp, const int64_t id) @@ -1117,7 +1121,8 @@ static void broadcast_ping(sdata_t *sdata); /* Build a hashlist of all transactions, allowing us to compare with the list of * existing transactions to determine which need to be propagated */ -static void add_txn(sdata_t *sdata, txntable_t **txns, const char *hash, const char *data) +static void add_txn(ckpool_t *ckp, sdata_t *sdata, txntable_t **txns, const char *hash, + const char *data) { bool found = false; txntable_t *txn; @@ -1127,7 +1132,10 @@ static void add_txn(sdata_t *sdata, txntable_t **txns, const char *hash, const c ck_rlock(&sdata->workbase_lock); HASH_FIND_STR(sdata->txns, hash, txn); if (txn) { - txn->refcount++; + if (ckp->node) + txn->refcount = 100; + else + txn->refcount = 20; found = true; } ck_runlock(&sdata->workbase_lock); @@ -1138,7 +1146,10 @@ static void add_txn(sdata_t *sdata, txntable_t **txns, const char *hash, const c txn = ckzalloc(sizeof(txntable_t)); memcpy(txn->hash, hash, 65); txn->data = strdup(data); - txn->refcount = 10; + if (ckp->node) + txn->refcount = 100; + else + txn->refcount = 20; HASH_ADD_STR(*txns, hash, txn); } @@ -1173,7 +1184,7 @@ static void send_node_transactions(sdata_t *sdata, const json_t *txn_val) /* Distill down a set of transactions into an efficient tree arrangement for * stratum messages and fast work assembly. */ -static void wb_merkle_bins(sdata_t *sdata, workbase_t *wb, json_t *txn_array) +static void wb_merkle_bins(ckpool_t *ckp, sdata_t *sdata, workbase_t *wb, json_t *txn_array) { int i, j, binleft, binlen, added = 0, purged = 0; txntable_t *txns = NULL, *tmp, *tmpa; @@ -1211,7 +1222,7 @@ static void wb_merkle_bins(sdata_t *sdata, workbase_t *wb, json_t *txn_array) arr_val = json_array_get(txn_array, i); hash = json_string_value(json_object_get(arr_val, "hash")); txn = json_string_value(json_object_get(arr_val, "data")); - add_txn(sdata, &txns, hash, txn); + add_txn(ckp, sdata, &txns, hash, txn); len = strlen(txn); memcpy(wb->txn_data + ofs, txn, len); ofs += len; @@ -1268,7 +1279,7 @@ static void wb_merkle_bins(sdata_t *sdata, workbase_t *wb, json_t *txn_array) * and remove them. */ ck_wlock(&sdata->workbase_lock); HASH_ITER(hh, sdata->txns, tmp, tmpa) { - if (tmp->refcount--) + if (tmp->refcount-- > 0) continue; HASH_DEL(sdata->txns, tmp); dealloc(tmp->data); @@ -1360,7 +1371,7 @@ retry: json_intcpy(&wb->height, val, "height"); json_strdup(&wb->flags, val, "flags"); txn_array = json_object_get(val, "transactions"); - wb_merkle_bins(sdata, wb, txn_array); + wb_merkle_bins(ckp, sdata, wb, txn_array); json_decref(val); generate_coinbase(ckp, wb); @@ -1393,7 +1404,7 @@ out_free: return NULL; } -static bool rebuild_txns(sdata_t *sdata, workbase_t *wb, json_t *txnhashes) +static bool rebuild_txns(ckpool_t *ckp, sdata_t *sdata, workbase_t *wb, json_t *txnhashes) { const char *hashes = json_string_value(txnhashes); json_t *txn_array; @@ -1427,7 +1438,7 @@ static bool rebuild_txns(sdata_t *sdata, workbase_t *wb, json_t *txnhashes) ret = false; goto out_unlock; } - txn->refcount += 2; + txn->refcount = 100; JSON_CPACK(txn_val, "{ss,ss}", "hash", hash, "data", txn->data); json_array_append_new(txn_array, txn_val); @@ -1437,7 +1448,7 @@ out_unlock: if (ret) { LOGINFO("Rebuilt txns into workbase with %d transactions", (int)i); - wb_merkle_bins(sdata, wb, txn_array); + wb_merkle_bins(ckp, sdata, wb, txn_array); } json_decref(txn_array); @@ -1481,11 +1492,18 @@ static void add_node_base(ckpool_t *ckp, json_t *val) } else { json_intcpy(&wb->txns, val, "txns"); txnhashes = json_object_get(val, "txn_hashes"); - if (!rebuild_txns(sdata, wb, txnhashes)) { - LOGWARNING("Unable to rebuild transactions from hashes to create workinfo"); + if (!rebuild_txns(ckp, sdata, wb, txnhashes)) { + if (!sdata->wbincomplete) { + sdata->wbincomplete = true; + LOGWARNING("Unable to rebuild transactions to create workinfo, ignore displayed hashrate"); + } free(wb); return; } + if (sdata->wbincomplete) { + LOGWARNING("Successfully resumed rebuilding transactions into workinfo"); + sdata->wbincomplete = false; + } } json_strdup(&wb->coinb1, val, "coinb1"); json_intcpy(&wb->coinb1len, val, "coinb1len"); @@ -5589,7 +5607,7 @@ out_unlock: } ckdbq_add(ckp, ID_SHARES, val); out: - if ((!result && !submit) || !share) { + if (!sdata->wbincomplete && ((!result && !submit) || !share)) { /* Is this the first in a run of invalids? */ if (client->first_invalid < client->last_share.tv_sec || !client->first_invalid) client->first_invalid = now_t; @@ -6320,7 +6338,7 @@ static void add_node_txns(sdata_t *sdata, const json_t *val) } HASH_FIND_STR(sdata->txns, hash, txn); if (txn) { - txn->refcount++; + txn->refcount = 100; continue; } txn = ckzalloc(sizeof(txntable_t)); @@ -6329,7 +6347,7 @@ static void add_node_txns(sdata_t *sdata, const json_t *val) /* Set the refcount for node transactions greater than the * upstream pool to ensure we never age them faster than the * pool does. */ - txn->refcount = 50; + txn->refcount = 100; HASH_ADD_STR(sdata->txns, hash, txn); added++; }