|  |  | @ -19,6 +19,7 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "bitcoin.h" |  |  |  | #include "bitcoin.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "uthash.h" |  |  |  | #include "uthash.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "utlist.h" |  |  |  | #include "utlist.h" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include "sha2.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static const char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"; |  |  |  | static const char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -45,6 +46,7 @@ struct workbase { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	uint32_t curtime; |  |  |  | 	uint32_t curtime; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	char prevhash[68]; |  |  |  | 	char prevhash[68]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	char ntime[12]; |  |  |  | 	char ntime[12]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	uint32_t ntime32; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	char bbversion[12]; |  |  |  | 	char bbversion[12]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	char nbit[12]; |  |  |  | 	char nbit[12]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	uint64_t coinbasevalue; |  |  |  | 	uint64_t coinbasevalue; | 
			
		
	
	
		
		
			
				
					|  |  | @ -252,8 +254,8 @@ static void generate_coinbase(ckpool_t *ckp, workbase_t *wb) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	LOGDEBUG("Coinb2: %s", wb->coinb2); |  |  |  | 	LOGDEBUG("Coinb2: %s", wb->coinb2); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/* Coinbase 2 complete */ |  |  |  | 	/* Coinbase 2 complete */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	snprintf(header, 225, "%08x%s%s%s%s%s%s", |  |  |  | 	snprintf(header, 225, "%s%s%s%s%s%s%s", | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		 wb->version, wb->prevhash, |  |  |  | 		 wb->bbversion, wb->prevhash, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		 "0000000000000000000000000000000000000000000000000000000000000000", |  |  |  | 		 "0000000000000000000000000000000000000000000000000000000000000000", | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 wb->ntime, wb->nbit, |  |  |  | 		 wb->ntime, wb->nbit, | 
			
		
	
		
		
			
				
					
					|  |  |  | 		 "00000000", /* nonce */ |  |  |  | 		 "00000000", /* nonce */ | 
			
		
	
	
		
		
			
				
					|  |  | @ -302,6 +304,7 @@ static void update_base(ckpool_t *ckp) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	json_uintcpy(&wb->curtime, val, "curtime"); |  |  |  | 	json_uintcpy(&wb->curtime, val, "curtime"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	json_strcpy(wb->prevhash, val, "prevhash"); |  |  |  | 	json_strcpy(wb->prevhash, val, "prevhash"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	json_strcpy(wb->ntime, val, "ntime"); |  |  |  | 	json_strcpy(wb->ntime, val, "ntime"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	sscanf(wb->ntime, "%x", &wb->ntime32); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	json_strcpy(wb->bbversion, val, "bbversion"); |  |  |  | 	json_strcpy(wb->bbversion, val, "bbversion"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	json_strcpy(wb->nbit, val, "nbit"); |  |  |  | 	json_strcpy(wb->nbit, val, "nbit"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	json_uint64cpy(&wb->coinbasevalue, val, "coinbasevalue"); |  |  |  | 	json_uint64cpy(&wb->coinbasevalue, val, "coinbasevalue"); | 
			
		
	
	
		
		
			
				
					|  |  | @ -728,15 +731,15 @@ static void add_submit_fail(stratum_instance_t *client, int diff) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	add_submit(client, diff); |  |  |  | 	add_submit(client, diff); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static double submit_diff(stratum_instance_t *client, workbase_t *wb, const char *nonce2, |  |  |  | static double submission_diff(stratum_instance_t *client, workbase_t *wb, const char *nonce2, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			  const char *ntime, const char *nonce) |  |  |  | 			      uint32_t ntime32, const char *nonce) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	uchar coinbase[256], swap[80], hash[32], hash1[32]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	unsigned char merkle_root[32], merkle_sha[64]; |  |  |  | 	unsigned char merkle_root[32], merkle_sha[64]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	uint32_t *data32, *swap32; |  |  |  | 	uint32_t *data32, *swap32, nonce32; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	uchar coinbase[256]; |  |  |  | 	char data[80], share[68]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	double ret = 0.0; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	int cblen = 0, i; |  |  |  | 	int cblen = 0, i; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	char data[112]; |  |  |  | 	double ret; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	memcpy(coinbase, wb->coinb1bin, wb->coinb1len); |  |  |  | 	memcpy(coinbase, wb->coinb1bin, wb->coinb1len); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	cblen += wb->coinb1len; |  |  |  | 	cblen += wb->coinb1len; | 
			
		
	
	
		
		
			
				
					|  |  | @ -758,9 +761,35 @@ static double submit_diff(stratum_instance_t *client, workbase_t *wb, const char | 
			
		
	
		
		
			
				
					
					|  |  |  | 	swap32 = (uint32_t *)merkle_root; |  |  |  | 	swap32 = (uint32_t *)merkle_root; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	flip_32(swap32, data32); |  |  |  | 	flip_32(swap32, data32); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	memcpy(data, wb->headerbin, 112); |  |  |  | 	/* Copy the cached header binary and insert the merkle root */ | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	memcpy(data, wb->headerbin, 80); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	memcpy(data + 36, merkle_root, 32); |  |  |  | 	memcpy(data + 36, merkle_root, 32); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/* Insert the nonce value into the data */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	sscanf(nonce, "%x", &nonce32); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	data32 = (uint32_t *)(data + 64 + 12); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	*data32 = htobe32(nonce32); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/* Insert the ntime value into the data */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	data32 = (uint32_t *)(data + 68); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	*data32 = htobe32(ntime32); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/* Hash the share */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	data32 = (uint32_t *)data; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	swap32 = (uint32_t *)swap; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	flip_80(swap32, data32); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	sha256(swap, 80, hash1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	sha256(hash1, 32, hash); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	data32 = (uint32_t *)hash1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	bswap_256(hash1, hash); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	__bin2hex(share, hash1, 32); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	ret = diff_from_target(hash); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	LOGINFO("Client %d share diff %.1f : %s", client->id, ret, share); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/* FIXME: Log share here */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return ret; |  |  |  | 	return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -768,10 +797,11 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, | 
			
		
	
		
		
			
				
					
					|  |  |  | 			    json_t *params_val, json_t **err_val) |  |  |  | 			    json_t *params_val, json_t **err_val) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	const char *user, *job_id, *nonce2, *ntime, *nonce; |  |  |  | 	const char *user, *job_id, *nonce2, *ntime, *nonce; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	uint32_t ntime32; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	bool ret = false; |  |  |  | 	bool ret = false; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	workbase_t *wb; |  |  |  | 	workbase_t *wb; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	double diff; |  |  |  | 	double sdiff; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	int id; |  |  |  | 	int diff, id; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (unlikely(!json_is_array(params_val))) { |  |  |  | 	if (unlikely(!json_is_array(params_val))) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		*err_val = json_string("params not an array"); |  |  |  | 		*err_val = json_string("params not an array"); | 
			
		
	
	
		
		
			
				
					|  |  | @ -810,7 +840,8 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, | 
			
		
	
		
		
			
				
					
					|  |  |  | 		*err_val = json_string("Worker mismatch"); |  |  |  | 		*err_val = json_string("Worker mismatch"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		goto out; |  |  |  | 		goto out; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	sscanf(job_id, "%08x", &id); |  |  |  | 	sscanf(job_id, "%x", &id); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	sscanf(ntime, "%x", &ntime32); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ck_rlock(&workbase_lock); |  |  |  | 	ck_rlock(&workbase_lock); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	HASH_FIND_INT(workbases, &id, wb); |  |  |  | 	HASH_FIND_INT(workbases, &id, wb); | 
			
		
	
	
		
		
			
				
					|  |  | @ -826,23 +857,27 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, | 
			
		
	
		
		
			
				
					
					|  |  |  | 		*err_val = json_string("Invalid nonce2 length"); |  |  |  | 		*err_val = json_string("Invalid nonce2 length"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		goto out_unlock; |  |  |  | 		goto out_unlock; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	diff = submit_diff(client, wb, nonce2, ntime, nonce); |  |  |  | 	/* Ntime cannot be less, but allow forward ntime rolling up to max */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	ret = true; |  |  |  | 	if (ntime32 < wb->ntime32 || ntime32 > wb->ntime32 + 7000) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		json_object_set_nocheck(json_msg, "reject-reason", json_string("Ntime out of range")); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		goto out_unlock; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	sdiff = submission_diff(client, wb, nonce2, ntime32, nonce); | 
			
		
	
		
		
			
				
					
					|  |  |  | out_unlock: |  |  |  | out_unlock: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	ck_runlock(&workbase_lock); |  |  |  | 	ck_runlock(&workbase_lock); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | out: |  |  |  | 	if (id < client->diff_change_job_id) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	if (ret) { |  |  |  | 		diff = client->old_diff; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		int diff; |  |  |  | 	else | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 		diff = client->diff; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		if (id < client->diff_change_job_id) |  |  |  | 	if (sdiff >= diff) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			diff = client->old_diff; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		else |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			diff = client->diff; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		add_submit_success(client, diff); |  |  |  | 		add_submit_success(client, diff); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} else |  |  |  | 		ret = true; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		add_submit_fail(client, client->diff); |  |  |  | 	} else { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 		add_submit_fail(client, diff); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		json_object_set_nocheck(json_msg, "reject-reason", json_string("Above target")); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | out: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return json_boolean(ret); |  |  |  | 	return json_boolean(ret); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |