You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

913 lines
34 KiB

8 years ago
/******************************************************************************
* 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. *
* *
******************************************************************************/
8 years ago
//
8 years ago
// LP_nativeDEX.c
8 years ago
// marketmaker
//
7 years ago
// autoprice based on formula
// sign critical api calls (pubkey reg, listunspent, orders?)
// stats using KV opreturn
7 years ago
// deal with offline pubkeys, reputations, etc.
7 years ago
// dPoW security -> 2: KMD notarized, 3: BTC notarized
7 years ago
// add interest to KMD withdraw
7 years ago
// verify portfolio, pricearray, withdraw
7 years ago
// dICO allocation
7 years ago
// alice only coins GAME UNO BTM ANC: GAME BTCD PPC RDD XZC POT EAC FTC BASH SPR WDC UNO XPM XCN BELA CHC DIME MEC NAUT MED AUR MAX DGC RIC EB3 DOT BTM GEO ANC CANN ICASH WBB SRC PTC ADZ TIPS EQT START EFL FST FJC NYC GCN
7 years ago
8 years ago
#include <stdio.h>
8 years ago
#include "LP_include.h"
7 years ago
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;
8 years ago
int32_t LP_canbind;
7 years ago
char *Broadcaststr,*Reserved_msgs[1000];
7 years ago
int32_t num_Reserved_msgs,max_Reserved_msgs;
8 years ago
struct LP_peerinfo *LP_peerinfos,*LP_mypeer;
8 years ago
struct LP_forwardinfo *LP_forwardinfos;
struct iguana_info *LP_coins;
8 years ago
#include "LP_network.c"
8 years ago
8 years ago
char *activecoins[] = { "BTC", "KMD" };
8 years ago
char GLOBAL_DBDIR[] = { "DB" };
7 years ago
char LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" };
8 years ago
char LP_gui[16] = { "cli" };
8 years ago
8 years ago
char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", };//"5.9.253.204" }; //
8 years ago
8 years ago
//uint32_t LP_deadman_switch;
8 years ago
uint16_t LP_fixed_pairport,LP_publicport;
7 years ago
uint32_t LP_lastnonce;
8 years ago
int32_t LP_mybussock = -1;
8 years ago
int32_t LP_mypubsock = -1;
8 years ago
int32_t LP_mypullsock = -1;
7 years ago
int32_t LP_showwif,IAMLP = 0;
8 years ago
double LP_profitratio = 1.;
7 years ago
struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; };
struct LP_globals
{
7 years ago
struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
7 years ago
bits256 LP_mypub25519,LP_mypriv25519;
uint64_t LP_skipstatus[10000];
7 years ago
uint8_t LP_myrmd160[20],LP_pubsecp[33];
7 years ago
uint32_t LP_sessionid,counter;
int32_t LP_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting,LP_numskips;
char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16];
7 years ago
struct LP_privkey LP_privkeys[100];
} G;
8 years ago
8 years ago
// stubs
8 years ago
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
}
8 years ago
8 years ago
char *LP_getdatadir()
{
8 years ago
return(USERHOME);
8 years ago
}
8 years ago
8 years ago
char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip)
{
return(0);
}
8 years ago
#include "LP_socket.c"
8 years ago
#include "LP_secp.c"
#include "LP_bitcoin.c"
8 years ago
#include "LP_coins.c"
#include "LP_rpc.c"
7 years ago
#include "LP_utxo.c"
7 years ago
#include "LP_prices.c"
8 years ago
#include "LP_scan.c"
8 years ago
#include "LP_transaction.c"
#include "LP_remember.c"
#include "LP_swap.c"
8 years ago
#include "LP_peers.c"
#include "LP_utxos.c"
8 years ago
#include "LP_forwarding.c"
8 years ago
#include "LP_ordermatch.c"
8 years ago
#include "LP_portfolio.c"
8 years ago
#include "LP_messages.c"
8 years ago
#include "LP_commands.c"
8 years ago
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
8 years ago
{
char *retstr=0;
8 years ago
if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 )
return(0);
8 years ago
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 )
8 years ago
{
8 years ago
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,"127.0.0.1",0)) != 0 )
8 years ago
{
8 years ago
//printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr);
8 years ago
//if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
//LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
8 years ago
}
7 years ago
} //else printf("finished tradecommand (%s)\n",jprint(argjson,0));
8 years ago
return(retstr);
}
8 years ago
char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp)
{
uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES],*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);
8 years ago
if ( cipherlen > 0 && cipherlen <= sizeof(decoded) )
8 years ago
{
7 years ago
if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,G.LP_mypriv25519)) != 0 )
8 years ago
{
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,(int32_t)sizeof(decoded));
*recvlenp = recvlen;
return(jsonstr);
}
8 years ago
char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,uint8_t *ptr,int32_t recvlen,int32_t recvsock)
8 years ago
{
8 years ago
static uint32_t dup,uniq;
8 years ago
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;
8 years ago
crc32 = calc_crc32(0,&ptr[2],recvlen-2);
if ( (crc32 & 0xff) == ptr[0] && ((crc32>>8) & 0xff) == ptr[1] )
encrypted = 1;
8 years ago
portable_mutex_lock(&LP_commandmutex);
8 years ago
i = LP_crc32find(&duplicate,-1,crc32);
8 years ago
if ( duplicate != 0 )
dup++;
else uniq++;
7 years ago
if ( (rand() % 10000) == 0 )
7 years ago
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);
8 years ago
if ( duplicate == 0 )
{
8 years ago
if ( i >= 0 )
LP_crc32find(&duplicate,i,crc32);
8 years ago
if ( encrypted != 0 )
8 years ago
jsonstr = LP_decrypt(ptr,&recvlen);
8 years ago
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 )
{
8 years ago
uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES];
8 years ago
//printf("[%s]\n",jsonstr);
8 years ago
cipherlen = 0;
8 years ago
if ( (cipherstr= jstr(argjson,"cipher")) != 0 && (cipherlen= is_hexstr(cipherstr,0)) > 32 && cipherlen <= sizeof(decoded)*2 )
{
8 years ago
method2 = jstr(argjson,"method2");
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"encrypted") == 0 ||(method2 != 0 && strcmp(method2,"encrypted") == 0)) )
8 years ago
{
cipherlen >>= 1;
decode_hex(decoded,cipherlen,cipherstr);
crc32 = calc_crc32(0,&decoded[2],cipherlen-2);
8 years ago
if ( (tmp= LP_decrypt(decoded,&cipherlen)) != 0 )
8 years ago
{
8 years ago
jsonstr = tmp;
free_json(argjson);
8 years ago
argjson = cJSON_Parse(jsonstr);
8 years ago
recvlen = cipherlen;
8 years ago
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);
8 years ago
}
else
{
8 years ago
printf("packet not for this node %u\n",crc32);
8 years ago
}
8 years ago
} else printf("error (%s) method is %s\n",jsonstr,method);
8 years ago
}
8 years ago
if ( jsonstr != 0 && argjson != 0 )
8 years ago
{
8 years ago
len = (int32_t)strlen(jsonstr) + 1;
if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len)) != 0 )
{
}
free_json(argjson);
8 years ago
}
}
8 years ago
} //else printf("DUPLICATE.(%s)\n",(char *)ptr);
8 years ago
portable_mutex_unlock(&LP_commandmutex);
8 years ago
if ( jsonstr != 0 && (void *)jsonstr != (void *)ptr && encrypted == 0 )
8 years ago
free(jsonstr);
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
8 years ago
return(retstr);
8 years ago
}
7 years ago
int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr)
8 years ago
{
7 years ago
int32_t recvlen=1,nonz = 0; cJSON *argjson; void *ptr; char *retstr,*str; struct nn_pollfd pfd;
8 years ago
if ( sock >= 0 )
{
7 years ago
while ( nonz < 100 && recvlen > 0 )
8 years ago
{
8 years ago
memset(&pfd,0,sizeof(pfd));
8 years ago
pfd.fd = sock;
pfd.events = NN_POLLIN;
7 years ago
if ( nn_poll(&pfd,1,1) != 1 )
8 years ago
break;
8 years ago
if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
7 years ago
//printf("RECV.(%s)\n",(char *)ptr);
8 years ago
nonz++;
8 years ago
if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 )
8 years ago
free(retstr);
7 years ago
if ( Broadcaststr != 0 )
{
7 years ago
//printf("self broadcast.(%s)\n",Broadcaststr);
7 years ago
str = Broadcaststr;
Broadcaststr = 0;
7 years ago
if ( (argjson= cJSON_Parse(str)) != 0 )
{
7 years ago
if ( jobj(argjson,"method") != 0 && strcmp("connect",jstr(argjson,"method")) == 0 )
printf("self.(%s)\n",str);
7 years ago
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
{
7 years ago
portable_mutex_lock(&LP_commandmutex);
7 years ago
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 )
7 years ago
free(retstr);
7 years ago
portable_mutex_unlock(&LP_commandmutex);
7 years ago
}
7 years ago
free_json(argjson);
}
7 years ago
free(str);
}
8 years ago
}
}
}
return(nonz);
}
7 years ago
int32_t LP_nanomsg_recvs(void *ctx)
8 years ago
{
7 years ago
static double lastmilli;
int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; double milli;
7 years ago
if ( (origipaddr= LP_myipaddr) == 0 )
8 years ago
origipaddr = "127.0.0.1";
7 years ago
milli = OS_milliseconds();
7 years ago
if ( lastmilli > 0. && milli > lastmilli+1000 )
7 years ago
fprintf(stderr,">>>>>>>>>>>>>>>>> BIG latency lag %.3f milliseconds\n",milli-lastmilli);
7 years ago
lastmilli = milli;
7 years ago
//portable_mutex_lock(&LP_nanorecvsmutex);
7 years ago
HASH_ITER(hh,LP_peerinfos,peer,tmp)
8 years ago
{
7 years ago
if ( peer->errors >= LP_MAXPEER_ERRORS )
8 years ago
{
7 years ago
if ( (rand() % 10000) == 0 )
peer->errors--;
else
8 years ago
{
7 years ago
//printf("skip %s\n",peer->ipaddr);
continue;
8 years ago
}
}
7 years ago
//printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr);
}
/*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("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1");
7 years ago
//portable_mutex_unlock(&LP_nanorecvsmutex);
7 years ago
return(nonz);
}
void command_rpcloop(void *myipaddr)
{
int32_t nonz = 0; void *ctx;
ctx = bitcoin_ctx();
while ( 1 )
{
nonz = LP_nanomsg_recvs(ctx);
8 years ago
//if ( LP_mybussock >= 0 )
// nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock);
8 years ago
if ( nonz == 0 )
7 years ago
{
if ( IAMLP != 0 )
7 years ago
usleep(1000);
else usleep(10000);
7 years ago
}
8 years ago
}
}
7 years ago
void LP_smartutxos_push(struct iguana_info *coin)
{
7 years ago
struct LP_peerinfo *peer,*tmp; uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; char *retstr; cJSON *array,*item,*req;
7 years ago
if ( coin->smartaddr[0] == 0 )
return;
7 years ago
if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 )
{
7 years ago
memset(zero.bytes,0,sizeof(zero));
7 years ago
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
7 years ago
//printf("PUSH %s %s\n",coin->symbol,coin->smartaddr);
7 years ago
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
vout = jint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
7 years ago
if ( IAMLP == 0 )
7 years ago
{
7 years ago
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( (retstr= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,vout,height,value)) != 0 )
free(retstr);
}
7 years ago
}
7 years ago
req = cJSON_CreateObject();
jaddstr(req,"method","uitem");
jaddstr(req,"coin",coin->symbol);
jaddstr(req,"coinaddr",coin->smartaddr);
jaddbits256(req,"txid",txid);
jaddnum(req,"vout",vout);
jaddnum(req,"ht",height);
jadd64bits(req,"value",value);
printf("ADDR_UNSPENTS[] <- %s\n",jprint(req,0));
LP_reserved_msg("","",zero,jprint(req,1));
7 years ago
}
}
free_json(array);
}
}
7 years ago
int32_t LP_utxos_sync(struct LP_peerinfo *peer)
{
int32_t i,j,n=0,m,v,posted=0; bits256 txid; cJSON *array,*item,*item2,*array2,*array3; uint64_t total,total2,metric; struct iguana_info *coin,*ctmp; struct LP_address *ap; char *retstr,*retstr2,*coinaddr;
7 years ago
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
return(0);
7 years ago
HASH_ITER(hh,LP_coins,coin,ctmp)
{
7 years ago
if ( IAMLP == 0 && coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) )
7 years ago
continue;
7 years ago
if ( coin->smartaddr[0] == 0 )
continue;
7 years ago
total = 0;
7 years ago
if ( (j= LP_listunspent_both(coin->symbol,coin->smartaddr,0)) == 0 )
7 years ago
continue;
7 years ago
if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
total += j64bits(item,"value");
}
}
if ( n > 0 && total > 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr)) != 0 )
{
7 years ago
//printf("UTXO sync.%d %s n.%d total %.8f -> %s (%s)\n",j,coin->symbol,n,dstr(total),peer->ipaddr,retstr);
7 years ago
total2 = 0;
if ( (array2= cJSON_Parse(retstr)) != 0 )
{
if ( (m= cJSON_GetArraySize(array2)) > 0 )
{
for (i=0; i<m; i++)
{
item2 = jitem(array2,i);
total2 += j64bits(item2,"value");
}
}
if ( total != total2 || n != m )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
for (j=0; j<m; j++)
{
if ( v == jint(jitem(array2,i),"tx_pos") && bits256_cmp(txid,jbits256(jitem(array2,i),"tx_hash")) == 0 )
break;
}
if ( j == m )
{
7 years ago
//printf("%s missing %s %s\n",peer->ipaddr,coin->symbol,jprint(item,0));
7 years ago
if ( (retstr2= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 )
free(retstr2);
posted++;
}
}
7 years ago
if ( 0 && posted != 0 )
7 years ago
printf(">>>>>>>> %s compare %s %s (%.8f n%d) (%.8f m%d)\n",peer->ipaddr,coin->symbol,coin->smartaddr,dstr(total),n,dstr(total2),m);
7 years ago
} //else printf("%s matches %s\n",peer->ipaddr,coin->symbol);
7 years ago
free_json(array2);
7 years ago
} else printf("parse error (%s)\n",retstr);
7 years ago
free(retstr);
7 years ago
}
7 years ago
else if ( n != 0 && total != 0 )
7 years ago
{
7 years ago
//printf("no response from %s for %s %s\n",peer->ipaddr,coin->symbol,coin->smartaddr);
7 years ago
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
if ( (retstr2= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 )
free(retstr2);
}
}
free_json(array);
7 years ago
}
7 years ago
if ( 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 )
7 years ago
{
if ( (array2= cJSON_Parse(retstr)) != 0 )
{
if ( (m= cJSON_GetArraySize(array2)) > 0 )
{
for (j=0; j<m; j++)
{
item = jitem(array2,j);
if ( (coinaddr= jfieldname(item)) != 0 )
{
7 years ago
metric = j64bits(item,coinaddr);
7 years ago
//printf("(%s) -> %.8f n.%d\n",coinaddr,dstr(metric>>16),(uint16_t)metric);
7 years ago
if ( (ap= LP_addressfind(coin,coinaddr)) == 0 || _LP_unspents_metric(ap->total,ap->n) != metric )
{
7 years ago
if ( ap == 0 || ap->n < (metric & 0xffff) )
7 years ago
{
if ( (retstr2= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coinaddr)) != 0 )
{
if ( (array3= cJSON_Parse(retstr2)) != 0 )
{
LP_unspents_array(coin,coinaddr,array3);
7 years ago
//printf("pulled.(%s)\n",retstr2);
7 years ago
free_json(array3);
}
free(retstr2);
}
7 years ago
} //else printf("wait for %s to pull %d vs %d\n",peer->ipaddr,ap!=0?ap->n:-1,(uint16_t)metric);
7 years ago
}
}
}
}
free_json(array2);
}
7 years ago
//printf("processed.(%s)\n",retstr);
7 years ago
free(retstr);
7 years ago
}
}
return(posted);
}
7 years ago
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport)
8 years ago
{
7 years ago
static uint32_t counter,numpeers;
7 years ago
struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; bits256 zero; int32_t needpings,j,height,nonz = 0;
8 years ago
now = (uint32_t)time(NULL);
8 years ago
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
if ( mypeer == 0 )
8 years ago
myipaddr = "127.0.0.1";
8 years ago
numpeers = LP_numpeers();
7 years ago
needpings = 0;
8 years ago
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
8 years ago
if ( peer->errors >= LP_MAXPEER_ERRORS )
8 years ago
{
8 years ago
if ( (rand() % 10000) == 0 )
8 years ago
{
8 years ago
peer->errors--;
7 years ago
if ( peer->errors < LP_MAXPEER_ERRORS )
peer->diduquery = 0;
8 years ago
}
8 years ago
if ( IAMLP == 0 )
continue;
8 years ago
}
7 years ago
if ( now > peer->lastpeers+60 || (rand() % 10000) == 0 )
8 years ago
{
8 years ago
if ( strcmp(peer->ipaddr,myipaddr) != 0 )
7 years ago
{
7 years ago
nonz++;
8 years ago
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport);
7 years ago
peer->diduquery = 0;
7 years ago
LP_utxos_sync(peer);
8 years ago
}
7 years ago
peer->lastpeers = now;
8 years ago
}
if ( peer->diduquery == 0 )
{
7 years ago
nonz++;
7 years ago
needpings++;
7 years ago
LP_peer_pricesquery(peer);
7 years ago
LP_utxos_sync(peer);
8 years ago
peer->diduquery = now;
}
7 years ago
if ( peer->needping != 0 )
{
7 years ago
nonz++;
7 years ago
needpings++;
7 years ago
if ( (retstr= issue_LP_notify(peer->ipaddr,peer->port,"127.0.0.1",0,numpeers,G.LP_sessionid,G.LP_myrmd160str,G.LP_mypub25519)) != 0 )
free(retstr);
peer->needping = 0;
}
8 years ago
}
7 years ago
if ( needpings != 0 || (counter % 6000) == 5 )
7 years ago
{
7 years ago
nonz++;
7 years ago
//printf("needpings.%d send notify\n",needpings);
7 years ago
LP_notify_pubkeys(ctx,pubsock);
}
7 years ago
if ( (counter % 6000) == 10 )
8 years ago
{
7 years ago
nonz++;
7 years ago
LP_privkey_updates(ctx,pubsock,0);
8 years ago
}
HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
7 years ago
memset(&zero,0,sizeof(zero));
7 years ago
if ( coin->addr_listunspent_requested != 0 )
7 years ago
{
7 years ago
printf("PUSH addr_listunspent_requested %u\n",coin->addr_listunspent_requested);
7 years ago
LP_smartutxos_push(coin);
7 years ago
coin->addr_listunspent_requested = 0;
}
if ( coin->inactive != 0 )
continue;
7 years ago
if ( coin->electrum != 0 )
continue;
7 years ago
//if ( coin->obooktime == 0 )
// continue;
if ( time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR )
{
7 years ago
nonz++;
7 years ago
if ( (height= LP_getheight(coin)) > coin->longestchain )
{
coin->longestchain = height;
if ( 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)time(NULL);
}
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;
}
8 years ago
if ( coin->lastscanht == coin->longestchain+1 )
continue;
8 years ago
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;
}
7 years ago
if ( (coin->lastscanht % 1000) == 0 )
printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
7 years ago
for (j=0; j<100; j++)
8 years ago
{
7 years ago
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
{
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
break;
}
coin->lastscanht++;
7 years ago
if ( coin->lastscanht == coin->longestchain+1 )
break;
8 years ago
}
7 years ago
if ( j < 100 )
continue;
7 years ago
nonz++;
7 years ago
//LP_getestimatedrate(coin);
break;
}
7 years ago
if ( (counter % 6000) == 60 )
8 years ago
{
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
{
//printf("SWAPS.(%s)\n",retstr);
7 years ago
nonz++;
8 years ago
free(retstr);
}
}
8 years ago
counter++;
return(nonz);
}
7 years ago
void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins)
8 years ago
{
8 years ago
int32_t i,n; cJSON *item;
8 years ago
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++)
8 years ago
{
8 years ago
fprintf(stderr,"%s ",activecoins[i]);
8 years ago
LP_coinfind(activecoins[i]);
8 years ago
LP_priceinfoadd(activecoins[i]);
}
8 years ago
if ( (n= cJSON_GetArraySize(coins)) > 0 )
{
for (i=0; i<n; i++)
8 years ago
{
item = jitem(coins,i);
8 years ago
fprintf(stderr,"%s ",jstr(item,"coin"));
8 years ago
LP_coincreate(item);
LP_priceinfoadd(jstr(item,"coin"));
}
8 years ago
}
8 years ago
fprintf(stderr,"privkey updates\n");
8 years ago
}
8 years ago
void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint16_t myport,char *seednode)
8 years ago
{
8 years ago
int32_t i,j; uint32_t r;
if ( IAMLP != 0 )
8 years ago
{
7 years ago
LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,0,0,G.LP_sessionid);
8 years ago
if ( myipaddr == 0 || mypeer == 0 )
8 years ago
{
8 years ago
printf("couldnt get myipaddr or null mypeer.%p\n",mypeer);
exit(-1);
8 years ago
}
8 years ago
if ( seednode == 0 || seednode[0] == 0 )
{
for (i=0; i<sizeof(default_LPnodes)/sizeof(*default_LPnodes); i++)
{
8 years ago
//if ( (rand() % 100) > 25 )
// continue;
8 years ago
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport);
8 years ago
}
8 years ago
} else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport);
8 years ago
}
else
{
if ( myipaddr == 0 )
{
printf("couldnt get myipaddr\n");
exit(-1);
}
if ( seednode == 0 || seednode[0] == 0 )
{
OS_randombytes((void *)&r,sizeof(r));
for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++)
{
i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes));
8 years ago
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport);
8 years ago
}
8 years ago
} else LP_peersquery(mypeer,pubsock,seednode,myport,"127.0.0.1",myport);
8 years ago
}
8 years ago
}
7 years ago
int32_t LP_reserved_msgs()
{
bits256 zero; int32_t n = 0;
memset(zero.bytes,0,sizeof(zero));
portable_mutex_lock(&LP_reservedmutex);
while ( num_Reserved_msgs > 0 )
{
num_Reserved_msgs--;
7 years ago
printf("%d BROADCASTING RESERVED.(%s)\n",num_Reserved_msgs,Reserved_msgs[num_Reserved_msgs]);
7 years ago
LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[num_Reserved_msgs]);
Reserved_msgs[num_Reserved_msgs] = 0;
n++;
}
portable_mutex_unlock(&LP_reservedmutex);
return(n);
}
7 years ago
int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg)
{
int32_t n = 0;
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs) )
{
Reserved_msgs[num_Reserved_msgs++] = msg;
n = num_Reserved_msgs;
} else LP_broadcast_message(LP_mypubsock,base,rel,pubkey,msg);
portable_mutex_unlock(&LP_reservedmutex);
if ( num_Reserved_msgs > max_Reserved_msgs )
{
max_Reserved_msgs = num_Reserved_msgs;
printf("New max_Reserved_msgs.%d\n",max_Reserved_msgs);
}
return(n);
}
8 years ago
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybusport,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson)
8 years ago
{
7 years ago
char *myipaddr=0; long filesize,n; int32_t timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx();
8 years ago
LP_showwif = juint(argjson,"wif");
8 years ago
if ( passphrase == 0 || passphrase[0] == 0 )
{
printf("jeezy says we cant use the nullstring as passphrase and I agree\n");
exit(-1);
}
8 years ago
IAMLP = !amclient;
8 years ago
#ifndef __linux__
if ( IAMLP != 0 )
{
printf("must run a unix node for LP node\n");
exit(-1);
}
#endif
8 years ago
OS_randombytes((void *)&n,sizeof(n));
8 years ago
if ( jobj(argjson,"gui") != 0 )
safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui));
8 years ago
if ( jobj(argjson,"canbind") == 0 )
8 years ago
{
#ifndef __linux__
8 years ago
LP_canbind = IAMLP;
8 years ago
#else
8 years ago
LP_canbind = IAMLP;
8 years ago
#endif
8 years ago
}
else
{
LP_canbind = jint(argjson,"canbind");
printf(">>>>>>>>>>> set LP_canbind.%d\n",LP_canbind);
}
8 years ago
if ( LP_canbind > 1000 && LP_canbind < 65536 )
LP_fixed_pairport = LP_canbind;
if ( LP_canbind != 0 )
LP_canbind = 1;
8 years ago
srand((int32_t)n);
8 years ago
if ( userhome != 0 && userhome[0] != 0 )
8 years ago
{
8 years ago
safecopy(USERHOME,userhome,sizeof(USERHOME));
8 years ago
#ifdef __APPLE__
strcat(USERHOME,"/Library/Application Support");
#endif
}
8 years ago
portable_mutex_init(&LP_peermutex);
portable_mutex_init(&LP_utxomutex);
8 years ago
portable_mutex_init(&LP_UTXOmutex);
8 years ago
portable_mutex_init(&LP_commandmutex);
8 years ago
portable_mutex_init(&LP_swaplistmutex);
8 years ago
portable_mutex_init(&LP_cachemutex);
8 years ago
portable_mutex_init(&LP_networkmutex);
8 years ago
portable_mutex_init(&LP_forwardmutex);
8 years ago
portable_mutex_init(&LP_psockmutex);
portable_mutex_init(&LP_coinmutex);
8 years ago
portable_mutex_init(&LP_pubkeymutex);
7 years ago
portable_mutex_init(&LP_electrummutex);
8 years ago
portable_mutex_init(&LP_messagemutex);
8 years ago
portable_mutex_init(&LP_portfoliomutex);
7 years ago
portable_mutex_init(&LP_butxomutex);
7 years ago
portable_mutex_init(&LP_reservedmutex);
7 years ago
portable_mutex_init(&LP_nanorecvsmutex);
#ifndef _WIN32
7 years ago
if ( system("curl -s4 checkip.amazonaws.com > DB/myipaddr") == 0 )
8 years ago
{
char ipfname[64];
strcpy(ipfname,"DB/myipaddr");
if ( (myipaddr= OS_filestr(&filesize,ipfname)) != 0 && myipaddr[0] != 0 )
8 years ago
{
n = strlen(myipaddr);
if ( myipaddr[n-1] == '\n' )
myipaddr[--n] = 0;
8 years ago
strcpy(LP_myipaddr,myipaddr);
8 years ago
} else printf("error getting myipaddr\n");
} else printf("error issuing curl\n");
#else
myipaddr = clonestr("127.0.0.1");
#endif
8 years ago
if ( IAMLP != 0 )
{
8 years ago
pubsock = -1;
nanomsg_transportname(0,subaddr,myipaddr,mypubport);
nanomsg_transportname(1,bindaddr,myipaddr,mypubport);
if ( (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 )
8 years ago
{
8 years ago
if ( nn_bind(pubsock,bindaddr) >= 0 )
8 years ago
{
7 years ago
timeout = 1;
8 years ago
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
}
else
{
printf("error binding to (%s).%d\n",subaddr,pubsock);
if ( pubsock >= 0 )
nn_close(pubsock), pubsock = -1;
}
} else printf("error getting pubsock %d\n",pubsock);
printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock);
LP_mypubsock = pubsock;
8 years ago
}
8 years ago
printf("got %s, initpeers\n",myipaddr);
8 years ago
LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"));
8 years ago
printf("get public socket\n");
8 years ago
LP_mypullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
8 years ago
strcpy(LP_publicaddr,pushaddr);
LP_publicport = mypullport;
8 years ago
LP_mybussock = LP_coinbus(mybusport);
//LP_deadman_switch = (uint32_t)time(NULL);
printf("canbind.%d my command address is (%s) pullsock.%d pullport.%u\n",LP_canbind,pushaddr,LP_mypullsock,mypullport);
7 years ago
if ( (coinsjson= jobj(argjson,"coins")) == 0 )
{
7 years ago
if ( (coins_str= OS_filestr(&filesize,"coins.json")) != 0 )
7 years ago
{
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 file, must abort\n");
exit(-1);
}
LP_initcoins(ctx,pubsock,coinsjson);
7 years ago
G.waiting = 1;
LP_passphrase_init(passphrase,jstr(argjson,"gui"));
8 years ago
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 )
8 years ago
{
8 years ago
printf("error launching LP_psockloop for (%s)\n",myipaddr);
8 years ago
exit(-1);
}
8 years ago
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);
}
8 years ago
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,(void *)&myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)queue_loop,(void *)&myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
8 years ago
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)prices_loop,(void *)&myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
8 years ago
//if ( (retstr= basilisk_swapentry(0,0)) != 0 )
// free(retstr);
7 years ago
int32_t nonz;
7 years ago
printf("start mainloop\n");
8 years ago
while ( 1 )
{
7 years ago
nonz = 0;
7 years ago
G.waiting = 1;
while ( G.initializing != 0 )
{
fprintf(stderr,".");
sleep(3);
}
if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport) != 0 )
7 years ago
nonz++;
if ( nonz == 0 )
7 years ago
usleep(10000);
7 years ago
else if ( IAMLP != 0 )
usleep(1000);
else usleep(10000);
8 years ago
}
8 years ago
}
8 years ago