diff --git a/src/libckpool.h b/src/libckpool.h index 98d3e54c..23c26c74 100644 --- a/src/libckpool.h +++ b/src/libckpool.h @@ -313,25 +313,39 @@ static inline void json_strdup(char **buf, json_t *val, const char *key) *buf = strdup(json_string_value(json_object_get(val, key))); } -static inline void json_set_string(json_t *val, const char *key, const char *str) +/* Helpers for setting a field will check for valid entry and print an error + * if it is unsuccessfully set. */ +static inline void _json_set_string(json_t *val, const char *key, const char *str, + const char *file, const char *func, const int line) { - json_object_set_new_nocheck(val, key, json_string(str)); + if (unlikely(json_object_set_new_nocheck(val, key, json_string(str)))) + LOGERR("Failed to set json string from %s %s:%d", file, func, line); } +#define json_set_string(val, key, str) _json_set_string(val, key, str, __FILE__, __func__, __LINE__) -static inline void json_set_int(json_t *val, const char *key, int64_t integer) +static inline void _json_set_int(json_t *val, const char *key, int64_t integer, + const char *file, const char *func, const int line) { - json_object_set_new_nocheck(val, key, json_integer(integer)); + if (unlikely(json_object_set_new_nocheck(val, key, json_integer(integer)))) + LOGERR("Failed to set json int from %s %s:%d", file, func, line); } +#define json_set_int(val, key, integer) _json_set_int(val, key, integer, __FILE__, __func__, __LINE__) -static inline void json_set_double(json_t *val, const char *key, double real) +static inline void _json_set_double(json_t *val, const char *key, double real, + const char *file, const char *func, const int line) { - json_object_set_new_nocheck(val, key, json_real(real)); + if (unlikely(json_object_set_new_nocheck(val, key, json_real(real)))) + LOGERR("Failed to set json double from %s %s:%d", file, func, line); } +#define json_set_double(val, key, real) _json_set_double(val, key, real, __FILE__, __func__, __LINE__) -static inline void json_set_bool(json_t *val, const char *key, bool boolean) +static inline void _json_set_bool(json_t *val, const char *key, bool boolean, + const char *file, const char *func, const int line) { - json_object_set_new_nocheck(val, key, json_boolean(boolean)); + if (unlikely(json_object_set_new_nocheck(val, key, json_boolean(boolean)))) + LOGERR("Failed to set json bool from %s %s:%d", file, func, line); } +#define json_set_bool(val, key, boolean) _json_set_bool(val, key, boolean, __FILE__, __func__, __LINE__) void rename_proc(const char *name); void create_pthread(pthread_t *thread, void *(*start_routine)(void *), void *arg); diff --git a/src/stratifier.c b/src/stratifier.c index 355951ca..31285670 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -192,6 +192,7 @@ struct user_instance { char username[128]; int64_t id; char *secondaryuserid; + bool btcaddress; int workers; }; @@ -267,6 +268,7 @@ static cklock_t share_lock; #define ID_POOLSTATS 5 #define ID_USERSTATS 6 #define ID_BLOCK 7 +#define ID_ADDRAUTH 8 static const char *ckdb_ids[] = { "authorise", @@ -276,7 +278,8 @@ static const char *ckdb_ids[] = { "shareerror", "poolstats", "userstats", - "block" + "block", + "addrauth", }; static void generate_coinbase(ckpool_t *ckp, workbase_t *wb) @@ -1250,17 +1253,35 @@ static json_t *parse_subscribe(int64_t client_id, json_t *params_val) return ret; } +static bool test_address(ckpool_t *ckp, const char *address) +{ + bool ret = false; + char *buf, *msg; + + ASPRINTF(&msg, "checkaddr:%s", address); + buf = send_recv_proc(ckp->generator, msg); + dealloc(msg); + if (!buf) + return ret; + ret = cmdmatch(buf, "true"); + dealloc(buf); + return ret; +} + /* This simply strips off the first part of the workername and matches it to a * user or creates a new one. */ -static user_instance_t *authorise_user(const char *workername) +static user_instance_t *authorise_user(ckpool_t *ckp, const char *workername) { char *base_username = strdupa(workername), *username; user_instance_t *instance; + bool new = false; + int len; username = strsep(&base_username, "._"); if (!username || !strlen(username)) username = base_username; - if (strlen(username) > 127) + len = strlen(username); + if (unlikely(len > 127)) username[127] = '\0'; ck_ilock(&instance_lock); @@ -1269,6 +1290,7 @@ static user_instance_t *authorise_user(const char *workername) /* New user instance. Secondary user id will be NULL */ instance = ckzalloc(sizeof(user_instance_t)); strcpy(instance->username, username); + new = true; ck_ulock(&instance_lock); instance->id = user_instance_id++; @@ -1277,6 +1299,14 @@ static user_instance_t *authorise_user(const char *workername) } ck_uilock(&instance_lock); + if (new) { + /* Is this a btc address based username? */ + if (len > 26 && len < 35) + instance->btcaddress = test_address(ckp, username); + LOGNOTICE("Added new user %s%s", username, instance->btcaddress ? + " as address based registration" : ""); + } + return instance; } @@ -1297,19 +1327,22 @@ static int send_recv_auth(stratum_instance_t *client) ts_realtime(&now); sprintf(cdfield, "%lu,%lu", now.tv_sec, now.tv_nsec); - JSON_CPACK(val, "{ss,ss,ss,ss,sI,ss,sb,ss,ss,ss,ss}", - "username", user_instance->username, - "workername", client->workername, - "poolinstance", ckp->name, - "useragent", client->useragent, - "clientid", client->id, - "enonce1", client->enonce1, - "preauth", false, - "createdate", cdfield, - "createby", "code", - "createcode", __func__, - "createinet", client->address); - json_msg = ckdb_msg(ckp, val, ID_AUTH); + val = json_object(); + json_set_string(val, "username", user_instance->username); + json_set_string(val, "workername", client->workername); + json_set_string(val, "poolinstance", ckp->name); + json_set_string(val, "useragent", client->useragent); + json_set_int(val, "clientid", client->id); + json_set_string(val,"enonce1", client->enonce1); + json_set_bool(val, "preauth", false); + json_set_string(val, "createdate", cdfield); + json_set_string(val, "createby", "code"); + json_set_string(val, "createcode", __func__); + json_set_string(val, "createinet", client->address); + if (user_instance->btcaddress) + json_msg = ckdb_msg(ckp, val, ID_ADDRAUTH); + else + json_msg = ckdb_msg(ckp, val, ID_AUTH); if (unlikely(!json_msg)) { LOGWARNING("Failed to dump json in send_recv_auth"); return ret; @@ -1397,7 +1430,7 @@ static json_t *parse_authorise(stratum_instance_t *client, json_t *params_val, j *err_val = json_string("Empty username parameter"); goto out; } - user_instance = client->user_instance = authorise_user(buf); + user_instance = client->user_instance = authorise_user(client->ckp, buf); client->user_id = user_instance->id; ts_realtime(&now); client->start_time = now.tv_sec; @@ -2566,21 +2599,6 @@ static void *statsupdate(void *arg) return NULL; } -static bool test_address(ckpool_t *ckp, const char *address) -{ - bool ret = false; - char *buf, *msg; - - ASPRINTF(&msg, "checkaddr:%s", address); - buf = send_recv_proc(ckp->generator, msg); - dealloc(msg); - if (!buf) - return ret; - ret = cmdmatch(buf, "true"); - dealloc(buf); - return ret; -} - int stratifier(proc_instance_t *pi) { pthread_t pth_blockupdate, pth_statsupdate;