Browse Source

Merge branch 'pxy_diff' into bfgminer

Luke Dashjr 11 years ago
parent
commit
da93b73090
10 changed files with 200 additions and 29 deletions
  1. 19 13
      driver-getwork.c
  2. 27 0
      driver-proxy.c
  3. 15 0
      driver-proxy.h
  4. 119 12
      driver-stratum.c
  5. 1 3
      miner.c
  6. 2 0
      miner.h
  7. 10 0
      util.c
  8. 3 0
      util.h
  9. 2 1
      work2d.c
  10. 2 0
      work2d.h

+ 19 - 13
driver-getwork.c

@@ -78,7 +78,7 @@ int handle_getwork(struct MHD_Connection *conn, bytes_t *upbuf)
 	json_error_t jerr;
 	json_error_t jerr;
 	struct work *work;
 	struct work *work;
 	char *reply;
 	char *reply;
-	const char *hashesdone = NULL;
+	long long hashes_done = -1;
 	int ret;
 	int ret;
 	
 	
 	if (bytes_len(upbuf))
 	if (bytes_len(upbuf))
@@ -123,7 +123,11 @@ int handle_getwork(struct MHD_Connection *conn, bytes_t *upbuf)
 	cgpu = client->cgpu;
 	cgpu = client->cgpu;
 	thr = cgpu->thr[0];
 	thr = cgpu->thr[0];
 	
 	
-	hashesdone = MHD_lookup_connection_value(conn, MHD_HEADER_KIND, "X-Hashes-Done");
+	{
+		const char * const hashesdone = MHD_lookup_connection_value(conn, MHD_HEADER_KIND, "X-Hashes-Done");
+		if (hashesdone)
+			hashes_done = strtoll(hashesdone, NULL, 0);
+	}
 	
 	
 	if (submit)
 	if (submit)
 	{
 	{
@@ -150,13 +154,8 @@ int handle_getwork(struct MHD_Connection *conn, bytes_t *upbuf)
 			else
 			else
 				rejreason = NULL;
 				rejreason = NULL;
 			
 			
-			if (!hashesdone)
-			{
-				if (opt_scrypt)
-					hashesdone = "0x10000";
-				else
-					hashesdone = "0x100000000";
-			}
+			if (hashes_done == -1)
+				hashes_done = (double)0x100000000 * work->nonce_diff;
 		}
 		}
 		
 		
 		reply = malloc(36 + idstr_sz);
 		reply = malloc(36 + idstr_sz);
@@ -186,8 +185,16 @@ int handle_getwork(struct MHD_Connection *conn, bytes_t *upbuf)
 		size_t replysz = 590 + idstr_sz;
 		size_t replysz = 590 + idstr_sz;
 		
 		
 		work = get_work(thr);
 		work = get_work(thr);
+		work->nonce_diff = client->desired_share_pdiff;
+		if (work->nonce_diff > work->work_difficulty)
+			work->nonce_diff = work->work_difficulty;
+		
 		reply = malloc(replysz);
 		reply = malloc(replysz);
-		memcpy(reply, "{\"error\":null,\"result\":{\"target\":\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000\",\"data\":\"", 108);
+		uint8_t target[0x20];
+		set_target_to_pdiff(target, work->nonce_diff);
+		memcpy(reply, "{\"error\":null,\"result\":{\"target\":\"", 34);
+		bin2hex(&reply[34], target, sizeof(target));
+		memcpy(&reply[98], "\",\"data\":\"", 10);
 		bin2hex(&reply[108], work->data, 128);
 		bin2hex(&reply[108], work->data, 128);
 		memcpy(&reply[364], "\",\"midstate\":\"", 14);
 		memcpy(&reply[364], "\",\"midstate\":\"", 14);
 		bin2hex(&reply[378], work->midstate, 32);
 		bin2hex(&reply[378], work->midstate, 32);
@@ -196,7 +203,6 @@ int handle_getwork(struct MHD_Connection *conn, bytes_t *upbuf)
 		memcpy(&reply[589 + idstr_sz], "}", 1);
 		memcpy(&reply[589 + idstr_sz], "}", 1);
 		if (opt_scrypt)
 		if (opt_scrypt)
 		{
 		{
-			memset(&reply[90], 'f', 4);
 			replysz += 21;
 			replysz += 21;
 			reply = realloc(reply, replysz);
 			reply = realloc(reply, replysz);
 			memmove(&reply[443 + 21], &reply[443], replysz - (443 + 21));
 			memmove(&reply[443 + 21], &reply[443], replysz - (443 + 21));
@@ -214,8 +220,8 @@ int handle_getwork(struct MHD_Connection *conn, bytes_t *upbuf)
 	}
 	}
 	
 	
 out:
 out:
-	if (hashesdone)
-		hashes_done2(thr, strtoll(hashesdone, NULL, 0), NULL);
+	if (hashes_done != -1)
+		hashes_done2(thr, hashes_done, NULL);
 	
 	
 	free(idstr);
 	free(idstr);
 	if (json)
 	if (json)

+ 27 - 0
driver-proxy.c

@@ -21,6 +21,7 @@
 #include "util.h"
 #include "util.h"
 
 
 BFG_REGISTER_DRIVER(proxy_drv)
 BFG_REGISTER_DRIVER(proxy_drv)
+static const struct bfg_set_device_definition proxy_set_device_funcs[];
 
 
 static
 static
 struct proxy_client *proxy_clients;
 struct proxy_client *proxy_clients;
@@ -94,6 +95,7 @@ struct proxy_client *proxy_find_or_create_client(const char *username)
 		client = malloc(sizeof(*client));
 		client = malloc(sizeof(*client));
 		*cgpu = (struct cgpu_info){
 		*cgpu = (struct cgpu_info){
 			.drv = &proxy_drv,
 			.drv = &proxy_drv,
+			.set_device_funcs = proxy_set_device_funcs,
 			.threads = 0,
 			.threads = 0,
 			.device_data = client,
 			.device_data = client,
 			.device_path = user,
 			.device_path = user,
@@ -110,6 +112,7 @@ struct proxy_client *proxy_find_or_create_client(const char *username)
 		*client = (struct proxy_client){
 		*client = (struct proxy_client){
 			.username = user,
 			.username = user,
 			.cgpu = cgpu,
 			.cgpu = cgpu,
+			.desired_share_pdiff = opt_scrypt ? (1./0x10000) : 1.,
 		};
 		};
 		
 		
 		b = HASH_COUNT(proxy_clients);
 		b = HASH_COUNT(proxy_clients);
@@ -118,6 +121,8 @@ struct proxy_client *proxy_find_or_create_client(const char *username)
 		
 		
 		if (!b)
 		if (!b)
 			proxy_first_client(cgpu);
 			proxy_first_client(cgpu);
+		
+		cgpu_set_defaults(cgpu);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -128,6 +133,23 @@ struct proxy_client *proxy_find_or_create_client(const char *username)
 	return client;
 	return client;
 }
 }
 
 
+static
+const char *proxy_set_diff(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const success)
+{
+	struct proxy_client * const client = proc->device_data;
+	const double nv = atof(newvalue);
+	if (nv <= 0)
+		return "Invalid difficulty";
+	
+	client->desired_share_pdiff = nv;
+	
+#ifdef USE_LIBEVENT
+	stratumsrv_client_changed_diff(client);
+#endif
+	
+	return NULL;
+}
+
 #ifdef HAVE_CURSES
 #ifdef HAVE_CURSES
 static
 static
 void proxy_wlogprint_status(struct cgpu_info *cgpu)
 void proxy_wlogprint_status(struct cgpu_info *cgpu)
@@ -137,6 +159,11 @@ void proxy_wlogprint_status(struct cgpu_info *cgpu)
 }
 }
 #endif
 #endif
 
 
+static const struct bfg_set_device_definition proxy_set_device_funcs[] = {
+	{"diff", proxy_set_diff, "desired share difficulty for clients"},
+	{NULL},
+};
+
 struct device_drv proxy_drv = {
 struct device_drv proxy_drv = {
 	.dname = "proxy",
 	.dname = "proxy",
 	.name = "PXY",
 	.name = "PXY",

+ 15 - 0
driver-proxy.h

@@ -5,15 +5,30 @@
 
 
 #include "miner.h"
 #include "miner.h"
 
 
+#ifdef USE_LIBEVENT
+struct stratumsrv_conn_userlist;
+#endif
+
+extern struct device_drv proxy_drv;
+
 struct proxy_client {
 struct proxy_client {
 	char *username;
 	char *username;
 	struct cgpu_info *cgpu;
 	struct cgpu_info *cgpu;
 	struct work *work;
 	struct work *work;
 	struct timeval tv_hashes_done;
 	struct timeval tv_hashes_done;
+	float desired_share_pdiff;
+	
+#ifdef USE_LIBEVENT
+	struct stratumsrv_conn_userlist *stratumsrv_connlist;
+#endif
 	
 	
 	UT_hash_handle hh;
 	UT_hash_handle hh;
 };
 };
 
 
 extern struct proxy_client *proxy_find_or_create_client(const char *user);
 extern struct proxy_client *proxy_find_or_create_client(const char *user);
 
 
+#ifdef USE_LIBEVENT
+extern void stratumsrv_client_changed_diff(struct proxy_client *);
+#endif
+
 #endif
 #endif

+ 119 - 12
driver-stratum.c

@@ -36,6 +36,7 @@
 #define _ssm_client_xnonce2sz  work2d_xnonce2sz
 #define _ssm_client_xnonce2sz  work2d_xnonce2sz
 static char *_ssm_notify;
 static char *_ssm_notify;
 static int _ssm_notify_sz;
 static int _ssm_notify_sz;
+static struct stratumsrv_job *_ssm_last_ssj;
 static struct event *ev_notify;
 static struct event *ev_notify;
 static notifier_t _ssm_update_notifier;
 static notifier_t _ssm_update_notifier;
 
 
@@ -44,6 +45,7 @@ struct stratumsrv_job {
 	
 	
 	struct timeval tv_prepared;
 	struct timeval tv_prepared;
 	struct stratum_work swork;
 	struct stratum_work swork;
+	float job_pdiff[WORK2D_MAX_DIVISIONS+1];
 	
 	
 	UT_hash_handle hh;
 	UT_hash_handle hh;
 };
 };
@@ -56,17 +58,39 @@ static struct event_base *_smm_evbase;
 static bool _smm_running;
 static bool _smm_running;
 static struct evconnlistener *_smm_listener;
 static struct evconnlistener *_smm_listener;
 
 
+struct stratumsrv_conn_userlist {
+	struct proxy_client *client;
+	struct stratumsrv_conn *conn;
+	struct stratumsrv_conn_userlist *client_next;
+	struct stratumsrv_conn_userlist *next;
+};
+
 struct stratumsrv_conn {
 struct stratumsrv_conn {
 	struct bufferevent *bev;
 	struct bufferevent *bev;
 	uint32_t xnonce1_le;
 	uint32_t xnonce1_le;
 	struct timeval tv_hashes_done;
 	struct timeval tv_hashes_done;
 	bool hashes_done_ext;
 	bool hashes_done_ext;
+	float current_share_pdiff;
+	float desired_share_pdiff;
+	struct stratumsrv_conn_userlist *authorised_users;
 	
 	
 	struct stratumsrv_conn *next;
 	struct stratumsrv_conn *next;
 };
 };
 
 
 static struct stratumsrv_conn *_ssm_connections;
 static struct stratumsrv_conn *_ssm_connections;
 
 
+static
+void stratumsrv_send_set_difficulty(struct stratumsrv_conn * const conn, const float share_pdiff)
+{
+	struct bufferevent * const bev = conn->bev;
+	char buf[0x100];
+	const double bdiff = pdiff_to_bdiff(share_pdiff);
+	conn->current_share_pdiff = share_pdiff;
+	const int prec = double_find_precision(bdiff, 10.);
+	const size_t bufsz = snprintf(buf, sizeof(buf), "{\"params\":[%.*f],\"id\":null,\"method\":\"mining.set_difficulty\"}\n", prec, bdiff);
+	bufferevent_write(bev, buf, bufsz);
+}
+
 #define _ssm_gen_dummy_work work2d_gen_dummy_work
 #define _ssm_gen_dummy_work work2d_gen_dummy_work
 
 
 static
 static
@@ -135,17 +159,52 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
 	assert(_ssm_notify_sz <= bufsz);
 	assert(_ssm_notify_sz <= bufsz);
 	free(_ssm_notify);
 	free(_ssm_notify);
 	_ssm_notify = buf;
 	_ssm_notify = buf;
+	_ssm_last_ssj = ssj;
 	
 	
+	float pdiff = target_diff(ssj->swork.target);
 	LL_FOREACH(_ssm_connections, conn)
 	LL_FOREACH(_ssm_connections, conn)
 	{
 	{
 		if (unlikely(!conn->xnonce1_le))
 		if (unlikely(!conn->xnonce1_le))
 			continue;
 			continue;
+		float conn_pdiff = conn->desired_share_pdiff;
+		if (pdiff < conn_pdiff)
+			conn_pdiff = pdiff;
+		ssj->job_pdiff[conn->xnonce1_le] = conn_pdiff;
+		if (conn_pdiff != conn->current_share_pdiff)
+			stratumsrv_send_set_difficulty(conn, conn_pdiff);
 		bufferevent_write(conn->bev, _ssm_notify, _ssm_notify_sz);
 		bufferevent_write(conn->bev, _ssm_notify, _ssm_notify_sz);
 	}
 	}
 	
 	
 	return true;
 	return true;
 }
 }
 
 
+void stratumsrv_client_changed_diff(struct proxy_client * const client)
+{
+	int connections_affected = 0, connections_changed = 0;
+	struct stratumsrv_conn_userlist *ule, *ule2;
+	LL_FOREACH(client->stratumsrv_connlist, ule)
+	{
+		struct stratumsrv_conn * const conn = ule->conn;
+		
+		++connections_affected;
+		
+		float desired_share_pdiff = client->desired_share_pdiff;
+		LL_FOREACH(conn->authorised_users, ule2)
+		{
+			struct proxy_client * const other_client = ule2->client;
+			if (other_client->desired_share_pdiff < desired_share_pdiff)
+				desired_share_pdiff = other_client->desired_share_pdiff;
+		}
+		if (conn->desired_share_pdiff != desired_share_pdiff)
+		{
+			conn->desired_share_pdiff = desired_share_pdiff;
+			++connections_changed;
+		}
+	}
+	if (connections_affected)
+		applog(LOG_DEBUG, "Proxy-share difficulty change for user '%s' affected %d connections (%d changed difficulty)", client->username, connections_affected, connections_changed);
+}
+
 static
 static
 void _ssj_free(struct stratumsrv_job * const ssj)
 void _ssj_free(struct stratumsrv_job * const ssj)
 {
 {
@@ -203,6 +262,7 @@ void stratumsrv_boot_all_subscribed(const char * const msg)
 	
 	
 	free(_ssm_notify);
 	free(_ssm_notify);
 	_ssm_notify = NULL;
 	_ssm_notify = NULL;
+	_ssm_last_ssj = NULL;
 	
 	
 	// Boot all connections
 	// Boot all connections
 	LL_FOREACH_SAFE(_ssm_connections, conn, tmp_conn)
 	LL_FOREACH_SAFE(_ssm_connections, conn, tmp_conn)
@@ -316,8 +376,9 @@ void _stratumsrv_success(struct bufferevent * const bev, const char * const idst
 }
 }
 
 
 static
 static
-void stratumsrv_mining_subscribe(struct bufferevent *bev, json_t *params, const char *idstr, uint32_t *xnonce1_p)
+void stratumsrv_mining_subscribe(struct bufferevent * const bev, json_t * const params, const char * const idstr, struct stratumsrv_conn * const conn)
 {
 {
+	uint32_t * const xnonce1_p = &conn->xnonce1_le;
 	char buf[90 + strlen(idstr) + (_ssm_client_octets * 2 * 2) + 0x10];
 	char buf[90 + strlen(idstr) + (_ssm_client_octets * 2 * 2) + 0x10];
 	char xnonce1x[(_ssm_client_octets * 2) + 1];
 	char xnonce1x[(_ssm_client_octets * 2) + 1];
 	int bufsz;
 	int bufsz;
@@ -339,23 +400,34 @@ void stratumsrv_mining_subscribe(struct bufferevent *bev, json_t *params, const
 	bin2hex(xnonce1x, xnonce1_p, _ssm_client_octets);
 	bin2hex(xnonce1x, xnonce1_p, _ssm_client_octets);
 	bufsz = sprintf(buf, "{\"id\":%s,\"result\":[[[\"mining.set_difficulty\",\"x\"],[\"mining.notify\",\"%s\"]],\"%s\",%d],\"error\":null}\n", idstr, xnonce1x, xnonce1x, _ssm_client_xnonce2sz);
 	bufsz = sprintf(buf, "{\"id\":%s,\"result\":[[[\"mining.set_difficulty\",\"x\"],[\"mining.notify\",\"%s\"]],\"%s\",%d],\"error\":null}\n", idstr, xnonce1x, xnonce1x, _ssm_client_xnonce2sz);
 	bufferevent_write(bev, buf, bufsz);
 	bufferevent_write(bev, buf, bufsz);
-	bufferevent_write(bev, "{\"params\":[", 11);
-	if (opt_scrypt)
-		bufferevent_write(bev, "0.000015258556232", 17);
-	else
-		bufferevent_write(bev, "0.9999847412109375", 18);
-	bufferevent_write(bev, "],\"id\":null,\"method\":\"mining.set_difficulty\"}\n", 46);
+	
+	float pdiff = target_diff(_ssm_last_ssj->swork.target);
+	if (pdiff > conn->desired_share_pdiff)
+		pdiff = conn->desired_share_pdiff;
+	_ssm_last_ssj->job_pdiff[*xnonce1_p] = pdiff;
+	stratumsrv_send_set_difficulty(conn, pdiff);
 	bufferevent_write(bev, _ssm_notify, _ssm_notify_sz);
 	bufferevent_write(bev, _ssm_notify, _ssm_notify_sz);
 }
 }
 
 
 static
 static
-void stratumsrv_mining_authorize(struct bufferevent *bev, json_t *params, const char *idstr, uint32_t *xnonce1_p)
+void stratumsrv_mining_authorize(struct bufferevent * const bev, json_t * const params, const char * const idstr, struct stratumsrv_conn * const conn)
 {
 {
 	struct proxy_client * const client = stratumsrv_find_or_create_client(__json_array_string(params, 0));
 	struct proxy_client * const client = stratumsrv_find_or_create_client(__json_array_string(params, 0));
 	
 	
 	if (unlikely(!client))
 	if (unlikely(!client))
 		return_stratumsrv_failure(20, "Failed creating new cgpu");
 		return_stratumsrv_failure(20, "Failed creating new cgpu");
 	
 	
+	if ((!conn->authorised_users) || client->desired_share_pdiff < conn->desired_share_pdiff)
+		conn->desired_share_pdiff = client->desired_share_pdiff;
+	
+	struct stratumsrv_conn_userlist *ule = malloc(sizeof(*ule));
+	*ule = (struct stratumsrv_conn_userlist){
+		.client = client,
+		.conn = conn,
+	};
+	LL_PREPEND(conn->authorised_users, ule);
+	LL_PREPEND2(client->stratumsrv_connlist, ule, client_next);
+	
 	_stratumsrv_success(bev, idstr);
 	_stratumsrv_success(bev, idstr);
 }
 }
 
 
@@ -373,7 +445,6 @@ void stratumsrv_mining_submit(struct bufferevent *bev, json_t *params, const cha
 	const char * const nonce = __json_array_string(params, 4);
 	const char * const nonce = __json_array_string(params, 4);
 	uint8_t xnonce2[work2d_xnonce2sz];
 	uint8_t xnonce2[work2d_xnonce2sz];
 	uint32_t ntime_n, nonce_n;
 	uint32_t ntime_n, nonce_n;
-	const float nonce_diff = opt_scrypt ? (1./0x10000) : 1.;
 	bool is_stale;
 	bool is_stale;
 	
 	
 	if (unlikely(!client))
 	if (unlikely(!client))
@@ -395,6 +466,13 @@ void stratumsrv_mining_submit(struct bufferevent *bev, json_t *params, const cha
 	if (!ssj)
 	if (!ssj)
 		return_stratumsrv_failure(21, "Job not found");
 		return_stratumsrv_failure(21, "Job not found");
 	
 	
+	float nonce_diff = ssj->job_pdiff[*xnonce1_p];
+	if (unlikely(nonce_diff <= 0))
+	{
+		applog(LOG_WARNING, "Unknown share difficulty for SSM job %s", ssj->my_job_id);
+		nonce_diff = conn->current_share_pdiff;
+	}
+	
 	hex2bin(xnonce2, extranonce2, work2d_xnonce2sz);
 	hex2bin(xnonce2, extranonce2, work2d_xnonce2sz);
 	
 	
 	// Submit nonce
 	// Submit nonce
@@ -416,7 +494,7 @@ void stratumsrv_mining_submit(struct bufferevent *bev, json_t *params, const cha
 		timer_set_now(&tv_now);
 		timer_set_now(&tv_now);
 		timersub(&tv_now, &conn->tv_hashes_done, &tv_delta);
 		timersub(&tv_now, &conn->tv_hashes_done, &tv_delta);
 		conn->tv_hashes_done = tv_now;
 		conn->tv_hashes_done = tv_now;
-		const uint64_t hashes = opt_scrypt ? 0x10000 : 0x100000000;
+		const uint64_t hashes = (float)0x100000000 * nonce_diff;
 		hashes_done(thr, hashes, &tv_delta, NULL);
 		hashes_done(thr, hashes, &tv_delta, NULL);
 	}
 	}
 }
 }
@@ -493,10 +571,10 @@ errout:
 		stratumsrv_mining_hashes_done(bev, params, idstr, conn);
 		stratumsrv_mining_hashes_done(bev, params, idstr, conn);
 	else
 	else
 	if (!strcasecmp(method, "mining.authorize"))
 	if (!strcasecmp(method, "mining.authorize"))
-		stratumsrv_mining_authorize(bev, params, idstr, &conn->xnonce1_le);
+		stratumsrv_mining_authorize(bev, params, idstr, conn);
 	else
 	else
 	if (!strcasecmp(method, "mining.subscribe"))
 	if (!strcasecmp(method, "mining.subscribe"))
-		stratumsrv_mining_subscribe(bev, params, idstr, &conn->xnonce1_le);
+		stratumsrv_mining_subscribe(bev, params, idstr, conn);
 	else
 	else
 		_stratumsrv_failure(bev, idstr, -3, "Method not supported");
 		_stratumsrv_failure(bev, idstr, -3, "Method not supported");
 	
 	
@@ -509,10 +587,18 @@ static
 void stratumsrv_client_close(struct stratumsrv_conn * const conn)
 void stratumsrv_client_close(struct stratumsrv_conn * const conn)
 {
 {
 	struct bufferevent * const bev = conn->bev;
 	struct bufferevent * const bev = conn->bev;
+	struct stratumsrv_conn_userlist *ule, *uletmp;
 	
 	
 	bufferevent_free(bev);
 	bufferevent_free(bev);
 	LL_DELETE(_ssm_connections, conn);
 	LL_DELETE(_ssm_connections, conn);
 	release_work2d_(conn->xnonce1_le);
 	release_work2d_(conn->xnonce1_le);
+	LL_FOREACH_SAFE(conn->authorised_users, ule, uletmp)
+	{
+		struct proxy_client * const client = ule->client;
+		LL_DELETE(conn->authorised_users, ule);
+		LL_DELETE(client->stratumsrv_connlist, ule);
+		free(ule);
+	}
 	free(conn);
 	free(conn);
 }
 }
 
 
@@ -548,6 +634,25 @@ void stratumsrv_event(struct bufferevent *bev, short events, void *p)
 	}
 	}
 }
 }
 
 
+static
+const char *stratumsrv_init_diff(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const success)
+{
+	struct stratumsrv_conn * const conn = proc->device_data;
+	
+	const double nv = atof(newvalue);
+	if (nv <= 0)
+		return "Invalid difficulty";
+	
+	conn->desired_share_pdiff = nv;
+	
+	return NULL;
+}
+
+static const struct bfg_set_device_definition stratumsrv_set_device_funcs_newconnect[] = {
+	{"diff", stratumsrv_init_diff, NULL},
+	{NULL},
+};
+
 static
 static
 void stratumlistener(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len, void *p)
 void stratumlistener(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len, void *p)
 {
 {
@@ -557,7 +662,9 @@ void stratumlistener(struct evconnlistener *listener, evutil_socket_t sock, stru
 	conn = malloc(sizeof(*conn));
 	conn = malloc(sizeof(*conn));
 	*conn = (struct stratumsrv_conn){
 	*conn = (struct stratumsrv_conn){
 		.bev = bev,
 		.bev = bev,
+		.desired_share_pdiff = opt_scrypt ? (1./0x10000) : 1.,
 	};
 	};
+	drv_set_defaults(&proxy_drv, stratumsrv_set_device_funcs_newconnect, conn, NULL, NULL, 1);
 	LL_PREPEND(_ssm_connections, conn);
 	LL_PREPEND(_ssm_connections, conn);
 	bufferevent_setcb(bev, stratumsrv_read, NULL, stratumsrv_event, conn);
 	bufferevent_setcb(bev, stratumsrv_read, NULL, stratumsrv_event, conn);
 	bufferevent_enable(bev, EV_READ | EV_WRITE);
 	bufferevent_enable(bev, EV_READ | EV_WRITE);

+ 1 - 3
miner.c

@@ -2918,8 +2918,6 @@ void refresh_bitcoind_address(const bool fresh)
 }
 }
 #endif
 #endif
 
 
-static double target_diff(const unsigned char *);
-
 #define GBT_XNONCESZ (sizeof(uint32_t))
 #define GBT_XNONCESZ (sizeof(uint32_t))
 
 
 #if BLKMAKER_VERSION > 4
 #if BLKMAKER_VERSION > 4
@@ -4917,7 +4915,7 @@ out:
 
 
 static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249215.0;
 static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249215.0;
 
 
-static double target_diff(const unsigned char *target)
+double target_diff(const unsigned char *target)
 {
 {
 	double targ = 0;
 	double targ = 0;
 	signed int i;
 	signed int i;

+ 2 - 0
miner.h

@@ -1057,6 +1057,8 @@ extern bool stale_work_future(struct work *, bool share, unsigned long ustime);
 extern void set_target_to_pdiff(void *dest_target, double pdiff);
 extern void set_target_to_pdiff(void *dest_target, double pdiff);
 #define bdiff_to_pdiff(n) (n * 1.0000152587)
 #define bdiff_to_pdiff(n) (n * 1.0000152587)
 extern void set_target_to_bdiff(void *dest_target, double bdiff);
 extern void set_target_to_bdiff(void *dest_target, double bdiff);
+#define pdiff_to_bdiff(n) (n * 0.9999847412109375)
+extern double target_diff(const unsigned char *target);
 
 
 extern void kill_work(void);
 extern void kill_work(void);
 extern void app_restart(void);
 extern void app_restart(void);

+ 10 - 0
util.c

@@ -13,6 +13,7 @@
 
 
 #include "config.h"
 #include "config.h"
 
 
+#include <math.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -1421,6 +1422,15 @@ double tdiff(struct timeval *end, struct timeval *start)
 }
 }
 
 
 
 
+int double_find_precision(double f, const double base)
+{
+	int rv = 0;
+	for ( ; floor(f) != f; ++rv)
+		f *= base;
+	return rv;
+}
+
+
 int utf8_len(const uint8_t b)
 int utf8_len(const uint8_t b)
 {
 {
 	if (!(b & 0x80))
 	if (!(b & 0x80))

+ 3 - 0
util.h

@@ -721,6 +721,9 @@ struct timeval *select_timeout(struct timeval *tvp_timeout, struct timeval *tvp_
 #define _SNP(...)  _SNP2(snprintf, __VA_ARGS__)
 #define _SNP(...)  _SNP2(snprintf, __VA_ARGS__)
 
 
 
 
+extern int double_find_precision(double, double base);
+
+
 #define REPLACEMENT_CHAR (0xFFFD)
 #define REPLACEMENT_CHAR (0xFFFD)
 #define U8_DEGREE "\xc2\xb0"
 #define U8_DEGREE "\xc2\xb0"
 #define U8_MICRO  "\xc2\xb5"
 #define U8_MICRO  "\xc2\xb5"

+ 2 - 1
work2d.c

@@ -15,8 +15,9 @@
 
 
 #include "miner.h"
 #include "miner.h"
 #include "util.h"
 #include "util.h"
+#include "work2d.h"
 
 
-#define MAX_DIVISIONS 255
+#define MAX_DIVISIONS  WORK2D_MAX_DIVISIONS
 
 
 static bool work2d_reserved[MAX_DIVISIONS + 1] = { true };
 static bool work2d_reserved[MAX_DIVISIONS + 1] = { true };
 int work2d_xnonce1sz;
 int work2d_xnonce1sz;

+ 2 - 0
work2d.h

@@ -4,6 +4,8 @@
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
 
 
+#define WORK2D_MAX_DIVISIONS  255
+
 extern int work2d_xnonce1sz;
 extern int work2d_xnonce1sz;
 extern int work2d_xnonce2sz;
 extern int work2d_xnonce2sz;