From 6f48d76e7eb40f76887947ad3699ae683a5cdb1a Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 5 Feb 2016 21:59:01 +1100 Subject: [PATCH 1/3] Tidy up transaction refcount by resetting it every time it's seen instead of just incrementing it, differentiating node refcounts from main pools --- src/stratifier.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 36673a6a..96a042e6 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1117,7 +1117,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 +1128,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 +1142,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 +1180,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 +1218,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 +1275,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 +1367,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 +1400,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 +1434,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 +1444,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,7 +1488,7 @@ 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)) { + if (!rebuild_txns(ckp, sdata, wb, txnhashes)) { LOGWARNING("Unable to rebuild transactions from hashes to create workinfo"); free(wb); return; @@ -6320,7 +6327,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 +6336,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++; } From 2a76d1ab535ecf87ab50bb62608f7416e4b2a6ed Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 5 Feb 2016 22:24:02 +1100 Subject: [PATCH 2/3] Add a failsafe mode to nodes that will allow miners to continue hashing even if workinfo is temporarily unavailable --- src/stratifier.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 96a042e6..24b9842b 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 */ @@ -1489,10 +1492,17 @@ static void add_node_base(ckpool_t *ckp, json_t *val) json_intcpy(&wb->txns, val, "txns"); txnhashes = json_object_get(val, "txn_hashes"); if (!rebuild_txns(ckp, sdata, wb, txnhashes)) { - LOGWARNING("Unable to rebuild transactions from hashes to create workinfo"); + 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"); @@ -5596,7 +5606,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; From df346876d8efaf72122d92db53737c1a9a722590 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 7 Feb 2016 15:35:01 +1100 Subject: [PATCH 3/3] Only send node workinfo in pool mode --- src/stratifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index 24b9842b..ecc92702 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -958,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)