mirror of
https://github.com/LBRYFoundation/pool.git
synced 2025-08-23 17:37:25 +00:00
blake (SFR) and whirlpool (J) tested ok with a sha256d merkleroot So add a stratum setting to allow single sha256 merkle root... The shares are now valid on the pool side, but remains to find an old wallet to test... like Whirlcoin or blakecoin keccak not tested, could have the same problem about merkle/miners
669 lines
13 KiB
C++
669 lines
13 KiB
C++
|
|
#include "stratum.h"
|
|
#include <math.h>
|
|
#include <limits.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool json_get_bool(json_value *json, const char *name)
|
|
{
|
|
for(int i=0; i<json->u.object.length; i++)
|
|
{
|
|
if(!strcmp(json->u.object.values[i].name, name))
|
|
return json->u.object.values[i].value->u.boolean;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
json_int_t json_get_int(json_value *json, const char *name)
|
|
{
|
|
for(int i=0; i<json->u.object.length; i++)
|
|
{
|
|
if(!strcmp(json->u.object.values[i].name, name))
|
|
return json->u.object.values[i].value->u.integer;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
double json_get_double(json_value *json, const char *name)
|
|
{
|
|
for(int i=0; i<json->u.object.length; i++)
|
|
{
|
|
if(!strcmp(json->u.object.values[i].name, name))
|
|
return json->u.object.values[i].value->u.dbl;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char *json_get_string(json_value *json, const char *name)
|
|
{
|
|
for(int i=0; i<json->u.object.length; i++)
|
|
{
|
|
if(!strcmp(json->u.object.values[i].name, name))
|
|
return json->u.object.values[i].value->u.string.ptr;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
json_value *json_get_array(json_value *json, const char *name)
|
|
{
|
|
for(int i=0; i<json->u.object.length; i++)
|
|
{
|
|
// if(json->u.object.values[i].value->type == json_array && !strcmp(json->u.object.values[i].name, name))
|
|
if(!strcmp(json->u.object.values[i].name, name))
|
|
return json->u.object.values[i].value;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//json_value *json_get_array_from_array(json_value *json, const char *name)
|
|
//{
|
|
// for(int i=0; i<json->u.array.length; i++)
|
|
// {
|
|
// if(!strcmp(json->u.array.values[i].name, name))
|
|
// return json->u.array.values[i].value;
|
|
// }
|
|
//
|
|
// return NULL;
|
|
//}
|
|
|
|
json_value *json_get_object(json_value *json, const char *name)
|
|
{
|
|
for(int i=0; i<json->u.object.length; i++)
|
|
{
|
|
if(!strcmp(json->u.object.values[i].name, name))
|
|
return json->u.object.values[i].value;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
FILE *g_debuglog = NULL;
|
|
FILE *g_stratumlog = NULL;
|
|
FILE *g_clientlog = NULL;
|
|
|
|
void initlog(const char *algo)
|
|
{
|
|
char debugfile[1024];
|
|
|
|
sprintf(debugfile, "%s.log", algo);
|
|
g_debuglog = fopen(debugfile, "w");
|
|
|
|
g_stratumlog = fopen("stratum.log", "a");
|
|
g_clientlog = fopen("client.log", "a");
|
|
}
|
|
|
|
void clientlog(YAAMP_CLIENT *client, const char *format, ...)
|
|
{
|
|
char buffer[YAAMP_SMALLBUFSIZE];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsprintf(buffer, format, args);
|
|
va_end(args);
|
|
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
char buffer2[80];
|
|
|
|
time(&rawtime);
|
|
timeinfo = localtime(&rawtime);
|
|
|
|
strftime(buffer2, 80, "%Y/%m/%d %H:%M:%S", timeinfo);
|
|
|
|
char buffer3[YAAMP_SMALLBUFSIZE];
|
|
sprintf(buffer3, "%s [%s] %s, %s, %s\n", buffer2, client->sock->ip, client->username, g_current_algo->name, buffer);
|
|
|
|
printf("%s", buffer3);
|
|
if(g_debuglog)
|
|
{
|
|
fprintf(g_debuglog, "%s", buffer3);
|
|
fflush(g_debuglog);
|
|
}
|
|
|
|
if(g_clientlog)
|
|
{
|
|
fprintf(g_clientlog, "%s", buffer3);
|
|
fflush(g_clientlog);
|
|
}
|
|
}
|
|
|
|
void debuglog(const char *format, ...)
|
|
{
|
|
char buffer[YAAMP_SMALLBUFSIZE];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsprintf(buffer, format, args);
|
|
va_end(args);
|
|
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
char buffer2[80];
|
|
|
|
time(&rawtime);
|
|
timeinfo = localtime(&rawtime);
|
|
|
|
strftime(buffer2, 80, "%H:%M:%S", timeinfo);
|
|
printf("%s: %s", buffer2, buffer);
|
|
|
|
if(g_debuglog)
|
|
{
|
|
fprintf(g_debuglog, "%s: %s", buffer2, buffer);
|
|
fflush(g_debuglog);
|
|
}
|
|
}
|
|
|
|
void stratumlog(const char *format, ...)
|
|
{
|
|
char buffer[YAAMP_SMALLBUFSIZE];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsprintf(buffer, format, args);
|
|
va_end(args);
|
|
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
char buffer2[80];
|
|
|
|
time(&rawtime);
|
|
timeinfo = localtime(&rawtime);
|
|
|
|
strftime(buffer2, 80, "%H:%M:%S", timeinfo);
|
|
printf("%s: %s", buffer2, buffer);
|
|
|
|
if(g_debuglog)
|
|
{
|
|
fprintf(g_debuglog, "%s: %s", buffer2, buffer);
|
|
fflush(g_debuglog);
|
|
}
|
|
|
|
if(g_stratumlog)
|
|
{
|
|
fprintf(g_stratumlog, "%s: %s", buffer2, buffer);
|
|
fflush(g_stratumlog);
|
|
}
|
|
}
|
|
|
|
bool yaamp_error(char const *message)
|
|
{
|
|
debuglog("ERROR: %d %s\n", errno, message);
|
|
exit(1);
|
|
}
|
|
|
|
void yaamp_create_mutex(pthread_mutex_t *mutex)
|
|
{
|
|
pthread_mutexattr_t attr;
|
|
pthread_mutexattr_init(&attr);
|
|
|
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
|
pthread_mutex_init(mutex, &attr);
|
|
|
|
pthread_mutexattr_destroy(&attr);
|
|
}
|
|
|
|
const char *header_value(const char *data, const char *search, char *value)
|
|
{
|
|
value[0] = 0;
|
|
|
|
char *p = (char *)strstr(data, search);
|
|
if(!p) return value;
|
|
|
|
p += strlen(search);
|
|
while(*p == ' ' || *p == ':') p++;
|
|
|
|
char *p2 = (char *)strstr(p, "\r\n");
|
|
if(!p2)
|
|
{
|
|
strncpy(value, p, 1024);
|
|
return value;
|
|
}
|
|
|
|
strncpy(value, p, min(1024, p2 - p));
|
|
value[min(1023, p2 - p)] = 0;
|
|
|
|
return value;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const unsigned char g_base64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
|
void base64_encode(char *base64, const char *normal)
|
|
{
|
|
int cb = strlen((char *)normal);
|
|
while(cb >= 3)
|
|
{
|
|
unsigned char b0 = ((normal[0] >> 2) & 0x3F);
|
|
unsigned char b1 = ((normal[0] & 0x03) << 4) | ((normal[1] >> 4) & 0x0F);
|
|
unsigned char b2 = ((normal[1] & 0x0F) << 2) | ((normal[2] >> 6) & 0x03);
|
|
unsigned char b3 = ((normal[2] & 0x3F));
|
|
|
|
*base64++ = g_base64_tab[b0];
|
|
*base64++ = g_base64_tab[b1];
|
|
*base64++ = g_base64_tab[b2];
|
|
*base64++ = g_base64_tab[b3];
|
|
|
|
normal += 3;
|
|
cb -= 3;
|
|
}
|
|
|
|
if(cb == 1)
|
|
{
|
|
unsigned char b0 = ((normal[0] >> 2) & 0x3F);
|
|
unsigned char b1 = ((normal[0] & 0x03) << 4) | 0;
|
|
|
|
*base64++ = g_base64_tab[b0];
|
|
*base64++ = g_base64_tab[b1];
|
|
|
|
*base64++ = '=';
|
|
*base64++ = '=';
|
|
}
|
|
else if(cb == 2)
|
|
{
|
|
unsigned char b0 = ((normal[0] >> 2) & 0x3F);
|
|
unsigned char b1 = ((normal[0] & 0x03) << 4) | ((normal[1] >> 4) & 0x0F);
|
|
unsigned char b2 = ((normal[1] & 0x0F) << 2) | 0;
|
|
|
|
*base64++ = g_base64_tab[b0];
|
|
*base64++ = g_base64_tab[b1];
|
|
*base64++ = g_base64_tab[b2];
|
|
*base64++ = '=';
|
|
}
|
|
|
|
*base64 = 0;
|
|
}
|
|
|
|
void base64_decode(char *normal, const char *base64)
|
|
{
|
|
int i;
|
|
|
|
unsigned char decoding_tab[256];
|
|
memset(decoding_tab, 255, 256);
|
|
|
|
for(i = 0; i < 64; i++)
|
|
decoding_tab[g_base64_tab[i]] = i;
|
|
|
|
unsigned long current = 0;
|
|
int bit_filled = 0;
|
|
|
|
for(i = 0; base64[i]; i++)
|
|
{
|
|
if(base64[i] == 0x0A || base64[i] == 0x0D || base64[i] == 0x20 || base64[i] == 0x09)
|
|
continue;
|
|
|
|
if(base64[i] == '=')
|
|
break;
|
|
|
|
unsigned char digit = decoding_tab[base64[i]];
|
|
|
|
current <<= 6;
|
|
current |= digit;
|
|
bit_filled += 6;
|
|
|
|
if(bit_filled >= 8)
|
|
{
|
|
unsigned long b = (current >> (bit_filled - 8));
|
|
|
|
*normal++ = (unsigned char)(b & 0xFF);
|
|
bit_filled -= 8;
|
|
}
|
|
}
|
|
|
|
*normal = 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//const unsigned char g_base58_tab[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
//
|
|
//void base58_decode(const char *input, char *output)
|
|
//{
|
|
// int i;
|
|
//
|
|
// unsigned char decoding_tab[256];
|
|
// memset(decoding_tab, 255, 256);
|
|
//
|
|
// for(i = 0; i < 58; i++)
|
|
// decoding_tab[g_base58_tab[i]] = i;
|
|
//
|
|
// unsigned long current = 0;
|
|
// int bit_filled = 0;
|
|
//
|
|
// for(i = 0; base58[i]; i++)
|
|
// {
|
|
// if(base58[i] == 0x0A || base58[i] == 0x0D || base58[i] == 0x20 || base58[i] == 0x09)
|
|
// continue;
|
|
//
|
|
// if(base58[i] == '=')
|
|
// break;
|
|
//
|
|
// unsigned char digit = decoding_tab[base58[i]];
|
|
//
|
|
// current <<= 6;
|
|
// current |= digit;
|
|
// bit_filled += 6;
|
|
//
|
|
// if(bit_filled >= 8)
|
|
// {
|
|
// unsigned long b = (current >> (bit_filled - 8));
|
|
//
|
|
// *normal++ = (unsigned char)(b & 0xFF);
|
|
// bit_filled -= 8;
|
|
// }
|
|
// }
|
|
//
|
|
// *normal = 0;
|
|
//}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void hexlify(char *hex, const unsigned char *bin, int len)
|
|
{
|
|
hex[0] = 0;
|
|
for(int i=0; i < len; i++)
|
|
sprintf(hex+strlen(hex), "%02x", bin[i]);
|
|
}
|
|
|
|
unsigned char binvalue(const char v)
|
|
{
|
|
if(v >= '0' && v <= '9')
|
|
return v-'0';
|
|
|
|
if(v >= 'a' && v <= 'f')
|
|
return v-'a'+10;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void binlify(unsigned char *bin, const char *hex)
|
|
{
|
|
int len = strlen(hex);
|
|
for(int i=0; i<len/2; i++)
|
|
bin[i] = binvalue(hex[i*2])<<4 | binvalue(hex[i*2+1]);
|
|
}
|
|
|
|
void strprecatchar(char *buffer, char c)
|
|
{
|
|
char tmp[64];
|
|
sprintf(tmp, "%02x%s", c, buffer);
|
|
strcpy(buffer, tmp);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ser_number(int n, char *a)
|
|
{
|
|
unsigned char s[32];
|
|
memset(s, 0, 32);
|
|
memset(a, 0, 32);
|
|
|
|
s[0] = 1;
|
|
while(n > 127)
|
|
{
|
|
s[s[0]] = n % 256;
|
|
n /= 256;
|
|
s[0]++;
|
|
}
|
|
|
|
s[s[0]] = n;
|
|
a[0] = 0;
|
|
|
|
for(int i=0; i<=s[0]; i++)
|
|
{
|
|
char tmp[32];
|
|
sprintf(tmp, "%02x", s[i]);
|
|
strcat(a, tmp);
|
|
}
|
|
|
|
// printf("ser_number %d, %s\n", n, a);
|
|
}
|
|
|
|
void ser_string_be(const char *input, char *output, int len)
|
|
{
|
|
for(int i=0; i<len; i++)
|
|
for(int j=0; j<8; j+=2)
|
|
memcpy(output + i*8 + (6-j), input + i*8 + j, 2);
|
|
}
|
|
|
|
void ser_string_be2(const char *input, char *output, int len)
|
|
{
|
|
for(int i=0; i<len; i++)
|
|
memcpy(output + i*8, input + (len-i-1)*8, 8);
|
|
}
|
|
|
|
void string_be(const char *input, char *output)
|
|
{
|
|
int len = strlen(input)/2;
|
|
|
|
for(int i=0; i<len; i++)
|
|
memcpy(output + (len-i-1)*2, input + i*2, 2);
|
|
}
|
|
|
|
void string_be1(char *s)
|
|
{
|
|
char s2[1024];
|
|
strcpy(s2, s);
|
|
|
|
int len = strlen(s2)/2;
|
|
|
|
for(int i=0; i<len; i++)
|
|
memcpy(s + (len-i-1)*2, s2 + i*2, 2);
|
|
}
|
|
|
|
uint64_t diff_to_target(double difficulty)
|
|
{
|
|
if(!difficulty) return 0;
|
|
|
|
uint64_t t = 0x0000ffff00000000*g_current_algo->diff_multiplier/difficulty;
|
|
return t;
|
|
}
|
|
|
|
double target_to_diff(uint64_t target)
|
|
{
|
|
if(!target) return 0;
|
|
|
|
double d = (double)0x0000ffff00000000/target;
|
|
return d;
|
|
}
|
|
|
|
uint64_t decode_compact(const char *input)
|
|
{
|
|
uint64_t c = htoi64(input);
|
|
|
|
int nShift = (c >> 24) & 0xff;
|
|
double d = (double)0x0000ffff / (double)(c & 0x00ffffff);
|
|
|
|
while (nShift < 29)
|
|
{
|
|
d *= 256.0;
|
|
nShift++;
|
|
}
|
|
|
|
while (nShift > 29)
|
|
{
|
|
d /= 256.0;
|
|
nShift--;
|
|
}
|
|
|
|
uint64_t v = 0x0000ffff00000000/d;
|
|
// debuglog("decode_compact %s -> %f -> %016llx\n", input, d, v);
|
|
|
|
// int nbytes = (c >> 24) & 0xFF;
|
|
//
|
|
// nbytes -= 25;
|
|
// v = (c & 0xFFFFFF) << (8 * nbytes);
|
|
//
|
|
// debuglog("decode_compact %s -> %016llx\n", input, v);
|
|
return v;
|
|
}
|
|
|
|
//def uint256_from_compact(c):
|
|
// c = int(c)
|
|
// nbytes = (c >> 24) & 0xFF
|
|
// v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
|
|
// return v
|
|
|
|
uint64_t get_hash_difficulty(unsigned char *input)
|
|
{
|
|
unsigned char *p = (unsigned char *)input;
|
|
|
|
uint64_t v =
|
|
(uint64_t)p[29] << 56 |
|
|
(uint64_t)p[28] << 48 |
|
|
(uint64_t)p[27] << 40 |
|
|
(uint64_t)p[26] << 32 |
|
|
(uint64_t)p[25] << 24 |
|
|
(uint64_t)p[24] << 16 |
|
|
(uint64_t)p[23] << 8 |
|
|
(uint64_t)p[22] << 0;
|
|
|
|
// char toto[1024];
|
|
// hexlify(toto, input, 32);
|
|
// debuglog("hash diff %s %016llx\n", toto, v);
|
|
return v;
|
|
}
|
|
|
|
unsigned int htoi(const char *s)
|
|
{
|
|
unsigned int val = 0;
|
|
int x = 0;
|
|
|
|
if(s[x] == '0' && (s[x+1] == 'x' || s[x+1] == 'X'))
|
|
x += 2;
|
|
|
|
while(s[x])
|
|
{
|
|
if(val > UINT_MAX)
|
|
return 0;
|
|
|
|
else if(s[x] >= '0' && s[x] <='9')
|
|
val = val * 16 + s[x] - '0';
|
|
|
|
else if(s[x]>='A' && s[x] <='F')
|
|
val = val * 16 + s[x] - 'A' + 10;
|
|
|
|
else if(s[x]>='a' && s[x] <='f')
|
|
val = val * 16 + s[x] - 'a' + 10;
|
|
|
|
else
|
|
return 0;
|
|
|
|
x++;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
uint64_t htoi64(const char *s)
|
|
{
|
|
uint64_t val = 0;
|
|
int x = 0;
|
|
|
|
if(s[x] == '0' && (s[x+1] == 'x' || s[x+1] == 'X'))
|
|
x += 2;
|
|
|
|
while(s[x])
|
|
{
|
|
if(val > ULLONG_MAX)
|
|
return 0;
|
|
|
|
else if(s[x] >= '0' && s[x] <='9')
|
|
val = val * 16 + s[x] - '0';
|
|
|
|
else if(s[x]>='A' && s[x] <='F')
|
|
val = val * 16 + s[x] - 'A' + 10;
|
|
|
|
else if(s[x]>='a' && s[x] <='f')
|
|
val = val * 16 + s[x] - 'a' + 10;
|
|
|
|
else
|
|
return 0;
|
|
|
|
x++;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
long long current_timestamp()
|
|
{
|
|
struct timeval te;
|
|
gettimeofday(&te, NULL);
|
|
|
|
long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000;
|
|
return milliseconds;
|
|
}
|
|
|
|
void string_lower(char *s)
|
|
{
|
|
for(int i = 0; s[i]; i++)
|
|
s[i] = tolower(s[i]);
|
|
}
|
|
|
|
void string_upper(char *s)
|
|
{
|
|
for(int i = 0; s[i]; i++)
|
|
s[i] = toupper(s[i]);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int getblocheight(const char *coinb1)
|
|
{
|
|
unsigned char coinb1_bin[1024];
|
|
binlify(coinb1_bin, coinb1);
|
|
|
|
int height = 0;
|
|
uint8_t hlen = 0, *p, *m;
|
|
|
|
// find 0xffff tag
|
|
p = (uint8_t*)coinb1_bin + 32;
|
|
m = p + 128;
|
|
while (*p != 0xff && p < m) p++;
|
|
while (*p == 0xff && p < m) p++;
|
|
|
|
if (*(p-1) == 0xff && *(p-2) == 0xff)
|
|
{
|
|
p++; hlen = *p;
|
|
p++; height = le16dec(p);
|
|
p += 2;
|
|
switch (hlen)
|
|
{
|
|
case 4:
|
|
height += 0x10000UL * le16dec(p);
|
|
break;
|
|
case 3:
|
|
height += 0x10000UL * (*p);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return height;
|
|
}
|
|
|
|
void sha256_double_hash_hex(const char *input, char *output, unsigned int len)
|
|
{
|
|
char output1[32];
|
|
|
|
sha256_double_hash(input, output1, len);
|
|
hexlify(output, (unsigned char *)output1, 32);
|
|
}
|
|
|
|
void sha256_hash_hex(const char *input, char *output, unsigned int len)
|
|
{
|
|
char output1[32];
|
|
|
|
sha256_hash(input, output1, len);
|
|
hexlify(output, (unsigned char *)output1, 32);
|
|
}
|
|
|