diff --git a/src/generator.c b/src/generator.c index e23a173c..b119857b 100644 --- a/src/generator.c +++ b/src/generator.c @@ -122,6 +122,60 @@ struct proxy_instance { typedef struct proxy_instance proxy_instance_t; +static bool server_alive(ckpool_t *ckp, server_instance_t *si, bool pinging) +{ + char *userpass = NULL; + bool ret = false; + connsock_t *cs; + gbtbase_t *gbt; + + cs = &si->cs; + if (!extract_sockaddr(si->url, &cs->url, &cs->port)) { + LOGWARNING("Failed to extract address from %s", si->url); + return ret; + } + userpass = strdup(si->auth); + realloc_strcat(&userpass, ":"); + realloc_strcat(&userpass, si->pass); + cs->auth = http_base64(userpass); + dealloc(userpass); + if (!cs->auth) { + LOGWARNING("Failed to create base64 auth from %s", userpass); + return ret; + } + + cs->fd = connect_socket(cs->url, cs->port); + if (cs->fd < 0) { + if (!pinging) + LOGWARNING("Failed to connect socket to %s:%s !", cs->url, cs->port); + return ret; + } + + /* Test we can connect, authorise and get a block template */ + gbt = ckzalloc(sizeof(gbtbase_t)); + si->data = gbt; + if (!gen_gbtbase(cs, gbt)) { + if (!pinging) { + LOGINFO("Failed to get test block template from %s:%s!", + cs->url, cs->port); + } + goto out_close; + } + clear_gbtbase(gbt); + if (!validate_address(cs, ckp->btcaddress)) { + LOGWARNING("Invalid btcaddress: %s !", ckp->btcaddress); + goto out_close; + } + ret = true; +out_close: + if (!ret) + close(cs->fd); + else + keep_sockalive(cs->fd); + return ret; +} + +/* Find the highest priority server alive and return it */ static server_instance_t *live_server(ckpool_t *ckp) { server_instance_t *alive = NULL; @@ -134,49 +188,12 @@ retry: goto out; for (i = 0; i < ckp->btcds; i++) { - server_instance_t *si; - char *userpass = NULL; - gbtbase_t *gbt; - - si = ckp->servers[i]; - cs = &si->cs; - if (!extract_sockaddr(si->url, &cs->url, &cs->port)) { - LOGWARNING("Failed to extract address from %s", si->url); - continue; - } - userpass = strdup(si->auth); - realloc_strcat(&userpass, ":"); - realloc_strcat(&userpass, si->pass); - cs->auth = http_base64(userpass); - dealloc(userpass); - if (!cs->auth) { - LOGWARNING("Failed to create base64 auth from %s", userpass); - continue; - } - - cs->fd = connect_socket(cs->url, cs->port); - if (cs->fd < 0) { - LOGWARNING("Failed to connect socket to %s:%s !", cs->url, cs->port); - continue; - } + server_instance_t *si = ckp->servers[i]; - keep_sockalive(cs->fd); - - /* Test we can connect, authorise and get a block template */ - gbt = ckzalloc(sizeof(gbtbase_t)); - si->data = gbt; - if (!gen_gbtbase(cs, gbt)) { - LOGINFO("Failed to get test block template from %s:%s!", - cs->url, cs->port); - continue; - } - clear_gbtbase(gbt); - if (!validate_address(cs, ckp->btcaddress)) { - LOGWARNING("Invalid btcaddress: %s !", ckp->btcaddress); - continue; + if (server_alive(ckp, si, false)) { + alive = si; + break; } - alive = si; - break; } if (!alive) { LOGWARNING("CRITICAL: No bitcoinds active!"); @@ -1253,6 +1270,46 @@ static void passthrough_add_send(proxy_instance_t *proxi, const char *msg) ckmsgq_add(proxi->passsends, pm); } +static bool proxy_alive(ckpool_t *ckp, server_instance_t *si, proxy_instance_t *proxi, + connsock_t *cs, bool pinging) +{ + if (!extract_sockaddr(si->url, &cs->url, &cs->port)) { + LOGWARNING("Failed to extract address from %s", si->url); + return false; + } + if (!connect_proxy(cs)) { + if (!pinging) { + LOGINFO("Failed to connect to %s:%s in proxy_mode!", + cs->url, cs->port); + } + return false; + } + if (ckp->passthrough) { + if (!passthrough_stratum(cs, proxi)) { + LOGWARNING("Failed initial passthrough to %s:%s !", + cs->url, cs->port); + return false; + } + return true; + } + /* Test we can connect, authorise and get stratum information */ + if (!subscribe_stratum(cs, proxi)) { + if (!pinging) { + LOGINFO("Failed initial subscribe to %s:%s !", + cs->url, cs->port); + } + return false; + } + if (!auth_stratum(cs, proxi)) { + if (!pinging) { + LOGWARNING("Failed initial authorise to %s:%s with %s:%s !", + cs->url, cs->port, si->auth, si->pass); + } + return false; + } + return true; +} + /* Cycle through the available proxies and find the first alive one */ static proxy_instance_t *live_proxy(ckpool_t *ckp) { @@ -1272,37 +1329,10 @@ retry: si = ckp->servers[i]; proxi = si->data; cs = proxi->cs; - if (!extract_sockaddr(si->url, &cs->url, &cs->port)) { - LOGWARNING("Failed to extract address from %s", si->url); - continue; - } - if (!connect_proxy(cs)) { - LOGINFO("Failed to connect to %s:%s in proxy_mode!", - cs->url, cs->port); - continue; - } - if (ckp->passthrough) { - if (!passthrough_stratum(cs, proxi)) { - LOGWARNING("Failed initial passthrough to %s:%s !", - cs->url, cs->port); - continue; - } + if (proxy_alive(ckp, si, proxi, cs, false)) { alive = proxi; break; } - /* Test we can connect, authorise and get stratum information */ - if (!subscribe_stratum(cs, proxi)) { - LOGINFO("Failed initial subscribe to %s:%s !", - cs->url, cs->port); - continue; - } - if (!auth_stratum(cs, proxi)) { - LOGWARNING("Failed initial authorise to %s:%s with %s:%s !", - cs->url, cs->port, si->auth, si->pass); - continue; - } - alive = proxi; - break; } if (!alive) { send_proc(ckp->stratifier, "dropall"); diff --git a/src/stratifier.c b/src/stratifier.c index 642322f6..779c3d05 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -79,7 +79,7 @@ static pool_stats_t stats; static pthread_mutex_t stats_lock; -static uint64_t enonce1_64; +static uint64_t enonce1_64 = 1; struct workbase { /* Hash table data */ @@ -159,7 +159,7 @@ static struct { static int64_t workbase_id; static int64_t blockchange_id; -static char lasthash[68]; +static char lasthash[68], lastswaphash[68]; struct json_params { json_t *params; @@ -556,10 +556,14 @@ static void add_base(ckpool_t *ckp, workbase_t *wb, bool *new_block) ck_wlock(&workbase_lock); wb->id = workbase_id++; - if (strncmp(wb->prevhash, lasthash, 64)) { + char bin[32], swap[32]; + *new_block = true; memcpy(lasthash, wb->prevhash, 65); + hex2bin(bin, lasthash, 32); + swap_256(swap, bin); + __bin2hex(lastswaphash, swap, 32); blockchange_id = wb->id; } if (*new_block && ckp->logshares) { @@ -1027,7 +1031,7 @@ static void drop_client(int64_t id) HASH_DEL(stratum_instances, client); HASH_FIND(hh, disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client); /* Only keep around one copy of the old client */ - if (!old_client) + if (!old_client && client->enonce1_64) HASH_ADD(hh, disconnected_instances, enonce1_64, sizeof(uint64_t), client); else // Keep around instance so we don't get a dereference HASH_ADD(hh, dead_instances, enonce1_64, sizeof(uint64_t), client); @@ -1193,7 +1197,7 @@ out: static void *blockupdate(void *arg) { ckpool_t *ckp = (ckpool_t *)arg; - char *buf = NULL, hash[68]; + char *buf = NULL; char request[8]; pthread_detach(pthread_self()); @@ -1204,14 +1208,12 @@ static void *blockupdate(void *arg) else sprintf(request, "getlast"); - memset(hash, 0, 68); while (42) { dealloc(buf); buf = send_recv_generator(ckp, request, GEN_LAX); - if (buf && strcmp(buf, hash) && !cmdmatch(buf, "failed")) { - strcpy(hash, buf); - LOGNOTICE("Block hash changed to %s", hash); - send_proc(ckp->stratifier, "update"); + if (buf && strcmp(buf, lastswaphash) && !cmdmatch(buf, "failed")) { + LOGNOTICE("Block hash changed to %s", buf); + update_base(ckp, GEN_PRIORITY); } else cksleep_ms(ckp->blockpoll); } @@ -1469,6 +1471,10 @@ static json_t *parse_authorise(stratum_instance_t *client, json_t *params_val, j *err_val = json_string("params missing array entries"); goto out; } + if (unlikely(!client->useragent)) { + *err_val = json_string("Failed subscription"); + goto out; + } buf = json_string_value(json_array_get(params_val, 0)); if (!buf) { *err_val = json_string("Invalid workername parameter"); @@ -1905,6 +1911,7 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, ck_rlock(&workbase_lock); HASH_FIND_I64(workbases, &id, wb); if (unlikely(!wb)) { + id = current_workbase->id; err = SE_INVALID_JOBID; json_set_string(json_msg, "reject-reason", SHARE_ERR(err)); strcpy(idstring, job_id);