pool/stratum/util.cpp
2017-05-19 13:20:56 +02:00

684 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 debuglog_hex(void *data, int len)
{
uint8_t* const bin = (uint8_t*) data;
char *hex = (char*) calloc(1, len*2 + 2);
if (!hex) return;
for(int i=0; i < len; i++)
sprintf(hex+strlen(hex), "%02x", bin[i]);
strcpy(hex+strlen(hex), "\n");
debuglog(hex);
free(hex);
}
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);
}
}
void stratumlogdate(const char *format, ...)
{
char buffer[YAAMP_SMALLBUFSIZE];
char date[16];
va_list args;
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(date, 16, "%Y-%m-%d", timeinfo);
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
stratumlog("%s %s", date, buffer);
}
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;
}
///////////////////////////////////////////////////////////////////////////////////////////////
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;
}
#if 0
// gettimeofday seems deprecated in POSIX
long long current_timestamp()
{
long long milliseconds;
struct timeval te;
gettimeofday(&te, NULL);
milliseconds = te.tv_sec*1000LL + te.tv_usec/1000;
return milliseconds;
}
#else
long long current_timestamp()
{
long long milliseconds;
struct timespec te;
clock_gettime(CLOCK_REALTIME, &te);
milliseconds = 1000LL*te.tv_sec + round(te.tv_nsec/1e6);
return milliseconds;
}
#endif
long long current_timestamp_dms() // allow 0.1 ms time
{
long long dms;
struct timespec te;
clock_gettime(CLOCK_REALTIME, &te);
dms = 10000LL*te.tv_sec + round(te.tv_nsec/1e5);
return dms;
}
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);
}