mirror of
https://github.com/LBRYFoundation/pool.git
synced 2025-08-23 17:37:25 +00:00
666 lines
13 KiB
C++
666 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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|