diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index 602c5a598..bb2fb1c4c 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -120,7 +120,7 @@ getprices(base, rel)\n\ sendmessage(base=coin, rel="", pubkey=zero, )\n\ getmessages(firsti=0, num=100)\n\ clearmessages(firsti=0, num=100)\n\ -secretaddresses(passphrase, num=10, pubtype=60, taddr=0)\n\ +secretaddresses(prefix='secretaddress', passphrase, num=10, pubtype=60, taddr=0)\n\ electrum(coin, ipaddr, port)\n\ snapshot(coin, height)\n\ snapshot_balance(coin, height, addresses[])\n\ @@ -186,7 +186,7 @@ dividends(coin, height, )\n\ uint8_t taddr,pubtype; pubtype = (jobj(argjson,"pubtype") == 0) ? 60 : juint(argjson,"pubtype"); taddr = (jobj(argjson,"taddr") == 0) ? 0 : juint(argjson,"taddr"); - return(LP_secretaddresses(ctx,jstr(argjson,"passphrase"),juint(argjson,"num"),taddr,pubtype)); + return(LP_secretaddresses(ctx,jstr(argjson,"prefix"),jstr(argjson,"passphrase"),juint(argjson,"num"),taddr,pubtype)); } if ( base != 0 && rel != 0 ) { @@ -311,6 +311,7 @@ dividends(coin, height, )\n\ jaddnum(retjson,"timestamp",time(NULL)); jadd(retjson,"alice",LP_inventory(coin)); //jadd(retjson,"bob",LP_inventory(coin,1)); + LP_smartutxos_push(ptr); return(jprint(retjson,1)); } } @@ -376,9 +377,19 @@ dividends(coin, height, )\n\ char *coinaddr; if ( (coinaddr= jstr(argjson,"address")) != 0 ) { - if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_mypriv25519) != 0 ) - LP_privkey_init(-1,ptr,G.LP_mypriv25519,G.LP_mypub25519); - LP_listunspent_issue(coin,coinaddr); + if ( coinaddr[0] != 0 ) + { + LP_listunspent_issue(coin,coinaddr); + if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_mypriv25519) != 0 ) + { + LP_privkey_init(-1,ptr,G.LP_mypriv25519,G.LP_mypub25519); + //LP_smartutxos_push(ptr); + } + else + { + + } + } return(jprint(LP_address_utxos(ptr,coinaddr,1),1)); } else return(clonestr("{\"error\":\"no address specified\"}")); } else return(clonestr("{\"error\":\"cant find coind\"}")); @@ -405,6 +416,26 @@ dividends(coin, height, )\n\ } else if ( strcmp(method,"checktxid") == 0 ) retstr = LP_spentcheck(argjson); + else if ( strcmp(method,"addr_unspents") == 0 ) + { + //printf("GOT ADDR_UNSPENTS\n"); + if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 ) + { + char *coinaddr; //cJSON *array,*item,*req; int32_t i,n,vout,height; bits256 zero,txid; uint64_t value; + if ( (coinaddr= jstr(argjson,"address")) != 0 ) + { + if ( coinaddr[0] != 0 ) + { + if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_mypriv25519) != 0 ) + { + //printf("%s %s is my address being asked for!\n",ptr->symbol,coinaddr); + ptr->addr_listunspent_requested = (uint32_t)time(NULL); + } + } + } + } + retstr = clonestr("{\"result\":\"success\"}"); + } else if ( strcmp(method,"getcoins") == 0 ) return(jprint(LP_coinsjson(0),1)); else if ( strcmp(method,"numutxos") == 0 ) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 5faed5c43..c3ee027af 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -183,7 +183,7 @@ struct iguana_info portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses; uint64_t txfee; int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; - uint32_t lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime; + uint32_t addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime; uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag; char symbol[16],smartaddr[64],userpass[1024],serverport[128],lastunspent[64]; // portfolio @@ -312,6 +312,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS int32_t LP_mempoolscan(char *symbol,bits256 searchtxid); int32_t LP_txheight(struct iguana_info *coin,bits256 txid); int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight); +void LP_smartutxos_push(struct iguana_info *coin); cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret); cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout); void LP_postutxos(char *symbol,char *coinaddr); @@ -325,5 +326,6 @@ double LP_getestimatedrate(struct iguana_info *coin); struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout); struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout); +void LP_listunspent_query(char *symbol,char *coinaddr); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 627f507ae..655cdb012 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -257,12 +257,14 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int { if ( jobj(argjson,"method") != 0 && strcmp("connect",jstr(argjson,"method")) == 0 ) printf("self.(%s)\n",str); + 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); } free_json(argjson); + portable_mutex_unlock(&LP_commandmutex); } free(str); } @@ -310,21 +312,71 @@ void command_rpcloop(void *myipaddr) if ( nonz == 0 ) { if ( IAMLP != 0 ) - usleep(10); - else usleep(1000); + usleep(1000); + else usleep(10000); } } } +void LP_smartutxos_push(struct iguana_info *coin) +{ + struct LP_peerinfo *peer,*tmp; uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; char *retstr; cJSON *array,*item,*req; + if ( coin->smartaddr[0] == 0 ) + return; + if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + printf("PUSH %s %s\n",coin->symbol,coin->smartaddr); + for (i=0; iipaddr,peer->port,coin->symbol,coin->smartaddr,txid,vout,height,value)) != 0 ) + free(retstr); + } + } + else + { + 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_broadcast_message(LP_mypubsock,"","",zero,jprint(req,1)); + } + } + } + free_json(array); + } +} + 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; + if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) + return(0); HASH_ITER(hh,LP_coins,coin,ctmp) { - if ( coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) ) + if ( IAMLP == 0 && coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) ) + continue; + if ( coin->smartaddr[0] == 0 ) continue; total = 0; - LP_listunspent_both(coin->symbol,coin->smartaddr); + if ( (j= LP_listunspent_both(coin->symbol,coin->smartaddr)) == 0 ) + continue; if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 ) { if ( (n= cJSON_GetArraySize(array)) > 0 ) @@ -337,6 +389,7 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer) } if ( n > 0 && total > 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr)) != 0 ) { + //printf("UTXO sync.%d %s n.%d total %.8f -> %s (%s)\n",j,coin->symbol,n,dstr(total),peer->ipaddr,retstr); total2 = 0; if ( (array2= cJSON_Parse(retstr)) != 0 ) { @@ -362,7 +415,7 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer) } if ( j == m ) { - //printf("%s missing %s\n",peer->ipaddr,jprint(item,0)); + //printf("%s missing %s %s\n",peer->ipaddr,coin->symbol,jprint(item,0)); 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++; @@ -370,13 +423,26 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer) } if ( 0 && posted != 0 ) printf(">>>>>>>> %s compare %s %s (%.8f n%d) (%.8f m%d)\n",peer->ipaddr,coin->symbol,coin->smartaddr,dstr(total),n,dstr(total2),m); - } //else printf("%s matches\n",peer->ipaddr); + } //else printf("%s matches %s\n",peer->ipaddr,coin->symbol); free_json(array2); - } + } else printf("parse error (%s)\n",retstr); free(retstr); } + else if ( n != 0 && total != 0 ) + { + //printf("no response from %s for %s %s\n",peer->ipaddr,coin->symbol,coin->smartaddr); + for (i=0; iipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 ) + free(retstr2); + } + } + free_json(array); } - if ( (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 ) + if ( 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 ) { if ( (array2= cJSON_Parse(retstr)) != 0 ) { @@ -387,7 +453,7 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer) item = jitem(array2,j); if ( (coinaddr= jfieldname(item)) != 0 ) { - metric = j64bits(item,"coinaddr"); + metric = j64bits(item,coinaddr); //printf("(%s) -> %.8f n.%d\n",coinaddr,dstr(metric>>16),(uint16_t)metric); if ( (ap= LP_addressfind(coin,coinaddr)) == 0 || _LP_unspents_metric(ap->total,ap->n) != metric ) { @@ -441,24 +507,28 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int if ( IAMLP == 0 ) continue; } - if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 1000) == 0) ) + if ( now > peer->lastpeers+60 || (rand() % 10000) == 0 ) { - peer->lastpeers = now; if ( strcmp(peer->ipaddr,myipaddr) != 0 ) { + nonz++; LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport); peer->diduquery = 0; LP_utxos_sync(peer); } + peer->lastpeers = now; } if ( peer->diduquery == 0 ) { + nonz++; + needpings++; LP_peer_pricesquery(peer); LP_utxos_sync(peer); peer->diduquery = now; } if ( peer->needping != 0 ) { + nonz++; needpings++; 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); @@ -467,16 +537,24 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int } if ( needpings != 0 || (counter % 6000) == 5 ) { + nonz++; //printf("needpings.%d send notify\n",needpings); LP_notify_pubkeys(ctx,pubsock); } if ( (counter % 6000) == 10 ) { + nonz++; LP_privkey_updates(ctx,pubsock,0); } HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { memset(&zero,0,sizeof(zero)); + if ( coin->addr_listunspent_requested != 0 ) + { + printf("addr_listunspent_requested %u\n",coin->addr_listunspent_requested); + LP_smartutxos_push(coin); + coin->addr_listunspent_requested = 0; + } if ( coin->inactive != 0 ) continue; if ( coin->electrum != 0 ) @@ -485,6 +563,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int // continue; if ( time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR ) { + nonz++; if ( (height= LP_getheight(coin)) > coin->longestchain ) { coin->longestchain = height; @@ -529,6 +608,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int } if ( j < 100 ) continue; + nonz++; //LP_getestimatedrate(coin); break; } @@ -537,6 +617,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int if ( (retstr= basilisk_swapentry(0,0)) != 0 ) { //printf("SWAPS.(%s)\n",retstr); + nonz++; free(retstr); } } @@ -773,8 +854,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport) != 0 ) nonz++; if ( nonz == 0 ) - usleep(50000); - else usleep(5000); + usleep(10000); + else if ( IAMLP != 0 ) + usleep(1000); + else usleep(10000); } } diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index 3cb45116e..f9bb6b3e9 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -244,6 +244,18 @@ void LP_notify_pubkeys(void *ctx,int32_t pubsock) LP_broadcast_message(pubsock,"","",zero,msg); } +void LP_listunspent_query(char *symbol,char *coinaddr) +{ + bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject(); + memset(zero.bytes,0,sizeof(zero)); + jaddstr(reqjson,"method","addr_unspents"); + jaddstr(reqjson,"coin",symbol); + jaddstr(reqjson,"address",coinaddr); + msg = jprint(reqjson,1); + printf("BROADCAST.(%s)\n",msg); + LP_broadcast_message(LP_mypubsock,"","",zero,msg); +} + char *LP_postedprice(cJSON *argjson) { bits256 pubkey; double price; char *base,*rel; @@ -449,13 +461,13 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,struct LP_address_utxo **u if ( (backupep= ep->prev) == 0 ) backupep = ep; } - //printf("LP_nearest_utxovalue %s utxos[%d]\n",coin->symbol,n); + printf("LP_nearest_utxovalue %s utxos[%d] target %.8f\n",coin->symbol,n,dstr(targetval)); for (i=0; iU.value - targetval); - //printf("nearest i.%d target %.8f val %.8f dist %.8f mindist %.8f mini.%d spent.%d\n",i,dstr(targetval),dstr(up->U.value),dstr(dist),dstr(mindist),mini,up->spendheight); + printf("nearest i.%d target %.8f val %.8f dist %.8f mindist %.8f mini.%d spent.%d\n",i,dstr(targetval),dstr(up->U.value),dstr(dist),dstr(mindist),mini,up->spendheight); if ( up->spendheight <= 0 ) { if ( coin->electrum != 0 ) @@ -478,7 +490,7 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,struct LP_address_utxo **u } } } - //printf("return mini.%d\n",mini); + printf("return mini.%d\n",mini); return(mini); } @@ -511,7 +523,7 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo ** up = utxos[mini]; utxos[mini] = 0; targetval2 = (targetval / 8) * 9 + 2*txfee; - //printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(utxos[mini]->U.value),dstr(targetval),dstr(targetval2),(double)utxos[mini]->U.value/targetval); + printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval); if ( (double)up->U.value/targetval < LP_MINVOL-1 ) { if ( (mini= LP_nearest_utxovalue(coin,utxos,m,targetval2 * 1.01)) >= 0 ) @@ -724,7 +736,7 @@ char *LP_connectedalice(cJSON *argjson) // alice int32_t LP_listunspent_both(char *symbol,char *coinaddr) { int32_t i,v,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; struct iguana_info *coin = LP_coinfind(symbol); - if ( coin != 0 && coin->inactive == 0 ) + if ( coin != 0 )//&& (IAMLP != 0 || coin->inactive == 0) ) { if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 ) { @@ -943,9 +955,26 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q return(jprint(bestitem,0)); } +struct LP_utxoinfo *LP_ordermatch_iter(struct LP_address_utxo **utxos,int32_t max,double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct iguana_info *basecoin,char *coinaddr,uint64_t asatoshis,double price,uint64_t txfee,uint64_t desttxfee,bits256 pubkey,char *gui) +{ + uint64_t basesatoshis; struct LP_utxoinfo *bestutxo; + basesatoshis = LP_basesatoshis(dstr(asatoshis),price,txfee,desttxfee); + if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 ) + { + bestutxo->pubkey = pubkey; + safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui)); + *bestsatoshisp = basesatoshis; + *ordermatchpricep = price; + *bestdestsatoshisp = asatoshis; + return(bestutxo); + } + return(0); +} + struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,char *gui,bits256 *avoids,int32_t numavoids) { - bits256 pubkey; char *obookstr,coinaddr[64],str[65]; cJSON *orderbook,*asks,*item; int32_t i,j,n,numasks,max = 10000; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; struct iguana_info *basecoin; uint64_t basesatoshis; struct LP_utxoinfo *bestutxo = 0; + bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*item; int32_t maxiters,i,j,numasks,max = 10000; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0; + maxiters = 100; *ordermatchpricep = 0.; *bestsatoshisp = *bestdestsatoshisp = 0; basecoin = LP_coinfind(base); @@ -978,22 +1007,20 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i if ( bits256_cmp(pubkey,G.LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) { bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); - n = LP_listunspent_both(base,coinaddr); - //printf("unspent.(%s) n.%d\n",coinaddr,n); - if ( n > 1 ) + LP_listunspent_query(base,coinaddr); + LP_listunspent_both(base,coinaddr); + asatoshis = autxo->S.satoshis; + for (j=0; jS.satoshis),price,txfee,desttxfee); - if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 ) + if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,price,txfee,desttxfee,pubp->pubkey,gui)) != 0 ) { - bestutxo->pubkey = pubp->pubkey; - safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui)); - *bestsatoshisp = basesatoshis; - *ordermatchpricep = price; - *bestdestsatoshisp = autxo->S.satoshis; - printf("ordermatch %.8f %.8f %.8f txfees (%.8f %.8f)\n",price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee)); + printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee)); break; } - } else printf("no unspents %s %s %s\n",base,coinaddr,bits256_str(str,pubkey)); + asatoshis = (asatoshis / 64) * 63; + } + if ( j < maxiters ) + break; } else printf("self trading or blacklisted peer\n"); } else diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 9ceb2623e..9bf11f909 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -360,6 +360,8 @@ void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj) void LP_peer_pricesquery(struct LP_peerinfo *peer) { char *retstr; cJSON *array; int32_t i,n; + if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) + return; peer->needping = (uint32_t)time(NULL); if ( (retstr= issue_LP_getprices(peer->ipaddr,peer->port)) != 0 ) { @@ -771,9 +773,10 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) jaddi(array,LP_orderbookjson(rel,bids[i])); if ( bids[i]->numutxos == 0 )//|| relcoin->electrum == 0 ) { + LP_address(relcoin,bids[i]->coinaddr); if ( relcoin->electrum == 0 ) LP_listunspent_issue(rel,bids[i]->coinaddr); - else LP_address(relcoin,bids[i]->coinaddr); + LP_listunspent_query(rel,bids[i]->coinaddr); n++; } free(bids[i]); @@ -789,9 +792,10 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) jaddi(array,LP_orderbookjson(base,asks[i])); if ( asks[i]->numutxos == 0 )//|| basecoin->electrum == 0 ) { + LP_address(basecoin,asks[i]->coinaddr); if ( basecoin->electrum == 0 ) LP_listunspent_issue(base,asks[i]->coinaddr); - else LP_address(basecoin,asks[i]->coinaddr); + LP_listunspent_query(base,asks[i]->coinaddr); n++; } free(asks[i]); diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index c50a47853..fca22ef2a 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -346,7 +346,7 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag n++; if ( n == 0 ) { - printf("if nothing sent, it is finished\n"); + //printf("if nothing sent, it is finished\n"); return(1); } if ( iambob != 0 ) @@ -661,8 +661,18 @@ int32_t LP_refht_update(char *symbol,bits256 txid) int32_t LP_swap_load(struct LP_swap_remember *rswap) { - int32_t i,needflag,addflag; long fsize; char fname[1024],str[65],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj; bits256 txid,checktxid; uint64_t value; + int32_t i,needflag,addflag; long fsize; char fname[1024],str[65],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj,*fileobj; bits256 txid,checktxid; uint64_t value; rswap->iambob = -1; + sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap->requestid,rswap->quoteid), OS_compatible_path(fname); + if ( (fstr= OS_filestr(&fsize,fname)) != 0 ) + { + if ( (fileobj= cJSON_Parse(fstr)) != 0 ) + { + rswap->origfinishedflag = rswap->finishedflag = 1; + free_json(fileobj); + } + free(fstr); + } for (i=0; ifinishedflag == 0 ) - printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); + printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); } } } //else printf("no symbol\n"); @@ -851,13 +860,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti printf("Bob.%p is null or Alice.%p is null\n",bob,alice); return(cJSON_Parse("{\"error\":\"null bob or alice coin\"}")); } - printf("ALICE.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.Adestaddr,alice->symbol,alice->firstrefht,alice->firstscanht,alice->lastscanht); - printf("BOB.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.destaddr,bob->symbol,bob->firstrefht,bob->firstscanht,bob->lastscanht); //printf("iambob.%d finishedflag.%d %s %.8f txfee, %s %.8f txfee\n",rswap.iambob,rswap.finishedflag,rswap.alicecoin,dstr(rswap.Atxfee),rswap.bobcoin,dstr(rswap.Btxfee)); //printf("privAm.(%s) %p/%p\n",bits256_str(str,rswap.privAm),Adest,AAdest); //printf("privBn.(%s) %p/%p\n",bits256_str(str,rswap.privBn),Bdest,ABdest); if ( rswap.finishedflag == 0 && rswap.bobcoin[0] != 0 && rswap.alicecoin[0] != 0 ) { + //printf("ALICE.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.Adestaddr,alice->symbol,alice->firstrefht,alice->firstscanht,alice->lastscanht); + //printf("BOB.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.destaddr,bob->symbol,bob->firstrefht,bob->firstscanht,bob->lastscanht); if ( alice->inactive != 0 || bob->inactive != 0 ) { printf("Alice.%s inactive.%u or Bob.%s inactive.%u\n",rswap.alicecoin,alice->inactive,rswap.bobcoin,bob->inactive); @@ -1075,30 +1084,33 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti printf("depositspent.(%s) alice.%d bob.%d %s %.8f\n",bits256_str(str,rswap.depositspent),rswap.sentflags[BASILISK_ALICECLAIM],rswap.sentflags[BASILISK_BOBREFUND],rswap.bobcoin,dstr(rswap.values[BASILISK_BOBDEPOSIT])); } LP_totals_update(rswap.iambob,rswap.alicecoin,rswap.bobcoin,KMDtotals,BTCtotals,rswap.sentflags,rswap.values); + int32_t numspent = 0; if ( bits256_nonz(rswap.paymentspent) == 0 ) { if ( bits256_nonz(rswap.txids[BASILISK_ALICESPEND]) != 0 ) rswap.paymentspent = rswap.txids[BASILISK_ALICESPEND]; else rswap.paymentspent = rswap.txids[BASILISK_BOBRECLAIM]; - } + } else numspent++; if ( bits256_nonz(rswap.depositspent) == 0 ) { if ( bits256_nonz(rswap.txids[BASILISK_BOBREFUND]) != 0 ) rswap.depositspent = rswap.txids[BASILISK_BOBREFUND]; else rswap.depositspent = rswap.txids[BASILISK_ALICECLAIM]; - } + } else numspent++; if ( bits256_nonz(rswap.Apaymentspent) == 0 ) { if ( bits256_nonz(rswap.txids[BASILISK_BOBSPEND]) != 0 ) rswap.Apaymentspent = rswap.txids[BASILISK_BOBSPEND]; else rswap.Apaymentspent = rswap.txids[BASILISK_ALICERECLAIM]; - } - rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent); + } else numspent++; + if ( numspent == 3 ) + rswap.finishedflag = 1; + else rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent); item = LP_swap_json(&rswap); if ( rswap.origfinishedflag == 0 && rswap.finishedflag != 0 ) { char fname[1024],*itemstr; FILE *fp; - //printf("SWAP %u-%u finished!\n",requestid,quoteid); + printf("SWAP %u-%u finished!\n",requestid,quoteid); sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap.requestid,rswap.quoteid), OS_compatible_path(fname); if ( (fp= fopen(fname,"wb")) != 0 ) { diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index aa6296325..f6a66ead1 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -94,10 +94,11 @@ char *issue_LP_getprices(char *destip,uint16_t destport) char *issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr) { - char url[512]; + char url[512],*retstr; sprintf(url,"http://%s:%u/api/stats/listunspent?coin=%s&address=%s",destip,destport,symbol,coinaddr); - //printf("listunspent.(%s)\n",url); - return(LP_issue_curl("listunspent",destip,destport,url)); + retstr = LP_issue_curl("listunspent",destip,destport,url); + //printf("listunspent.(%s) -> (%s)\n",url,retstr); + return(retstr); } char *LP_apicall(struct iguana_info *coin,char *method,char *params) @@ -425,7 +426,7 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr) return(cJSON_Parse("{\"error\":\"null symbol\"}")); coin = LP_coinfind(symbol); //printf("LP_listunspent.(%s %s)\n",symbol,coinaddr); - if ( coin == 0 || coin->inactive != 0 ) + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) return(cJSON_Parse("{\"error\":\"no coin\"}")); if ( coin->electrum == 0 ) { @@ -439,7 +440,7 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr) int32_t LP_listunspent_issue(char *symbol,char *coinaddr) { - struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0,destip[64]; uint16_t destport; + struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0;// uint16_t destport; if ( symbol == 0 || symbol[0] == 0 ) return(0); if ( (coin= LP_coinfind(symbol)) != 0 ) @@ -459,11 +460,14 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr) retjson = LP_listunspent(symbol,coinaddr); //printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr); } - else if ( (destport= LP_randpeer(destip)) > 0 ) + else if ( IAMLP == 0 ) + LP_listunspent_query(coin->symbol,coin->smartaddr); + /*else if ( (destport= LP_randpeer(destip)) > 0 ) { retstr = issue_LP_listunspent(destip,destport,symbol,coinaddr); + printf("issue %s %s %s -> (%s)\n",coin->symbol,coinaddr,destip,retstr); retjson = cJSON_Parse(retstr); - } else printf("LP_listunspent_issue couldnt get a random peer?\n"); + } else printf("LP_listunspent_issue couldnt get a random peer?\n");*/ if ( retjson != 0 ) { n = cJSON_GetArraySize(retjson); diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index 15647fcb7..f17c9284a 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -909,7 +909,7 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) } else { - printf("launched.(%s:%u)\n",ep->ipaddr,ep->port); + printf("launched electrum.(%s:%u)\n",ep->ipaddr,ep->port); jaddstr(retjson,"result","success"); ep->prev = coin->electrum; coin->electrum = ep; diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 0f839b6af..c59d9f203 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -671,7 +671,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime) { - char *retstr; cJSON *retjson=0; uint32_t divisor=8,expiration = (uint32_t)(time(NULL) + duration); + char *retstr; cJSON *retjson=0; uint32_t expiration = (uint32_t)(time(NULL) + duration); printf("wait %d:%d for SWAP.(r%u/q%u) to complete\n",duration,sleeptime,requestid,quoteid); sleep(10); //if ( sleeptime < divisor*60 ) diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index a5d66d712..869b17d59 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -935,13 +935,21 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout) { - bits256 spendtxid; int32_t spendvin; char coinaddr[64],str[65]; + bits256 spendtxid; int32_t spendvin; char coinaddr[64],str[65]; cJSON *retjson; struct iguana_info *coin; // listtransactions or listspents destaddr[0] = 0; coinaddr[0] = 0; memset(&spendtxid,0,sizeof(spendtxid)); if ( LP_spendsearch(&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 ) printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout); + else if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 ) + { + if ( (retjson= LP_gettxout(symbol,coinaddr,utxotxid,vout)) == 0 ) + { + decode_hex(spendtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + printf("couldnt find spend of %s/v%d, but no gettxout\n",bits256_str(str,utxotxid),vout); + } else free_json(retjson); + } return(spendtxid); //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); } diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 982e45cbb..eedac4669 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -189,7 +189,7 @@ struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coina int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight) { - struct LP_address *ap; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; char str[65]; + struct LP_address *ap; cJSON *txobj; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; char str[65]; //printf("%s add addr.%s ht.%d\n",coin->symbol,coinaddr,height); if ( coin == 0 ) return(0); @@ -216,6 +216,14 @@ int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid, } if ( flag == 0 ) { + if ( coin->electrum == 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) == 0 ) + { + //printf("prevent utxoadd since gettxout %s/v%d missing\n",bits256_str(str,txid),vout); + return(0); + } else free_json(txobj); + } up = calloc(1,sizeof(*up)); up->U.txid = txid; up->U.vout = vout; @@ -333,7 +341,7 @@ int32_t LP_merkleproof(struct iguana_info *coin,struct electrum_info *ep,bits256 cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret) { - cJSON *array,*item; int32_t n; uint64_t total; struct LP_address *ap=0,*atmp; struct LP_address_utxo *up,*tmp; struct electrum_info *ep,*backupep=0; + cJSON *array,*item; int32_t n; uint64_t total; struct LP_address *ap=0,*atmp; struct LP_address_utxo *up,*tmp; cJSON *txobj; struct electrum_info *ep,*backupep=0; array = cJSON_CreateArray(); if ( coinaddr != 0 && coinaddr[0] != 0 ) { @@ -350,11 +358,20 @@ cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrum { if ( up->spendheight <= 0 && up->U.height > 0 ) { - if ( backupep != 0 && up->SPV == 0 ) - up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height); - jaddi(array,LP_address_item(coin,up,electrumret)); - n++; - total += up->U.value; + if ( coin->electrum == 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,coinaddr,up->U.txid,up->U.vout)) == 0 ) + up->spendheight = 1; + else free_json(txobj); + } + if ( up->spendheight <= 0 ) + { + if ( backupep != 0 && up->SPV == 0 ) + up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height); + jaddi(array,LP_address_item(coin,up,electrumret)); + n++; + total += up->U.value; + } //printf("new array %s\n",jprint(array,0)); } } diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index a651813b2..588ccd3f3 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -345,7 +345,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t } if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,vout2,0)) <= 0 ) { - printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms); + printf("LP_utxoadd reject2 numconfirms.%d %s %s/v%d\n",numconfirms,symbol,bits256_str(str,txid2),vout2); return(0); } } @@ -472,7 +472,7 @@ cJSON *LP_inventory(char *symbol) // LP_utxo_clientpublish(utxo); jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); } - else if ( LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 ) + else if ( 0 && LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 ) printf("skip %s %s %d %d %d %d\n",utxo->coin,bits256_str(str,utxo->payment.txid),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); } return(array); @@ -512,9 +512,9 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri { int32_t enable_utxos = 0; char *script,destaddr[64]; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,value,total = 0; int64_t targetval; - if ( coin == 0 || coin->inactive != 0 ) + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) { - printf("coin not active\n"); + //printf("coin not active\n"); return(0); } //printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr); @@ -654,10 +654,12 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri return(flag); } -char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype) +char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype) { int32_t i; uint8_t tmptype,pubkey33[33],rmd160[20]; char output[777*45],str[65],str2[65],buf[8192],wifstr[128],coinaddr[64]; bits256 checkprivkey,privkey,pubkey; cJSON *retjson; retjson = cJSON_CreateObject(); + if ( prefix == 0 || prefix[0] == 0 ) + prefix = "secretaddress"; if ( passphrase == 0 || passphrase[0] == 0 ) passphrase = "password"; if ( n <= 0 ) @@ -670,7 +672,7 @@ char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint sprintf(output,"\"addresses\":["); for (i=0; iinactive == 0 ) + else if ( IAMLP == 0 || coin->inactive == 0 ) { if ( LP_privkey_init(pubsock,coin,G.LP_mypriv25519,G.LP_mypub25519) == 0 && (rand() % 10) == 0 ) LP_postutxos(coin->symbol,coin->smartaddr); diff --git a/iguana/exchanges/enable b/iguana/exchanges/enable index d6a287b3a..75c0bc838 100755 --- a/iguana/exchanges/enable +++ b/iguana/exchanges/enable @@ -1,3 +1,4 @@ #!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"REVS\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"CHIPS\"}" diff --git a/iguana/exchanges/listunspent b/iguana/exchanges/listunspent index aa7ca4963..9b03640f3 100755 --- a/iguana/exchanges/listunspent +++ b/iguana/exchanges/listunspent @@ -1,3 +1,2 @@ -#!/bin/bash source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"listunspent\",\"coin\":\"BTC\",\"address\":\"1DPDsPCNNCF5SHhPPrddXcJe78rM6CBcH3\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"listunspent\",\"coin\":\"CHIPS\",\"address\":\"RMfQwu5ey23eWJ4as2ckd8dqsQJwo836ny\"}" diff --git a/iguana/exchanges/mm.c b/iguana/exchanges/mm.c index 84758ac24..73d998990 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -886,7 +886,7 @@ int main(int argc, const char * argv[]) { printf("error launching LP_main (%s)\n",jprint(retjson,0)); exit(-1); - } else printf("(%s) launched.(%s)\n",argv[1],passphrase); + } //else printf("(%s) launched.(%s)\n",argv[1],passphrase); incr = 100.; while ( (1) ) sleep(1); diff --git a/iguana/exchanges/stats.c b/iguana/exchanges/stats.c index 7eb82bba9..ec525d29d 100644 --- a/iguana/exchanges/stats.c +++ b/iguana/exchanges/stats.c @@ -556,163 +556,194 @@ int32_t iguana_getheadersize(char *buf,int32_t recvlen) return(recvlen); } -void stats_rpcloop(void *args) +uint16_t RPC_port; +extern portable_mutex_t LP_commandmutex; + +void LP_rpc_processreq(void *_ptr) { - static char *jsonbuf; - uint16_t port; char filetype[128],content_type[128]; - int32_t recvlen,flag,bindsock,postflag=0,contentlen,sock,remains,numsent,jsonflag=0,hdrsize,len; - socklen_t clilen; char helpname[512],remoteaddr[64],*buf,*retstr,*space; - struct sockaddr_in cli_addr; uint32_t ipbits,i,size = 32*IGUANA_MAXPACKETSIZE + 512; - if ( (port= *(uint16_t *)args) == 0 ) - port = 7779; - if ( jsonbuf == 0 ) - jsonbuf = calloc(1,IGUANA_MAXPACKETSIZE); - while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 ) - { - //if ( coin->MAXPEERS == 1 ) - // break; - //exit(-1); - sleep(3); - } - printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock); + uint64_t arg64 = *(uint64_t *)_ptr; + char filetype[128],content_type[128]; + int32_t recvlen,flag,postflag=0,contentlen,remains,sock,numsent,jsonflag=0,hdrsize,len; + char helpname[512],remoteaddr[64],*buf,*retstr,*space,*jsonbuf; + uint32_t ipbits,i,size = 32*IGUANA_MAXPACKETSIZE + 512; + ipbits = (arg64 >> 32); + expand_ipbits(remoteaddr,ipbits); + sock = (arg64 & 0xffffffff); + recvlen = flag = 0; + retstr = 0; space = calloc(1,size); - while ( bindsock >= 0 ) + jsonbuf = calloc(1,size); + remains = size-1; + buf = jsonbuf; + while ( remains > 0 ) { - clilen = sizeof(cli_addr); - sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen); - if ( sock < 0 ) - { - //printf("iguana_rpcloop ERROR on accept usock.%d errno %d %s\n",sock,errno,strerror(errno)); - continue; - } - memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); - expand_ipbits(remoteaddr,ipbits); - //printf("remote RPC request from (%s) %x\n",remoteaddr,ipbits); - - memset(jsonbuf,0,IGUANA_MAXPACKETSIZE); - remains = (int32_t)(IGUANA_MAXPACKETSIZE - 1); - buf = jsonbuf; - recvlen = flag = 0; - retstr = 0; - while ( remains > 0 ) + //printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen); + if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 ) { - //printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen); - if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 ) + if ( errno == EAGAIN ) { - if ( errno == EAGAIN ) - { - printf("EAGAIN for len %d, remains.%d\n",len,remains); - usleep(10000); - } - break; + printf("EAGAIN for len %d, remains.%d\n",len,remains); + usleep(10000); } - else + break; + } + else + { + if ( len > 0 ) { - if ( len > 0 ) + buf[len] = 0; + if ( recvlen == 0 ) { - buf[len] = 0; - if ( recvlen == 0 ) + if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 ) { - if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 ) + hdrsize = iguana_getheadersize(buf,recvlen); + if ( hdrsize > 0 ) { - hdrsize = iguana_getheadersize(buf,recvlen); - if ( hdrsize > 0 ) + if ( len < (hdrsize + contentlen) ) { - if ( len < (hdrsize + contentlen) ) - { - remains = (hdrsize + contentlen) - len; - buf = &buf[len]; - flag = 1; - //printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len); - continue; - } + remains = (hdrsize + contentlen) - len; + buf = &buf[len]; + flag = 1; + //printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len); + continue; } } } - recvlen += len; - remains -= len; - buf = &buf[len]; - if ( flag == 0 || remains <= 0 ) - break; - } - else - { - usleep(10000); - //printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len); - //retstr = iguana_rpcparse(space,size,&postflag,jsonbuf); - if ( flag == 0 ) - break; } + recvlen += len; + remains -= len; + buf = &buf[len]; + if ( flag == 0 || remains <= 0 ) + break; } - } - content_type[0] = 0; - if ( recvlen > 0 ) - { - retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,port); - if ( filetype[0] != 0 ) + else { - static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize; - sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR); - if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 ) - { - mimejson = cJSON_Parse(tmp); - free(tmp); - } - if ( mimejson != 0 ) - { - if ( (typestr= jstr(mimejson,filetype)) != 0 ) - sprintf(content_type,"Content-Type: %s\r\n",typestr); - } else printf("parse error.(%s)\n",tmp); - //printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type); + usleep(10000); + //printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len); + //retstr = iguana_rpcparse(space,size,&postflag,jsonbuf); + if ( flag == 0 ) + break; } } - if ( retstr != 0 ) + } + content_type[0] = 0; + if ( recvlen > 0 ) + { + jsonflag = postflag = 0; + portable_mutex_lock(&LP_commandmutex); + retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,RPC_port); + //if ( strcmp("5.9.253.195",remoteaddr) == 0 ) + // printf("RPC.(%s)%s\n",jsonbuf,retstr); + portable_mutex_unlock(&LP_commandmutex); + if ( filetype[0] != 0 ) { - char *response,hdrs[1024]; - //printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag); - if ( jsonflag != 0 || postflag != 0 ) + static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize; + sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR); + if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 ) { - if ( retstr == 0 ) - retstr = clonestr("{}"); - response = malloc(strlen(retstr)+1024+1+1); - sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); - response[0] = '\0'; - strcat(response,hdrs); - strcat(response,retstr); - strcat(response,"\n"); - if ( retstr != space ) - free(retstr); - retstr = response; - //printf("RET.(%s)\n",retstr); + mimejson = cJSON_Parse(tmp); + free(tmp); } - remains = (int32_t)strlen(retstr); - i = 0; - while ( remains > 0 ) + if ( mimejson != 0 ) { - if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 ) - { - if ( errno != EAGAIN && errno != EWOULDBLOCK ) - { - //printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock); - break; - } - } - else if ( remains > 0 ) + if ( (typestr= jstr(mimejson,filetype)) != 0 ) + sprintf(content_type,"Content-Type: %s\r\n",typestr); + } else printf("parse error.(%s)\n",tmp); + //printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type); + } + } + if ( retstr != 0 ) + { + char *response,hdrs[1024]; + //printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag); + if ( jsonflag != 0 || postflag != 0 ) + { + if ( retstr == 0 ) + retstr = clonestr("{}"); + response = malloc(strlen(retstr)+1024+1+1); + sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); + response[0] = '\0'; + strcat(response,hdrs); + strcat(response,retstr); + strcat(response,"\n"); + if ( retstr != space ) + free(retstr); + retstr = response; + //printf("RET.(%s)\n",retstr); + } + remains = (int32_t)strlen(retstr); + i = 0; + while ( remains > 0 ) + { + if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 ) + { + if ( errno != EAGAIN && errno != EWOULDBLOCK ) { - remains -= numsent; - i += numsent; - if ( remains > 0 ) - printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen); + //printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock); + break; } } - if ( retstr != space) - free(retstr); + else if ( remains > 0 ) + { + remains -= numsent; + i += numsent; + if ( remains > 0 ) + printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen); + } + } + if ( retstr != space) + free(retstr); + } + free(space); + free(jsonbuf); + closesocket(sock); +} + +void stats_rpcloop(void *args) +{ + uint16_t port; int32_t sock,bindsock; socklen_t clilen; struct sockaddr_in cli_addr; uint32_t ipbits; uint64_t arg64; void *arg64ptr; + if ( (port= *(uint16_t *)args) == 0 ) + port = 7779; + RPC_port = port; + while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 ) + { + //if ( coin->MAXPEERS == 1 ) + // break; + //exit(-1); + sleep(3); + } + printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock); + while ( bindsock >= 0 ) + { + clilen = sizeof(cli_addr); + sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen); + if ( sock < 0 ) + { + //printf("iguana_rpcloop ERROR on accept usock.%d errno %d %s\n",sock,errno,strerror(errno)); + continue; } - closesocket(sock); + memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); + //printf("remote RPC request from (%s) %x\n",remoteaddr,ipbits); + arg64 = ((uint64_t)ipbits << 32) | (sock & 0xffffffff); + arg64ptr = malloc(sizeof(arg64)); + memcpy(arg64ptr,&arg64,sizeof(arg64)); + if ( 1 ) + { + LP_rpc_processreq((void *)&arg64); + free(arg64ptr); + } + else if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_rpc_processreq,arg64ptr) != 0 ) + { + printf("error launching rpc handler on port %d\n",port); + } + // yes, small leak per command } } #ifndef FROM_MARKETMAKER + +portable_mutex_t LP_commandmutex; + void stats_kvjson(FILE *logfp,int32_t height,int32_t savedheight,uint32_t timestamp,char *key,cJSON *kvjson,bits256 pubkey,bits256 sigprev) { struct tai T; int32_t seconds,datenum,n;