Browse Source

Maximise the nonce2 size in proxy mode and ensure we don't clash enonce1 instances, rejecting clients when there is no more space available

master
Con Kolivas 10 years ago
parent
commit
3d6601d20c
  1. 5
      src/connector.c
  2. 93
      src/stratifier.c

5
src/connector.c

@ -455,9 +455,10 @@ static void send_client(conn_instance_t *ci, int64_t id, char *buf)
ck_runlock(&ci->lock); ck_runlock(&ci->lock);
if (unlikely(fd == -1)) { if (unlikely(fd == -1)) {
if (client) if (client) {
LOGINFO("Client id %ld disconnected", id); LOGINFO("Client id %ld disconnected", id);
else invalidate_client(ci->pi->ckp, ci, client);
} else
LOGINFO("Connector failed to find client id %ld to send to", id); LOGINFO("Connector failed to find client id %ld to send to", id);
free(buf); free(buf);
return; return;

93
src/stratifier.c

@ -79,7 +79,7 @@ static pool_stats_t stats;
static pthread_mutex_t stats_lock; static pthread_mutex_t stats_lock;
static uint64_t enonce1_64 = 1; static uint64_t enonce1_64;
struct workbase { struct workbase {
/* Hash table data */ /* Hash table data */
@ -775,8 +775,10 @@ static bool update_subscribe(ckpool_t *ckp)
proxy_base.nonce2len = json_integer_value(json_object_get(val, "nonce2len")); proxy_base.nonce2len = json_integer_value(json_object_get(val, "nonce2len"));
if (proxy_base.nonce2len > 7) if (proxy_base.nonce2len > 7)
proxy_base.enonce1varlen = 4; proxy_base.enonce1varlen = 4;
else else if (proxy_base.nonce2len > 5)
proxy_base.enonce1varlen = 2; proxy_base.enonce1varlen = 2;
else
proxy_base.enonce1varlen = 1;
proxy_base.enonce2varlen = proxy_base.nonce2len - proxy_base.enonce1varlen; proxy_base.enonce2varlen = proxy_base.nonce2len - proxy_base.enonce1varlen;
ck_wunlock(&workbase_lock); ck_wunlock(&workbase_lock);
@ -1061,6 +1063,8 @@ static void drop_client(int64_t id)
stratum_instance_t *client = NULL; stratum_instance_t *client = NULL;
bool dec = false; bool dec = false;
LOGINFO("Stratifier dropping client %ld", id);
ck_ilock(&instance_lock); ck_ilock(&instance_lock);
client = __instance_by_id(id); client = __instance_by_id(id);
if (client) { if (client) {
@ -1264,32 +1268,84 @@ static void *blockupdate(void *arg)
return NULL; return NULL;
} }
static void new_enonce1(stratum_instance_t *client) static inline bool enonce1_free(uint64_t enonce1)
{ {
stratum_instance_t *client, *tmp;
bool ret = true;
if (unlikely(!enonce1)) {
ret = false;
goto out;
}
HASH_ITER(hh, stratum_instances, client, tmp) {
if (client->enonce1_64 == enonce1) {
ret = false;
break;
}
}
out:
return ret;
}
/* Create a new enonce1 from the 64 bit enonce1_64 value, using only the number
* of bytes we have to work with when we are proxying with a split nonce2.
* When the proxy space is less than 32 bits to work with, we look for an
* unused enonce1 value and reject clients instead if there is no space left */
static bool new_enonce1(stratum_instance_t *client)
{
void *enoncev = &enonce1_64;
uint32_t *enonce1_32 = enoncev;
uint16_t *enonce1_16 = enoncev;
uint8_t *enonce1_8 = enoncev;
bool ret = false;
workbase_t *wb; workbase_t *wb;
int i;
ck_wlock(&workbase_lock); ck_wlock(&workbase_lock);
client->enonce1_64 = enonce1_64;
wb = current_workbase; wb = current_workbase;
if (wb->enonce1varlen == 8) { switch(wb->enonce1varlen) {
case 8:
enonce1_64++; enonce1_64++;
} else if (wb->enonce1varlen == 2) { LOGWARNING("Enonce1_64 is %lu", enonce1_64);
uint16_t *enonce1_16 = (uint16_t *)&enonce1_64; ret = true;
break;
++(*enonce1_16); case 4:
} else {
uint32_t *enonce1_32 = (uint32_t *)&enonce1_64;
++(*enonce1_32); ++(*enonce1_32);
LOGWARNING("Enonce1_32 is %lu", *enonce1_32);
ret = true;
break;
case 2:
i = 0;
do {
++(*enonce1_16);
ret = enonce1_free(enonce1_64);
} while (++i < 65536 && !ret);
break;
case 1:
i = 0;
do {
++(*enonce1_8);
ret = enonce1_free(enonce1_64);
} while (++i < 256 && !ret);
break;
} }
if (ret)
client->enonce1_64 = enonce1_64;
if (wb->enonce1constlen) if (wb->enonce1constlen)
memcpy(client->enonce1bin, wb->enonce1constbin, wb->enonce1constlen); memcpy(client->enonce1bin, wb->enonce1constbin, wb->enonce1constlen);
memcpy(client->enonce1bin + wb->enonce1constlen, &client->enonce1_64, wb->enonce1varlen); memcpy(client->enonce1bin + wb->enonce1constlen, &client->enonce1_64, wb->enonce1varlen);
__bin2hex(client->enonce1var, &client->enonce1_64, wb->enonce1varlen); __bin2hex(client->enonce1var, &client->enonce1_64, wb->enonce1varlen);
__bin2hex(client->enonce1, client->enonce1bin, wb->enonce1constlen + wb->enonce1varlen); __bin2hex(client->enonce1, client->enonce1bin, wb->enonce1constlen + wb->enonce1varlen);
ck_wunlock(&workbase_lock); ck_wunlock(&workbase_lock);
if (unlikely(!ret))
LOGWARNING("Enonce1 space exhausted! Proxy rejecting clients");
return ret;
} }
static void stratum_send_message(stratum_instance_t *client, const char *msg);
/* Extranonce1 must be set here */ /* Extranonce1 must be set here */
static json_t *parse_subscribe(stratum_instance_t *client, int64_t client_id, json_t *params_val) static json_t *parse_subscribe(stratum_instance_t *client, int64_t client_id, json_t *params_val)
{ {
@ -1298,11 +1354,15 @@ static json_t *parse_subscribe(stratum_instance_t *client, int64_t client_id, js
json_t *ret; json_t *ret;
int n2len; int n2len;
if (unlikely(!json_is_array(params_val))) if (unlikely(!json_is_array(params_val))) {
stratum_send_message(client, "Invalid json: params not an array");
return json_string("params not an array"); return json_string("params not an array");
}
if (unlikely(!current_workbase)) if (unlikely(!current_workbase)) {
stratum_send_message(client, "Pool Initialising");
return json_string("Initialising"); return json_string("Initialising");
}
arr_size = json_array_size(params_val); arr_size = json_array_size(params_val);
if (arr_size > 0) { if (arr_size > 0) {
@ -1328,7 +1388,10 @@ static json_t *parse_subscribe(stratum_instance_t *client, int64_t client_id, js
client->useragent = ckzalloc(1); client->useragent = ckzalloc(1);
if (!old_match) { if (!old_match) {
/* Create a new extranonce1 based on a uint64_t pointer */ /* Create a new extranonce1 based on a uint64_t pointer */
new_enonce1(client); if (!new_enonce1(client)) {
stratum_send_message(client, "Pool full of clients");
return json_string("proxy full");
}
LOGINFO("Set new subscription %ld to new enonce1 %s", client->id, LOGINFO("Set new subscription %ld to new enonce1 %s", client->id,
client->enonce1); client->enonce1);
} else { } else {

Loading…
Cancel
Save