/******************************************************************************
* Copyright © 2014 - 2017 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//
// LP_nativeDEX.c
// marketmaker
//
// portfolio to set prices from historical
// portfolio value based on ask?
// else claim path
//
// WONTFIX:
// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections
// bigendian architectures need to use little endian for sighash calcs
// improve critical section detection when parallel trades
// use electrum in case of addr change in swap
// locktime claiming on sporadic assetchains
// there is an issue about waiting for notarization for a swap that never starts (expiration ok)
# include <stdio.h>
long LP_cjson_allocated , LP_cjson_total , LP_cjson_count ;
struct LP_millistats
{
double lastmilli , millisum , threshold ;
uint32_t count ;
char name [ 64 ] ;
} LP_psockloop_stats , LP_reserved_msgs_stats , utxosQ_loop_stats , command_rpcloop_stats , queue_loop_stats , prices_loop_stats , LP_coinsloop_stats , LP_coinsloopBTC_stats , LP_coinsloopKMD_stats , LP_pubkeysloop_stats , LP_swapsloop_stats , LP_gcloop_stats , LP_tradesloop_stats ;
extern int32_t IAMLP ;
char LP_methodstr [ 64 ] ;
void LP_millistats_update ( struct LP_millistats * mp )
{
double elapsed , millis ;
if ( mp = = 0 )
{
if ( IAMLP ! = 0 )
{
mp = & LP_psockloop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
}
mp = & LP_reserved_msgs_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & utxosQ_loop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & command_rpcloop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & queue_loop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & prices_loop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & LP_coinsloop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & LP_coinsloopBTC_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & LP_coinsloopKMD_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & LP_pubkeysloop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & LP_tradesloop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & LP_swapsloop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
mp = & LP_gcloop_stats , printf ( " %32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u \n " , mp - > name , OS_milliseconds ( ) - mp - > lastmilli , mp - > threshold , mp - > millisum / ( mp - > count > 0 ? mp - > count : 1 ) , mp - > count ) ;
}
else
{
if ( mp - > lastmilli = = 0. )
mp - > lastmilli = OS_milliseconds ( ) ;
else
{
mp - > count + + ;
millis = OS_milliseconds ( ) ;
elapsed = ( millis - mp - > lastmilli ) ;
mp - > millisum + = elapsed ;
if ( mp - > threshold ! = 0. & & elapsed > mp - > threshold )
{
//if ( IAMLP == 0 )
printf ( " %32s elapsed %10.2f millis > threshold %10.2f, ave %10.2f millis, count.%u %s \n " , mp - > name , elapsed , mp - > threshold , mp - > millisum / mp - > count , mp - > count , LP_methodstr ) ;
}
mp - > lastmilli = millis ;
}
}
}
# include "LP_include.h"
portable_mutex_t LP_peermutex , LP_UTXOmutex , LP_utxomutex , LP_commandmutex , LP_cachemutex , LP_swaplistmutex , LP_forwardmutex , LP_pubkeymutex , LP_networkmutex , LP_psockmutex , LP_coinmutex , LP_messagemutex , LP_portfoliomutex , LP_electrummutex , LP_butxomutex , LP_reservedmutex , LP_nanorecvsmutex , LP_tradebotsmutex , LP_gcmutex , LP_inusemutex , LP_cJSONmutex , LP_logmutex , LP_statslogmutex , LP_tradesmutex , LP_commandQmutex , LP_blockinit_mutex , LP_pendswap_mutex , LP_listmutex ;
int32_t LP_canbind ;
char * Broadcaststr , * Reserved_msgs [ 2 ] [ 1000 ] ;
int32_t num_Reserved_msgs [ 2 ] , max_Reserved_msgs [ 2 ] ;
struct LP_peerinfo * LP_peerinfos , * LP_mypeer ;
struct LP_forwardinfo * LP_forwardinfos ;
struct iguana_info * LP_coins ;
struct LP_pubkey_info * LP_pubkeyinfos ;
struct rpcrequest_info * LP_garbage_collector ;
struct LP_address_utxo * LP_garbage_collector2 ;
struct LP_trade * LP_trades , * LP_tradesQ ;
//uint32_t LP_deadman_switch;
uint16_t LP_fixed_pairport ; //,LP_publicport;
uint32_t LP_lastnonce , LP_swap_endcritical , LP_swap_critical , LP_RTcount , LP_swapscount ;
int32_t LP_STOP_RECEIVED , LP_numactive_LP ; //,LP_mybussock = -1;
int32_t LP_mypubsock = - 1 ;
int32_t LP_cmdcount , LP_mypullsock = - 1 ;
int32_t LP_numfinished , LP_showwif , IAMLP = 0 ;
double LP_profitratio = 1. ;
struct LP_privkey { bits256 privkey ; uint8_t rmd160 [ 20 ] ; } ;
struct LP_globals
{
//struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
bits256 LP_mypub25519 , LP_privkey , LP_mypriv25519 , LP_passhash ;
uint64_t LP_skipstatus [ 10000 ] ;
uint16_t netid ;
uint8_t LP_myrmd160 [ 20 ] , LP_pubsecp [ 33 ] ;
uint32_t LP_sessionid , counter ;
int32_t LP_IAMLP , LP_pendingswaps , USERPASS_COUNTER , LP_numprivkeys , initializing , waiting , LP_numskips ;
char seednode [ 64 ] , USERPASS [ 65 ] , USERPASS_WIFSTR [ 64 ] , LP_myrmd160str [ 41 ] , gui [ 65 ] , LP_NXTaddr [ 64 ] ;
struct LP_privkey LP_privkeys [ 100 ] ;
} G ;
uint32_t LP_rand ( )
{
uint32_t retval ;
retval = rand ( ) ;
retval = ( retval < < 7 ) ^ ( retval > > 17 ) ^ rand ( ) ;
retval = ( retval < < 13 ) ^ ( retval > > 13 ) ^ rand ( ) ;
retval = ( retval < < 17 ) ^ ( retval > > 7 ) ^ rand ( ) ;
return ( retval ) ;
}
# include "LP_network.c"
char * activecoins [ ] = { " BTC " , " KMD " } ;
char GLOBAL_DBDIR [ ] = { " DB " } ;
char LP_myipaddr [ 64 ] , USERHOME [ 512 ] = { " /root " } ;
char LP_gui [ 65 ] = { " cli " } ;
char * default_LPnodes [ ] = { " 5.9.253.195 " , " 173.212.225.176 " , " 136.243.45.140 " , " 23.254.202.142 " , " 45.32.19.196 "
//"24.54.206.138", "107.72.162.127", "72.50.16.86", "51.15.202.191", "173.228.198.88",
//"51.15.203.171", "51.15.86.136", "51.15.94.249", "51.15.80.18", "51.15.91.40", "51.15.54.2", "51.15.86.31", "51.15.82.29", "51.15.89.155", "173.212.225.176", "136.243.45.140"
} ;
// stubs
void tradebot_swap_balancingtrade ( struct basilisk_swap * swap , int32_t iambob )
{
}
void tradebot_pendingadd ( cJSON * tradejson , char * base , double basevolume , char * rel , double relvolume )
{
// add to trades
}
char * LP_getdatadir ( )
{
return ( USERHOME ) ;
}
char * blocktrail_listtransactions ( char * symbol , char * coinaddr , int32_t num , int32_t skip )
{
return ( 0 ) ;
}
# include "LP_mmjson.c"
# include "LP_socket.c"
# include "LP_secp.c"
# include "LP_bitcoin.c"
# include "LP_coins.c"
# include "LP_rpc.c"
# include "LP_NXT.c"
# include "LP_cache.c"
# include "LP_RTmetrics.c"
# include "LP_utxo.c"
# include "LP_prices.c"
# include "LP_scan.c"
# include "LP_transaction.c"
# ifndef NOTETOMIC
# include "LP_etomic.c"
# endif
# include "LP_stats.c"
# include "LP_remember.c"
# include "LP_instantdex.c"
# include "LP_swap.c"
# include "LP_peers.c"
# include "LP_privkey.c"
# include "LP_forwarding.c"
# include "LP_signatures.c"
# include "LP_ordermatch.c"
# include "LP_tradebots.c"
# include "LP_portfolio.c"
# include "LP_messages.c"
# include "LP_commands.c"
char * LP_command_process ( void * ctx , char * myipaddr , int32_t pubsock , cJSON * argjson , uint8_t * data , int32_t datalen , int32_t stats_JSONonly )
{
char * retstr = 0 ; cJSON * retjson ; bits256 zero ;
if ( jobj ( argjson , " result " ) ! = 0 | | jobj ( argjson , " error " ) ! = 0 )
return ( 0 ) ;
if ( stats_JSONonly ! = 0 | | LP_tradecommand ( ctx , myipaddr , pubsock , argjson , data , datalen ) < = 0 )
{
if ( ( retstr = stats_JSON ( ctx , myipaddr , pubsock , argjson , " 127.0.0.1 " , stats_JSONonly ) ) ! = 0 )
{
//printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr);
//if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
//LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
}
}
else if ( LP_statslog_parse ( ) > 0 & & 0 )
{
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
if ( ( retjson = LP_statslog_disp ( 2000000000 , 2000000000 , " " , zero , 0 , 0 ) ) ) // pending swaps
free_json ( retjson ) ;
}
return ( retstr ) ;
}
char * LP_decrypt ( uint8_t decoded [ LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES ] , uint8_t * ptr , int32_t * recvlenp )
{
uint8_t * nonce , * cipher ; int32_t recvlen , cipherlen ; char * jsonstr = 0 ;
recvlen = * recvlenp ;
nonce = & ptr [ 2 ] ;
cipher = & ptr [ 2 + crypto_box_NONCEBYTES ] ;
cipherlen = recvlen - ( 2 + crypto_box_NONCEBYTES ) ;
if ( cipherlen > 0 & & cipherlen < = LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES )
{
if ( ( jsonstr = ( char * ) _SuperNET_decipher ( nonce , cipher , decoded , cipherlen , GENESIS_PUBKEY , G . LP_mypriv25519 ) ) ! = 0 )
{
recvlen = ( cipherlen - crypto_box_ZEROBYTES ) ;
if ( strlen ( jsonstr ) + 1 ! = recvlen )
{
printf ( " unexpected len %d vs recvlen.%d \n " , ( int32_t ) strlen ( jsonstr ) + 1 , recvlen ) ;
jsonstr = 0 ;
} //else printf("decrypted (%s)\n",jsonstr);
}
} else printf ( " cipher.%d too big for %d \n " , cipherlen , LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES ) ;
* recvlenp = recvlen ;
return ( jsonstr ) ;
}
char * LP_process_message ( void * ctx , char * typestr , char * myipaddr , int32_t pubsock , uint8_t * ptr , int32_t recvlen , int32_t recvsock )
{
static uint32_t dup , uniq ;
uint8_t jdecoded [ LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES ] ; int32_t i , len , cipherlen , datalen = 0 , duplicate = 0 , encrypted = 0 ; char * method , * method2 , * tmp , * cipherstr , * retstr = 0 , * jsonstr = 0 ; cJSON * argjson ; uint32_t crc32 ;
//double millis = OS_milliseconds();
crc32 = calc_crc32 ( 0 , & ptr [ 2 ] , recvlen - 2 ) ;
if ( ( crc32 & 0xff ) = = ptr [ 0 ] & & ( ( crc32 > > 8 ) & 0xff ) = = ptr [ 1 ] )
encrypted = 1 ;
i = LP_crc32find ( & duplicate , - 1 , crc32 ) ;
if ( duplicate ! = 0 )
dup + + ;
else uniq + + ;
portable_mutex_lock ( & LP_commandmutex ) ;
if ( ( LP_rand ( ) % 100000 ) = = 0 )
printf ( " %s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x \n " , typestr , duplicate , dup , dup + uniq , ( double ) 100 * dup / ( dup + uniq ) , encrypted , crc32 , ptr [ 0 ] , ptr [ 1 ] , crc32 & 0xff , ( crc32 > > 8 ) & 0xff ) ;
if ( duplicate = = 0 )
{
if ( i > = 0 )
LP_crc32find ( & duplicate , i , crc32 ) ;
if ( encrypted ! = 0 )
jsonstr = LP_decrypt ( jdecoded , ptr , & recvlen ) ;
else if ( ( datalen = is_hexstr ( ( char * ) ptr , 0 ) ) > 0 )
{
datalen > > = 1 ;
jsonstr = malloc ( datalen + 1 ) ;
decode_hex ( ( void * ) jsonstr , datalen , ( char * ) ptr ) ;
jsonstr [ datalen ] = 0 ;
} else jsonstr = ( char * ) ptr ;
if ( jsonstr ! = 0 & & ( argjson = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
uint8_t decoded [ LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES ] ;
//printf("[%s]\n",jsonstr);
cipherlen = 0 ;
if ( ( cipherstr = jstr ( argjson , " cipher " ) ) ! = 0 & & ( cipherlen = is_hexstr ( cipherstr , 0 ) ) > 32 & & cipherlen < = sizeof ( decoded ) * 2 )
{
method2 = jstr ( argjson , " method2 " ) ;
if ( ( method = jstr ( argjson , " method " ) ) ! = 0 & & ( strcmp ( method , " encrypted " ) = = 0 | | ( method2 ! = 0 & & strcmp ( method2 , " encrypted " ) = = 0 ) ) )
{
cipherlen > > = 1 ;
decode_hex ( decoded , cipherlen , cipherstr ) ;
crc32 = calc_crc32 ( 0 , & decoded [ 2 ] , cipherlen - 2 ) ;
if ( ( tmp = LP_decrypt ( jdecoded , decoded , & cipherlen ) ) ! = 0 )
{
jsonstr = tmp ;
free_json ( argjson ) ;
argjson = cJSON_Parse ( jsonstr ) ;
recvlen = cipherlen ;
encrypted = 1 ;
if ( ( crc32 & 0xff ) = = decoded [ 0 ] & & ( ( crc32 > > 8 ) & 0xff ) = = decoded [ 1 ] )
{
i = LP_crc32find ( & duplicate , - 1 , crc32 ) ;
if ( duplicate = = 0 & & i > = 0 )
LP_crc32find ( & duplicate , i , crc32 ) ;
}
printf ( " %02x %02x %08x duplicate.%d decrypted.(%s) \n " , decoded [ 0 ] , decoded [ 1 ] , crc32 , duplicate , jsonstr ) ;
}
else
{
//printf("packet not for this node %u\n",crc32);
}
} else printf ( " error (%s) method is %s \n " , jsonstr , method ) ;
}
if ( jsonstr ! = 0 & & argjson ! = 0 )
{
len = ( int32_t ) strlen ( jsonstr ) + 1 ;
if ( ( method = jstr ( argjson , " method " ) ) ! = 0 & & strcmp ( method , " gettradestatus " ) ! = 0 & & strcmp ( method , " psock " ) ! = 0 & & strcmp ( method , " broadcast " ) = = 0 )
{
bits256 zero ; cJSON * reqjson ; char * cipherstr ; int32_t cipherlen ; uint8_t cipher [ LP_ENCRYPTED_MAXSIZE ] ;
if ( ( reqjson = LP_dereference ( argjson , " broadcast " ) ) ! = 0 )
{
Broadcaststr = jprint ( reqjson , 0 ) ;
if ( ( cipherstr = jstr ( reqjson , " cipher " ) ) ! = 0 )
{
cipherlen = ( int32_t ) strlen ( cipherstr ) > > 1 ;
if ( cipherlen < = sizeof ( cipher ) )
{
decode_hex ( cipher , cipherlen , cipherstr ) ;
LP_queuesend ( calc_crc32 ( 0 , & cipher [ 2 ] , cipherlen - 2 ) , LP_mypubsock , " " , " " , cipher , cipherlen ) ;
} else retstr = clonestr ( " { \" error \" : \" cipher too big \" } " ) ;
}
else
{
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
if ( 0 & & ( method = jstr ( reqjson , " method " ) ) ! = 0 & & ( strcmp ( method , " tradestatus " ) = = 0 ) )
printf ( " broadcast.(%s) \n " , Broadcaststr ) ;
LP_reserved_msg ( 0 , " " , " " , zero , jprint ( reqjson , 0 ) ) ;
}
retstr = clonestr ( " { \" result \" : \" success \" } " ) ;
free_json ( reqjson ) ;
} else retstr = clonestr ( " { \" error \" : \" couldnt dereference sendmessage \" } " ) ;
}
else
{
LP_queuecommand ( 0 , jsonstr , pubsock , 0 ) ;
//if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len)) != 0 )
//{
//}
}
}
if ( argjson ! = 0 )
free_json ( argjson ) ;
}
} //else printf("DUPLICATE.(%s)\n",(char *)ptr);
portable_mutex_unlock ( & LP_commandmutex ) ;
if ( jsonstr ! = 0 & & ( void * ) jsonstr ! = ( void * ) ptr & & encrypted = = 0 )
free ( jsonstr ) ;
return ( retstr ) ;
}
int32_t LP_sock_check ( char * typestr , void * ctx , char * myipaddr , int32_t pubsock , int32_t sock , char * remoteaddr , int32_t maxdepth )
{
static char * line ;
int32_t recvlen = 1 , msglen , nonz = 0 ; cJSON * recvjson ; void * ptr , * msg ; char methodstr [ 64 ] , * decodestr , * retstr , * str ; struct nn_pollfd pfd ;
if ( line = = 0 )
line = calloc ( 1 , 1024 * 1024 ) ;
if ( sock > = 0 )
{
while ( nonz < maxdepth & & recvlen > 0 )
{
decodestr = 0 ;
nonz + + ;
memset ( & pfd , 0 , sizeof ( pfd ) ) ;
pfd . fd = sock ;
pfd . events = NN_POLLIN ;
if ( nn_poll ( & pfd , 1 , 1 ) ! = 1 )
break ;
ptr = 0 ;
if ( ( recvlen = nn_recv ( sock , & ptr , NN_MSG , 0 ) ) > 0 )
{
//printf("%s nn_recv.%d\n",typestr,recvlen);
decodestr = 0 ;
if ( recvlen > 32768 )
{
printf ( " unexpectedly large packet \n " ) ;
}
else
{
msg = ptr ;
msglen = recvlen ;
if ( ( recvjson = cJSON_Parse ( ( char * ) ptr ) ) = = 0 )
{
if ( ( decodestr = MMJSON_decode ( ptr , recvlen ) ) ! = 0 )
{
if ( ( recvjson = cJSON_Parse ( decodestr ) ) ! = 0 )
{
msg = decodestr ;
msglen = ( int32_t ) strlen ( decodestr ) + 1 ;
}
//printf("decoded.(%s)\n",decodestr);
} else printf ( " couldnt decode linebuf[%d] \n " , recvlen ) ;
}
methodstr [ 0 ] = 0 ;
if ( recvjson ! = 0 )
{
safecopy ( LP_methodstr , jstr ( recvjson , " method " ) , sizeof ( LP_methodstr ) ) ;
free_json ( recvjson ) ;
}
int32_t validreq = 1 ;
/*if ( strlen((char *)ptr)+sizeof(bits256) <= recvlen )
{
if ( LP_magic_check ( ptr , recvlen , remoteaddr ) < = 0 )
{
//printf("magic check error\n");
} else validreq = 1 ;
recvlen - = sizeof ( bits256 ) ;
} */
if ( validreq ! = 0 )
{
if ( ( retstr = LP_process_message ( ctx , typestr , myipaddr , pubsock , msg , msglen , sock ) ) ! = 0 )
free ( retstr ) ;
if ( Broadcaststr ! = 0 )
{
//printf("self broadcast.(%s)\n",Broadcaststr);
str = Broadcaststr ;
Broadcaststr = 0 ;
LP_queuecommand ( 0 , str , pubsock , 0 ) ;
/*if ( (argjson= cJSON_Parse(str)) != 0 )
{
//portable_mutex_lock(&LP_commandmutex);
if ( LP_tradecommand ( ctx , myipaddr , pubsock , argjson , 0 , 0 ) < = 0 )
{
if ( ( retstr = stats_JSON ( ctx , myipaddr , pubsock , argjson , remoteaddr , 0 ) ) ! = 0 )
free ( retstr ) ;
}
//portable_mutex_unlock(&LP_commandmutex);
free_json ( argjson ) ;
} */
free ( str ) ;
}
}
}
}
if ( ptr ! = 0 )
{
nn_freemsg ( ptr ) , ptr = 0 ;
//free(buf);
}
if ( decodestr ! = 0 )
free ( decodestr ) ;
}
}
return ( nonz ) ;
}
int32_t LP_nanomsg_recvs ( void * ctx )
{
int32_t n = 0 , nonz = 0 ; char * origipaddr ; struct LP_peerinfo * peer , * tmp ;
if ( ( origipaddr = LP_myipaddr ) = = 0 )
origipaddr = " 127.0.0.1 " ;
portable_mutex_lock ( & LP_nanorecvsmutex ) ;
HASH_ITER ( hh , LP_peerinfos , peer , tmp )
{
if ( n + + > 0 & & peer - > errors > = LP_MAXPEER_ERRORS )
{
if ( ( LP_rand ( ) % 10000 ) = = 0 )
peer - > errors - - ;
else
{
//printf("skip %s\n",peer->ipaddr);
continue ;
}
}
nonz + = LP_sock_check ( " SUB " , ctx , origipaddr , LP_mypubsock , peer - > subsock , peer - > ipaddr , 1 ) ;
}
/*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
if ( coin - > inactive ! = 0 )
continue ;
if ( coin - > bussock > = 0 )
nonz + = LP_sock_check ( coin - > symbol , ctx , origipaddr , - 1 , coin - > bussock , LP_profitratio - 1. ) ;
} */
if ( LP_mypullsock > = 0 )
{
nonz + = LP_sock_check ( " PULL " , ctx , origipaddr , - 1 , LP_mypullsock , " 127.0.0.1 " , 1 ) ;
}
portable_mutex_unlock ( & LP_nanorecvsmutex ) ;
return ( nonz ) ;
}
void command_rpcloop ( void * ctx )
{
int32_t nonz = 0 ;
strcpy ( command_rpcloop_stats . name , " command_rpcloop " ) ;
command_rpcloop_stats . threshold = 2500. ;
while ( LP_STOP_RECEIVED = = 0 )
{
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
LP_millistats_update ( & command_rpcloop_stats ) ;
nonz = LP_nanomsg_recvs ( ctx ) ;
//if ( LP_mybussock >= 0 )
// nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock);
if ( nonz = = 0 )
{
if ( IAMLP ! = 0 )
usleep ( 10000 ) ;
else usleep ( 50000 ) ;
}
else if ( IAMLP = = 0 )
usleep ( 1000 ) ;
}
}
void LP_coinsloop ( void * _coins )
{
struct LP_address * ap = 0 ; struct LP_transaction * tx ; cJSON * retjson ; struct LP_address_utxo * up , * tmp ; struct iguana_info * coin , * ctmp ; char str [ 65 ] ; struct electrum_info * ep , * backupep = 0 ; bits256 zero ; int32_t notarized , oldht , j , nonz ; char * coins = _coins ;
if ( strcmp ( " BTC " , coins ) = = 0 )
{
strcpy ( LP_coinsloopBTC_stats . name , " BTC coin loop " ) ;
LP_coinsloopBTC_stats . threshold = 20000. ;
}
else if ( strcmp ( " KMD " , coins ) = = 0 )
{
strcpy ( LP_coinsloopKMD_stats . name , " KMD coin loop " ) ;
LP_coinsloopKMD_stats . threshold = 10000. ;
}
else
{
strcpy ( LP_coinsloop_stats . name , " other coins loop " ) ;
LP_coinsloop_stats . threshold = 5000. ;
}
while ( LP_STOP_RECEIVED = = 0 )
{
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
if ( strcmp ( " BTC " , coins ) = = 0 )
LP_millistats_update ( & LP_coinsloopBTC_stats ) ;
else if ( strcmp ( " KMD " , coins ) = = 0 )
LP_millistats_update ( & LP_coinsloopKMD_stats ) ;
else LP_millistats_update ( & LP_coinsloop_stats ) ;
nonz = 0 ;
HASH_ITER ( hh , LP_coins , coin , ctmp ) // firstrefht,firstscanht,lastscanht
{
if ( coins ! = 0 )
{
if ( coins [ 0 ] ! = 0 )
{
if ( strcmp ( coins , coin - > symbol ) ! = 0 )
continue ;
}
else // avoid hardcode special case LP_coinsloop
{
if ( strcmp ( " BTC " , coin - > symbol ) = = 0 | | strcmp ( " KMD " , coin - > symbol ) = = 0 )
continue ;
}
}
if ( coin - > smartaddr [ 0 ] = = 0 )
{
//printf("%s has no smartaddress??\n",coin->symbol);
continue ;
}
memset ( & zero , 0 , sizeof ( zero ) ) ;
if ( coin - > inactive ! = 0 )
continue ;
if ( coin - > did_addrutxo_reset = = 0 )
{
LP_address_utxo_reset ( coin ) ;
coin - > did_addrutxo_reset = 1 ;
}
if ( coin - > longestchain = = 1 ) // special init value
coin - > longestchain = LP_getheight ( & notarized , coin ) ;
if ( ( ep = coin - > electrum ) ! = 0 )
{
if ( ( backupep = ep - > prev ) = = 0 )
backupep = ep ;
if ( ( retjson = electrum_address_listunspent ( coin - > symbol , ep , & retjson , coin - > smartaddr , 1 , zero , zero ) ) ! = 0 )
free_json ( retjson ) ;
if ( ( ap = LP_addressfind ( coin , coin - > smartaddr ) ) ! = 0 )
{
DL_FOREACH_SAFE ( ap - > utxos , up , tmp )
{
if ( up - > U . height > 0 & & up - > spendheight < 0 )
{
if ( up - > SPV = = 0 )
{
nonz + + ;
up - > SPV = LP_merkleproof ( coin , coin - > smartaddr , backupep , up - > U . txid , up - > U . height ) ;
if ( up - > SPV > 0 )
{
if ( ( tx = LP_transactionfind ( coin , up - > U . txid ) ) ! = 0 & & tx - > SPV = = 0 )
{
tx - > SPV = up - > SPV ;
//printf("%s %s: SPV.%d\n",coin->symbol,bits256_str(str,up->U.txid),up->SPV);
}
}
}
else if ( up - > SPV = = - 1 )
{
nonz + + ;
printf ( " SPV failure for %s %s \n " , coin - > symbol , bits256_str ( str , up - > U . txid ) ) ;
oldht = up - > U . height ;
LP_txheight_check ( coin , ap - > coinaddr , up - > U . txid ) ;
if ( oldht ! = up - > U . height )
up - > SPV = LP_merkleproof ( coin , coin - > smartaddr , backupep , up - > U . txid , up - > U . height ) ;
if ( up - > SPV < = 0 )
up - > SPV = - 2 ;
else printf ( " %s %s: corrected SPV.%d \n " , coin - > symbol , bits256_str ( str , up - > U . txid ) , up - > SPV ) ;
}
}
}
}
while ( ep ! = 0 )
{
if ( time ( NULL ) > ep - > keepalive + LP_ELECTRUM_KEEPALIVE )
{
//printf("%s electrum.%p needs a keepalive: lag.%d\n",ep->symbol,ep,(int32_t)(time(NULL) - ep->keepalive));
if ( ( retjson = electrum_banner ( coin - > symbol , ep , & retjson ) ) ! = 0 )
free_json ( retjson ) ;
ep - > keepalive = ( uint32_t ) time ( NULL ) ;
}
ep = ep - > prev ;
}
continue ;
}
if ( coin - > firstrefht = = 0 )
continue ;
else if ( coin - > firstscanht = = 0 )
coin - > lastscanht = coin - > firstscanht = coin - > firstrefht ;
else if ( coin - > firstrefht < coin - > firstscanht )
{
printf ( " detected %s firstrefht.%d < firstscanht.%d \n " , coin - > symbol , coin - > firstrefht , coin - > firstscanht ) ;
coin - > lastscanht = coin - > firstscanht = coin - > firstrefht ;
}
if ( coin - > lastscanht = = coin - > longestchain + 1 )
{
//printf("%s lastscanht.%d is longest.%d + 1\n",coin->symbol,coin->lastscanht,coin->longestchain);
continue ;
}
else if ( coin - > lastscanht > coin - > longestchain + 1 )
{
printf ( " detected chain rewind lastscanht.%d vs longestchain.%d, first.%d ref.%d \n " , coin - > lastscanht , coin - > longestchain , coin - > firstscanht , coin - > firstrefht ) ;
LP_undospends ( coin , coin - > longestchain - 1 ) ;
//LP_mempoolscan(coin->symbol,zero);
coin - > lastscanht = coin - > longestchain - 1 ;
if ( coin - > firstscanht < coin - > lastscanht )
coin - > lastscanht = coin - > firstscanht ;
continue ;
}
//if ( strcmp(coin->symbol,"BTC") != 0 && strcmp(coin->symbol,"KMD") != 0 ) // SPV as backup
{
nonz + + ;
if ( strcmp ( " BTC " , coins ) = = 0 ) //&& coin->lastscanht < coin->longestchain-3 )
printf ( " [%s]: %s ref.%d scan.%d to %d, longest.%d \n " , coins , coin - > symbol , coin - > firstrefht , coin - > firstscanht , coin - > lastscanht , coin - > longestchain ) ;
for ( j = 0 ; j < 100 ; j + + )
{
if ( LP_blockinit ( coin , coin - > lastscanht ) < 0 )
{
printf ( " blockinit.%s %d error \n " , coin - > symbol , coin - > lastscanht ) ;
sleep ( 10 ) ;
break ;
}
coin - > lastscanht + + ;
if ( coin - > lastscanht = = coin - > longestchain + 1 | | strcmp ( " BTC " , coins ) = = 0 )
break ;
}
if ( strcmp ( " BTC " , coins ) = = 0 )
printf ( " done [%s]: %s ref.%d scan.%d to %d, longest.%d \n " , coins , coin - > symbol , coin - > firstrefht , coin - > firstscanht , coin - > lastscanht , coin - > longestchain ) ;
}
}
if ( coins = = 0 )
return ;
//if ( nonz == 0 )
usleep ( 100000 ) ;
}
}
int32_t LP_mainloop_iter ( void * ctx , char * myipaddr , struct LP_peerinfo * mypeer , int32_t pubsock )
{
static uint32_t counter ; //,didinstantdex;
struct iguana_info * coin , * ctmp ; char * origipaddr ; uint32_t now ; int32_t notarized , height , nonz = 0 ;
if ( ( origipaddr = myipaddr ) = = 0 )
origipaddr = " 127.0.0.1 " ;
if ( mypeer = = 0 )
myipaddr = " 127.0.0.1 " ;
HASH_ITER ( hh , LP_coins , coin , ctmp ) // firstrefht,firstscanht,lastscanht
{
now = ( uint32_t ) time ( NULL ) ;
# ifdef bruteforce
if ( IAMLP ! = 0 & & coin - > inactive = = 0 & & coin - > electrum = = 0 & & didinstantdex = = 0 & & strcmp ( " KMD " , coin - > symbol ) = = 0 )
{
LP_instantdex_deposits ( coin ) ;
didinstantdex = now ;
}
# endif
/*if ( (coin->addr_listunspent_requested != 0 && now > coin->lastpushtime+LP_ORDERBOOK_DURATION*.5) || now > coin->lastpushtime+LP_ORDERBOOK_DURATION*5 )
{
//printf("PUSH addr_listunspent_requested %u\n",coin->addr_listunspent_requested);
coin - > lastpushtime = ( uint32_t ) now ;
LP_smartutxos_push ( coin ) ;
coin - > addr_listunspent_requested = 0 ;
} */
if ( coin - > electrum = = 0 & & coin - > inactive = = 0 & & now > coin - > lastgetinfo + LP_GETINFO_INCR )
{
nonz + + ;
if ( ( height = LP_getheight ( & notarized , coin ) ) > coin - > longestchain )
{
coin - > longestchain = height ;
if ( notarized ! = 0 & & notarized > coin - > notarized )
{
coin - > notarized = notarized ;
if ( IAMLP ! = 0 )
LP_dPoW_broadcast ( coin ) ;
}
if ( 0 & & coin - > firstrefht ! = 0 )
printf ( " >>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d]) \n " , coin - > symbol , height , coin - > firstrefht , coin - > firstscanht , coin - > lastscanht ) ;
} //else LP_mempoolscan(coin->symbol,zero);
coin - > lastgetinfo = ( uint32_t ) now ;
}
}
counter + + ;
return ( nonz ) ;
}
int my_strncasecmp ( const char * s1 , const char * s2 , size_t n )
{
size_t i = 0 ;
while ( i < n )
{
char c1 = s1 [ i ] ;
char c2 = s2 [ i ] ;
if ( c1 > = ' A ' & & c1 < = ' Z ' )
c1 = ( c1 - ' A ' ) + ' a ' ;
if ( c2 > = ' A ' & & c2 < = ' Z ' )
c2 = ( c2 - ' A ' ) + ' a ' ;
if ( c1 < c2 )
return ( - 1 ) ;
if ( c1 > c2 )
return ( 1 ) ;
if ( c1 = = 0 )
return ( 0 ) ;
+ + i ;
}
return ( 0 ) ;
}
void bech32_tests ( )
{
//char *test = "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs";
//char *test = "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a";
//char *test = "bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy";
//char *test = "prefix:x64nx6hz";
char * test = " bitcoincash:pq4p38fll9uuh2mzkesqhmgt66du4u0zzy92jchqqa " ; // 35Xbnq3kLoNsjN67knFewiRc9fqewrCzMW
uint8_t data [ 82 ] , data2 [ 64 ] , rmd160 [ 21 ] , addrtype ; char rebuild [ 92 ] , hrp [ 84 ] ; int32_t data_len , data_len2 ; int32_t i ;
if ( bech32_decode ( hrp , data , & data_len , test ) = = 0 )
{
printf ( " bech32_decode fails: '%s' \n " , test ) ;
}
else
{
bitcoin_addr2rmd160 ( " BCH " , 0 , & addrtype , rmd160 , " pq4p38fll9uuh2mzkesqhmgt66du4u0zzy92jchqqa " ) ;
bitcoin_address ( " BTC " , rebuild , 0 , 5 , rmd160 , 20 ) ;
for ( i = 0 ; i < 20 ; i + + )
printf ( " %02x " , rmd160 [ i ] ) ;
printf ( " addr2rmd160 %d -> %s \n " , addrtype , rebuild ) ;
data_len2 = 0 ;
if ( bech32_convert_bits ( data2 , & data_len2 , 8 , data , data_len , 5 , 0 ) = = 0 )
printf ( " error converting data5 \n " ) ;
for ( i = 0 ; i < data_len2 ; i + + )
printf ( " %02x " , data2 [ i ] ) ;
printf ( " compacted 5's -> %d \n " , data_len2 ) ;
bitcoin_addr2rmd160 ( " BTC " , 0 , & addrtype , rmd160 + 1 , " 35Xbnq3kLoNsjN67knFewiRc9fqewrCzMW " ) ;
for ( i = 0 ; i < data_len ; i + + )
printf ( " %02x " , data [ i ] ) ;
printf ( " datalen.%d <- %s (%s) -> " , ( int32_t ) data_len , test , " 35Xbnq3kLoNsjN67knFewiRc9fqewrCzMW " ) ;
for ( i = 0 ; i < 20 ; i + + )
printf ( " %02x " , rmd160 [ i + 1 ] ) ;
printf ( " \n " ) ;
}
data_len2 = 0 ;
rmd160 [ 0 ] = ( 1 < < 3 ) ;
bech32_convert_bits ( data2 , & data_len2 , 5 , rmd160 , 21 , 8 , 1 ) ;
for ( i = 0 ; i < data_len2 ; i + + )
printf ( " %02x " , data2 [ i ] ) ;
printf ( " converted bits.%d \n " , ( int32_t ) data_len2 ) ;
if ( bech32_encode ( rebuild , hrp , data2 , data_len2 ) = = 0 )
{
for ( i = 0 ; i < data_len ; i + + )
printf ( " %02x " , data [ i ] ) ;
printf ( " bech32_encode fails: '%s' -> hrp.(%s) datalen.%d \n " , test , hrp , ( int32_t ) data_len ) ;
}
if ( my_strncasecmp ( rebuild , test , 92 ) )
{
printf ( " bech32_encode produces incorrect result: '%s' vs (%s) \n " , test , rebuild ) ;
}
printf ( " end of bech32 tests \n " ) ;
}
void LP_initcoins ( void * ctx , int32_t pubsock , cJSON * coins )
{
int32_t i , n , notarized ; cJSON * item ; char * symbol , * etomic ; struct iguana_info * coin ;
for ( i = 0 ; i < sizeof ( activecoins ) / sizeof ( * activecoins ) ; i + + )
{
printf ( " %s, " , activecoins [ i ] ) ;
LP_coinfind ( activecoins [ i ] ) ;
LP_priceinfoadd ( activecoins [ i ] ) ;
if ( ( coin = LP_coinfind ( activecoins [ i ] ) ) ! = 0 )
{
if ( LP_getheight ( & notarized , coin ) < = 0 )
coin - > inactive = ( uint32_t ) time ( NULL ) ;
else
{
LP_unspents_load ( coin - > symbol , coin - > smartaddr ) ;
if ( strcmp ( coin - > symbol , " KMD " ) = = 0 )
{
LP_importaddress ( " KMD " , BOTS_BONDADDRESS ) ;
LP_dPoW_request ( coin ) ;
}
}
if ( coin - > txfee = = 0 & & strcmp ( coin - > symbol , " BTC " ) ! = 0 )
coin - > txfee = LP_MIN_TXFEE ;
}
}
if ( ( n = cJSON_GetArraySize ( coins ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( coins , i ) ;
if ( ( symbol = jstr ( item , " coin " ) ) ! = 0 )
{
printf ( " %s, " , jstr ( item , " coin " ) ) ;
LP_coincreate ( item ) ;
LP_priceinfoadd ( jstr ( item , " coin " ) ) ;
if ( ( coin = LP_coinfind ( symbol ) ) ! = 0 )
{
if ( ( etomic = jstr ( item , " etomic " ) ) ! = 0 )
safecopy ( coin - > etomic , etomic , sizeof ( coin - > etomic ) ) ;
else
{
if ( LP_getheight ( & notarized , coin ) < = 0 )
coin - > inactive = ( uint32_t ) time ( NULL ) ;
else LP_unspents_load ( coin - > symbol , coin - > smartaddr ) ;
}
if ( coin - > txfee = = 0 & & strcmp ( coin - > symbol , " BTC " ) ! = 0 )
coin - > txfee = LP_MIN_TXFEE ;
if ( 0 & & strcmp ( coin - > symbol , " BCH " ) = = 0 )
{
bech32_tests ( ) ;
}
}
}
}
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( coins , i ) ;
printf ( " \" %s \" , " , jstr ( item , " coin " ) ) ;
}
}
printf ( " privkey updates \n " ) ;
}
void LP_initpeers ( int32_t pubsock , struct LP_peerinfo * mypeer , char * myipaddr , uint16_t myport , uint16_t netid , char * seednode )
{
int32_t i , j ; uint32_t r ; uint16_t pushport , subport , busport ; char fixedseed [ 64 ] ;
LP_ports ( & pushport , & subport , & busport , netid ) ;
if ( IAMLP ! = 0 )
{
LP_mypeer = mypeer = LP_addpeer ( mypeer , pubsock , myipaddr , myport , pushport , subport , 1 , G . LP_sessionid , netid ) ;
if ( myipaddr = = 0 | | mypeer = = 0 )
{
printf ( " couldnt get myipaddr or null mypeer.%p \n " , mypeer ) ;
exit ( - 1 ) ;
}
if ( seednode = = 0 | | seednode [ 0 ] = = 0 )
{
if ( netid = = 0 )
{
printf ( " load default seednodes \n " ) ;
for ( i = 0 ; i < sizeof ( default_LPnodes ) / sizeof ( * default_LPnodes ) ; i + + )
{
LP_addpeer ( mypeer , pubsock , default_LPnodes [ i ] , myport , pushport , subport , 0 , G . LP_sessionid , netid ) ;
}
}
} else LP_addpeer ( mypeer , pubsock , seednode , myport , pushport , subport , 1 , G . LP_sessionid , netid ) ;
}
else
{
if ( myipaddr = = 0 )
{
printf ( " couldnt get myipaddr \n " ) ;
exit ( - 1 ) ;
}
if ( ( netid > 0 & & netid < 9 ) & & ( seednode = = 0 | | seednode [ 0 ] = = 0 ) )
{
sprintf ( fixedseed , " 5.9.253.%d " , 195 + netid ) ;
seednode = fixedseed ;
}
if ( seednode = = 0 | | seednode [ 0 ] = = 0 )
{
printf ( " default seed nodes for netid.%d \n " , netid ) ;
OS_randombytes ( ( void * ) & r , sizeof ( r ) ) ;
r = 0 ;
for ( j = 0 ; j < sizeof ( default_LPnodes ) / sizeof ( * default_LPnodes ) ; j + + )
{
i = ( r + j ) % ( sizeof ( default_LPnodes ) / sizeof ( * default_LPnodes ) ) ;
LP_addpeer ( mypeer , pubsock , default_LPnodes [ i ] , myport , pushport , subport , 0 , G . LP_sessionid , netid ) ;
}
} else LP_addpeer ( mypeer , pubsock , seednode , myport , pushport , subport , 1 , G . LP_sessionid , netid ) ;
}
}
void LP_pubkeysloop ( void * ctx )
{
static uint32_t lasttime ;
strcpy ( LP_pubkeysloop_stats . name , " LP_pubkeysloop " ) ;
LP_pubkeysloop_stats . threshold = 15000. ;
sleep ( 10 ) ;
while ( LP_STOP_RECEIVED = = 0 )
{
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
{
LP_millistats_update ( & LP_pubkeysloop_stats ) ;
if ( time ( NULL ) > lasttime + 100 )
{
//printf("LP_pubkeysloop %u\n",(uint32_t)time(NULL));
LP_notify_pubkeys ( ctx , LP_mypubsock ) ;
lasttime = ( uint32_t ) time ( NULL ) ;
}
}
sleep ( 3 ) ;
}
}
struct LP_pendswap
{
struct LP_pendswap * next , * prev ;
uint32_t expiration , requestid , quoteid , finished ;
} ;
struct LP_pendswap * LP_pendingswaps ;
void LP_pendswap_add ( uint32_t expiration , uint32_t requestid , uint32_t quoteid )
{
struct LP_pendswap * sp ;
printf ( " LP_pendswap_add expiration.%u %u-%u \n " , expiration , requestid , quoteid ) ;
portable_mutex_lock ( & LP_pendswap_mutex ) ;
sp = calloc ( 1 , sizeof ( * sp ) ) ;
sp - > expiration = expiration ;
sp - > requestid = requestid ;
sp - > quoteid = quoteid ;
DL_APPEND ( LP_pendingswaps , sp ) ;
portable_mutex_unlock ( & LP_pendswap_mutex ) ;
}
void LP_swapsloop ( void * ctx )
{
char * retstr ; cJSON * retjson ; uint32_t requestid , quoteid ; int32_t nonz ; struct LP_pendswap * sp , * tmp ;
strcpy ( LP_swapsloop_stats . name , " LP_swapsloop " ) ;
LP_swapsloop_stats . threshold = 605000. ;
if ( ( retstr = basilisk_swapentry ( 0 , 0 , 0 , 1 ) ) ! = 0 )
{
if ( ( retjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
if ( ( requestid = juint ( retjson , " requestid " ) ) ! = 0 & & ( quoteid = juint ( retjson , " quoteid " ) ) ! = 0 & & jobj ( retjson , " error " ) = = 0 )
LP_pendswap_add ( 0 , requestid , quoteid ) ;
}
free ( retstr ) ;
}
while ( LP_STOP_RECEIVED = = 0 )
{
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
LP_millistats_update ( & LP_swapsloop_stats ) ;
nonz = 0 ;
DL_FOREACH_SAFE ( LP_pendingswaps , sp , tmp )
{
if ( sp - > finished = = 0 )
{
nonz + + ;
if ( ( sp - > finished = LP_swapwait ( 0 , sp - > requestid , sp - > quoteid , - 1 , 0 ) ) ! = 0 )
{
}
}
}
if ( nonz = = 0 )
sleep ( 60 ) ;
}
}
void gc_loop ( void * ctx )
{
uint32_t now ; struct LP_address_utxo * up , * utmp ; struct rpcrequest_info * req , * rtmp ; int32_t flag = 0 ;
strcpy ( LP_gcloop_stats . name , " gc_loop " ) ;
LP_gcloop_stats . threshold = 11000. ;
while ( LP_STOP_RECEIVED = = 0 )
{
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
flag = 0 ;
LP_millistats_update ( & LP_gcloop_stats ) ;
portable_mutex_lock ( & LP_gcmutex ) ;
DL_FOREACH_SAFE ( LP_garbage_collector , req , rtmp )
{
DL_DELETE ( LP_garbage_collector , req ) ;
//printf("garbage collect ipbits.%x\n",req->ipbits);
free ( req ) ;
flag + + ;
}
now = ( uint32_t ) time ( NULL ) ;
DL_FOREACH_SAFE ( LP_garbage_collector2 , up , utmp )
{
if ( now > ( uint32_t ) up - > spendheight + 120 )
{
DL_DELETE ( LP_garbage_collector2 , up ) ;
//char str[65]; printf("garbage collect %s/v%d lag.%d\n",bits256_str(str,up->U.txid),up->U.vout,now-up->spendheight);
free ( up ) ;
}
flag + + ;
}
portable_mutex_unlock ( & LP_gcmutex ) ;
if ( 0 & & flag ! = 0 )
printf ( " gc_loop.%d \n " , flag ) ;
sleep ( 10 ) ;
}
}
void queue_loop ( void * ctx )
{
struct LP_queue * ptr , * tmp ; cJSON * json ; uint8_t linebuf [ 32768 ] ; int32_t k , sentbytes , nonz , flag , duplicate , n = 0 ;
strcpy ( queue_loop_stats . name , " queue_loop " ) ;
queue_loop_stats . threshold = 1000. ;
while ( LP_STOP_RECEIVED = = 0 )
{
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
LP_millistats_update ( & queue_loop_stats ) ;
n = nonz = flag = 0 ;
DL_FOREACH_SAFE ( LP_Q , ptr , tmp )
{
n + + ;
flag = 0 ;
if ( ptr - > sock > = 0 )
{
printf ( " sock.%d len.%d notready.%d \n " , ptr - > sock , ptr - > msglen , ptr - > notready ) ;
if ( ptr - > notready = = 0 | | ( LP_rand ( ) % ptr - > notready ) = = 0 )
{
if ( LP_sockcheck ( ptr - > sock ) > 0 )
{
//bits256 magic;
//magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256)));
//memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic));
if ( 0 )
{
static FILE * fp ;
if ( fp = = 0 )
fp = fopen ( " packet.log " , " wb " ) ;
if ( fp ! = 0 )
{
fprintf ( fp , " %s \n " , ( char * ) ptr - > msg ) ;
fflush ( fp ) ;
}
}
if ( ( json = cJSON_Parse ( ( char * ) ptr - > msg ) ) ! = 0 )
{
if ( 1 & & ptr - > msglen < sizeof ( linebuf ) )
{
if ( ( k = MMJSON_encode ( linebuf , ( char * ) ptr - > msg ) ) > 0 )
{
if ( ( sentbytes = nn_send ( ptr - > sock , linebuf , k , 0 ) ) ! = k )
printf ( " %d LP_send mmjson sent %d instead of %d \n " , n , sentbytes , k ) ;
else
{
flag + + ;
ptr - > sock = - 1 ;
}
}
printf ( " k.%d flag.%d SEND.(%s) sock.%d \n " , k , flag , ( char * ) ptr - > msg , ptr - > sock ) ;
}
free_json ( json ) ;
}
if ( flag = = 0 )
{
printf ( " non-encoded len.%d SEND.(%s) sock.%d \n " , ptr - > msglen , ( char * ) ptr - > msg , ptr - > sock ) ;
if ( ( sentbytes = nn_send ( ptr - > sock , ptr - > msg , ptr - > msglen , 0 ) ) ! = ptr - > msglen )
printf ( " %d LP_send sent %d instead of %d \n " , n , sentbytes , ptr - > msglen ) ;
else
{
flag + + ;
ptr - > sock = - 1 ;
}
}
if ( ptr - > peerind > 0 )
ptr - > starttime = ( uint32_t ) time ( NULL ) ;
}
/*else
{
if ( ptr - > notready + + > 1000 )
{
flag = 1 ;
ptr - > sock = - 1 ;
printf ( " queue_loop notready.%d, skip \n " , ptr - > notready ) ;
}
} */
}
}
else if ( 0 & & time ( NULL ) > ptr - > starttime + 13 )
{
LP_crc32find ( & duplicate , - 1 , ptr - > crc32 ) ;
if ( duplicate > 0 )
{
LP_Qfound + + ;
if ( ( LP_Qfound % 100 ) = = 0 )
printf ( " found.%u Q.%d err.%d match.%d \n " , ptr - > crc32 , LP_Qenqueued , LP_Qerrors , LP_Qfound ) ;
flag + + ;
}
else if ( 0 ) // too much beyond duplicate filter when network is busy
{
printf ( " couldnt find.%u peerind.%d Q.%d err.%d match.%d \n " , ptr - > crc32 , ptr - > peerind , LP_Qenqueued , LP_Qerrors , LP_Qfound ) ;
ptr - > peerind + + ;
if ( ( ptr - > sock = LP_peerindsock ( & ptr - > peerind ) ) < 0 )
{
printf ( " %d no more peers to try at peerind.%d %p Q_LP.%p \n " , n , ptr - > peerind , ptr , LP_Q ) ;
flag + + ;
LP_Qerrors + + ;
}
}
}
if ( flag ! = 0 )
{
nonz + + ;
portable_mutex_lock ( & LP_networkmutex ) ;
DL_DELETE ( LP_Q , ptr ) ;
portable_mutex_unlock ( & LP_networkmutex ) ;
free ( ptr ) ;
ptr = 0 ;
break ;
}
}
if ( nonz = = 0 )
{
if ( IAMLP = = 0 )
usleep ( 50000 ) ;
else usleep ( 10000 ) ;
}
}
}
void LP_reserved_msgs ( void * ignore )
{
bits256 zero ; int32_t flag , nonz ; struct nn_pollfd pfd ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
strcpy ( LP_reserved_msgs_stats . name , " LP_reserved_msgs " ) ;
LP_reserved_msgs_stats . threshold = 1000. ;
while ( LP_STOP_RECEIVED = = 0 )
{
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
nonz = 0 ;
LP_millistats_update ( & LP_reserved_msgs_stats ) ;
if ( num_Reserved_msgs [ 1 ] > 0 )
{
nonz + + ;
portable_mutex_lock ( & LP_reservedmutex ) ;
if ( num_Reserved_msgs [ 1 ] > 0 )
{
num_Reserved_msgs [ 1 ] - - ;
printf ( " PRIORITY BROADCAST.(%s) \n " , Reserved_msgs [ 1 ] [ num_Reserved_msgs [ 1 ] ] ) ;
LP_broadcast_message ( LP_mypubsock , " " , " " , zero , Reserved_msgs [ 1 ] [ num_Reserved_msgs [ 1 ] ] ) ;
Reserved_msgs [ 1 ] [ num_Reserved_msgs [ 1 ] ] = 0 ;
}
portable_mutex_unlock ( & LP_reservedmutex ) ;
}
else if ( num_Reserved_msgs [ 0 ] > 0 )
{
nonz + + ;
flag = 0 ;
if ( flag = = 0 & & LP_mypubsock > = 0 )
{
memset ( & pfd , 0 , sizeof ( pfd ) ) ;
pfd . fd = LP_mypubsock ;
pfd . events = NN_POLLOUT ;
if ( nn_poll ( & pfd , 1 , 1 ) = = 1 )
flag = 1 ;
} else flag = 1 ;
if ( flag = = 1 )
{
portable_mutex_lock ( & LP_reservedmutex ) ;
num_Reserved_msgs [ 0 ] - - ;
//printf("BROADCAST.(%s)\n",Reserved_msgs[0][num_Reserved_msgs[0]]);
LP_broadcast_message ( LP_mypubsock , " " , " " , zero , Reserved_msgs [ 0 ] [ num_Reserved_msgs [ 0 ] ] ) ;
Reserved_msgs [ 0 ] [ num_Reserved_msgs [ 0 ] ] = 0 ;
portable_mutex_unlock ( & LP_reservedmutex ) ;
}
}
if ( ignore = = 0 )
break ;
if ( nonz = = 0 )
usleep ( 5000 ) ;
}
}
int32_t LP_reserved_msg ( int32_t priority , char * base , char * rel , bits256 pubkey , char * msg )
{
struct LP_pubkey_info * pubp ; uint32_t timestamp ; char * method ; cJSON * argjson ; int32_t skip , sentbytes , n = 0 ;
skip = 0 ;
if ( ( argjson = cJSON_Parse ( msg ) ) ! = 0 )
{
if ( ( method = jstr ( argjson , " method " ) ) ! = 0 )
{
if ( strcmp ( method , " gettradestatus " ) = = 0 | | strcmp ( method , " wantnotify " ) = = 0 | | strcmp ( method , " getdPoW " ) = = 0 )
skip = 1 ;
}
if ( ( timestamp = juint ( argjson , " timestamp " ) ) ! = 0 & & time ( NULL ) > timestamp + 60 )
skip = 1 ;
free_json ( argjson ) ;
}
if ( skip ! = 0 )
return ( - 1 ) ;
//if ( strcmp(G.USERPASS,"1d8b27b21efabcd96571cd56f91a40fb9aa4cc623d273c63bf9223dc6f8cd81f") == 0 )
// return(-1);
if ( priority > 0 & & bits256_nonz ( pubkey ) ! = 0 )
{
if ( ( pubp = LP_pubkeyfind ( pubkey ) ) ! = 0 )
{
if ( pubp - > pairsock > = 0 )
{
if ( ( sentbytes = nn_send ( pubp - > pairsock , msg , ( int32_t ) strlen ( msg ) + 1 , 0 ) ) < 0 )
{
//pubp->pairsock = -1;
//LP_peer_pairsock(pubkey);
//printf("mark cmdchannel %d closed sentbytes.%d\n",pubp->pairsock,sentbytes);
}
else
{
printf ( " sent %d bytes to cmdchannel.%d \n " , sentbytes , pubp - > pairsock ) ;
return ( sentbytes ) ;
}
}
}
}
portable_mutex_lock ( & LP_reservedmutex ) ;
if ( num_Reserved_msgs [ priority ] < sizeof ( Reserved_msgs [ priority ] ) / sizeof ( * Reserved_msgs [ priority ] ) )
{
Reserved_msgs [ priority ] [ num_Reserved_msgs [ priority ] + + ] = msg ;
n = num_Reserved_msgs [ priority ] ;
} //else LP_broadcast_message(LP_mypubsock,base,rel,pubkey,msg);
if ( num_Reserved_msgs [ priority ] > max_Reserved_msgs [ priority ] )
{
max_Reserved_msgs [ priority ] = num_Reserved_msgs [ priority ] ;
//if ( (max_Reserved_msgs[priority] % 100) == 0 )
printf ( " New priority.%d max_Reserved_msgs.%d \n " , priority , max_Reserved_msgs [ priority ] ) ;
}
portable_mutex_unlock ( & LP_reservedmutex ) ;
return ( n ) ;
}
extern int32_t bitcoind_RPC_inittime ;
void LPinit ( uint16_t myport , uint16_t mypullport , uint16_t mypubport , uint16_t mybusport , char * passphrase , int32_t amclient , char * userhome , cJSON * argjson )
{
char * myipaddr = 0 , version [ 64 ] ; long filesize , n ; int32_t valid , timeout ; struct LP_peerinfo * mypeer = 0 ; char pushaddr [ 128 ] , subaddr [ 128 ] , bindaddr [ 128 ] , * coins_str = 0 ; cJSON * coinsjson = 0 ; void * ctx = bitcoin_ctx ( ) ;
sprintf ( version , " Marketmaker %s.%s %s rsize.%ld " , LP_MAJOR_VERSION , LP_MINOR_VERSION , LP_BUILD_NUMBER , sizeof ( struct basilisk_request ) ) ;
bitcoind_RPC_inittime = 1 ;
if ( LP_MAXPRICEINFOS > 256 )
{
printf ( " LP_MAXPRICEINFOS %d wont fit in a uint8_t, need to increase the width of the baseind and relind for struct LP_pubkey_quote \n " , LP_MAXPRICEINFOS ) ;
exit ( - 1 ) ;
}
LP_showwif = juint ( argjson , " wif " ) ;
printf ( " showwif.%d %s %u \n " , LP_showwif , version , calc_crc32 ( 0 , version , ( int32_t ) strlen ( version ) ) ) ;
if ( passphrase = = 0 | | passphrase [ 0 ] = = 0 )
{
printf ( " jeezy says we cant use the nullstring as passphrase and I agree \n " ) ;
exit ( - 1 ) ;
}
IAMLP = ! amclient ;
# ifndef __linux__
if ( IAMLP ! = 0 )
{
printf ( " must run a unix node for LP node \n " ) ;
exit ( - 1 ) ;
}
# endif
OS_randombytes ( ( void * ) & n , sizeof ( n ) ) ;
srand ( ( uint32_t ) n ) ;
if ( jobj ( argjson , " gui " ) ! = 0 )
safecopy ( LP_gui , jstr ( argjson , " gui " ) , sizeof ( LP_gui ) ) ;
if ( jobj ( argjson , " canbind " ) = = 0 )
{
# ifndef __linux__
LP_canbind = IAMLP ;
# else
LP_canbind = IAMLP ;
# endif
}
else
{
LP_canbind = jint ( argjson , " canbind " ) ;
printf ( " >>>>>>>>>>> set LP_canbind.%d \n " , LP_canbind ) ;
}
if ( LP_canbind > 1000 & & LP_canbind < 65536 )
LP_fixed_pairport = LP_canbind ;
if ( LP_canbind ! = 0 )
LP_canbind = 1 ;
srand ( ( int32_t ) n ) ;
if ( userhome ! = 0 & & userhome [ 0 ] ! = 0 )
{
safecopy ( USERHOME , userhome , sizeof ( USERHOME ) ) ;
# ifdef __APPLE__
strcat ( USERHOME , " /Library/Application Support " ) ;
# endif
}
portable_mutex_init ( & LP_peermutex ) ;
portable_mutex_init ( & LP_utxomutex ) ;
portable_mutex_init ( & LP_UTXOmutex ) ;
portable_mutex_init ( & LP_commandmutex ) ;
portable_mutex_init ( & LP_swaplistmutex ) ;
portable_mutex_init ( & LP_cachemutex ) ;
portable_mutex_init ( & LP_networkmutex ) ;
portable_mutex_init ( & LP_gcmutex ) ;
portable_mutex_init ( & LP_forwardmutex ) ;
portable_mutex_init ( & LP_inusemutex ) ;
portable_mutex_init ( & LP_psockmutex ) ;
portable_mutex_init ( & LP_coinmutex ) ;
portable_mutex_init ( & LP_pubkeymutex ) ;
portable_mutex_init ( & LP_electrummutex ) ;
portable_mutex_init ( & LP_messagemutex ) ;
portable_mutex_init ( & LP_portfoliomutex ) ;
portable_mutex_init ( & LP_butxomutex ) ;
portable_mutex_init ( & LP_reservedmutex ) ;
portable_mutex_init ( & LP_nanorecvsmutex ) ;
portable_mutex_init ( & LP_tradebotsmutex ) ;
portable_mutex_init ( & LP_cJSONmutex ) ;
portable_mutex_init ( & LP_logmutex ) ;
portable_mutex_init ( & LP_statslogmutex ) ;
portable_mutex_init ( & LP_tradesmutex ) ;
portable_mutex_init ( & LP_commandQmutex ) ;
portable_mutex_init ( & LP_blockinit_mutex ) ;
portable_mutex_init ( & LP_pendswap_mutex ) ;
portable_mutex_init ( & LP_listmutex ) ;
myipaddr = clonestr ( " 127.0.0.1 " ) ;
# ifndef _WIN32
# ifndef FROM_JS
if ( system ( " curl -s4 checkip.amazonaws.com > myipaddr " ) = = 0 )
{
char ipfname [ 64 ] ;
strcpy ( ipfname , " myipaddr " ) ;
if ( ( myipaddr = OS_filestr ( & filesize , ipfname ) ) ! = 0 & & myipaddr [ 0 ] ! = 0 )
{
n = strlen ( myipaddr ) ;
if ( myipaddr [ n - 1 ] = = ' \n ' )
myipaddr [ - - n ] = 0 ;
strcpy ( LP_myipaddr , myipaddr ) ;
} else printf ( " error getting myipaddr \n " ) ;
} else printf ( " error issuing curl \n " ) ;
# else
IAMLP = 0 ;
# endif
# endif
if ( IAMLP ! = 0 )
{
G . netid = juint ( argjson , " netid " ) ;
LP_mypubsock = - 1 ;
nanomsg_transportname ( 0 , subaddr , myipaddr , mypubport ) ;
nanomsg_transportname ( 1 , bindaddr , myipaddr , mypubport ) ;
valid = 0 ;
if ( ( LP_mypubsock = nn_socket ( AF_SP , NN_PUB ) ) > = 0 )
{
valid = 0 ;
if ( nn_bind ( LP_mypubsock , bindaddr ) > = 0 )
valid + + ;
if ( valid > 0 )
{
timeout = 100 ;
nn_setsockopt ( LP_mypubsock , NN_SOL_SOCKET , NN_SNDTIMEO , & timeout , sizeof ( timeout ) ) ;
//timeout = 10;
//nn_setsockopt(LP_mypubsock,NN_SOL_SOCKET,NN_MAXTTL,&timeout,sizeof(timeout));
}
else
{
printf ( " error binding to (%s).%d \n " , subaddr , LP_mypubsock ) ;
if ( LP_mypubsock > = 0 )
nn_close ( LP_mypubsock ) , LP_mypubsock = - 1 ;
}
} else printf ( " error getting pubsock %d \n " , LP_mypubsock ) ;
printf ( " >>>>>>>>> myipaddr.(%s) (%s) valid.%d pubbindaddr.%s pubsock.%d \n " , bindaddr , subaddr , valid , bindaddr , LP_mypubsock ) ;
LP_mypullsock = LP_initpublicaddr ( ctx , & mypullport , pushaddr , myipaddr , mypullport , 0 ) ;
}
if ( ( coinsjson = jobj ( argjson , " coins " ) ) = = 0 )
{
if ( ( coins_str = OS_filestr ( & filesize , " coins.json " ) ) ! = 0 | | ( coins_str = OS_filestr ( & filesize , " exchanges/coins.json " ) ) ! = 0 )
{
unstringify ( coins_str ) ;
printf ( " UNSTRINGIFIED.(%s) \n " , coins_str ) ;
coinsjson = cJSON_Parse ( coins_str ) ;
free ( coins_str ) ;
// yes I know this coinsjson is not freed, not sure about if it is referenced
}
}
if ( coinsjson = = 0 )
{
printf ( " no coins object or coins.json file, must abort \n " ) ;
exit ( - 1 ) ;
}
LP_initcoins ( ctx , LP_mypubsock , coinsjson ) ;
RPC_port = myport ;
G . waiting = 1 ;
LP_initpeers ( LP_mypubsock , LP_mypeer , LP_myipaddr , RPC_port , juint ( argjson , " netid " ) , jstr ( argjson , " seednode " ) ) ;
//LP_mypullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
//strcpy(LP_publicaddr,pushaddr);
//LP_publicport = mypullport;
//LP_mybussock = LP_coinbus(mybusport);
printf ( " got %s, initpeers. LP_mypubsock.%d pullsock.%d RPC_port.%u mypullport.%d mypubport.%d pushaddr.%s \n " , myipaddr , LP_mypubsock , LP_mypullsock , RPC_port , mypullport , mypubport , pushaddr ) ;
LP_passphrase_init ( passphrase , jstr ( argjson , " gui " ) , juint ( argjson , " netid " ) , jstr ( argjson , " seednode " ) ) ;
# ifndef FROM_JS
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_psockloop , ( void * ) myipaddr ) ! = 0 )
{
printf ( " error launching LP_psockloop for (%s) \n " , myipaddr ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_reserved_msgs , ( void * ) myipaddr ) ! = 0 )
{
printf ( " error launching LP_reserved_msgs for (%s) \n " , myipaddr ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) stats_rpcloop , ( void * ) & myport ) ! = 0 )
{
printf ( " error launching stats rpcloop for port.%u \n " , myport ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) command_rpcloop , ctx ) ! = 0 )
{
printf ( " error launching command_rpcloop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) queue_loop , ctx ) ! = 0 )
{
printf ( " error launching queue_loop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) gc_loop , ctx ) ! = 0 )
{
printf ( " error launching gc_loop for port.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) prices_loop , ctx ) ! = 0 )
{
printf ( " error launching prices_loop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_coinsloop , ( void * ) " " ) ! = 0 )
{
printf ( " error launching LP_coinsloop for (%s) \n " , " " ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_coinsloop , ( void * ) " BTC " ) ! = 0 )
{
printf ( " error launching LP_coinsloop for (%s) \n " , " BTC " ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_coinsloop , ( void * ) " KMD " ) ! = 0 )
{
printf ( " error launching LP_coinsloop for (%s) \n " , " KMD " ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_pubkeysloop , ctx ) ! = 0 )
{
printf ( " error launching LP_pubkeysloop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_tradesloop , ctx ) ! = 0 )
{
printf ( " error launching LP_tradessloop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_commandQ_loop , ctx ) ! = 0 )
{
printf ( " error launching LP_commandQ_loop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) LP_swapsloop , ctx ) ! = 0 )
{
printf ( " error launching LP_swapsloop for ctx.%p \n " , ctx ) ;
exit ( - 1 ) ;
}
int32_t nonz , didremote = 0 ;
LP_statslog_parse ( ) ;
bitcoind_RPC_inittime = 0 ;
while ( LP_STOP_RECEIVED = = 0 )
{
nonz = 0 ;
G . waiting = 1 ;
while ( G . initializing ! = 0 ) //&& strcmp(G.USERPASS,"1d8b27b21efabcd96571cd56f91a40fb9aa4cc623d273c63bf9223dc6f8cd81f") == 0 )
{
//fprintf(stderr,".");
sleep ( 3 ) ;
}
if ( G . initializing ! = 0 )
{
sleep ( 1 ) ;
continue ;
}
if ( LP_mainloop_iter ( ctx , myipaddr , mypeer , LP_mypubsock ) ! = 0 )
nonz + + ;
if ( IAMLP ! = 0 & & didremote = = 0 & & LP_cmdcount > 0 )
{
didremote = 1 ;
uint16_t myport2 = RPC_port - 1 ;
printf ( " start remote port \n " ) ;
if ( OS_thread_create ( malloc ( sizeof ( pthread_t ) ) , NULL , ( void * ) stats_rpcloop , ( void * ) & myport2 ) ! = 0 )
{
printf ( " error launching stats rpcloop for port.%u \n " , myport ) ;
exit ( - 1 ) ;
}
}
if ( nonz = = 0 )
usleep ( 1000 ) ;
else if ( IAMLP = = 0 )
usleep ( 1000 ) ;
}
# endif
printf ( " marketmaker exiting in 5 seconds \n " ) ;
sleep ( 5 ) ;
exit ( 0 ) ;
}
# ifdef FROM_JS
extern void * Nanomsg_threadarg ;
void * nn_thread_main_routine ( void * arg ) ;
void emscripten_usleep ( int32_t x )
{
}
char * bitcoind_RPC ( char * * retstrp , char * debugstr , char * url , char * userpass , char * command , char * params , int32_t timeout )
{
static uint32_t counter ; char fname [ 512 ] , * retstr ; long fsize ;
if ( strncmp ( " http:// " , url , strlen ( " http:// " ) ) ! = 0 )
return ( clonestr ( " { \" error \" : \" only http allowed \" } " ) ) ;
sprintf ( fname , " bitcoind_RPC/request.%d " , counter % 10 ) ;
counter + + ;
//printf("issue.(%s)\n",url);
emscripten_wget ( url , fname ) ;
retstr = OS_filestr ( & fsize , fname ) ;
//printf("bitcoind_RPC(%s) -> fname.(%s) %s\n",url,fname,retstr);
return ( retstr ) ;
}
char * barterDEX ( char * argstr )
{
static void * ctx ;
cJSON * argjson ; char * retstr ;
if ( ctx = = 0 )
ctx = bitcoin_ctx ( ) ;
printf ( " barterDEX.(%s) \n " , argstr ) ;
if ( ( argjson = cJSON_Parse ( argstr ) ) ! = 0 )
{
LP_queuecommand ( & retstr , argstr , LP_mypubsock ) ;
//retstr = LP_command_process(ctx,LP_myipaddr,LP_mypubsock,argjson,(uint8_t *)argstr,(int32_t)strlen(argstr));
while ( retstr = = 0 )
usleep ( 50000 ) ;
free_json ( argjson ) ;
} else retstr = clonestr ( " { \" error \" : \" couldnt parse request \" } " ) ;
return ( retstr ) ;
}
void LP_fromjs_iter ( )
{
static void * ctx ; char * retstr ;
if ( G . initializing ! = 0 )
{
printf ( " LP_fromjs_iter during G.initializing, skip \n " ) ;
return ;
}
if ( ctx = = 0 )
ctx = bitcoin_ctx ( ) ;
//if ( Nanomsg_threadarg != 0 )
// nn_thread_main_routine(Nanomsg_threadarg);
//LP_pubkeys_query();
//LP_utxosQ_process();
//LP_nanomsg_recvs(ctx);
LP_mainloop_iter ( ctx , LP_myipaddr , 0 , LP_mypubsock ) ;
//queue_loop(0);
if ( 0 ) // 10 seconds
{
LP_coinsloop ( 0 ) ;
if ( 0 ) // 100 seconds
{
LP_notify_pubkeys ( ctx , LP_mypubsock ) ;
LP_privkey_updates ( ctx , LP_mypubsock , 0 ) ;
if ( ( retstr = basilisk_swapentry ( 0 , 0 , 0 , 0 ) ) ! = 0 )
free ( retstr ) ;
}
}
}
# endif
# undef calloc
# undef free
# undef realloc
# undef clonestr
struct LP_memory_list
{
struct LP_memory_list * next , * prev ;
uint32_t timestamp , len ;
void * ptr ;
} * LP_memory_list ;
int32_t zeroval ( ) { return ( 0 ) ; }
void * LP_alloc ( uint64_t len )
{
//return(calloc(1,len));
LP_cjson_allocated + = len ;
LP_cjson_total + = len ;
LP_cjson_count + + ;
struct LP_memory_list * mp ;
mp = calloc ( 1 , sizeof ( * mp ) + len ) ;
mp - > ptr = calloc ( 1 , len ) ;
//printf(">>>>>>>>>>> LP_alloc mp.%p ptr.%p len.%llu %llu\n",mp,mp->ptr,(long long)len,(long long)LP_cjson_allocated);
mp - > timestamp = ( uint32_t ) time ( NULL ) ;
mp - > len = ( uint32_t ) len ;
portable_mutex_lock ( & LP_cJSONmutex ) ;
DL_APPEND ( LP_memory_list , mp ) ;
portable_mutex_unlock ( & LP_cJSONmutex ) ;
return ( mp - > ptr ) ;
}
void LP_free ( void * ptr )
{
static uint32_t lasttime , unknown ; static int64_t lasttotal ;
//free(ptr); return;
uint32_t now ; char str [ 65 ] ; int32_t n , lagging ; uint64_t total = 0 ; struct LP_memory_list * mp , * tmp ;
if ( ( now = ( uint32_t ) time ( NULL ) ) > lasttime + 1 )
{
n = lagging = 0 ;
DL_FOREACH_SAFE ( LP_memory_list , mp , tmp )
{
total + = mp - > len ;
n + + ;
if ( 0 & & now > mp - > timestamp + 120 )
{
lagging + + ;
if ( now > mp - > timestamp + 240 )
{
portable_mutex_lock ( & LP_cJSONmutex ) ;
DL_DELETE ( LP_memory_list , mp ) ;
portable_mutex_unlock ( & LP_cJSONmutex ) ;
free ( mp - > ptr ) ;
free ( mp ) ;
}
}
}
printf ( " [%lld] total %d allocated total %llu/%llu [%llu %llu] %.1f ave %s unknown.%u lagging.%d \n " , ( long long ) ( total - lasttotal ) , n , ( long long ) total , ( long long ) LP_cjson_allocated , ( long long ) LP_cjson_total , ( long long ) LP_cjson_count , ( double ) LP_cjson_total / LP_cjson_count , mbstr ( str , total ) , unknown , lagging ) ;
lasttime = ( uint32_t ) time ( NULL ) ;
lasttotal = total ;
}
DL_FOREACH_SAFE ( LP_memory_list , mp , tmp )
{
if ( mp - > ptr = = ptr )
break ;
mp = 0 ;
}
if ( mp ! = 0 )
{
LP_cjson_allocated - = mp - > len ;
portable_mutex_lock ( & LP_cJSONmutex ) ;
DL_DELETE ( LP_memory_list , mp ) ;
portable_mutex_unlock ( & LP_cJSONmutex ) ;
//printf(">>>>>>>>>>> LP_free ptr.%p mp.%p len.%u %llu\n",ptr,mp,mp->len,(long long)LP_cjson_allocated);
free ( mp - > ptr ) ;
free ( mp ) ;
} else unknown + + ; // free from source file with #define redirect for alloc that wasnt
}
/*char *LP_clonestr(char *str)
{
char * retstr = LP_alloc ( strlen ( str ) + 1 ) ;
strcpy ( retstr , str ) ;
return ( retstr ) ;
}
void * LP_realloc ( void * ptr , uint64_t len )
{
return ( realloc ( ptr , len ) ) ;
} */