// Copyright (c) 2016-2024 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
/******************************************************************************
* Copyright © 2014 - 2019 The SuperNET Developers . *
* *
* See the AUTHORS , DEVELOPER - AGREEMENT and LICENSE files at *
* the top - level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing . *
* *
* Unless otherwise agreed in a custom licensing agreement , no part of the *
* SuperNET software , including this file may be copied , modified , propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// requires CHAINNAME and GAMEMAIN() to be #defined
# include <stdio.h>
# include <stdint.h>
# include <memory.h>
# include <string.h>
# include <unistd.h>
# include <curl/curl.h>
# include <curl/easy.h>
extern struct games_state globalR ;
void * gamesiterate ( struct games_state * rs ) ;
char USERPASS [ 8192 ] ; uint16_t GAMES_PORT ;
char Gametxidstr [ 67 ] ;
char * clonestr ( char * str ) ;
# define MAXSTR 1024
char whoami [ MAXSTR ] ;
# define SMALLVAL 0.000000000000001
# define SATOSHIDEN ((uint64_t)100000000L)
# define dstr(x) ((double)(x) / SATOSHIDEN)
# define HUSH_SMART_CHAIN_MAXLEN 65
char ASSETCHAINS_SYMBOL [ HUSH_SMART_CHAIN_MAXLEN ] , IPADDRESS [ 100 ] ;
# ifndef _BITS256
# define _BITS256
union _bits256 { uint8_t bytes [ 32 ] ; uint16_t ushorts [ 16 ] ; uint32_t uints [ 8 ] ; uint64_t ulongs [ 4 ] ; uint64_t txid ; } ;
typedef union _bits256 bits256 ;
# endif
# ifdef _WIN32
# ifdef _MSC_VER
int gettimeofday ( struct timeval * tp , struct timezone * tzp )
{
// Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
static const uint64_t EPOCH = ( ( uint64_t ) 116444736000000000ULL ) ;
SYSTEMTIME system_time ;
FILETIME file_time ;
uint64_t time ;
GetSystemTime ( & system_time ) ;
SystemTimeToFileTime ( & system_time , & file_time ) ;
time = ( ( uint64_t ) file_time . dwLowDateTime ) ;
time + = ( ( uint64_t ) file_time . dwHighDateTime ) < < 32 ;
tp - > tv_sec = ( long ) ( ( time - EPOCH ) / 10000000L ) ;
tp - > tv_usec = ( long ) ( system_time . wMilliseconds * 1000 ) ;
return 0 ;
}
# endif // _MSC_VER
# endif
double OS_milliseconds ( )
{
struct timeval tv ; double millis ;
# ifdef __MINGW32__
mingw_gettimeofday ( & tv , NULL ) ;
# else
gettimeofday ( & tv , NULL ) ;
# endif
millis = ( ( double ) tv . tv_sec * 1000. + ( double ) tv . tv_usec / 1000. ) ;
//printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis);
return ( millis ) ;
}
int32_t _unhex ( char c )
{
if ( c > = ' 0 ' & & c < = ' 9 ' )
return ( c - ' 0 ' ) ;
else if ( c > = ' a ' & & c < = ' f ' )
return ( c - ' a ' + 10 ) ;
else if ( c > = ' A ' & & c < = ' F ' )
return ( c - ' A ' + 10 ) ;
return ( - 1 ) ;
}
int32_t is_hexstr ( char * str , int32_t n )
{
int32_t i ;
if ( str = = 0 | | str [ 0 ] = = 0 )
return ( 0 ) ;
for ( i = 0 ; str [ i ] ! = 0 ; i + + )
{
if ( n > 0 & & i > = n )
break ;
if ( _unhex ( str [ i ] ) < 0 )
break ;
}
if ( n = = 0 )
return ( i ) ;
return ( i = = n ) ;
}
int32_t unhex ( char c )
{
int32_t hex ;
if ( ( hex = _unhex ( c ) ) < 0 )
{
//printf("unhex: illegal hexchar.(%c)\n",c);
}
return ( hex ) ;
}
unsigned char _decode_hex ( char * hex ) { return ( ( unhex ( hex [ 0 ] ) < < 4 ) | unhex ( hex [ 1 ] ) ) ; }
int32_t decode_hex ( uint8_t * bytes , int32_t n , char * hex )
{
int32_t adjust , i = 0 ;
//printf("decode.(%s)\n",hex);
if ( is_hexstr ( hex , n ) < = 0 )
{
memset ( bytes , 0 , n ) ;
return ( n ) ;
}
if ( hex [ n - 1 ] = = ' \n ' | | hex [ n - 1 ] = = ' \r ' )
hex [ - - n ] = 0 ;
if ( n = = 0 | | ( hex [ n * 2 + 1 ] = = 0 & & hex [ n * 2 ] ! = 0 ) )
{
if ( n > 0 )
{
bytes [ 0 ] = unhex ( hex [ 0 ] ) ;
printf ( " decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld \n " , n , hex [ 0 ] , bytes [ 0 ] , hex , hex [ n * 2 + 1 ] , hex [ n * 2 ] , hex [ n * 2 ] , ( long ) strlen ( hex ) ) ;
}
bytes + + ;
hex + + ;
adjust = 1 ;
} else adjust = 0 ;
if ( n > 0 )
{
for ( i = 0 ; i < n ; i + + )
bytes [ i ] = _decode_hex ( & hex [ i * 2 ] ) ;
}
//bytes[i] = 0;
return ( n + adjust ) ;
}
char hexbyte ( int32_t c )
{
c & = 0xf ;
if ( c < 10 )
return ( ' 0 ' + c ) ;
else if ( c < 16 )
return ( ' a ' + c - 10 ) ;
else return ( 0 ) ;
}
int32_t init_hexbytes_noT ( char * hexbytes , unsigned char * message , long len )
{
int32_t i ;
if ( len < = 0 )
{
hexbytes [ 0 ] = 0 ;
return ( 1 ) ;
}
for ( i = 0 ; i < len ; i + + )
{
hexbytes [ i * 2 ] = hexbyte ( ( message [ i ] > > 4 ) & 0xf ) ;
hexbytes [ i * 2 + 1 ] = hexbyte ( message [ i ] & 0xf ) ;
//printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]);
}
hexbytes [ len * 2 ] = 0 ;
//printf("len.%ld\n",len*2+1);
return ( ( int32_t ) len * 2 + 1 ) ;
}
char * bits256_str ( char hexstr [ 65 ] , bits256 x )
{
init_hexbytes_noT ( hexstr , x . bytes , sizeof ( x ) ) ;
return ( hexstr ) ;
}
long _stripwhite ( char * buf , int accept )
{
int32_t i , j , c ;
if ( buf = = 0 | | buf [ 0 ] = = 0 )
return ( 0 ) ;
for ( i = j = 0 ; buf [ i ] ! = 0 ; i + + )
{
buf [ j ] = c = buf [ i ] ;
if ( c = = accept | | ( c ! = ' ' & & c ! = ' \n ' & & c ! = ' \r ' & & c ! = ' \t ' & & c ! = ' \b ' ) )
j + + ;
}
buf [ j ] = 0 ;
return ( j ) ;
}
char * parse_conf_line ( char * line , char * field )
{
line + = strlen ( field ) ;
for ( ; * line ! = ' = ' & & * line ! = 0 ; line + + )
break ;
if ( * line = = 0 )
return ( 0 ) ;
if ( * line = = ' = ' )
line + + ;
while ( line [ strlen ( line ) - 1 ] = = ' \r ' | | line [ strlen ( line ) - 1 ] = = ' \n ' | | line [ strlen ( line ) - 1 ] = = ' ' )
line [ strlen ( line ) - 1 ] = 0 ;
//printf("LINE.(%s)\n",line);
_stripwhite ( line , 0 ) ;
return ( clonestr ( line ) ) ;
}
int32_t safecopy ( char * dest , char * src , long len )
{
int32_t i = - 1 ;
if ( src ! = 0 & & dest ! = 0 & & src ! = dest )
{
if ( dest ! = 0 )
memset ( dest , 0 , len ) ;
for ( i = 0 ; i < len & & src [ i ] ! = 0 ; i + + )
dest [ i ] = src [ i ] ;
if ( i = = len )
{
printf ( " safecopy: %s too long %ld \n " , src , len ) ;
# ifdef __APPLE__
//getchar();
# endif
return ( - 1 ) ;
}
dest [ i ] = 0 ;
}
return ( i ) ;
}
# define true 1
# define false 0
//#ifdef STANDALONE
//#include "../hush3/src/hush_cJSON.c"
//#else
# include "../hush_cJSON.c"
//#endif
int32_t games_replay ( uint64_t seed , int32_t sleeptime ) ;
gamesevent * games_keystrokesload ( int32_t * numkeysp , uint64_t seed , int32_t counter ) ;
int GAMEMAIN ( int argc , char * * argv ) ;
void * OS_loadfile ( char * fname , uint8_t * * bufp , long * lenp , long * allocsizep )
{
FILE * fp ;
long filesize , buflen = * allocsizep ;
uint8_t * buf = * bufp ;
* lenp = 0 ;
if ( ( fp = fopen ( fname , " rb " ) ) ! = 0 )
{
fseek ( fp , 0 , SEEK_END ) ;
filesize = ftell ( fp ) ;
if ( filesize = = 0 )
{
fclose ( fp ) ;
* lenp = 0 ;
printf ( " OS_loadfile null size.(%s) \n " , fname ) ;
return ( 0 ) ;
}
if ( filesize > buflen )
{
* allocsizep = filesize ;
* bufp = buf = ( uint8_t * ) realloc ( buf , ( long ) * allocsizep + 64 ) ;
}
rewind ( fp ) ;
if ( buf = = 0 )
printf ( " Null buf ??? \n " ) ;
else
{
if ( fread ( buf , 1 , ( long ) filesize , fp ) ! = ( unsigned long ) filesize )
printf ( " error reading filesize.%ld \n " , ( long ) filesize ) ;
buf [ filesize ] = 0 ;
}
fclose ( fp ) ;
* lenp = filesize ;
//printf("loaded.(%s)\n",buf);
} //else printf("OS_loadfile couldnt load.(%s)\n",fname);
return ( buf ) ;
}
uint8_t * OS_fileptr ( long * allocsizep , char * fname )
{
long filesize = 0 ; uint8_t * buf = 0 ; void * retptr ;
* allocsizep = 0 ;
retptr = OS_loadfile ( fname , & buf , & filesize , allocsizep ) ;
return ( ( uint8_t * ) retptr ) ;
}
struct MemoryStruct { char * memory ; size_t size ; } ;
struct return_string { char * ptr ; size_t len ; } ;
// return data from the server
# define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
# define CURL_GLOBAL_SSL (1<<0)
# define CURL_GLOBAL_WIN32 (1<<1)
/************************************************************************
*
* Initialize the string handler so that it is thread safe
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void init_string ( struct return_string * s )
{
s - > len = 0 ;
s - > ptr = ( char * ) calloc ( 1 , s - > len + 1 ) ;
if ( s - > ptr = = NULL )
{
fprintf ( stderr , " init_string malloc() failed \n " ) ;
exit ( - 1 ) ;
}
s - > ptr [ 0 ] = ' \0 ' ;
}
/************************************************************************
*
* Use the " writer " to accumulate text until done
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t accumulatebytes ( void * ptr , size_t size , size_t nmemb , struct return_string * s )
{
size_t new_len = s - > len + size * nmemb ;
s - > ptr = ( char * ) realloc ( s - > ptr , new_len + 1 ) ;
if ( s - > ptr = = NULL )
{
fprintf ( stderr , " accumulate realloc() failed \n " ) ;
exit ( - 1 ) ;
}
memcpy ( s - > ptr + s - > len , ptr , size * nmemb ) ;
s - > ptr [ new_len ] = ' \0 ' ;
s - > len = new_len ;
return ( size * nmemb ) ;
}
/************************************************************************
*
* return the current system time in milliseconds
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field
# ifdef EXTRACT_BITCOIND_RESULT
/************************************************************************
*
* perform post processing of the results
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * post_process_bitcoind_RPC ( char * debugstr , char * command , char * rpcstr , char * params )
{
long i , j , len ; char * retstr = 0 ; cJSON * json , * result , * error ;
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command = = 0 | | rpcstr = = 0 | | rpcstr [ 0 ] = = 0 )
{
if ( strcmp ( command , " signrawtransaction " ) ! = 0 )
printf ( " <<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s] \n " , debugstr , command , rpcstr ) ;
return ( rpcstr ) ;
}
json = cJSON_Parse ( rpcstr ) ;
if ( json = = 0 )
{
printf ( " <<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s) \n " , debugstr , command , rpcstr , params ) ;
free ( rpcstr ) ;
return ( 0 ) ;
}
result = cJSON_GetObjectItem ( json , " result " ) ;
error = cJSON_GetObjectItem ( json , " error " ) ;
if ( error ! = 0 & & result ! = 0 )
{
if ( ( error - > type & 0xff ) = = cJSON_NULL & & ( result - > type & 0xff ) ! = cJSON_NULL )
{
retstr = cJSON_Print ( result ) ;
len = strlen ( retstr ) ;
if ( retstr [ 0 ] = = ' " ' & & retstr [ len - 1 ] = = ' " ' )
{
for ( i = 1 , j = 0 ; i < len - 1 ; i + + , j + + )
retstr [ j ] = retstr [ i ] ;
retstr [ j ] = 0 ;
}
}
else if ( ( error - > type & 0xff ) ! = cJSON_NULL | | ( result - > type & 0xff ) ! = cJSON_NULL )
{
if ( strcmp ( command , " signrawtransaction " ) ! = 0 )
printf ( " <<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s \n " , debugstr , command , rpcstr ) ;
}
free ( rpcstr ) ;
} else retstr = rpcstr ;
free_json ( json ) ;
//fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
return ( retstr ) ;
}
# endif
# ifdef _WIN32
# ifdef _MSC_VER
# define sleep(x) Sleep(1000*(x))
# endif
# endif
/************************************************************************
*
* perform the query
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * bitcoind_RPC ( char * * retstrp , char * debugstr , char * url , char * userpass , char * command , char * params )
{
static int didinit , count , count2 ; static double elapsedsum , elapsedsum2 ;
struct curl_slist * headers = NULL ; struct return_string s ; CURLcode res ; CURL * curl_handle ;
char * bracket0 , * bracket1 , * databuf = 0 ; long len ; int32_t specialcase , numretries ; double starttime ;
if ( didinit = = 0 )
{
didinit = 1 ;
curl_global_init ( CURL_GLOBAL_ALL ) ; //init the curl session
}
numretries = 0 ;
if ( debugstr ! = 0 & & strcmp ( debugstr , " BTCD " ) = = 0 & & command ! = 0 & & strcmp ( command , " SuperNET " ) = = 0 )
specialcase = 1 ;
else specialcase = 0 ;
if ( url [ 0 ] = = 0 )
strcpy ( url , " http://127.0.0.1:7876/nxt " ) ;
if ( specialcase ! = 0 & & 0 )
printf ( " <<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s) \n " , debugstr , url , command , params ) ;
try_again :
if ( retstrp ! = 0 )
* retstrp = 0 ;
starttime = OS_milliseconds ( ) ;
curl_handle = curl_easy_init ( ) ;
init_string ( & s ) ;
headers = curl_slist_append ( 0 , " Expect: " ) ;
curl_easy_setopt ( curl_handle , CURLOPT_USERAGENT , " mozilla/4.0 " ) ; //"Mozilla/4.0 (compatible; )");
curl_easy_setopt ( curl_handle , CURLOPT_HTTPHEADER , headers ) ;
curl_easy_setopt ( curl_handle , CURLOPT_URL , url ) ;
curl_easy_setopt ( curl_handle , CURLOPT_WRITEFUNCTION , ( void * ) accumulatebytes ) ; // send all data to this function
curl_easy_setopt ( curl_handle , CURLOPT_WRITEDATA , & s ) ; // we pass our 's' struct to the callback
curl_easy_setopt ( curl_handle , CURLOPT_NOSIGNAL , 1L ) ; // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt ( curl_handle , CURLOPT_NOPROGRESS , 1L ) ; // no progress callback
if ( strncmp ( url , " https " , 5 ) = = 0 )
{
curl_easy_setopt ( curl_handle , CURLOPT_SSL_VERIFYPEER , 0 ) ;
curl_easy_setopt ( curl_handle , CURLOPT_SSL_VERIFYHOST , 0 ) ;
}
if ( userpass ! = 0 )
curl_easy_setopt ( curl_handle , CURLOPT_USERPWD , userpass ) ;
databuf = 0 ;
if ( params ! = 0 )
{
if ( command ! = 0 & & specialcase = = 0 )
{
len = strlen ( params ) ;
if ( len > 0 & & params [ 0 ] = = ' [ ' & & params [ len - 1 ] = = ' ] ' ) {
bracket0 = bracket1 = ( char * ) " " ;
}
else
{
bracket0 = ( char * ) " [ " ;
bracket1 = ( char * ) " ] " ;
}
databuf = ( char * ) malloc ( 256 + strlen ( command ) + strlen ( params ) ) ;
sprintf ( databuf , " { \" id \" : \" jl777 \" , \" method \" : \" %s \" , \" params \" :%s%s%s} " , command , bracket0 , params , bracket1 ) ;
//printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
//
} //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
curl_easy_setopt ( curl_handle , CURLOPT_POST , 1L ) ;
if ( databuf ! = 0 )
curl_easy_setopt ( curl_handle , CURLOPT_POSTFIELDS , databuf ) ;
else curl_easy_setopt ( curl_handle , CURLOPT_POSTFIELDS , params ) ;
}
//laststart = milliseconds();
res = curl_easy_perform ( curl_handle ) ;
curl_slist_free_all ( headers ) ;
curl_easy_cleanup ( curl_handle ) ;
if ( databuf ! = 0 ) // clean up temporary buffer
{
free ( databuf ) ;
databuf = 0 ;
}
if ( res ! = CURLE_OK )
{
numretries + + ;
if ( specialcase ! = 0 )
{
printf ( " <<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d \n " , url , command , params , s . ptr , res ) ;
free ( s . ptr ) ;
return ( 0 ) ;
}
else if ( numretries > = 1 )
{
//printf("Maximum number of retries exceeded!\n");
free ( s . ptr ) ;
return ( 0 ) ;
}
if ( ( rand ( ) % 1000 ) = = 0 )
printf ( " curl_easy_perform() failed: %s %s.(%s %s), retries: %d \n " , curl_easy_strerror ( res ) , debugstr , url , command , numretries ) ;
free ( s . ptr ) ;
sleep ( ( 1 < < numretries ) ) ;
goto try_again ;
}
else
{
if ( command ! = 0 & & specialcase = = 0 )
{
count + + ;
elapsedsum + = ( OS_milliseconds ( ) - starttime ) ;
if ( ( count % 1000000 ) = = 0 )
printf ( " %d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s) \n " , count , elapsedsum / count , ( OS_milliseconds ( ) - starttime ) , command , url ) ;
if ( retstrp ! = 0 )
{
* retstrp = s . ptr ;
return ( s . ptr ) ;
}
return ( post_process_bitcoind_RPC ( debugstr , command , s . ptr , params ) ) ;
}
else
{
if ( 0 & & specialcase ! = 0 )
fprintf ( stderr , " <<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s) \n " , params , s . ptr ) ;
count2 + + ;
elapsedsum2 + = ( OS_milliseconds ( ) - starttime ) ;
if ( ( count2 % 10000 ) = = 0 )
printf ( " %d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s) \n " , count2 , elapsedsum2 / count2 , ( double ) ( OS_milliseconds ( ) - starttime ) , url , command ) ;
return ( s . ptr ) ;
}
}
printf ( " bitcoind_RPC: impossible case \n " ) ;
free ( s . ptr ) ;
return ( 0 ) ;
}
static size_t WriteMemoryCallback ( void * ptr , size_t size , size_t nmemb , void * data )
{
size_t realsize = ( size * nmemb ) ;
struct MemoryStruct * mem = ( struct MemoryStruct * ) data ;
mem - > memory = ( char * ) ( ( ptr ! = 0 ) ? realloc ( mem - > memory , mem - > size + realsize + 1 ) : malloc ( mem - > size + realsize + 1 ) ) ;
if ( mem - > memory ! = 0 )
{
if ( ptr ! = 0 )
memcpy ( & ( mem - > memory [ mem - > size ] ) , ptr , realsize ) ;
mem - > size + = realsize ;
mem - > memory [ mem - > size ] = 0 ;
}
//printf("got %d bytes\n",(int32_t)(size*nmemb));
return ( realsize ) ;
}
char * curl_post ( CURL * * cHandlep , char * url , char * userpass , char * postfields , char * hdr0 , char * hdr1 , char * hdr2 , char * hdr3 )
{
struct MemoryStruct chunk ; CURL * cHandle ; long code ; struct curl_slist * headers = 0 ;
if ( ( cHandle = * cHandlep ) = = NULL )
* cHandlep = cHandle = curl_easy_init ( ) ;
else curl_easy_reset ( cHandle ) ;
//#ifdef DEBUG
//curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1);
//#endif
curl_easy_setopt ( cHandle , CURLOPT_USERAGENT , " mozilla/4.0 " ) ; //"Mozilla/4.0 (compatible; )");
curl_easy_setopt ( cHandle , CURLOPT_SSL_VERIFYPEER , 0 ) ;
//curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1);
curl_easy_setopt ( cHandle , CURLOPT_URL , url ) ;
curl_easy_setopt ( cHandle , CURLOPT_CONNECTTIMEOUT , 10 ) ;
if ( userpass ! = 0 & & userpass [ 0 ] ! = 0 )
curl_easy_setopt ( cHandle , CURLOPT_USERPWD , userpass ) ;
if ( postfields ! = 0 & & postfields [ 0 ] ! = 0 )
{
curl_easy_setopt ( cHandle , CURLOPT_POST , 1 ) ;
curl_easy_setopt ( cHandle , CURLOPT_POSTFIELDS , postfields ) ;
}
if ( hdr0 ! = NULL & & hdr0 [ 0 ] ! = 0 )
{
//printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:"");
headers = curl_slist_append ( headers , hdr0 ) ;
if ( hdr1 ! = 0 & & hdr1 [ 0 ] ! = 0 )
headers = curl_slist_append ( headers , hdr1 ) ;
if ( hdr2 ! = 0 & & hdr2 [ 0 ] ! = 0 )
headers = curl_slist_append ( headers , hdr2 ) ;
if ( hdr3 ! = 0 & & hdr3 [ 0 ] ! = 0 )
headers = curl_slist_append ( headers , hdr3 ) ;
} //headers = curl_slist_append(0,"Expect:");
if ( headers ! = 0 )
curl_easy_setopt ( cHandle , CURLOPT_HTTPHEADER , headers ) ;
//res = curl_easy_perform(cHandle);
memset ( & chunk , 0 , sizeof ( chunk ) ) ;
curl_easy_setopt ( cHandle , CURLOPT_WRITEFUNCTION , WriteMemoryCallback ) ;
curl_easy_setopt ( cHandle , CURLOPT_WRITEDATA , ( void * ) & chunk ) ;
curl_easy_perform ( cHandle ) ;
curl_easy_getinfo ( cHandle , CURLINFO_RESPONSE_CODE , & code ) ;
if ( headers ! = 0 )
curl_slist_free_all ( headers ) ;
if ( code ! = 200 )
printf ( " (%s) server responded with code %ld (%s) \n " , url , code , chunk . memory ) ;
return ( chunk . memory ) ;
}
uint16_t _hush_userpass ( char * username , char * password , FILE * fp )
{
char * rpcuser , * rpcpassword , * str , * ipaddress , line [ 8192 ] ; uint16_t port = 0 ;
rpcuser = rpcpassword = 0 ;
username [ 0 ] = password [ 0 ] = 0 ;
while ( fgets ( line , sizeof ( line ) , fp ) ! = 0 )
{
if ( line [ 0 ] = = ' # ' )
continue ;
//printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword"));
if ( ( str = strstr ( line , ( char * ) " rpcuser " ) ) ! = 0 )
rpcuser = parse_conf_line ( str , ( char * ) " rpcuser " ) ;
else if ( ( str = strstr ( line , ( char * ) " rpcpassword " ) ) ! = 0 )
rpcpassword = parse_conf_line ( str , ( char * ) " rpcpassword " ) ;
else if ( ( str = strstr ( line , ( char * ) " rpcport " ) ) ! = 0 )
{
port = atoi ( parse_conf_line ( str , ( char * ) " rpcport " ) ) ;
//fprintf(stderr,"rpcport.%u in file\n",port);
}
else if ( ( str = strstr ( line , ( char * ) " ipaddress " ) ) ! = 0 )
{
ipaddress = parse_conf_line ( str , ( char * ) " ipaddress " ) ;
strcpy ( IPADDRESS , ipaddress ) ;
}
}
if ( rpcuser ! = 0 & & rpcpassword ! = 0 )
{
strcpy ( username , rpcuser ) ;
strcpy ( password , rpcpassword ) ;
}
//printf("rpcuser.(%s) rpcpassword.(%s) %u ipaddress.%s\n",rpcuser,rpcpassword,port,ipaddress);
if ( rpcuser ! = 0 )
free ( rpcuser ) ;
if ( rpcpassword ! = 0 )
free ( rpcpassword ) ;
return ( port ) ;
}
uint16_t hush_userpass ( char * userpass , char * symbol )
{
FILE * fp ; uint16_t port = 0 ; char fname [ 512 ] , username [ 512 ] , password [ 512 ] , confname [ HUSH_SMART_CHAIN_MAXLEN ] ;
userpass [ 0 ] = 0 ;
sprintf ( confname , " %s.conf " , symbol ) ;
//hush_statefname(fname,symbol,confname);
if ( ( fp = fopen ( confname , " rb " ) ) ! = 0 )
{
port = _hush_userpass ( username , password , fp ) ;
sprintf ( userpass , " %s:%s " , username , password ) ;
if ( strcmp ( symbol , ASSETCHAINS_SYMBOL ) = = 0 )
strcpy ( USERPASS , userpass ) ;
fclose ( fp ) ;
}
return ( port ) ;
}
# define is_cJSON_True(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_True)
char * hush_issuemethod ( char * userpass , char * method , char * params , uint16_t port )
{
//static void *cHandle;
char url [ 512 ] , * retstr = 0 , * retstr2 = 0 , postdata [ 8192 ] ;
if ( params = = 0 | | params [ 0 ] = = 0 )
params = ( char * ) " [] " ;
if ( strlen ( params ) < sizeof ( postdata ) - 128 )
{
sprintf ( url , ( char * ) " http://%s:%u " , IPADDRESS , port ) ;
sprintf ( postdata , " { \" method \" : \" %s \" , \" params \" :%s} " , method , params ) ;
//printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,USERPASS);
retstr2 = bitcoind_RPC ( & retstr , ( char * ) " debug " , url , userpass , method , params ) ;
//retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0);
}
return ( retstr2 ) ;
}
int32_t games_sendrawtransaction ( char * rawtx )
{
char * params , * retstr , * hexstr ; cJSON * retjson , * resobj ; int32_t retval = - 1 ;
params = ( char * ) malloc ( strlen ( rawtx ) + 16 ) ;
sprintf ( params , " [ \" %s \" ] " , rawtx ) ;
if ( ( retstr = hush_issuemethod ( USERPASS , ( char * ) " sendrawtransaction " , params , GAMES_PORT ) ) ! = 0 )
{
if ( 0 ) // causes 4th level crash
{
static FILE * fp ;
if ( fp = = 0 )
fp = fopen ( " games.sendlog " , " wb " ) ;
if ( fp ! = 0 )
{
fprintf ( fp , " %s \n " , retstr ) ;
fflush ( fp ) ;
}
}
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( resobj = jobj ( retjson , ( char * ) " result " ) ) ! = 0 )
{
if ( ( hexstr = jstr ( resobj , 0 ) ) ! = 0 & & is_hexstr ( hexstr , 64 ) = = 64 )
retval = 0 ;
}
free_json ( retjson ) ;
}
/* log sendrawtx result in file */
/*
FILE * debug_file ;
debug_file = fopen ( " tx_debug.log " , " a " ) ;
fprintf ( debug_file , " %s \n " , retstr ) ;
fflush ( debug_file ) ;
fclose ( debug_file ) ;
*/
free ( retstr ) ;
}
free ( params ) ;
return ( retval ) ;
}
int32_t games_progress ( struct games_state * rs , int32_t waitflag , uint64_t seed , gamesevent * keystrokes , int32_t num )
{
char cmd [ 16384 ] , hexstr [ 16384 ] , params [ 32768 ] , * retstr , * errstr , * rawtx ; int32_t i , len , retflag = - 1 ; cJSON * retjson , * resobj ;
if ( rs - > guiflag ! = 0 & & Gametxidstr [ 0 ] ! = 0 )
{
if ( rs - > keystrokeshex ! = 0 )
{
if ( games_sendrawtransaction ( rs - > keystrokeshex ) = = 0 )
{
if ( waitflag = = 0 )
return ( 0 ) ;
else if ( 0 )
{
while ( games_sendrawtransaction ( rs - > keystrokeshex ) = = 0 )
{
//fprintf(stderr,"pre-rebroadcast\n");
sleep ( 10 ) ;
}
}
}
free ( rs - > keystrokeshex ) , rs - > keystrokeshex = 0 ;
}
memset ( hexstr , 0 , sizeof ( hexstr ) ) ;
for ( i = 0 ; i < num ; i + + )
{
if ( sizeof ( gamesevent ) = = 1 )
sprintf ( & hexstr [ i < < 1 ] , " %02x " , ( uint8_t ) keystrokes [ i ] & 0xff ) ;
else if ( sizeof ( gamesevent ) = = 2 )
sprintf ( & hexstr [ i < < 2 ] , " %04x " , ( uint16_t ) keystrokes [ i ] & 0xffff ) ;
else if ( sizeof ( gamesevent ) = = 4 )
sprintf ( & hexstr [ i < < 3 ] , " %08x " , ( uint32_t ) keystrokes [ i ] & 0xffffffff ) ;
else if ( sizeof ( gamesevent ) = = 8 )
sprintf ( & hexstr [ i < < 4 ] , " %016llx " , ( long long ) ( keystrokes [ i ] & 0xffffffffffffffffLL ) ) ;
}
static FILE * fp ;
if ( fp = = 0 )
fp = fopen ( " keystrokes.log " , " a " ) ;
sprintf ( params , " [ \" keystrokes \" , \" 17 \" , \" [%%22%s%%22,%%22%s%%22] \" ] " , Gametxidstr , hexstr ) ;
if ( ( retstr = hush_issuemethod ( USERPASS , ( char * ) " cclib " , params , GAMES_PORT ) ) ! = 0 )
{
if ( fp ! = 0 )
{
fprintf ( fp , " %s \n " , params ) ;
fprintf ( fp , " %s \n " , retstr ) ;
fflush ( fp ) ;
}
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( resobj = jobj ( retjson , ( char * ) " result " ) ) ! = 0 & & ( rawtx = jstr ( resobj , ( char * ) " hex " ) ) ! = 0 )
{
if ( rs - > keystrokeshex ! = 0 )
free ( rs - > keystrokeshex ) ;
if ( ( errstr = jstr ( resobj , ( char * ) " error " ) ) = = 0 )
{
rs - > keystrokeshex = ( char * ) malloc ( strlen ( rawtx ) + 1 ) ;
strcpy ( rs - > keystrokeshex , rawtx ) ;
retflag = 1 ;
} else fprintf ( stderr , " error sending keystrokes tx \n " ) , sleep ( 1 ) ;
//fprintf(stderr,"set keystrokestx <- %s\n",rs->keystrokeshex);
}
free_json ( retjson ) ;
}
free ( retstr ) ;
}
}
return ( retflag ) ;
}
int32_t gamesfname ( char * fname , uint64_t seed , int32_t counter )
{
sprintf ( fname , " %s.%llu.%d " , GAMENAME , ( long long ) seed , counter ) ;
return ( 0 ) ;
}
int32_t flushkeystrokes_local ( struct games_state * rs , int32_t waitflag )
{
# ifdef STANDALONE
char fname [ 1024 ] ; FILE * fp ; int32_t i , retflag = - 1 ;
rs - > counter + + ;
gamesfname ( fname , rs - > origseed , rs - > counter ) ;
if ( ( fp = fopen ( fname , " wb " ) ) ! = 0 )
{
if ( fwrite ( rs - > buffered , sizeof ( * rs - > buffered ) , rs - > num , fp ) = = rs - > num )
{
rs - > num = 0 ;
retflag = 0 ;
fclose ( fp ) ;
gamesfname ( fname , rs - > origseed , rs - > counter + 1 ) ;
if ( ( fp = fopen ( fname , " wb " ) ) ! = 0 ) // truncate next file
fclose ( fp ) ;
//fprintf(stderr,"savefile <- %s retflag.%d\n",fname,retflag);
//}
} else fprintf ( stderr , " error writing (%s) \n " , fname ) ;
} else fprintf ( stderr , " error creating (%s) \n " , fname ) ;
return ( retflag ) ;
# else
return ( 0 ) ;
# endif
}
# ifndef STANDALONE
// stubs for inside daemon
int32_t games_progress ( struct games_state * rs , int32_t waitflag , uint64_t seed , char * keystrokes , int32_t num )
{
return ( 0 ) ;
}
int32_t games_setplayerdata ( struct games_state * rs , char * gametxidstr )
{
return ( - 1 ) ;
}
# endif
int32_t flushkeystrokes ( struct games_state * rs , int32_t waitflag )
{
if ( rs - > num > 0 )
{
if ( games_progress ( rs , waitflag , rs - > origseed , rs - > buffered , rs - > num ) > 0 )
{
flushkeystrokes_local ( rs , waitflag ) ;
memset ( rs - > buffered , 0 , sizeof ( rs - > buffered ) ) ;
}
}
return ( 0 ) ;
}
void gamesbailout ( struct games_state * rs )
{
flushkeystrokes ( rs , 1 ) ;
}
# ifdef _WIN32
# ifdef _MSC_VER
# define sleep(x) Sleep(1000*(x))
# endif
# endif
long get_filesize ( FILE * fp )
{
long fsize , fpos = ftell ( fp ) ;
fseek ( fp , 0 , SEEK_END ) ;
fsize = ftell ( fp ) ;
fseek ( fp , fpos , SEEK_SET ) ;
return ( fsize ) ;
}
gamesevent * games_keystrokesload ( int32_t * numkeysp , uint64_t seed , int32_t counter )
{
char fname [ 1024 ] ; gamesevent * keystrokes = 0 ; FILE * fp ; long fsize ; int32_t i , num = 0 ;
* numkeysp = 0 ;
while ( 1 )
{
gamesfname ( fname , seed , counter ) ;
//printf("check (%s)\n",fname);
if ( ( fp = fopen ( fname , " rb " ) ) = = 0 )
break ;
if ( ( fsize = get_filesize ( fp ) ) < = 0 )
{
fclose ( fp ) ;
//printf("fsize.%ld\n",fsize);
break ;
}
if ( ( keystrokes = ( gamesevent * ) realloc ( keystrokes , sizeof ( * keystrokes ) * num + fsize ) ) = = 0 )
{
fprintf ( stderr , " error reallocating keystrokes \n " ) ;
fclose ( fp ) ;
return ( 0 ) ;
}
if ( fread ( & keystrokes [ num ] , 1 , fsize , fp ) ! = fsize )
{
fprintf ( stderr , " error reading keystrokes from (%s) \n " , fname ) ;
fclose ( fp ) ;
free ( keystrokes ) ;
return ( 0 ) ;
}
fclose ( fp ) ;
num + = ( int32_t ) ( fsize / sizeof ( gamesevent ) ) ;
//for (i=0; i<num; i++)
// keystrokes[i] = games_revendian(keystrokes[i]);
counter + + ;
//fprintf(stderr,"loaded %ld from (%s) total %d\n",fsize,fname,num);
break ;
}
* numkeysp = num ;
return ( keystrokes ) ;
}
void games_exit ( )
{
uint32_t counter ;
//resetltchars();
if ( globalR . guiflag ! = 0 | | globalR . sleeptime ! = 0 )
exit ( 0 ) ;
else if ( counter + + < 10 )
{
fprintf ( stderr , " would have exit sleeptime.%d \n " , globalR . sleeptime ) ;
globalR . replaydone = 1 ;
}
}
int32_t games_replay ( uint64_t seed , int32_t sleeptime )
{
FILE * fp ; char fname [ 1024 ] ; gamesevent * keystrokes = 0 ; long fsize ; int32_t i , num = 0 , counter = 0 ; struct games_state * rs ; struct games_player P , * player = 0 ;
if ( seed = = 0 )
seed = 777 ;
keystrokes = games_keystrokesload ( & num , seed , counter ) ;
//fprintf(stderr,"keystrokes.%p num.%d\n",keystrokes,num);
if ( num > 0 )
{
sprintf ( fname , " %s.%llu.player " , GAMENAME , ( long long ) seed ) ;
if ( ( fp = fopen ( fname , " rb " ) ) ! = 0 )
{
if ( fread ( & P , 1 , sizeof ( P ) , fp ) > 0 )
{
//printf("max size player\n");
player = & P ;
}
fclose ( fp ) ;
}
games_replay2 ( 0 , seed , keystrokes , num , player , sleeptime ) ;
mvaddstr ( LINES - 2 , 0 , ( char * ) " replay completed " ) ;
endwin ( ) ;
games_exit ( ) ;
}
if ( keystrokes ! = 0 )
free ( keystrokes ) ;
return ( num ) ;
}
int32_t games_setplayerdata ( struct games_state * rs , char * gametxidstr )
{
char cmd [ 32768 ] ; int32_t i , n , retval = - 1 ; char params [ 1024 ] , * filestr = 0 , * pname , * statusstr , * datastr , fname [ 128 ] ; long allocsize ; cJSON * retjson , * array , * item , * resultjson ;
if ( rs - > guiflag = = 0 )
return ( - 1 ) ;
if ( gametxidstr = = 0 | | * gametxidstr = = 0 )
return ( retval ) ;
if ( 0 )
{
sprintf ( fname , " %s.gameinfo " , gametxidstr ) ;
sprintf ( cmd , " ./hush-cli -ac_name=%s cclib gameinfo 17 \\ \" [%%22%s%%22] \\ \" > %s " , ASSETCHAINS_SYMBOL , gametxidstr , fname ) ;
if ( system ( cmd ) ! = 0 )
fprintf ( stderr , " error issuing (%s) \n " , cmd ) ;
else filestr = ( char * ) OS_fileptr ( & allocsize , fname ) ;
}
else
{
sprintf ( params , " [ \" gameinfo \" , \" 17 \" , \" [%%22%s%%22] \" ] " , gametxidstr ) ;
filestr = hush_issuemethod ( USERPASS , ( char * ) " cclib " , params , GAMES_PORT ) ;
}
if ( filestr ! = 0 )
{
if ( ( retjson = cJSON_Parse ( filestr ) ) ! = 0 & & ( resultjson = jobj ( retjson , ( char * ) " result " ) ) ! = 0 )
{
//fprintf(stderr,"gameinfo.(%s)\n",jprint(resultjson,0));
if ( ( array = jarray ( & n , resultjson , ( char * ) " players " ) ) ! = 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
if ( is_cJSON_True ( jobj ( item , ( char * ) " ismine " ) ) ! = 0 & & ( statusstr = jstr ( item , ( char * ) " status " ) ) ! = 0 )
{
if ( strcmp ( statusstr , ( char * ) " registered " ) = = 0 )
{
retval = 0 ;
if ( ( item = jobj ( item , ( char * ) " player " ) ) ! = 0 & & ( datastr = jstr ( item , ( char * ) " data " ) ) ! = 0 )
{
if ( ( pname = jstr ( item , ( char * ) " pname " ) ) ! = 0 & & strlen ( pname ) < MAXSTR - 1 )
strcpy ( whoami , pname ) ;
decode_hex ( ( uint8_t * ) & rs - > P , ( int32_t ) strlen ( datastr ) / 2 , datastr ) ;
fprintf ( stderr , " set pname[%s] %s \n " , pname = = 0 ? " " : pname , jprint ( item , 0 ) ) ;
rs - > restoring = 1 ;
}
}
}
}
}
free_json ( retjson ) ;
}
free ( filestr ) ;
}
return ( retval ) ;
}
# ifdef _WIN32
# ifdef _MSC_VER
__inline int msver ( void ) {
switch ( _MSC_VER ) {
case 1500 : return 2008 ;
case 1600 : return 2010 ;
case 1700 : return 2012 ;
case 1800 : return 2013 ;
case 1900 : return 2015 ;
//case 1910: return 2017;
default : return ( _MSC_VER / 100 ) ;
}
}
static inline bool is_x64 ( void ) {
# if defined(__x86_64__) || defined(_WIN64) || defined(__aarch64__)
return 1 ;
# elif defined(__amd64__) || defined(__amd64) || defined(_M_X64) || defined(_M_IA64)
return 1 ;
# else
return 0 ;
# endif
}
# define BUILD_DATE __DATE__ " " __TIME__
# endif // _WIN32
# endif // _MSC_VER
int main ( int argc , char * * argv )
{
uint64_t seed ; FILE * fp = 0 ; int32_t i , j , c ; char userpass [ 8192 ] ;
# ifdef _WIN32
# ifdef _MSC_VER
printf ( " *** games for Windows [ Build %s ] *** \n " , BUILD_DATE ) ;
const char * arch = is_x64 ( ) ? " 64-bits " : " 32-bits " ;
printf ( " Built with VC++ %d (%ld) %s \n \n " , msver ( ) , _MSC_FULL_VER , arch ) ;
# endif
# endif
for ( i = j = 0 ; argv [ 0 ] [ i ] ! = 0 & & j < sizeof ( ASSETCHAINS_SYMBOL ) ; i + + )
{
c = argv [ 0 ] [ i ] ;
if ( c = = ' \\ ' | | c = = ' / ' )
{
j = 0 ;
continue ;
}
ASSETCHAINS_SYMBOL [ j + + ] = toupper ( c ) ;
}
ASSETCHAINS_SYMBOL [ j + + ] = 0 ;
# ifdef _WIN32
# ifdef _MSC_VER
char cmpa [ 64 ] , cmpb [ 64 ] ;
sprintf ( cmpa , " %s.EXE " , CHAINNAME ) ;
sprintf ( cmpb , " %s54.EXE " , CHAINNAME ) ;
if ( strncmp ( ASSETCHAINS_SYMBOL , cmpa , sizeof ( ASSETCHAINS_SYMBOL ) ) = = 0 | | strncmp ( ASSETCHAINS_SYMBOL , cmpb , sizeof ( ASSETCHAINS_SYMBOL ) ) = = 0 ) {
strcpy ( ASSETCHAINS_SYMBOL , CHAINNAME ) ;
}
# endif
# endif
strcpy ( ASSETCHAINS_SYMBOL , CHAINNAME ) ;
GAMES_PORT = hush_userpass ( userpass , ASSETCHAINS_SYMBOL ) ;
if ( IPADDRESS [ 0 ] = = 0 )
strcpy ( IPADDRESS , " 127.0.0.1 " ) ;
printf ( " ASSETCHAINS_SYMBOL.(%s) port.%u (%s) IPADDRESS.%s \n " , ASSETCHAINS_SYMBOL , GAMES_PORT , USERPASS , IPADDRESS ) ; sleep ( 1 ) ;
if ( argc = = 2 & & ( fp = fopen ( argv [ 1 ] , " rb " ) ) = = 0 )
{
# ifdef _WIN32
# ifdef _MSC_VER
seed = _strtoui64 ( argv [ 1 ] , NULL , 10 ) ;
fprintf ( stderr , " replay seed.str(%s) seed.uint64_t(%I64u) " , argv [ 1 ] , seed ) ;
# else
fprintf ( stderr , " replay seed.str(%s) seed.uint64_t(%llu) " , argv [ 1 ] , ( long long ) seed ) ;
seed = atol ( argv [ 1 ] ) ; // windows, but not MSVC
# endif // _MSC_VER
# else
seed = atol ( argv [ 1 ] ) ; // non-windows
# endif // _WIN32
fprintf ( stderr , " replay %llu \n " , ( long long ) seed ) ;
return ( games_replay ( seed , 3 ) ) ;
}
else
{
if ( fp ! = 0 )
fclose ( fp ) ;
if ( GAMES_PORT = = 0 )
{
printf ( " you must copy %s.conf from ~/.hush/%s/%s.conf (or equivalent location) to current dir \n " , ASSETCHAINS_SYMBOL , ASSETCHAINS_SYMBOL , ASSETCHAINS_SYMBOL ) ;
return ( - 1 ) ;
}
return ( GAMEMAIN ( argc , argv ) ) ;
}
}