Skip to content

Commit 949d004

Browse files
committed
Merge branch 'split_mappings'
2 parents b23e091 + 13e493e commit 949d004

File tree

11 files changed

+559
-1
lines changed

11 files changed

+559
-1
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_executable(datum_gateway
2121
src/datum_blocktemplates.c
2222
src/datum_coinbaser.c
2323
src/datum_conf.c
24+
src/datum_conf_tests.c
2425
src/datum_gateway.c
2526
src/datum_jsonrpc.c
2627
src/datum_logger.c
@@ -29,6 +30,7 @@ add_executable(datum_gateway
2930
src/datum_sockets.c
3031
src/datum_stratum.c
3132
src/datum_stratum_dupes.c
33+
src/datum_stratum_tests.c
3234
src/datum_submitblock.c
3335
src/datum_utils.c
3436
src/datum_utils_tests.c

src/datum_api.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,10 @@ size_t datum_api_fill_config_var(const char *var_start, const size_t var_name_le
10291029
DLOG_ERROR("%s: %s not implemented", __func__, "DATUM_CONF_STRING_ARRAY");
10301030
break;
10311031
}
1032+
case DATUM_CONF_USERNAME_MODS: {
1033+
DLOG_ERROR("%s: %s not implemented", __func__, "DATUM_CONF_USERNAME_MODS");
1034+
break;
1035+
}
10321036
}
10331037
} else {
10341038
DLOG_ERROR("%s: '%.*s' not implemented", __func__, (int)(var_end - var_start_2), var_start_2);

src/datum_conf.c

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535

3636
// Custom configurator and help output generator
3737

38+
#include <assert.h>
3839
#include <limits.h>
40+
#include <math.h>
3941
#include <stdio.h>
4042
#include <stdlib.h>
4143
#include <string.h>
@@ -49,7 +51,13 @@
4951

5052
global_config_t datum_config;
5153

52-
const char *datum_conf_var_type_text[] = { "boolean", "integer", "string", "string_array" };
54+
const char *datum_conf_var_type_text[] = {
55+
"boolean",
56+
"integer",
57+
"string",
58+
"string_array",
59+
"{\"modname\":{\"address\":proportion,...},...}",
60+
};
5361

5462
const T_DATUM_CONFIG_ITEM datum_config_options[] = {
5563
// Bitcoind configs
@@ -102,6 +110,7 @@ const T_DATUM_CONFIG_ITEM datum_config_options[] = {
102110
.required = false, .ptr = &datum_config.stratum_v1_idle_timeout_no_share, .default_int = 7200 },
103111
{ .var_type = DATUM_CONF_INT, .category = "stratum", .name = "idle_timeout_max_last_work", .description = "Seconds we allow a subscribed connection to be idle since its last accepted share? (0 disables)",
104112
.required = false, .ptr = &datum_config.stratum_v1_idle_timeout_max_last_work, .default_int = 0 },
113+
{ .var_type = DATUM_CONF_USERNAME_MODS, .category = "stratum", .name = "username_modifiers", .description = "Modifiers to redirect some portion of shares to alternate usernames", .required = false, .ptr = &datum_config.stratum_username_mod, },
105114

106115
// mining settings
107116
{ .var_type = DATUM_CONF_STRING, .category = "mining", .name = "pool_address", .description = "Bitcoin address used for mining rewards.",
@@ -234,7 +243,109 @@ void datum_config_set_default(const T_DATUM_CONFIG_ITEM *c) {
234243
((char *)c->ptr)[0] = 0;
235244
break;
236245
}
246+
247+
case DATUM_CONF_USERNAME_MODS: {
248+
struct datum_username_mod ** const umods_p = c->ptr;
249+
free(*umods_p);
250+
*umods_p = NULL;
251+
break;
252+
}
253+
}
254+
}
255+
256+
int datum_config_parse_username_mods(struct datum_username_mod ** const umods_p, json_t * const item, const bool log_errors) {
257+
if (!json_object_size(item)) {
258+
if (json_is_null(item) || json_is_object(item)) {
259+
free(*umods_p);
260+
*umods_p = NULL;
261+
return 1;
262+
}
263+
return -1;
264+
}
265+
266+
size_t sz = (sizeof(**umods_p) + _Alignof(struct datum_username_mod) - 1) * (json_object_size(item) + 1);
267+
const char *modname, *addr;
268+
json_t *moddefn, *proportion_j;
269+
bool at_least_one_mod = false;
270+
json_object_foreach(item, modname, moddefn) {
271+
if (json_is_null(moddefn)) continue;
272+
if (!json_is_object(moddefn)) return -1;
273+
274+
at_least_one_mod = true;
275+
sz += strlen(modname) + 1 + (sizeof(*((*umods_p)->ranges)) * (json_object_size(moddefn) + 1));
276+
277+
json_object_foreach(moddefn, addr, proportion_j) {
278+
if (json_is_null(proportion_j)) continue;
279+
if (!json_is_number(proportion_j)) return -1;
280+
if (json_number_value(proportion_j) < 0) return -1;
281+
sz += strlen(addr) + 1;
282+
}
283+
}
284+
285+
free(*umods_p);
286+
287+
if (!at_least_one_mod) {
288+
*umods_p = NULL;
289+
return 1;
290+
}
291+
292+
uint8_t *p = malloc(sz);
293+
assert(p);
294+
*umods_p = (struct datum_username_mod*)p;
295+
json_object_foreach(item, modname, moddefn) {
296+
if (json_is_null(moddefn)) continue;
297+
298+
struct datum_username_mod * const umod = (struct datum_username_mod*)p;
299+
umod->sz = sizeof(*umod) + (sizeof(*umod->ranges) * (json_object_size(moddefn) + 1));
300+
p += umod->sz;
301+
umod->modname_len = strlen(modname);
302+
umod->modname = memcpy(p, modname, umod->modname_len);
303+
p += umod->modname_len;
304+
305+
double sum = 0;
306+
struct datum_addr_range *addr_range = umod->ranges;
307+
json_object_foreach(moddefn, addr, proportion_j) {
308+
if (json_is_null(proportion_j)) continue;
309+
310+
sum += json_number_value(proportion_j);
311+
const double nonce_max_d = ceil(sum * 0x10000) - 1;
312+
if (nonce_max_d < 0) continue;
313+
const uint16_t nonce_max = (nonce_max_d > 0xffff) ? (uint16_t)0xffff : (uint16_t)nonce_max_d;
314+
addr_range->addr_len = strlen(addr);
315+
addr_range->addr = memcpy(p, addr, addr_range->addr_len + 1);
316+
addr_range->max = nonce_max;
317+
p = &p[addr_range->addr_len + 1];
318+
++addr_range;
319+
if (nonce_max == 0xffff) break;
320+
}
321+
if (log_errors && (addr_range == umod->ranges || addr_range[-1].max != 0xffff)) {
322+
double missing_percent = 100 * (1 - sum);
323+
const unsigned int missing_percent_precision = datum_double_precision(&missing_percent);
324+
DLOG_ERROR("Username modifier '%s' is configured to not distribute %.*f%% of shares!", modname, missing_percent_precision, missing_percent);
325+
}
326+
addr_range[0].addr = NULL;
327+
assert((uint8_t*)addr_range <= &((uint8_t*)umod)[umod->sz]); // otherwise we overwrote strings!
328+
assert(p <= &((uint8_t*)*umods_p)[sz]); // otherwise we overran the buffer!
329+
umod->sz = datum_align_sz(p - (uint8_t*)umod, _Alignof(struct datum_username_mod));
330+
p = &((uint8_t*)umod)[umod->sz];
237331
}
332+
((struct datum_username_mod*)p)->sz = 0;
333+
334+
return 1;
335+
}
336+
337+
struct datum_username_mod *datum_username_mods_next(struct datum_username_mod * const prev_umod) {
338+
struct datum_username_mod * const next_umod = (struct datum_username_mod *)&(((uint8_t*)prev_umod)[prev_umod->sz]);
339+
return next_umod->sz ? next_umod : NULL;
340+
}
341+
342+
struct datum_username_mod *datum_username_mods_find(struct datum_username_mod *umod, const char * const modname, const size_t modname_len) {
343+
for ( ; umod; umod = datum_username_mods_next(umod)) {
344+
if (modname_len != umod->modname_len) continue;
345+
if (strncmp(modname, umod->modname, modname_len)) continue;
346+
return umod;
347+
}
348+
return NULL;
238349
}
239350

240351
int datum_config_parse_value(const T_DATUM_CONFIG_ITEM *c, json_t *item) {
@@ -293,6 +404,10 @@ int datum_config_parse_value(const T_DATUM_CONFIG_ITEM *c, json_t *item) {
293404
((char (*)[1024])c->ptr)[i][0] = 0;
294405
return 1;
295406
}
407+
408+
case DATUM_CONF_USERNAME_MODS: {
409+
return datum_config_parse_username_mods(c->ptr, item, true);
410+
}
296411
}
297412

298413
return -1;
@@ -590,6 +705,11 @@ void datum_gateway_example_conf(void) {
590705
puts("[]");
591706
break;
592707
}
708+
709+
case DATUM_CONF_USERNAME_MODS: {
710+
puts("{}");
711+
break;
712+
}
593713
}
594714
}
595715
}

src/datum_conf.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@
4646
#include <jansson.h>
4747

4848
enum datum_conf_vartype {
49+
// NOTE: Keep in sync with datum_conf_var_type_text
4950
DATUM_CONF_BOOL,
5051
DATUM_CONF_INT,
5152
DATUM_CONF_STRING,
5253
DATUM_CONF_STRING_ARRAY,
54+
DATUM_CONF_USERNAME_MODS,
5355
};
5456

5557
typedef struct {
@@ -76,6 +78,23 @@ typedef struct {
7678
const T_DATUM_CONFIG_ITEM *datum_config_get_option_info(const char *category, size_t category_len, const char *name, size_t name_len);
7779
const T_DATUM_CONFIG_ITEM *datum_config_get_option_info2(const char *category, const char *name);
7880

81+
struct datum_addr_range {
82+
char *addr;
83+
size_t addr_len;
84+
uint16_t max;
85+
};
86+
87+
struct datum_username_mod {
88+
size_t sz;
89+
char *modname;
90+
size_t modname_len;
91+
struct datum_addr_range ranges[];
92+
};
93+
94+
int datum_config_parse_username_mods(struct datum_username_mod **umods_p, json_t *item, bool log_errors);
95+
struct datum_username_mod *datum_username_mods_next(struct datum_username_mod *prev_umod);
96+
struct datum_username_mod *datum_username_mods_find(struct datum_username_mod *umod, const char *modname, size_t modname_len);
97+
7998
// Globally accessable config options
8099
typedef struct {
81100
char bitcoind_rpcuserpass[256];
@@ -103,6 +122,8 @@ typedef struct {
103122
int stratum_v1_idle_timeout_no_share;
104123
int stratum_v1_idle_timeout_max_last_work;
105124

125+
void *stratum_username_mod;
126+
106127
char mining_pool_address[256];
107128
char mining_coinbase_tag_primary[64];
108129
char mining_coinbase_tag_secondary[64];

0 commit comments

Comments
 (0)