diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index f624cd342..6bb5d3a12 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -96,6 +96,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) { retstr = jprint(result,0); + //printf("%s %s rpc retstr.%p\n",command,params,retstr); len = strlen(retstr); if ( retstr[0] == '"' && retstr[len-1] == '"' ) { @@ -112,7 +113,10 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * rpcstr = 0; } if ( rpcstr != 0 ) + { + //printf("free rpcstr.%p\n",rpcstr); free(rpcstr); + } } else retstr = rpcstr; free_json(json); //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); @@ -231,30 +235,30 @@ try_again: free(databuf); databuf = 0; } + retstr = chunk.memory; // retstr = s.ptr; if ( res != CURLE_OK ) { numretries++; if ( specialcase != 0 || timeout != 0 ) { - //printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); - free(chunk.memory); //free(s.ptr); + //printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,retstr,res); + free(retstr); return(0); } else if ( numretries >= 4 ) { printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); //printf("Maximum number of retries exceeded!\n"); - free(chunk.memory);//free(s.ptr); + free(retstr); return(0); } - free(chunk.memory);//free(s.ptr); + free(retstr); sleep((1<memory = (ptr != 0) ? realloc(mem->memory,needed) : malloc(needed); + //printf("mem->memory.%p len.%d\n",mem->memory,(int32_t)needed); mem->allocsize = needed; } //mem->memory = (ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1); diff --git a/iguana/dpow/dpow_network.c b/iguana/dpow/dpow_network.c index 9899b9cac..c7e5d311a 100755 --- a/iguana/dpow/dpow_network.c +++ b/iguana/dpow/dpow_network.c @@ -584,6 +584,8 @@ char *dex_response(int32_t *broadcastflagp,struct supernet_info *myinfo,struct d { char buf[65],*retstr = 0; int32_t i,datalen; bits256 hash2; cJSON *retjson=0; struct iguana_info *coin; struct dex_request dexreq; *broadcastflagp = 0; +return(clonestr("{\"error\":\"basilisk disabled\"}")); + if ( strcmp(dexp->handler,"request") == 0 ) { datalen = dex_rwrequest(0,dexp->packet,&dexreq); diff --git a/iguana/exchanges/LP_RTmetrics.c b/iguana/exchanges/LP_RTmetrics.c index 53466e5e7..7bbab1c38 100644 --- a/iguana/exchanges/LP_RTmetrics.c +++ b/iguana/exchanges/LP_RTmetrics.c @@ -27,11 +27,13 @@ struct LP_metricinfo int32_t ind,numutxos,age,pendingswaps; }; +#define LP_NUMRT 1024 struct LP_RTmetrics_pendings { - char refbase[65],refrel[65]; - int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[1024]; - bits256 avoidtxids[8192],whitelist[1024],blacklist[1024],pending_pubkeys[1024]; + char refbase[128],refrel[128]; + int64_t pending_kmdvalue[LP_NUMRT]; + int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[LP_NUMRT]; + bits256 avoidtxids[8192],whitelist[LP_NUMRT],blacklist[LP_NUMRT],pending_pubkeys[LP_NUMRT]; } LP_RTmetrics; int32_t LP_bits256_find(bits256 *list,int32_t num,bits256 val) @@ -72,11 +74,14 @@ int32_t LP_RTmetrics_blacklistadd(bits256 pubkey) return(LP_bits256_add("LP_RTmetrics_blacklistadd blacklist",LP_RTmetrics.blacklist,&LP_RTmetrics.numblacklist,(int32_t)(sizeof(LP_RTmetrics.blacklist)/sizeof(*LP_RTmetrics.blacklist)),pubkey)); } -int32_t LP_RTmetrics_pendingswap(bits256 pubkey) +int32_t LP_RTmetrics_pendingswap(bits256 pubkey,int64_t kmdvalue) { int32_t ind; if ( (ind= LP_bits256_add("LP_RTmetrics_pendingswap",LP_RTmetrics.pending_pubkeys,&LP_RTmetrics.numpendings,(int32_t)(sizeof(LP_RTmetrics.pending_pubkeys)/sizeof(*LP_RTmetrics.pending_pubkeys)),pubkey)) >= 0 ) + { LP_RTmetrics.pending_swaps[ind]++; + LP_RTmetrics.pending_kmdvalue[ind] += kmdvalue; + } return(ind); } @@ -113,7 +118,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums base = ""; if ( (rel= jstr(item,"rel")) == 0 ) rel = ""; - if ( strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 ) + if ( refbase[0] != 0 && strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 ) + continue; + if ( refrel[0] != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 ) continue; aliceid = j64bits(item,"aliceid"); basesatoshis = SATOSHIDEN * jdouble(item,"basevol"); @@ -123,8 +130,8 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums price = jdouble(item,"price"); requestid = juint(item,"requestid"); quoteid = juint(item,"quoteid"); - LP_RTmetrics_pendingswap(srcpub); - LP_RTmetrics_pendingswap(destpub); + LP_RTmetrics_pendingswap(srcpub,LP_kmdvalue(base,basesatoshis)); + LP_RTmetrics_pendingswap(destpub,LP_kmdvalue(rel,relsatoshis)); if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) // no need for this { if ( (swapjson= cJSON_Parse(retstr)) != 0 ) @@ -142,9 +149,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums } } -void LP_RTmetrics_update(char *base,char *rel) +/*void LP_RTmetrics_init() { - struct LP_pubkeyinfo *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 zero; char *retstr; cJSON *statsjson,*swaps; + struct LP_pubkey_info *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 pubkey,zero; cJSON *statsjson,*swaps; memset(&LP_RTmetrics,0,sizeof(LP_RTmetrics)); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { @@ -152,31 +159,38 @@ void LP_RTmetrics_update(char *base,char *rel) LP_RTmetrics_whitelistadd(pubp->pubkey); else if ( pubp->istrusted < 0 ) LP_RTmetrics_blacklistadd(pubp->pubkey); + pubp->swaps_kmdvalue = 0; } futuretime = (uint32_t)time(NULL) + 3600*100; memset(zero.bytes,0,sizeof(zero)); - if ( (retstr= LP_statslog_disp(100,futuretime,futuretime,"",zero)) != 0 ) + if ( (statsjson= LP_statslog_disp(futuretime,futuretime,"",zero,0,0)) != 0 ) { - if ( (statsjson= cJSON_Parse(retstr)) != 0 ) + if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 ) { - if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 ) - { - //printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0)); - if ( numswaps > 0 ) - LP_RTmetrics_swapsinfo(base,rel,swaps,numswaps); - } - free_json(statsjson); + //printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0)); + if ( numswaps > 0 ) + LP_RTmetrics_swapsinfo("","",swaps,numswaps); } - free(retstr); + free_json(statsjson); } for (i=0; i LP_MAXPENDING_SWAPS ) { - char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,LP_RTmetrics.pending_pubkeys[i]),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS); - LP_RTmetrics_blacklistadd(LP_RTmetrics.pending_pubkeys[i]); + char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS); + LP_RTmetrics_blacklistadd(pubkey); } + else if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) + { + char str[65]; printf("%s has %d pending swaps %.8f kmdvalue\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],dstr(LP_RTmetrics.pending_kmdvalue[i])); + pubp->swaps_kmdvalue = LP_RTmetrics.pending_kmdvalue[i]; + } + } //printf("%d pubkeys have pending swaps, whitelist.%d blacklist.%d avoidtxids.%d\n",LP_RTmetrics.numpendings,LP_RTmetrics.numwhitelist,LP_RTmetrics.numblacklist,LP_RTmetrics.numavoidtxids); -} +}*/ + + double _LP_RTmetric_calc(struct LP_metricinfo *mp,double bestprice,double maxprice,double relvolume) { diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index 15080f4e8..d76293234 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -1959,13 +1959,13 @@ int32_t bitcoin_timelockspend(uint8_t *script,int32_t n,uint8_t rmd160[20],uint3 return(n); } -int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t cltv_rmd160[20],uint8_t anytime_rmd160[20]) +int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t *cltvpub33,uint8_t *elsepub33) { script[n++] = SCRIPT_OP_IF; n = bitcoin_checklocktimeverify(script,n,unlocktimestamp); - n = bitcoin_standardspend(script,n,cltv_rmd160); + n = bitcoin_pubkeyspend(script,n,cltvpub33); script[n++] = SCRIPT_OP_ELSE; - n = bitcoin_standardspend(script,n,anytime_rmd160); + n = bitcoin_pubkeyspend(script,n,elsepub33); script[n++] = SCRIPT_OP_ENDIF; calc_rmd160_sha256(p2sh_rmd160,script,n); return(n); @@ -3309,9 +3309,9 @@ bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2sht dest.vins[i].userdatalen = 0; } len = iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys,zcash); - for (i=0; i 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 && { #ifdef BTC2_VERSION @@ -3322,7 +3322,7 @@ bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2sht revsigtxid = bits256_doublesha256(0,serialized,len); for (i=0; ielectrum,coin->smartaddr,retjson,1); + electrum_process_array(coin,coin->electrum,addr,retjson,1); free_json(retjson); } free(arraystr); diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index cfc83e95f..0bf61e969 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -286,20 +286,6 @@ cJSON *LP_coinsjson(int32_t showwif) return(array); } -uint32_t LP_sighash(char *symbol,int32_t zcash) -{ - uint32_t sighash; - sighash = SIGHASH_ALL; - if ( zcash == LP_IS_BITCOINCASH ) - sighash |= SIGHASH_FORKID; - else if ( zcash == LP_IS_BITCOINGOLD ) - { - sighash |= SIGHASH_FORKID; - sighash |= (LP_IS_BITCOINGOLD << 8); - } - return(sighash); -} - char *LP_getcoin(char *symbol) { int32_t numenabled,numdisabled; struct iguana_info *coin,*tmp; cJSON *item=0,*retjson; diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index d2f72406d..e8c9c401f 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -38,7 +38,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r method = jstr(argjson,"method"); if ( method != 0 && (strcmp(method,"addr_unspents") == 0 || strcmp(method,"uitem") == 0 || strcmp(method,"postutxos") == 0) ) return(0); -//printf("stats_JSON %s\n",method); +//printf("stats_JSON.(%s)\n",jprint(argjson,0)); /*if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) ) { if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 ) @@ -68,8 +68,16 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r } if ( strcmp(method,"hello") == 0 ) { + //int32_t i; cJSON *array = cJSON_CreateArray(); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"status","got hello"); + //for (i=0; i<10000; i++) + // jaddinum(array,i); + //jadd(retjson,"array",array); + return(jprint(retjson,1)); //printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport); - return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}")); + //return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}")); } /*else if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 ) { @@ -94,8 +102,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r else if ( strcmp(method,"help") == 0 ) return(clonestr("{\"result\":\" \ available localhost RPC commands: \n \ -pricearray(base, rel, starttime=0, endtime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\ -setprice(base, rel, price)\n\ +setprice(base, rel, price, broadcast=1)\n\ autoprice(base, rel, fixed, minprice, margin, refbase, refrel, factor, offset)*\n\ goal(coin=*, val=)\n\ myprice(base, rel)\n\ @@ -103,7 +110,9 @@ enable(coin)\n\ disable(coin)\n\ notarizations(coin)\n\ parselog()\n\ -statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\ +statsdisp(starttime=0, endtime=0, gui="", pubkey="", base="", rel="")\n\ +tradesarray(base, rel, starttime=-timescale*1024, endtime=, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]\n\ +pricearray(base, rel, starttime=0, endtime=0, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\ getrawtransaction(coin, txid)\n\ inventory(coin, reset=0, [passphrase=])\n\ bestfit(rel, relvolume)\n\ @@ -146,7 +155,8 @@ bot_settings(botid, newprice, newvolume)\n\ bot_status(botid)\n\ bot_stop(botid)\n\ bot_pause(botid)\n\ -bot_resume(botid)\n\ +zeroconf_deposit(weeks, amount, broadcast=0)\n\ +zeroconf_claim(address, expiration=0)\n\ \"}")); //sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\ @@ -183,6 +193,26 @@ bot_resume(botid)\n\ return(jprint(retjson,1)); } } + else if ( strcmp(method,"zeroconf_deposit") == 0 ) + { + if ( (ptr= LP_coinsearch("KMD")) != 0 ) + { + if ( jint(argjson,"weeks") < 0 || jdouble(argjson,"amount") < 10. ) + return(clonestr("{\"error\":\"deposit_create needs to have weeks and amount\"}")); + else return(LP_zeroconf_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jint(argjson,"broadcast"))); + } + return(clonestr("{\"error\":\"cant find KMD\"}")); + } + else if ( strcmp(method,"zeroconf_claim") == 0 ) + { + if ( (ptr= LP_coinsearch("KMD")) != 0 ) + { + if ( jstr(argjson,"address") == 0 ) + return(clonestr("{\"error\":\"deposit_claim needs to have address\"}")); + else return(LP_zeroconf_claim(ptr,jstr(argjson,"address"),juint(argjson,"expiration"))); + } + return(clonestr("{\"error\":\"cant find KMD\"}")); + } /*else if ( strcmp(method,"sendmessage") == 0 ) { if ( jobj(argjson,"method2") == 0 ) @@ -242,14 +272,13 @@ bot_resume(botid)\n\ } else if ( strcmp(method,"parselog") == 0 ) { - bits256 zero; int32_t n = LP_statslog_parse(); + bits256 zero; memset(zero.bytes,0,sizeof(zero)); - return(LP_statslog_disp(n,2000000000,2000000000,"",zero)); + return(jprint(LP_statslog_disp(2000000000,2000000000,"",zero,0,0),1)); } else if ( strcmp(method,"statsdisp") == 0 ) { - int32_t n = LP_statslog_parse(); - return(LP_statslog_disp(n,juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"))); + return(jprint(LP_statslog_disp(juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"),jstr(argjson,"base"),jstr(argjson,"rel")),1)); } else if ( strcmp(method,"secretaddresses") == 0 ) { @@ -262,13 +291,31 @@ bot_resume(botid)\n\ { uint32_t requestid,quoteid; if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) + { return(basilisk_swapentry(requestid,quoteid)); + } else if ( coin[0] != 0 ) return(basilisk_swapentries(coin,0,jint(argjson,"limit"))); else if ( base[0] != 0 && rel[0] != 0 ) return(basilisk_swapentries(base,rel,jint(argjson,"limit"))); else return(basilisk_swaplist(0,0)); } + else if ( strcmp(method,"dynamictrust") == 0 ) + { + struct LP_address *ap; char *coinaddr; + if ( (ptr= LP_coinsearch("KMD")) != 0 && (coinaddr= jstr(argjson,"address")) != 0 ) + { + if ( (ap= LP_addressfind(ptr,coinaddr)) != 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"address",coinaddr); + jaddnum(retjson,"zcredits",dstr(ap->zeroconf_credits)); + return(jprint(retjson,1)); + } + } + return(clonestr("{\"error\":\"cant find address\"}")); + } else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 ) return(retstr); if ( base[0] != 0 && rel[0] != 0 ) @@ -280,6 +327,20 @@ bot_resume(botid)\n\ return(clonestr("{\"error\":\"couldnt set autoprice\"}")); else return(clonestr("{\"result\":\"success\"}")); } + else if ( strcmp(method,"pricearray") == 0 ) + { + uint32_t firsttime; + if ( base[0] != 0 && rel[0] != 0 ) + { + if ( (firsttime= juint(argjson,"starttime")) < time(NULL)-30*24*3600 ) + firsttime = (uint32_t)(time(NULL)-30*24*3600); + return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } else return(clonestr("{\"error\":\"pricearray needs base and rel\"}")); + } + else if ( strcmp(method,"tradesarray") == 0 ) + { + return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) return(clonestr("{\"error\":\"at least one of coins disabled\"}")); price = jdouble(argjson,"price"); @@ -289,22 +350,10 @@ bot_resume(botid)\n\ return(clonestr("{\"error\":\"couldnt set price\"}")); //else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 ) // return(clonestr("{\"error\":\"couldnt set price\"}")); - else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio)); - } - else if ( strcmp(method,"pricearray") == 0 ) - { - uint32_t firsttime; - if ( base[0] != 0 && rel[0] != 0 ) - { - if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 ) - firsttime = (uint32_t)(time(NULL)-30*24*3600); - return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1)); - } else return(clonestr("{\"error\":\"pricearray needs base and rel\"}")); + else if ( jint(argjson,"broadcast") != 0 || jobj(argjson,"broadcast") == 0 ) + return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio)); + else return(clonestr("{\"result\":\"success\"}")); } - /*else if ( strcmp(method,"pricearray") == 0 ) - { - return(jprint(LP_pricearray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); - }*/ else if ( strcmp(method,"orderbook") == 0 ) return(LP_orderbook(base,rel,jint(argjson,"duration"))); else if ( strcmp(method,"myprice") == 0 ) @@ -361,13 +410,19 @@ bot_resume(botid)\n\ { ptr->inactive = 0; cJSON *array; - if ( ptr->smartaddr[0] != 0 ) - LP_unspents_load(coin,ptr->smartaddr); if ( LP_getheight(ptr) <= 0 ) { ptr->inactive = (uint32_t)time(NULL); return(clonestr("{\"error\":\"coin cant be activated till synced\"}")); - } else LP_unspents_load(coin,ptr->smartaddr); + } + else + { + if ( ptr->smartaddr[0] != 0 ) + LP_unspents_load(coin,ptr->smartaddr); + LP_unspents_load(coin,ptr->smartaddr); + if ( strcmp(ptr->symbol,"KMD") == 0 ) + LP_importaddress("KMD",BOTS_BONDADDRESS); + } array = cJSON_CreateArray(); jaddi(array,LP_coinjson(ptr,0)); return(jprint(array,1)); @@ -397,20 +452,13 @@ bot_resume(botid)\n\ LP_address(ptr,coinaddr); if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 ) { - LP_listunspent_issue(coin,coinaddr,2); - LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519); - //LP_smartutxos_push(ptr); - if ( ptr->electrum != 0 ) - return(LP_unspents_filestr(coin,ptr->smartaddr)); - else return(jprint(LP_address_utxos(ptr,coinaddr,1),1)); - } - else - { - return(clonestr("{\"error\":\"not my address\"}")); + //LP_listunspent_issue(coin,coinaddr,2); + //LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519); } + return(jprint(LP_listunspent(coin,coinaddr),1)); } - return(jprint(LP_address_utxos(ptr,coinaddr,1),1)); - } else return(clonestr("{\"error\":\"no address specified\"}")); + } + return(clonestr("{\"error\":\"no address specified\"}")); } else return(clonestr("{\"error\":\"cant find coind\"}")); } else if ( strcmp(method,"balance") == 0 ) @@ -539,9 +587,22 @@ bot_resume(botid)\n\ } argjson = reqjson; } + if ( strcmp(method,"gettradestatus") == 0 ) + retstr = clonestr("{\"result\":\"success\"}"); + } + else + { + if ( strcmp(method,"gettradestatus") == 0 ) + return(LP_gettradestatus(j64bits(argjson,"aliceid"))); + else if ( strcmp(method,"tradesarray") == 0 ) + { + return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } } // received response - if ( strcmp(method,"postprice") == 0 ) + if ( strcmp(method,"swapstatus") == 0 ) + return(LP_swapstatus_recv(argjson)); + else if ( strcmp(method,"postprice") == 0 ) return(LP_postprice_recv(argjson)); else if ( strcmp(method,"postutxos") == 0 ) return(LP_postutxos_recv(argjson)); @@ -568,8 +629,15 @@ bot_resume(botid)\n\ else if ( strcmp(method,"tradestatus") == 0 ) { + bits256 zero; cJSON *tmpjson; LP_tradecommand_log(argjson); - printf("GOT TRADESTATUS! %s\n",jprint(argjson,0)); + //printf("GOT TRADESTATUS! %s\n",jprint(argjson,0)); + if ( LP_statslog_parse() > 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (tmpjson= LP_statslog_disp(2000000000,2000000000,"",zero,0,0))) // pending swaps + free_json(tmpjson); + } retstr = clonestr("{\"result\":\"success\"}"); } else if ( strcmp(method,"wantnotify") == 0 ) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index adc089b75..1ba94ebfb 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -23,7 +23,7 @@ #define LP_MAJOR_VERSION "0" #define LP_MINOR_VERSION "1" -#define LP_BUILD_NUMBER "15256" +#define LP_BUILD_NUMBER "15377" #define LP_BARTERDEX_VERSION 1 #define LP_MAGICBITS 8 @@ -49,6 +49,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define LP_ELECTRUM_KEEPALIVE 60 #define LP_ELECTRUM_MAXERRORS 777 #define LP_MEMPOOL_TIMEINCR 10 +#define LP_SCREENWIDTH 1024 #define LP_MIN_PEERS 8 #define LP_MAX_PEERS 32 @@ -82,7 +83,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define LP_SWAPSTEP_TIMEOUT 30 #define LP_MIN_TXFEE 10000 #define LP_MINVOL 20 -#define LP_MINCLIENTVOL 100 +#define LP_MINCLIENTVOL 20 #define LP_MINSIZE_TXFEEMULT 10 #define LP_REQUIRED_TXFEE 0.8 @@ -98,6 +99,10 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" #define INSTANTDEX_KMD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" +#define BOTS_BONDADDRESS "RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P" +#define BOTS_BONDPUBKEY33 "03e641d22e1ff5a7d45c8880537e0b0a114d7b9fee2c18a6b4a8a80b6285292990" +#define LP_WEEKMULT (7 * 24 * 2600) +#define LP_FIRSTWEEKTIME 1510790400 // must be 0 mod LP_WEEKMULT //#define BASILISK_DISABLEWAITTX //#define BASILISK_DISABLESENDTX @@ -268,7 +273,7 @@ struct iguana_info portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses; uint64_t txfee; int32_t numutxos,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; - uint32_t loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime; + uint32_t loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime,electrumzeroconf; uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms; char symbol[128],smartaddr[64],userpass[1024],serverport[128]; // portfolio @@ -317,7 +322,7 @@ struct LP_address UT_hash_handle hh; struct LP_address_utxo *utxos; bits256 pubkey; - int64_t balance,total; + int64_t balance,total,zeroconf_credits; uint32_t timestamp,n,unspenttime; int32_t unspentheight; char coinaddr[40]; @@ -373,14 +378,27 @@ struct LP_pubkey_quote uint8_t baseind,relind,numutxos,scale; }; +struct LP_swapstats +{ + UT_hash_handle hh; + struct LP_quoteinfo Q; + bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent; + double qprice; + uint64_t aliceid; + uint32_t ind,methodind,finished,expired,lasttime; + char alicegui[32],bobgui[32]; +}; + +struct LP_pubswap { struct LP_pubswap *next,*prev; struct LP_swapstats *swap; }; + #define LP_MAXPRICEINFOS 256 -struct LP_pubkeyinfo +struct LP_pubkey_info { UT_hash_handle hh; bits256 pubkey; struct LP_pubkey_quote *quotes; - //float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; - //uint32_t timestamps[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; + struct LP_pubswap *bobswaps,*aliceswaps; + uint64_t dynamictrust; uint32_t timestamp,numerrors,lasttime; int32_t istrusted; uint8_t rmd160[20],sig[65],pubsecp[33],siglen; @@ -400,7 +418,7 @@ struct electrum_info }; uint32_t LP_sighash(char *symbol,int32_t zcash); -int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item); +int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item); int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp); int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson); struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr); @@ -408,7 +426,7 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx); uint32_t basilisk_requestid(struct basilisk_request *rp); uint32_t basilisk_quoteid(struct basilisk_request *rp); -struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp); +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust); char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params); uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend); //double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub); @@ -421,10 +439,12 @@ struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port); uint64_t LP_value_extract(cJSON *obj,int32_t addinterest); int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout); char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen); +int64_t LP_kmdvalue(char *symbol,int64_t satoshis); int64_t LP_komodo_interest(bits256 txid,int64_t value); void LP_availableset(bits256 txid,int32_t vout); int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2); int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock); +int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item); void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag); uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired); //void LP_utxo_clientpublish(struct LP_utxoinfo *utxo); @@ -440,6 +460,7 @@ struct iguana_info *LP_coinfind(char *symbol); int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32); char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price); int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height); +cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr); int32_t _LP_utxos_remove(bits256 txid,int32_t vout); int32_t LP_utxos_remove(bits256 txid,int32_t vout); struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins); @@ -453,7 +474,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout); int32_t LP_destaddr(char *destaddr,cJSON *item); int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration); -char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey); +cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel); uint32_t LP_heighttime(char *symbol,int32_t height); uint64_t LP_unspents_load(char *symbol,char *addr); int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout); @@ -472,6 +493,8 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout); void LP_postutxos(char *symbol,char *coinaddr); int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag); uint16_t LP_randpeer(char *destip); +uint32_t LP_atomic_locktime(char *base,char *rel); +struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey); char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired); char *LP_unspents_filestr(char *symbol,char *addr); cJSON *bitcoin_data2json(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); @@ -481,6 +504,8 @@ int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid); 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); +int64_t LP_dynamictrust(bits256 pubkey,int64_t kmdvalue); +struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr); void LP_listunspent_query(char *symbol,char *coinaddr); int32_t bitcoin_priv2wif(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype); diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index e0597dd41..d320b2e67 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -17,19 +17,20 @@ // LP_nativeDEX.c // marketmaker // +// feature requests: +// electrum memleak? // alice waiting for bestprice -// MNZ getcoin strangeness -// [{"date":1405699200,"high":0.0045388,"low":0.00403001,"open":0.00404545,"close":0.00435873,"relvol":44.34555992,"basevol":10311.88079097,"aveprice":0.00430043}, // minute, -// trying to do bot_sell and the output he sent me is this -//{"base":"KMD","rel":"MNZ","basevolume":"0.08","minprice":5.608418011097937,"gui":"gecko","method":"bot_sell","userpass":"4011dddbfd920f9fab037907c2a13ba7eec207245487efa61cd0c484f8b1d607"} -//{"error":"not enough funds","coin":"KMD","abalance":0.00204856,"balance":9.9999,"relvolume":0.08,"txfees":0.001,"shortfall":-9.9189,"withdraw": -//i assume bot_sell detected he didn't had the proper utxos, tried to make some with the withdraw-method and failed with "not enough funds" -// the reason: bot_sell uses basevolume:0.08 and the withdraw-method uses relvolume:0.08 - +// USD paxprice based USDvalue in portfolio +// cancel bid/ask // https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki for signing BCH/BTG -// improve critical section detection when parallel trades -// reduce mem: dont redundant store pubkey utxo info +// +// bugs, validations: +// waiting for alice and alice disconnects, can find bobpayment based on Q.txid +// portfolio value based on ask? +// disable basilisk +// verify encrypted destpubkey, broadcast:0 setprice +// improve critical section detection when parallel trades // previously, it used to show amount, kmd equiv, perc // dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections // bigendian architectures need to use little endian for sighash calcs @@ -89,21 +90,21 @@ void LP_millistats_update(struct LP_millistats *mp) } #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; +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; 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_pubkeyinfo *LP_pubkeyinfos; +struct LP_pubkey_info *LP_pubkeyinfos; struct rpcrequest_info *LP_garbage_collector; struct LP_address_utxo *LP_garbage_collector2; //uint32_t LP_deadman_switch; uint16_t LP_fixed_pairport,LP_publicport; -uint32_t LP_lastnonce,LP_counter,LP_swap_endcritical,LP_swap_critical; +uint32_t LP_lastnonce,LP_counter,LP_swap_endcritical,LP_swap_critical,LP_RTcount,LP_swapscount; int32_t LP_mybussock = -1; int32_t LP_mypubsock = -1; int32_t LP_mypullsock = -1; @@ -181,6 +182,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_transaction.c" #include "LP_stats.c" #include "LP_remember.c" +#include "LP_zeroconf.c" #include "LP_swap.c" #include "LP_peers.c" #include "LP_utxos.c" @@ -194,7 +196,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - char *retstr=0; + char *retstr=0; cJSON *retjson; bits256 zero; if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 ) return(0); if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 ) @@ -205,7 +207,13 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson //if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && //LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); } - } //else printf("finished tradecommand (%s)\n",jprint(argjson,0)); + } + else if ( LP_statslog_parse() > 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (retjson= LP_statslog_disp(2000000000,2000000000,"",zero,0,0))) // pending swaps + free_json(retjson); + } return(retstr); } @@ -315,8 +323,8 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, else { memset(zero.bytes,0,sizeof(zero)); - /*if ( (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"request") == 0 || strcmp(method,"requested") == 0 || strcmp(method,"connect") == 0 || strcmp(method,"connected") == 0) ) - printf("broadcast.(%s)\n",Broadcaststr);*/ + 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\"}"); @@ -538,6 +546,11 @@ void LP_coinsloop(void *_coins) coin->longestchain = LP_getheight(coin); if ( (ep= coin->electrum) != 0 ) { + if ( strcmp("KMD",coin->symbol) == 0 && coin->electrumzeroconf == 0 ) + { + LP_zeroconf_deposits(coin); + coin->electrumzeroconf = (uint32_t)time(NULL); + } if ( (backupep= ep->prev) == 0 ) backupep = ep; if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) @@ -547,8 +560,9 @@ void LP_coinsloop(void *_coins) } HASH_ITER(hh,coin->addresses,ap,atmp) { + break; //printf("call unspent %s\n",ap->coinaddr); - if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) + if ( strcmp(coin->smartaddr,ap->coinaddr) != 0 && (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) free_json(retjson); } if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) @@ -647,7 +661,7 @@ void LP_coinsloop(void *_coins) int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport) { - static uint32_t counter; + static uint32_t counter,didzeroconf; struct iguana_info *coin,*ctmp; char *origipaddr; uint32_t now; int32_t height,nonz = 0; if ( (origipaddr= myipaddr) == 0 ) origipaddr = "127.0.0.1"; @@ -656,6 +670,11 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { now = (uint32_t)time(NULL); + if ( coin->inactive == 0 && didzeroconf == 0 && strcmp("KMD",coin->symbol) == 0 ) + { + LP_zeroconf_deposits(coin); + didzeroconf = now; + } 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); @@ -694,7 +713,12 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) { if ( LP_getheight(coin) <= 0 ) coin->inactive = (uint32_t)time(NULL); - else LP_unspents_load(coin->symbol,coin->smartaddr); + else + { + LP_unspents_load(coin->symbol,coin->smartaddr); + if ( strcmp(coin->symbol,"KMD") == 0 ) + LP_importaddress("KMD",BOTS_BONDADDRESS); + } if ( coin->txfee == 0 && strcmp(coin->symbol,"BTC") != 0 ) coin->txfee = LP_MIN_TXFEE; } @@ -811,7 +835,7 @@ void LP_privkeysloop(void *ctx) void LP_swapsloop(void *ignore) { - char *retstr; + char *retstr; struct iguana_info *coin; strcpy(LP_swapsloop_stats.name,"LP_swapsloop"); LP_swapsloop_stats.threshold = 605000.; sleep(50); @@ -823,6 +847,124 @@ void LP_swapsloop(void *ignore) if ( (retstr= basilisk_swapentry(0,0)) != 0 ) free(retstr); sleep(600); + if ( (coin= LP_coinfind("KMD")) != 0 ) + LP_zeroconf_deposits(coin); + } +} + +void gc_loop(void *arg) +{ + 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 ( 1 ) + { + 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 *arg) +{ + struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0; + strcpy(queue_loop_stats.name,"queue_loop"); + queue_loop_stats.threshold = 1000.; + while ( 1 ) + { + LP_millistats_update(&queue_loop_stats); + //printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0); + n = nonz = flag = 0; + DL_FOREACH_SAFE(LP_Q,ptr,tmp) + { + n++; + flag = 0; + if ( ptr->sock >= 0 ) + { + 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 ( (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; + } + } + } + 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 ( arg == 0 ) + break; + if ( nonz == 0 ) + { + if ( IAMLP == 0 ) + usleep(50000); + else usleep(10000); + } } } @@ -969,6 +1111,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu portable_mutex_init(&LP_nanorecvsmutex); portable_mutex_init(&LP_tradebotsmutex); portable_mutex_init(&LP_cJSONmutex); + portable_mutex_init(&LP_logmutex); myipaddr = clonestr("127.0.0.1"); #ifndef _WIN32 #ifndef FROM_JS @@ -1125,6 +1268,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu exit(-1); } int32_t nonz; + LP_statslog_parse(); while ( 1 ) { nonz = 0; diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index d1b147bc8..0f680ad0b 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -265,122 +265,6 @@ int32_t LP_peerindsock(int32_t *peerindp) return(-1); } -void gc_loop(void *arg) -{ - 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 ( 1 ) - { - 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 *arg) -{ - struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0; - strcpy(queue_loop_stats.name,"queue_loop"); - queue_loop_stats.threshold = 1000.; - while ( 1 ) - { - LP_millistats_update(&queue_loop_stats); - //printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0); - n = nonz = flag = 0; - DL_FOREACH_SAFE(LP_Q,ptr,tmp) - { - n++; - flag = 0; - if ( ptr->sock >= 0 ) - { - 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 ( (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; - } - } - } - 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 ( arg == 0 ) - break; - if ( nonz == 0 ) - { - if ( IAMLP == 0 ) - usleep(50000); - else usleep(10000); - } - } -} - void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32_t msglen,int32_t needack) { int32_t maxind,peerind = 0; //sentbytes, diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index a8922f36a..c78fd2a2f 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -454,7 +454,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,cJSON *argjson,char *base,c printf("requestid.%u quoteid.%u is already in progres\n",qp->R.requestid,qp->R.quoteid); return(-1); } - if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp)) == 0 ) + if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp,LP_dynamictrust(qp->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis)) > 0)) == 0 ) { printf("cant initialize swap\n"); return(-1); @@ -614,6 +614,7 @@ char *LP_connectedalice(cJSON *argjson) // alice LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0); return(clonestr("{\"error\":\"no price set\"}")); } + //LP_RTmetrics_update(Q.srccoin,Q.destcoin); printf("%s/%s bid %.8f ask %.8f values %.8f %.8f\n",Q.srccoin,Q.destcoin,bid,ask,dstr(butxo->payment.value),dstr(butxo->deposit.value)); price = bid; if ( (coin= LP_coinfind(Q.destcoin)) == 0 ) @@ -625,7 +626,7 @@ char *LP_connectedalice(cJSON *argjson) // alice if ( bits256_nonz(Q.privkey) != 0 )//&& Q.quotetime >= Q.timestamp-3 ) { retjson = cJSON_CreateObject(); - if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q)) == 0 ) + if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q,LP_dynamictrust(Q.srchash,LP_kmdvalue(Q.srccoin,Q.satoshis)) > 0)) == 0 ) { jaddstr(retjson,"error","couldnt swapinit"); LP_availableset(Q.desttxid,Q.vout); @@ -733,7 +734,7 @@ char *LP_bestfit(char *rel,double relvolume) if ( relvolume <= 0. || LP_priceinfofind(rel) == 0 ) return(clonestr("{\"error\":\"invalid parameter\"}")); if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) - return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + return(clonestr("{\"error\":\"cant find utxo that is close enough in size\"}")); return(jprint(LP_utxojson(autxo),1)); } @@ -786,7 +787,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, LP_quoteparse(&Q,argjson); LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); LP_tradecommand_log(argjson); - printf("(%-10u %10u) %12s aliceid.%22llu %5s/%-5s %12.8f -> %12.8f price %12.8f\n",Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis); + printf("(%-10u %10u) %12s aliceid.%22llu %5s/%-5s %12.8f -> %12.8f price %12.8f | RT.%d %d\n",Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,LP_RTcount,LP_swapscount); retval = 1; autxo = &A; butxo = &B; @@ -907,7 +908,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, if ( counter > 3 || price > bestprice ) // skip if late or bad price return(retval); } else return(retval); - LP_RTmetrics_update(Q.srccoin,Q.destcoin); + //LP_RTmetrics_update(Q.srccoin,Q.destcoin); if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 ) { printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); @@ -1019,7 +1020,7 @@ struct LP_utxoinfo *LP_ordermatch_iter(struct LP_address_utxo **utxos,int32_t ma 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 destpubkey) { - bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*rawasks,*item; int32_t maxiters,i,j,numasks,max; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0; + bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*rawasks,*item; int32_t maxiters,i,j,numasks,max; struct LP_address_utxo **utxos; double price; struct LP_pubkey_info *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0; maxiters = 100; *ordermatchpricep = 0.; *bestsatoshisp = *bestdestsatoshisp = 0; @@ -1149,9 +1150,9 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel memset(pubkeys,0,sizeof(pubkeys)); LP_txfees(&txfee,&desttxfee,base,rel); destsatoshis = SATOSHIDEN * relvolume; - LP_address_utxo_reset(relcoin); + //LP_address_utxo_reset(relcoin); if ( (autxo= LP_utxo_bestfit(rel,destsatoshis + 2*desttxfee)) == 0 ) - return(clonestr("{\"error\":\"cant find alice utxo that is big enough\"}")); + return(clonestr("{\"error\":\"cant find alice utxo that is close enough in size\"}")); //printf("bestfit selected alice (%.8f %.8f) for %.8f sats %.8f\n",dstr(autxo->payment.value),dstr(autxo->fee.value),dstr(destsatoshis),dstr(autxo->S.satoshis)); if ( destsatoshis - desttxfee < autxo->S.satoshis ) { @@ -1181,7 +1182,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel LP_mypriceset(&changed,autxo->coin,base,1. / maxprice); return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey)); #ifdef oldway - LP_RTmetrics_update(base,rel); + //LP_RTmetrics_update(base,rel); while ( 1 ) { if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) diff --git a/iguana/exchanges/LP_portfolio.c b/iguana/exchanges/LP_portfolio.c index 4004a8c41..e8d42ffd1 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -94,7 +94,7 @@ char *LP_portfolio() if ( iter == 0 ) { //printf("from portfolio\n"); - LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519); + //LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519); coin->balanceA = LP_balance(&coin->valuesumA,0,coin->symbol,coin->smartaddr); coin->balanceB = LP_balance(&coin->valuesumB,1,coin->symbol,coin->smartaddr); if ( strcmp(coin->symbol,"KMD") != 0 ) diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 7c91647aa..4812891b0 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,7 +18,15 @@ // marketmaker // -struct LP_orderbookentry { bits256 pubkey; double price; uint64_t avesatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; }; +struct LP_orderbookentry +{ + bits256 pubkey; + double price; + uint64_t avesatoshis,maxsatoshis,depth,dynamictrust; + uint32_t timestamp; + int32_t numutxos; + char coinaddr[64]; +}; struct LP_priceinfo { @@ -49,7 +57,7 @@ struct LP_cacheinfo } *LP_cacheinfos; -float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind) +float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind) { struct LP_pubkey_quote *pq,*tmp; int32_t scale; int64_t scale64; *numutxosp = 0; @@ -75,7 +83,7 @@ float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatos return(0); } -void LP_pubkey_update(struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo) +void LP_pubkey_update(struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo) { struct LP_pubkey_quote *pq,*tmp; int64_t aveutxo,scale64,ave64,max64; int32_t scale; DL_FOREACH_SAFE(pubp->quotes,pq,tmp) @@ -214,9 +222,9 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout return(ptr); } -struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) +struct LP_pubkey_info *LP_pubkey_rmd160find(uint8_t rmd160[20]) { - struct LP_pubkeyinfo *pubp=0,*tmp; + struct LP_pubkey_info *pubp=0,*tmp; portable_mutex_lock(&LP_pubkeymutex); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { @@ -230,7 +238,7 @@ struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) { - uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp; HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 ) { @@ -246,7 +254,7 @@ struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) { - uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp; ap = calloc(1,sizeof(*ap)); safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); @@ -260,18 +268,18 @@ struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) return(ap); } -struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) +struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey) { - struct LP_pubkeyinfo *pubp=0; + struct LP_pubkey_info *pubp=0; portable_mutex_lock(&LP_pubkeymutex); HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); portable_mutex_unlock(&LP_pubkeymutex); return(pubp); } -struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) +struct LP_pubkey_info *LP_pubkeyadd(bits256 pubkey) { - char str[65]; struct LP_pubkeyinfo *pubp=0; + char str[65]; struct LP_pubkey_info *pubp=0; portable_mutex_lock(&LP_pubkeymutex); HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); if ( pubp == 0 ) @@ -294,7 +302,7 @@ struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) int32_t LP_pubkey_istrusted(bits256 pubkey) { - struct LP_pubkeyinfo *pubp; + struct LP_pubkey_info *pubp; if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) return(pubp->istrusted != 0); return(0); @@ -302,7 +310,7 @@ int32_t LP_pubkey_istrusted(bits256 pubkey) char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) { - struct LP_pubkeyinfo *pubp; + struct LP_pubkey_info *pubp; if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) { pubp->istrusted = trustval; @@ -313,7 +321,7 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) char *LP_pubkey_trusted() { - struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray(); + struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray(); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { if ( pubp->istrusted != 0 ) @@ -343,7 +351,7 @@ uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) return(metric); } -cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) +cJSON *LP_pubkeyjson(struct LP_pubkey_info *pubp) { int32_t baseid,relid,numutxos; int64_t avesatoshis,maxsatoshis; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj; obj = cJSON_CreateObject(); @@ -380,7 +388,7 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) char *LP_prices() { - struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray(); + struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray(); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { jaddi(array,LP_pubkeyjson(pubp)); @@ -390,7 +398,7 @@ char *LP_prices() /*void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj) { - struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr; double askprice; uint32_t now; + struct LP_pubkey_info *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr; double askprice; uint32_t now; now = (uint32_t)time(NULL); pubkey = jbits256(obj,"pubkey"); if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) @@ -555,7 +563,7 @@ char *LP_myprices() int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price) { - struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; + struct LP_priceinfo *basepp,*relpp; struct LP_pubkey_info *pubp; *changedp = 0; if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { @@ -750,11 +758,12 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op) jaddnum(item,"depth",dstr(op->depth)*0.8); jaddbits256(item,"pubkey",op->pubkey); jaddnum(item,"age",time(NULL)-op->timestamp); + jaddnum(item,"zcredits",dstr(op->dynamictrust)); } return(item); } -struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t avesatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance) +struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t avesatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance,uint64_t dynamictrust) { struct LP_orderbookentry *op; if ( (op= calloc(1,sizeof(*op))) != 0 ) @@ -767,13 +776,14 @@ struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,d op->pubkey = pubkey; op->timestamp = timestamp; op->depth = balance; + op->dynamictrust = dynamictrust; } return(op); } void LP_pubkeys_query() { - uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkeyinfo *pubp=0,*tmp; + uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkey_info *pubp=0,*tmp; memset(zero.bytes,0,sizeof(zero)); memset(zeroes,0,sizeof(zeroes)); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) @@ -792,7 +802,7 @@ void LP_pubkeys_query() int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration) { - char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis; + char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkey_info *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis; if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) baseid = basepp->ind; else return(num); @@ -827,7 +837,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char * } //printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total)); } - if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance)) != 0 ) + if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance,pubp->dynamictrust)) != 0 ) { *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); (*arrayp)[num++] = op; @@ -977,6 +987,16 @@ uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance) return(KMDvalue); } +int64_t LP_kmdvalue(char *symbol,int64_t satoshis) +{ + struct iguana_info *coin; int64_t kmdvalue = 0; + if ( (coin= LP_coinfind(symbol)) != 0 ) + kmdvalue = LP_KMDvalue(coin,satoshis); + if ( kmdvalue == 0 ) + kmdvalue = satoshis; + return(kmdvalue); +} + void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]) { LP_priceinfoupdate(base,rel,price); @@ -1112,7 +1132,7 @@ cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,i void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,char *utxocoin,int32_t numrelutxos,int64_t balance,int64_t minutxo,int64_t maxutxo) { - struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *pubp; char str[65],fname[512]; FILE *fp; + struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkey_info *pubp; char str[65],fname[512]; FILE *fp; //printf("check PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey)); if ( LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index f5ea3229a..5d4f33b2c 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -389,6 +389,7 @@ uint32_t LP_extract(uint32_t requestid,uint32_t quoteid,char *rootfname,char *fi t = (t << 8) | redeem[2]; //printf("extracted timestamp.%u\n",t); } + free_json(json); } free(filestr); } @@ -483,7 +484,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap) if ( rswap->sentflags[i] != 0 ) jaddistr(array,txnames[i]); if ( rswap->txbytes[i] != 0 ) - free(rswap->txbytes[i]); + free(rswap->txbytes[i]), rswap->txbytes[i] = 0; } jadd(item,"sentflags",array); array = cJSON_CreateArray(); @@ -637,6 +638,7 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t } } } + free_json(txobj); } rswap->origfinishedflag = basilisk_swap_isfinished(rswap->iambob,rswap->txids,rswap->sentflags,rswap->paymentspent,rswap->Apaymentspent,rswap->depositspent); rswap->finishedflag = rswap->origfinishedflag; @@ -773,6 +775,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap) //printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); } } + free_json(txobj); } //else printf("no symbol\n"); free(fstr); } else if ( 0 && rswap->finishedflag == 0 ) @@ -1140,6 +1143,8 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti jaddstr(item,"method","tradestatus"); jaddnum(item,"finishtime",rswap.finishtime); jaddstr(item,"gui",G.gui); + //jaddbits256(item,"srchash",rswap.Q.srchash); + //jaddbits256(item,"desthash",rswap.desthash); itemstr = jprint(item,0); fprintf(fp,"%s\n",itemstr); LP_tradecommand_log(item); @@ -1150,7 +1155,10 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti fclose(fp); } } - return(item); + for (i=0; i 0 ) jaddnum(retjson,"avesell",(double)-Btotal/Ktotal); } - /*array = cJSON_CreateArray(); - for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) - { - if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 ) - jaddi(array,linfo_json(&myinfo->linfos[i])); - } - jadd(retjson,"quotes",array);*/ portable_mutex_unlock(&LP_swaplistmutex); return(jprint(retjson,1)); } diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index 8639646ee..d2f3702c6 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -586,7 +586,7 @@ cJSON *LP_validateaddress(char *symbol,char *address) } bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20); jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse()); - jadd(retjson,"iswatchonly",cJSON_CreateFalse()); + jadd(retjson,"iswatchonly",cJSON_CreateTrue()); jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse()); return(retjson); } @@ -599,12 +599,30 @@ cJSON *LP_validateaddress(char *symbol,char *address) int32_t LP_address_ismine(char *symbol,char *address) { - int32_t doneflag = 0; cJSON *retjson; + int32_t doneflag = 0; cJSON *retjson,*obj; if ( symbol == 0 || symbol[0] == 0 ) return(0); if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) { - if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 ) + if ( (obj= jobj(retjson,"ismine")) != 0 && is_cJSON_True(obj) != 0 ) + { + doneflag = 1; + //printf("%s ismine (%s)\n",address,jprint(retjson,0)); + } + //printf("%s\n",jprint(retjson,0)); + free_json(retjson); + } + return(doneflag); +} + +int32_t LP_address_iswatched(char *symbol,char *address) +{ + int32_t doneflag = 0; cJSON *retjson,*obj; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) + { + if ( (obj= jobj(retjson,"iswatched")) != 0 && is_cJSON_True(obj) != 0 ) { doneflag = 1; //printf("%s ismine (%s)\n",address,jprint(retjson,0)); @@ -635,26 +653,76 @@ int32_t LP_address_isvalid(char *symbol,char *address) cJSON *LP_listunspent(char *symbol,char *coinaddr) { - char buf[128]; cJSON *retjson; int32_t numconfs; struct iguana_info *coin; + char buf[128],*retstr; struct LP_address *ap; cJSON *retjson; int32_t numconfs,usecache=1; struct iguana_info *coin; if ( symbol == 0 || symbol[0] == 0 ) return(cJSON_Parse("{\"error\":\"null symbol\"}")); coin = LP_coinfind(symbol); - //printf("LP_listunspent.(%s %s)\n",symbol,coinaddr); if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) return(cJSON_Parse("{\"error\":\"no coin\"}")); if ( coin->electrum == 0 ) { - if ( LP_address_ismine(symbol,coinaddr) > 0 ) + if ( (ap= LP_addressfind(coin,symbol)) != 0 ) + { + if ( ap->unspenttime == 0 ) + usecache = 0; + else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+30 ) + usecache = 0; + if ( usecache != 0 && (retstr= LP_unspents_filestr(symbol,coinaddr)) != 0 ) + { + retjson = cJSON_Parse(retstr); + free(retstr); + return(retjson); + } + } + if ( LP_address_ismine(symbol,coinaddr) > 0 || LP_address_iswatched(symbol,coinaddr) > 0 ) { if ( strcmp(symbol,"BTC") == 0 ) numconfs = 0; else numconfs = 1; sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr); - return(bitcoin_json(coin,"listunspent",buf)); + //printf("LP_listunspent.(%s %s)\n",symbol,coinaddr); + retjson = bitcoin_json(coin,"listunspent",buf); + retstr = jprint(retjson,0); + LP_unspents_cache(coin->symbol,coinaddr,retstr,1); + free(retstr); + if ( ap != 0 ) + ap->unspenttime = (uint32_t)time(NULL); + return(retjson); } else return(LP_address_utxos(coin,coinaddr,0)); } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)); } +cJSON *LP_listreceivedbyaddress(char *symbol,char *coinaddr) +{ + char buf[128],*addr; cJSON *retjson,*array,*item; int32_t i,n; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( coin->electrum == 0 ) + { + sprintf(buf,"[1, false, true]"); + if ( (array= bitcoin_json(coin,"listreceivedbyaddress",buf)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ielectrum,&retjson,coinaddr)); +} + int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) { struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0; @@ -664,7 +732,7 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) { if ( coin->electrum != 0 ) { - if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)) != 0 ) + if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,fullflag)) != 0 ) { n = cJSON_GetArraySize(retjson); //printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0)); @@ -672,17 +740,8 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) } else { - if ( strcmp(coin->smartaddr,coinaddr) == 0 ) - { - retjson = LP_listunspent(symbol,coinaddr); - coin->numutxos = cJSON_GetArraySize(retjson); - //printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr); - } - else if ( IAMLP == 0 ) - { - //printf("LP_listunspent_query.(%s %s)\n",symbol,coinaddr); - LP_listunspent_query(coin->symbol,coin->smartaddr); - } + retjson = LP_listunspent(symbol,coinaddr); + coin->numutxos = cJSON_GetArraySize(retjson); if ( retjson != 0 ) { n = cJSON_GetArraySize(retjson); @@ -998,17 +1057,19 @@ bits256 LP_getbestblockhash(struct iguana_info *coin) char *LP_blockhashstr(char *symbol,int32_t height) { - cJSON *array; char *paramstr,*retstr; struct iguana_info *coin; + char params[64],*retstr; struct iguana_info *coin; //cJSON *array; if ( symbol == 0 || symbol[0] == 0 ) return(0); coin = LP_coinfind(symbol); if ( coin == 0 || coin->electrum != 0 ) return(0); - array = cJSON_CreateArray(); - jaddinum(array,height); - paramstr = jprint(array,1); - retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",paramstr); - free(paramstr); + //array = cJSON_CreateArray(); + //jaddinum(array,height); + //paramstr = jprint(array,1); + sprintf(params,"[%d]",height); + retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",params); + //free(paramstr); + //printf("blockhashstr.(%s)\n",retstr); return(retstr); } diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c index 6e99495cb..4fab2feca 100644 --- a/iguana/exchanges/LP_signatures.c +++ b/iguana/exchanges/LP_signatures.c @@ -276,7 +276,7 @@ bits256 LP_utxos_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,bits int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,bits256 utxoshash) { - static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkeyinfo *pubp; + static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkey_info *pubp; if ( ctx == 0 ) ctx = bitcoin_ctx(); pubp = LP_pubkeyfind(pubkey); @@ -362,7 +362,7 @@ struct LP_utxos_qitem { struct queueitem DL; cJSON *argjson; }; char *LP_postutxos_recv(cJSON *argjson) { - struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkeyinfo *pubp; + struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkey_info *pubp; printf("LP_postutxos_recv deprecated\n"); pubkey = jbits256(argjson,"pubkey"); pubp = LP_pubkeyfind(pubkey); @@ -416,7 +416,7 @@ int32_t LP_utxosQ_process() int32_t LP_price_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,char *base,char *rel,uint64_t price64) { - static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkeyinfo *pubp; + static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkey_info *pubp; if ( ctx == 0 ) ctx = bitcoin_ctx(); pubp = LP_pubkeyfind(pubkey); @@ -454,7 +454,7 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re struct iguana_info *basecoin,*relcoin; struct LP_address *ap; char pubsecpstr[67]; uint32_t numutxos,timestamp; uint64_t price64,balance,minsize,maxsize; bits256 zero; cJSON *reqjson; reqjson = cJSON_CreateObject(); // LP_addsig - if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 )//&& relcoin->electrum == 0 ) + if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 )//&& basecoin->electrum == 0 )//&& relcoin->electrum == 0 ) { memset(zero.bytes,0,sizeof(zero)); jaddbits256(reqjson,"pubkey",G.LP_mypub25519); @@ -521,7 +521,7 @@ int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub return(LP_bitcoinsig_add(item,priv,pubsecp,sighash)); } -int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item) +int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item) { int32_t i,len,siglen,retval=-1; uint8_t rmd160[20],checkrmd160[20],pubsecp[33],sig[65],zeroes[20]; char *sigstr,*hexstr,*pubsecpstr; if ( (hexstr= jstr(item,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) ) @@ -603,7 +603,7 @@ void LP_notify_pubkeys(void *ctx,int32_t pubsock) char *LP_notify_recv(cJSON *argjson) { - bits256 pub; struct LP_pubkeyinfo *pubp; char *ipaddr; + bits256 pub; struct LP_pubkey_info *pubp; char *ipaddr; pub = jbits256(argjson,"pub"); if ( bits256_nonz(pub) != 0 ) { @@ -700,8 +700,8 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_ { if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 ) { - LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); - LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); + LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash); + LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash); } else { @@ -718,13 +718,15 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_ msg = jprint(reqjson,1); msg2 = clonestr(msg); printf("QUERY.(%s)\n",msg); - memset(&zero,0,sizeof(zero)); - portable_mutex_lock(&LP_reservedmutex); - if ( num_Reserved_msgs[1] < sizeof(Reserved_msgs[1])/sizeof(*Reserved_msgs[1])-2 ) - Reserved_msgs[1][num_Reserved_msgs[1]++] = msg; - if ( num_Reserved_msgs[0] < sizeof(Reserved_msgs[0])/sizeof(*Reserved_msgs[0])-2 ) - Reserved_msgs[0][num_Reserved_msgs[0]++] = msg2; - //LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg2); - portable_mutex_unlock(&LP_reservedmutex); + if ( bits256_nonz(qp->srchash) == 0 || strcmp(method,"request") != 0 ) + { + memset(&zero,0,sizeof(zero)); + portable_mutex_lock(&LP_reservedmutex); + if ( num_Reserved_msgs[1] < sizeof(Reserved_msgs[1])/sizeof(*Reserved_msgs[1])-2 ) + Reserved_msgs[1][num_Reserved_msgs[1]++] = msg; + if ( num_Reserved_msgs[0] < sizeof(Reserved_msgs[0])/sizeof(*Reserved_msgs[0])-2 ) + Reserved_msgs[0][num_Reserved_msgs[0]++] = msg2; + portable_mutex_unlock(&LP_reservedmutex); + } else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg2); } diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index f1a895b38..d17930dc3 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -606,12 +606,9 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON //LP_postutxos(coin->symbol,addr); updatedflag = 1; } - if ( strcmp(addr,coin->smartaddr) == 0 ) - { - retstr = jprint(retjson,0); - LP_unspents_cache(coin->symbol,coin->smartaddr,retstr,1); - free(retstr); - } + retstr = jprint(retjson,0); + LP_unspents_cache(coin->symbol,addr,retstr,1); + free(retstr); if ( ap != 0 ) { ap->unspenttime = (uint32_t)time(NULL); @@ -627,7 +624,7 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON } if ( retjson == 0 ) { - if ( strcmp(addr,coin->smartaddr) == 0 && (retstr= LP_unspents_filestr(symbol,coin->smartaddr)) != 0 ) + if ( (retstr= LP_unspents_filestr(symbol,addr)) != 0 ) { retjson = cJSON_Parse(retstr); free(retstr); diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index 54d9ddc95..01d966310 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -3039,6 +3039,29 @@ if ( (0) ) #undef aptr #undef bptr }*/ +/*if ( (sobj= jobj(v,"scriptPubKey")) != 0 ) + { + if ( (scriptstr= jstr(sobj,"hex")) != 0 ) + { + printf("amount64 %.8f vout.%d (%s) weeki.%d %.8f (%s)\n",dstr(amount64),vout,jprint(v,0),weeki,dstr(satoshis),scriptstr); + len = (int32_t)strlen(scriptstr) >> 1; + if ( len <= sizeof(spendscript)/sizeof(*spendscript) ) + { + decode_hex(spendscript,len,scriptstr); + if ( spendscript[11] == 33 ) + { + pub33 = &spendscript[12]; + redeemlen = LP_deposit_addr(p2shaddr,redeemscript,coin->taddr,coin->p2shtype,timestamp,pub33); + if ( len == redeemlen && (timestamp % LP_WEEKMULT) == 0 ) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pub33,33); + printf("%s -> matched %s script t.%u weeki.%d deposit %.8f\n",coinaddr,p2shaddr,timestamp,(timestamp-LP_FIRSTWEEKTIME)/LP_WEEKMULT,dstr(satoshis)); + // add to pubp->credits; + } + } + } + } + }*/ /*portable_mutex_lock(&ep->pendingQ.mutex); if ( ep->pendingQ.list != 0 ) diff --git a/iguana/exchanges/LP_stats.c b/iguana/exchanges/LP_stats.c index 40569f027..9c3dd87cd 100644 --- a/iguana/exchanges/LP_stats.c +++ b/iguana/exchanges/LP_stats.c @@ -20,32 +20,17 @@ #define LP_STATSLOG_FNAME "stats.log" -struct LP_swapstats -{ - UT_hash_handle hh; - struct LP_quoteinfo Q; - bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent; - double qprice; - uint64_t aliceid; - uint32_t ind,methodind,finished,expired; - char alicegui[32],bobgui[32]; -} *LP_swapstats; +struct LP_swapstats *LP_swapstats,*LP_RTstats; int32_t LP_statslog_parsequote(char *method,cJSON *lineobj); char *LP_stats_methods[] = { "unknown", "request", "reserved", "connect", "connected", "tradestatus" }; -uint32_t LP_atomic_locktime(char *base,char *rel) -{ - if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 ) - return(INSTANTDEX_LOCKTIME); - else return(INSTANTDEX_LOCKTIME * 10); -} - static uint32_t LP_requests,LP_reserveds,LP_connects,LP_connecteds,LP_tradestatuses,LP_parse_errors,LP_unknowns,LP_duplicates,LP_aliceids; void LP_tradecommand_log(cJSON *argjson) { static FILE *logfp; char *jsonstr; + portable_mutex_lock(&LP_logmutex); if ( logfp == 0 ) { if ( (logfp= fopen(LP_STATSLOG_FNAME,"rb+")) != 0 ) @@ -59,6 +44,7 @@ void LP_tradecommand_log(cJSON *argjson) free(jsonstr); fflush(logfp); } + portable_mutex_unlock(&LP_logmutex); } void LP_statslog_parseline(cJSON *lineobj) @@ -130,18 +116,22 @@ int32_t LP_statslog_parse() struct LP_swapstats *LP_swapstats_find(uint64_t aliceid) { struct LP_swapstats *sp; - HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp); + HASH_FIND(hh,LP_RTstats,&aliceid,sizeof(aliceid),sp); + if ( sp == 0 ) + HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp); return(sp); } -struct LP_swapstats *LP_swapstats_add(uint64_t aliceid) +struct LP_swapstats *LP_swapstats_add(uint64_t aliceid,int32_t RTflag) { struct LP_swapstats *sp; if ( (sp= LP_swapstats_find(aliceid)) == 0 ) { sp = calloc(1,sizeof(*sp)); sp->aliceid = aliceid; - HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp); + if ( RTflag != 0 ) + HASH_ADD(hh,LP_RTstats,aliceid,sizeof(aliceid),sp); + else HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp); } return(LP_swapstats_find(aliceid)); } @@ -180,6 +170,7 @@ bits256 LP_swapstats_txid(cJSON *argjson,char *name,bits256 oldtxid) int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSON *lineobj) { char *statusstr,*base,*rel,gui[64]; uint32_t requestid,quoteid; uint64_t satoshis,destsatoshis; + sp->lasttime = (uint32_t)time(NULL); safecopy(gui,sp->Q.gui,sizeof(gui)); if ( strcmp(LP_stats_methods[sp->methodind],"tradestatus") == 0 ) { @@ -189,7 +180,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO quoteid = juint(lineobj,"quoteid"); satoshis = jdouble(lineobj,"srcamount") * SATOSHIDEN; destsatoshis = jdouble(lineobj,"destamount") * SATOSHIDEN; - if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && ((satoshis+2*sp->Q.txfee)|1) == (sp->Q.satoshis|1) && ((destsatoshis+2*sp->Q.desttxfee)|1) == (sp->Q.destsatoshis|1) ) + if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && llabs((int64_t)(satoshis+2*sp->Q.txfee) - (int64_t)sp->Q.satoshis) <= sp->Q.txfee && llabs((int64_t)(destsatoshis+2*sp->Q.desttxfee) - (int64_t)sp->Q.destsatoshis) <= sp->Q.desttxfee ) { sp->bobdeposit = LP_swapstats_txid(lineobj,"bobdeposit",sp->bobdeposit); sp->alicepayment = LP_swapstats_txid(lineobj,"alicepayment",sp->alicepayment); @@ -208,7 +199,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO } else { - if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid ) + //if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid ) printf("mismatched tradestatus aliceid.%22llu b%s/%s r%s/%s r%u/%u q%u/%u %.8f/%.8f -> %.8f/%.8f\n",(long long)sp->aliceid,base,sp->Q.srccoin,rel,sp->Q.destcoin,requestid,sp->Q.R.requestid,quoteid,sp->Q.R.quoteid,dstr(satoshis+2*sp->Q.txfee),dstr(sp->Q.satoshis),dstr(destsatoshis+2*sp->Q.desttxfee),dstr(sp->Q.destsatoshis)); return(-1); } @@ -222,7 +213,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) { static uint32_t unexpected; - struct LP_swapstats *sp,*tmp; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + struct LP_swapstats *sp,*tmp; struct LP_pubkey_info *pubp; struct LP_pubswap *ptr; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,RTflag,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *statusstr,*gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; memset(numtrades,0,sizeof(numtrades)); memset(basevols,0,sizeof(basevols)); memset(relvols,0,sizeof(relvols)); @@ -242,8 +233,11 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) if ( (sp= LP_swapstats_find(aliceid)) != 0 ) { sp->methodind = methodind; + sp->Q.R.requestid = requestid; + sp->Q.R.quoteid = quoteid; if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) flag = 1; + //else printf("LP_swapstats_update error\n"); } if ( flag == 0 ) { @@ -253,14 +247,16 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) { sp->methodind = methodind; if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) + { flag = 1; - else printf("error after delayed match\n"); - break; + break; + } + printf("error after delayed match\n"); } } } if ( flag == 0 ) - printf("unexpected.%d tradestatus.(%s)\n",unexpected++,jprint(lineobj,0)); + printf("unexpected.%d tradestatus aliceid.%llu requestid.%u quoteid.%u\n",unexpected++,(long long)aliceid,requestid,quoteid);//,jprint(lineobj,0)); return(0); } if ( LP_quoteparse(&Q,lineobj) < 0 ) @@ -290,6 +286,9 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) destvout = jint(lineobj,"destvout"); feetxid = jbits256(lineobj,"feetxid"); feevout = jint(lineobj,"feevout"); + if ( (statusstr= jstr(lineobj,"status")) != 0 && strcmp(statusstr,"finished") == 0 ) + RTflag = 0; + else RTflag = 1; qprice = ((double)destsatoshis / (satoshis - txfee)); //printf("%s/v%d %s/v%d\n",bits256_str(str,desttxid),destvout,bits256_str(str2,feetxid),feevout); aliceid = LP_aliceid_calc(desttxid,destvout,feetxid,feevout); @@ -305,16 +304,31 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) } else { - if ( (sp= LP_swapstats_add(aliceid)) != 0 ) + //printf("create aliceid.%llu\n",(long long)aliceid); + if ( (sp= LP_swapstats_add(aliceid,RTflag)) != 0 ) { sp->Q = Q; sp->qprice = qprice; sp->methodind = methodind; sp->ind = LP_aliceids++; + sp->lasttime = (uint32_t)time(NULL); strcpy(sp->bobgui,"nogui"); strcpy(sp->alicegui,"nogui"); - //LP_swapstats_line(numtrades,basevols,relvols,line,sp); - //printf("%s\n",line); + if ( sp->finished == 0 && sp->expired == 0 ) + { + if ( (pubp= LP_pubkeyadd(sp->Q.srchash)) != 0 ) + { + ptr = calloc(1,sizeof(*ptr)); + ptr->swap = sp; + DL_APPEND(pubp->bobswaps,ptr); + } + if ( (pubp= LP_pubkeyadd(sp->Q.desthash)) != 0 ) + { + ptr = calloc(1,sizeof(*ptr)); + ptr->swap = sp; + DL_APPEND(pubp->aliceswaps,ptr); + } + } } else printf("unexpected LP_swapstats_add failure\n"); } if ( sp != 0 ) @@ -330,11 +344,103 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) return(duplicate == 0); } -char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey) +cJSON *LP_swapstats_json(struct LP_swapstats *sp) +{ + cJSON *item = cJSON_CreateObject(); + jaddnum(item,"timestamp",sp->Q.timestamp); + jadd64bits(item,"aliceid",sp->aliceid); + jaddbits256(item,"src",sp->Q.srchash); + jaddstr(item,"base",sp->Q.srccoin); + jaddnum(item,"basevol",dstr(sp->Q.satoshis)); + jaddbits256(item,"dest",sp->Q.desthash); + jaddstr(item,"rel",sp->Q.destcoin); + jaddnum(item,"relvol",dstr(sp->Q.destsatoshis)); + jaddnum(item,"price",sp->qprice); + jaddnum(item,"requestid",sp->Q.R.requestid); + jaddnum(item,"quoteid",sp->Q.R.quoteid); + jaddnum(item,"finished",sp->finished); + jaddnum(item,"expired",sp->expired); + jaddnum(item,"ind",sp->methodind); + //jaddstr(item,"line",line); + return(item); +} + +char *LP_swapstatus_recv(cJSON *argjson) +{ + struct LP_swapstats *sp; int32_t methodind; + //printf("swapstatus.(%s)\n",jprint(argjson,0)); + if ( (sp= LP_swapstats_find(j64bits(argjson,"aliceid"))) != 0 ) + { + sp->lasttime = (uint32_t)time(NULL); + if ( (methodind= jint(argjson,"ind")) > sp->methodind && methodind < sizeof(LP_stats_methods)/sizeof(*LP_stats_methods) ) + { + if ( sp->finished == 0 && sp->expired == 0 ) + printf("SWAPSTATUS updated %llu %s %u %u\n",(long long)sp->aliceid,LP_stats_methods[sp->methodind],juint(argjson,"finished"),juint(argjson,"expired")); + sp->methodind = methodind; + sp->finished = juint(argjson,"finished"); + sp->expired = juint(argjson,"expired"); + } + } + return(clonestr("{\"result\":\"success\"}")); +} + +char *LP_gettradestatus(uint64_t aliceid) { - cJSON *retjson,*array,*item; struct LP_swapstats *sp,*tmp; int32_t i,dispflag,numtrades[LP_MAXPRICEINFOS]; char line[1024]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + struct LP_swapstats *sp; cJSON *reqjson; bits256 zero; + //printf("gettradestatus.(%llu)\n",(long long)aliceid); + if ( (sp= LP_swapstats_find(aliceid)) != 0 && time(NULL) > sp->lasttime+60 ) + { + if ( (reqjson= LP_swapstats_json(sp)) != 0 ) + { + jaddstr(reqjson,"method","swapstatus"); + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); + } + } + return(clonestr("{\"error\":\"cant find aliceid\"}")); +} + +int32_t LP_stats_dispiter(cJSON *array,struct LP_swapstats *sp,uint32_t starttime,uint32_t endtime,char *refbase,char *refrel,char *refgui,bits256 refpubkey) +{ + int32_t dispflag,retval = 0; + if ( sp->finished == 0 && sp->expired == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 ) + sp->expired = (uint32_t)time(NULL); + if ( sp->finished != 0 || sp->expired != 0 ) + retval = 1; + dispflag = 0; + if ( starttime == 0 && endtime == 0 ) + dispflag = 1; + else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 ) + dispflag = 1; + else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime ) + dispflag = 1; + if ( refbase != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( refrel != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( dispflag != 0 ) + { + dispflag = 0; + if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 ) + { + if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 ) + dispflag = 1; + } + } + if ( dispflag != 0 ) + jaddi(array,LP_swapstats_json(sp)); + return(retval); +} + +cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel) +{ + static int32_t rval; + cJSON *retjson,*array,*item,*reqjson; struct LP_pubkey_info *pubp,*ptmp; bits256 zero; uint32_t now; struct LP_swapstats *sp,*tmp; int32_t i,n,numtrades[LP_MAXPRICEINFOS]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + if ( rval == 0 ) + rval = (LP_rand() % 300) + 60; if ( starttime > endtime ) starttime = endtime; + n = LP_statslog_parse(); memset(basevols,0,sizeof(basevols)); memset(relvols,0,sizeof(relvols)); memset(numtrades,0,sizeof(numtrades)); @@ -342,45 +448,41 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu jaddstr(retjson,"result","success"); jaddnum(retjson,"newlines",n); array = cJSON_CreateArray(); - HASH_ITER(hh,LP_swapstats,sp,tmp) + LP_RTcount = LP_swapscount = 0; + now = (uint32_t)time(NULL); + HASH_ITER(hh,LP_RTstats,sp,tmp) { - if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 ) - sp->expired = (uint32_t)time(NULL); - dispflag = 0; - if ( starttime == 0 && endtime == 0 ) - dispflag = 1; - else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 ) - dispflag = 1; - else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime ) - dispflag = 1; - if ( dispflag != 0 ) + if ( LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey) > 0 ) { - dispflag = 0; - if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 ) - { - if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 ) - dispflag = 1; - } + HASH_DELETE(hh,LP_RTstats,sp); + HASH_ADD(hh,LP_swapstats,aliceid,sizeof(sp->aliceid),sp); } - if ( dispflag != 0 ) + else { - LP_swapstats_line(numtrades,basevols,relvols,line,sp); - item = cJSON_CreateObject(); - jadd64bits(item,"aliceid",sp->aliceid); - jaddbits256(item,"src",sp->Q.srchash); - jaddstr(item,"base",sp->Q.srccoin); - jaddnum(item,"basevol",dstr(sp->Q.satoshis)); - jaddbits256(item,"dest",sp->Q.desthash); - jaddstr(item,"rel",sp->Q.destcoin); - jaddnum(item,"relvol",dstr(sp->Q.destsatoshis)); - jaddnum(item,"price",sp->qprice); - jaddnum(item,"requestid",sp->Q.R.requestid); - jaddnum(item,"quoteid",sp->Q.R.quoteid); - jaddstr(item,"line",line); - jaddi(array,item); + LP_RTcount++; + if ( now > sp->lasttime+rval ) + { + reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","gettradestatus"); + jadd64bits(reqjson,"aliceid",sp->aliceid); + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); + } } } + HASH_ITER(hh,LP_swapstats,sp,tmp) + { + LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey); + LP_swapscount++; + } + HASH_ITER(hh,LP_pubkeyinfos,pubp,ptmp) + { + pubp->dynamictrust = LP_dynamictrust(pubp->pubkey,0); + } + //printf("RT.%d completed.%d\n",LP_RTcount,LP_swapscount); jadd(retjson,"swaps",array); + jaddnum(retjson,"RTcount",LP_RTcount); + jaddnum(retjson,"swapscount",LP_swapscount); array = cJSON_CreateArray(); for (i=0; i-timescale*1024, endtime=, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades] + +struct LP_ohlc +{ + uint32_t timestamp,firsttime,lasttime,numtrades; + double high,low,open,close,relsum,basesum; +}; + +cJSON *LP_ohlc_json(struct LP_ohlc *bar) +{ + cJSON *item; + if ( bar->numtrades != 0 && bar->relsum > SMALLVAL && bar->basesum > SMALLVAL ) + { + item = cJSON_CreateArray(); + jaddinum(item,bar->timestamp); + jaddinum(item,bar->high); + jaddinum(item,bar->low); + jaddinum(item,bar->open); + jaddinum(item,bar->close); + jaddinum(item,bar->relsum); + jaddinum(item,bar->basesum); + jaddinum(item,bar->relsum / bar->basesum); + jaddinum(item,bar->numtrades); + return(item); + } + return(0); +} + +void LP_ohlc_update(struct LP_ohlc *bar,uint32_t timestamp,double basevol,double relvol) +{ + double price; + if ( basevol > SMALLVAL && relvol > SMALLVAL ) + { + price = relvol / basevol; + if ( bar->firsttime == 0 || timestamp < bar->firsttime ) + { + bar->firsttime = timestamp; + bar->open = price; + } + if ( bar->lasttime == 0 || timestamp > bar->lasttime ) + { + bar->lasttime = timestamp; + bar->close = price; + } + if ( bar->low == 0. || price < bar->low ) + bar->low = price; + if ( bar->high == 0. || price > bar->high ) + bar->high = price; + bar->basesum += basevol; + bar->relsum += relvol; + bar->numtrades++; + //printf("%d %.8f/%.8f -> %.8f\n",bar->numtrades,basevol,relvol,price); + } } +cJSON *LP_tradesarray(char *base,char *rel,uint32_t starttime,uint32_t endtime,int32_t timescale) +{ + struct LP_ohlc *bars; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; int32_t i,n,numbars,bari; + if ( timescale < 60 ) + return(cJSON_Parse("{\"error\":\"one minute is shortest timescale\"}")); + memset(zero.bytes,0,sizeof(zero)); + if ( endtime == 0 ) + endtime = (((uint32_t)time(NULL) / timescale) * timescale); + if ( starttime == 0 || starttime >= endtime ) + starttime = (endtime - LP_SCREENWIDTH*timescale); + numbars = ((endtime - starttime) / timescale) + 1; + bars = calloc(numbars,sizeof(*bars)); + for (bari=0; bari= starttime && timestamp <= endtime ) + { + bari = (timestamp - starttime) / timescale; + LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"basevol"),jdouble(item,"relvol")); + } else printf("skip.(%s)\n",jprint(item,0)); + } + } + free_json(statsjson); + } + array = cJSON_CreateArray(); + for (bari=0; barivins != 0 ) @@ -1041,7 +1048,7 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * } else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr); } -struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp) +struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp,int32_t dynamictrust) { //FILE *fp; char fname[512]; uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *bobcoin,*alicecoin; @@ -1101,14 +1108,18 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->I.iambob = 0; swap->I.otherhash = swap->I.req.desthash; swap->I.aliceistrusted = 1; - swap->I.otheristrusted = swap->I.bobistrusted = LP_pubkey_istrusted(swap->I.req.srchash); + if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.srchash) != 0 ) + dynamictrust = 1; + swap->I.otheristrusted = swap->I.bobistrusted = dynamictrust; } else { swap->I.iambob = 1; swap->I.otherhash = swap->I.req.srchash; swap->I.bobistrusted = 1; - swap->I.otheristrusted = swap->I.aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash); + if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.desthash) != 0 ) + dynamictrust = 1; + swap->I.otheristrusted = swap->I.aliceistrusted = dynamictrust; } if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE ) { @@ -1198,7 +1209,7 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 return(swap); } -struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp) +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust) { struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33]; swap = calloc(1,sizeof(*swap)); @@ -1217,7 +1228,7 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 swap->persistent_privkey = privkey; memcpy(swap->persistent_pubkey33,pubkey33,33); calc_rmd160_sha256(swap->changermd160,pubkey33,33); - if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp) == 0 ) + if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp,dynamictrust) == 0 ) { printf("error doing swapinit\n"); free(swap); diff --git a/iguana/exchanges/LP_tradebots.c b/iguana/exchanges/LP_tradebots.c index d4a2fdfd5..0e20caf80 100644 --- a/iguana/exchanges/LP_tradebots.c +++ b/iguana/exchanges/LP_tradebots.c @@ -195,7 +195,7 @@ cJSON *LP_tradebot_json(struct LP_tradebot *bot) jadd(json,"trades",array); if ( bot->basesum > SMALLVAL && bot->relsum > SMALLVAL && bot->completed > 0 ) { - jaddnum(json,"completed",bot->completed); + jadd(json,"complete",bot->completed!=0?jtrue():jfalse()); jaddnum(json,"percentage",100. * (bot->relsum / bot->totalrelvolume)); if ( bot->dispdir > 0 ) { diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 34bec55b9..96ed9976a 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -420,7 +420,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, //printf(" scriptlen.%d\n",scriptlen); //printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen); sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys,zcash); - printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen); + //printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen); if ( bits256_nonz(sigtxid) != 0 ) { vp = &V[vini]; @@ -461,14 +461,14 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, { flag++; numsigs++; - int32_t z; char tmpaddr[64]; + /*int32_t z; char tmpaddr[64]; for (z=0; zsigners[j].pubkey[z]); bitcoin_address(tmpaddr,0,0,vp->signers[j].pubkey,33); - printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr); + printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr);*/ } } if ( numsigs >= vp->M ) @@ -731,7 +731,7 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt jaddstr(retjson,"error","interpreter rejects tx"); else complete = 1; jadd(retjson,"interpreter",log); - jaddnum(retjson,"complete",complete); + jadd(retjson,"complete",complete!=0?jtrue():jfalse()); free(serialized), free(serialized2); if ( signedtx != 0 ) free(signedtx); @@ -980,8 +980,10 @@ cJSON *LP_inputjson(bits256 txid,int32_t vout,char *spendscriptstr) uint64_t _komodo_interestnew(uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) { int32_t minutes; uint64_t interest = 0; - if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) + if ( tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= 60 ) { + //minutes.71582779 tiptime.1511292969 locktime.1511293505 + printf("minutes.%d tiptime.%u locktime.%u\n",minutes,tiptime,nLockTime); if ( minutes > 365 * 24 * 60 ) minutes = 365 * 24 * 60; minutes -= 59; @@ -1124,20 +1126,21 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ if ( LP_validSPV(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout) < 0 ) continue; } - + if ( LP_allocated(up->U.txid,up->U.vout) != 0 ) + continue; up->spendheight = 1; total += up->U.value; remains -= up->U.value; interest = 0; if ( up->U.height < 7777777 && strcmp(coin->symbol,"KMD") == 0 ) { - if ( 0 && (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 ) + if ( (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 ) { interestsum += interest; char str[65]; printf("%s/%d %.8f interest %.8f -> sum %.8f\n",bits256_str(str,up->U.txid),up->U.vout,dstr(up->U.value),dstr(interest),dstr(interestsum)); } } - //printf("numunspents.%d vini.%d value %.8f, total %.8f remains %.8f interest %.8f sum %.8f %s/v%d\n",numunspents,n,dstr(up->U.value),dstr(total),dstr(remains),dstr(interest),dstr(interestsum),bits256_str(str,up->U.txid),up->U.vout); + printf("numunspents.%d vini.%d value %.8f, total %.8f remains %.8f interest %.8f sum %.8f %s/v%d\n",numunspents,n,dstr(up->U.value),dstr(total),dstr(remains),dstr(interest),dstr(interestsum),bits256_str(str,up->U.txid),up->U.vout); vp = &V[n++]; vp->N = vp->M = 1; vp->signers[0].privkey = privkey; @@ -1146,7 +1149,7 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ vp->suppress_pubkeys = suppress_pubkeys; vp->ignore_cltverr = ignore_cltverr; jaddi(vins,LP_inputjson(up->U.txid,up->U.vout,spendscriptstr)); - LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+600,G.LP_mypub25519); + LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+LP_RESERVETIME,G.LP_mypub25519); if ( remains <= 0 && i >= numpre-1 ) break; if ( numunspents < 0 ) @@ -1264,6 +1267,12 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf if ( addrtype == coin->pubtype ) spendlen = bitcoin_standardspend(spendscript,0,rmd160); else spendlen = bitcoin_p2shspend(spendscript,0,rmd160); + if ( i == numvouts-1 && strcmp(coinaddr,coin->smartaddr) == 0 && change != 0 ) + { + printf("combine last vout %.8f with change %.8f\n",dstr(value+adjust),dstr(change)); + value += change; + change = 0; + } txobj = bitcoin_txoutput(txobj,spendscript,spendlen,value + adjust); } else diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 8ea1d2db5..d0c26c788 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -99,9 +99,10 @@ struct LP_inuse_info *_LP_inuse_add(uint32_t expiration,bits256 otherpub,bits256 { if ( bits256_nonz(otherpub) != 0 ) lp->otherpub = otherpub; - if ( expiration > lp->expiration || expiration == 0 ) + //if ( expiration > lp->expiration || expiration == 0 ) lp->expiration = expiration; } + char str[65]; printf("set inuse until %u lag.%d for %s/v%d\n",expiration,(int32_t)(expiration-(uint32_t)time(NULL)),bits256_str(str,txid),vout); return(lp); } else printf("_LP_inuse_add [%d] overflow\n",LP_numinuse); return(0); @@ -446,20 +447,7 @@ struct LP_address *LP_address_utxo_reset(struct iguana_info *coin) { //{"tx_hash":"38d1b7c73015e1b1d6cb7fc314cae402a635b7d7ea294970ab857df8777a66f4","tx_pos":0,"height":577975,"value":238700} item = jitem(array,i); - if ( coin->electrum != 0 ) - { - txid = jbits256(item,"tx_hash"); - vout = juint(item,"tx_pos"); - value = j64bits(item,"value"); - height = jint(item,"height"); - } - else - { - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - value = LP_value_extract(item,0); - height = LP_txheight(coin,txid); - } + value = LP_listunspent_parseitem(coin,&txid,&vout,&height,item); LP_address_utxoadd(now,"withdraw",coin,coin->smartaddr,txid,vout,value,height,-1); if ( (up= LP_address_utxofind(coin,coin->smartaddr,txid,vout)) == 0 ) printf("couldnt find just added %s/%d ht.%d %.8f\n",bits256_str(str,txid),vout,height,dstr(value)); @@ -573,9 +561,9 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr } else { - if ( strcmp(coin->smartaddr,coinaddr) == 0 ) + //if ( strcmp(coin->smartaddr,coinaddr) == 0 ) balance = LP_unspents_load(coin->symbol,coinaddr); - else + /*else { if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) { @@ -589,7 +577,7 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr } free_json(array); } - } + }*/ } retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index 90e0aafc8..7d637e459 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -559,6 +559,26 @@ int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targe return(mini); } +int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item) +{ + int64_t satoshis = 0; + if ( coin->electrum == 0 ) + { + *txidp = jbits256(item,"txid"); + *voutp = juint(item,"vout"); + satoshis = LP_value_extract(item,0); + *heightp = LP_txheight(coin,*txidp); + } + else + { + *txidp = jbits256(item,"tx_hash"); + *voutp = juint(item,"tx_pos"); + satoshis = j64bits(item,"value"); + *heightp = jint(item,"height"); + } + return(satoshis); +} + int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) { int32_t enable_utxos = 0; @@ -572,8 +592,8 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri return(0); coin->privkeydepth++; LP_address(coin,coin->smartaddr); - if ( coin->inactive == 0 ) - LP_listunspent_issue(coin->symbol,coin->smartaddr,0); + //if ( coin->inactive == 0 ) + // LP_listunspent_issue(coin->symbol,coin->smartaddr,0); array = LP_listunspent(coin->symbol,coin->smartaddr); if ( array != 0 ) { @@ -591,20 +611,7 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri for (i=0; ielectrum == 0 ) - { - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - value = LP_value_extract(item,0); - height = LP_txheight(coin,txid);//LP_getheight(coin) - jint(item,"confirmations") + 1; - } - else - { - txid = jbits256(item,"tx_hash"); - vout = juint(item,"tx_pos"); - value = j64bits(item,"value"); - height = jint(item,"height"); - } + value = LP_listunspent_parseitem(coin,&txid,&vout,&height,item); satoshis = LP_txvalue(destaddr,coin->symbol,txid,vout); if ( satoshis != 0 && satoshis != value ) printf("%s %s privkey_init value %.8f vs %.8f (%s) %.8f %.8f\n",coin->symbol,coin->smartaddr,dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest")); @@ -848,7 +855,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) else if ( IAMLP == 0 || coin->inactive == 0 ) { //printf("from updates %s\n",coin->symbol); - if ( LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 ) + if ( 0 && LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 ) { //LP_postutxos(coin->symbol,coin->smartaddr); } diff --git a/iguana/exchanges/LP_zeroconf.c b/iguana/exchanges/LP_zeroconf.c new file mode 100644 index 000000000..876ac4128 --- /dev/null +++ b/iguana/exchanges/LP_zeroconf.c @@ -0,0 +1,278 @@ + +/****************************************************************************** + * 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_zeroconf.c +// marketmaker +// + +int32_t LP_deposit_addr(char *p2shaddr,uint8_t *script,uint8_t taddr,uint8_t p2shtype,uint32_t timestamp,uint8_t *pubsecp33) +{ + uint8_t elsepub33[33],p2sh_rmd160[20]; int32_t n; + decode_hex(elsepub33,33,BOTS_BONDPUBKEY33); + n = bitcoin_performancebond(p2sh_rmd160,script,0,timestamp,pubsecp33,elsepub33); + bitcoin_address(p2shaddr,taddr,p2shtype,script,n); + return(n); +} + +char *LP_zeroconf_deposit(struct iguana_info *coin,int32_t weeks,double amount,int32_t broadcast) +{ + char p2shaddr[64],*retstr,*hexstr; uint8_t script[512]; int32_t weeki,scriptlen; cJSON *argjson,*retjson,*array,*item,*obj; uint32_t timestamp; bits256 txid,sendtxid; uint64_t amount64; + if ( strcmp(coin->symbol,"KMD") != 0 ) + return(clonestr("{\"error\":\"zeroconf deposit must be in KMD\"}")); + if ( amount < 10.0 ) + return(clonestr("{\"error\":\"minimum zeroconf deposit is 10 KMD\"}")); + if ( weeks < 0 || weeks > 52 ) + return(clonestr("{\"error\":\"weeks must be between 0 and 52\"}")); + if ( weeks > 0 ) + { + timestamp = (uint32_t)time(NULL); + timestamp /= LP_WEEKMULT; + timestamp += weeks+1; + timestamp *= LP_WEEKMULT; + weeki = (timestamp - LP_FIRSTWEEKTIME) / LP_WEEKMULT; + if ( weeks >= 10000 ) + return(clonestr("{\"error\":\"numweeks must be less than 10000\"}")); + } else timestamp = (uint32_t)time(NULL) + 300, weeki = 0; + scriptlen = LP_deposit_addr(p2shaddr,script,coin->taddr,coin->p2shtype,timestamp,G.LP_pubsecp); + argjson = cJSON_CreateObject(); + array = cJSON_CreateArray(); + item = cJSON_CreateObject(); + jaddnum(item,p2shaddr,amount); + jaddi(array,item); + item = cJSON_CreateObject(); + amount64 = (amount * SATOSHIDEN) / 1000; + amount64 = (amount64 / 10000) * 10000 + weeki; + jaddnum(item,BOTS_BONDADDRESS,dstr(amount64)); + jaddi(array,item); + item = cJSON_CreateObject(); + jaddnum(item,coin->smartaddr,0.0001); + jaddi(array,item); + jadd(argjson,"outputs",array); + //printf("deposit.(%s)\n",jprint(argjson,0)); + if ( (retstr= LP_withdraw(coin,argjson)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,"result") != 0 ) + jdelete(retjson,"result"); + jaddstr(retjson,"address",p2shaddr); + jaddnum(retjson,"expiration",timestamp); + jaddnum(retjson,"deposit",amount); + if ( (obj= jobj(retjson,"complete")) != 0 && is_cJSON_True(obj) != 0 && (hexstr= jstr(retjson,"hex")) != 0 ) + { + txid = jbits256(retjson,"txid"); + if ( broadcast != 0 ) + { + if (bits256_nonz(txid) != 0 ) + { + sendtxid = LP_broadcast("deposit","KMD",hexstr,txid); + if ( bits256_cmp(sendtxid,txid) != 0 ) + { + jaddstr(retjson,"error","broadcast txid mismatch"); + jaddbits256(retjson,"broadcast",sendtxid); + free(retstr); + return(jprint(retjson,1)); + } + else + { + jaddstr(retjson,"result","success"); + jaddbits256(retjson,"broadcast",sendtxid); + free(retstr); + return(jprint(retjson,1)); + } + } + else + { + jaddstr(retjson,"error","couldnt broadcast since no txid created"); + free(retstr); + return(jprint(retjson,1)); + } + } + else + { + jaddstr(retjson,"result","success"); + free(retstr); + return(jprint(retjson,1)); + } + } + else + { + jaddstr(retjson,"error","couldnt create deposit txid"); + free(retstr); + return(jprint(retjson,1)); + } + free_json(retjson); + } + free(retstr); + } + return(clonestr("{\"error\":\"error with LP_withdraw for zeroconf deposit\"}")); +} + +char *LP_zeroconf_claim(struct iguana_info *coin,char *depositaddr,uint32_t expiration) +{ + static void *ctx; + uint8_t redeemscript[512],userdata[64]; char vinaddr[64],str[65],*signedtx=0; uint32_t timestamp,now,redeemlen,claimtime; int32_t i,n,height,utxovout,userdatalen; bits256 signedtxid,utxotxid,sendtxid; int64_t sum,destamount,satoshis; cJSON *array,*item,*txids,*retjson; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( strcmp(coin->symbol,"KMD") != 0 ) + return(clonestr("{\"error\":\"zeroconf deposit must be in KMD\"}")); + now = (uint32_t)time(NULL); + sum = 0; + txids = cJSON_CreateArray(); + timestamp = (now / LP_WEEKMULT) * LP_WEEKMULT + LP_WEEKMULT; + while ( timestamp > LP_FIRSTWEEKTIME ) + { + if ( expiration != 0 ) + timestamp = expiration; + else timestamp -= LP_WEEKMULT; + redeemlen = LP_deposit_addr(vinaddr,redeemscript,coin->taddr,coin->p2shtype,timestamp,G.LP_pubsecp); + if ( strcmp(depositaddr,vinaddr) == 0 ) + { + claimtime = (uint32_t)time(NULL)-777/2; + if ( claimtime <= timestamp ) + { + printf("claimtime.%u vs locktime.%u, need to wait %d seconds\n",claimtime,timestamp,(int32_t)timestamp-claimtime); + } + else + { + printf("found %s at timestamp.%u\n",vinaddr,timestamp); + if ( (array= LP_listunspent(coin->symbol,vinaddr)) != 0 ) + { + userdata[0] = 0x51; + userdatalen = 1; + utxovout = 0; + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; isymbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,G.LP_privkey,0,redeemscript,redeemlen,userdata,userdatalen,utxotxid,utxovout,coin->smartaddr,G.LP_pubsecp,0,claimtime,&destamount,0,0,vinaddr,1,coin->zcash)) != 0 ) + { + printf("signedtx.(%s)\n",signedtx); + sendtxid = LP_broadcast("claim","KMD",signedtx,signedtxid); + if ( bits256_cmp(sendtxid,signedtxid) == 0 ) + { + jaddibits256(txids,sendtxid); + sum += (satoshis-coin->txfee); + } + else printf("error sending %s\n",bits256_str(str,signedtxid)); + free(signedtx); + } else printf("error claiming zeroconf deposit %s/v%d %.8f\n",bits256_str(str,utxotxid),utxovout,dstr(satoshis)); + } + } + free_json(array); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddnum(retjson,"claimed",dstr(sum)); + jadd(retjson,"txids",txids); + return(jprint(retjson,1)); + } + } + } + if ( expiration != 0 ) + break; + } + return(clonestr("{\"error\":\"no zeroconf deposits to claim\"}")); +} + +void LP_zeroconf_credit(char *coinaddr,uint64_t satoshis,int32_t weeki,char *p2shaddr) +{ + uint32_t timestamp; struct LP_address *ap; struct iguana_info *coin = LP_coinfind("KMD"); + if ( coin != 0 ) + { + timestamp = LP_FIRSTWEEKTIME + weeki*LP_WEEKMULT; + if ( time(NULL) < timestamp-24*3600 && (ap= LP_address(coin,coinaddr)) != 0 ) + { + ap->zeroconf_credits += satoshis; + printf("ZEROCONF credit.(%s) %.8f weeki.%d (%s) -> sum %.8f\n",coinaddr,dstr(satoshis),weeki,p2shaddr,dstr(ap->zeroconf_credits)); + } + } +} + +void LP_zeroconf_deposits(struct iguana_info *coin) +{ + cJSON *array,*item,*txjson,*vouts,*v,*txobj; int32_t i,n,numvouts,height,vout,weeki; bits256 txid; char destaddr[64],p2shaddr[64]; struct LP_address *ap,*tmp; int64_t satoshis,amount64; + HASH_ITER(hh,coin->addresses,ap,tmp) + { + ap->zeroconf_credits = 0; + } + if ( (array= LP_listreceivedbyaddress("KMD",BOTS_BONDADDRESS)) != 0 ) + { + //printf("ZEROCONF.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ielectrum != 0 ) + { + item = jitem(array,i); + LP_listunspent_parseitem(coin,&txid,&vout,&height,item); + } else txid = jbits256i(array,i); + if ( (txjson= LP_gettx(coin->symbol,txid)) != 0 ) + { + // vout0 deposit, vout1 botsfee, vout2 smartaddress + if ( (vouts= jarray(&numvouts,txjson,"vout")) > 0 && numvouts >= 3 && LP_destaddr(destaddr,jitem(vouts,2)) == 0 ) + { + amount64 = LP_value_extract(jitem(vouts,1),0); + weeki = (amount64 % 10000); + v = jitem(vouts,0); + satoshis = LP_value_extract(v,0); + //printf("%s funded %.8f weeki.%d\n",destaddr,dstr(satoshis),weeki); + if ( LP_destaddr(p2shaddr,v) == 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,p2shaddr,txid,0)) != 0 ) + { + free_json(txobj); + LP_zeroconf_credit(destaddr,satoshis,weeki,p2shaddr); + } + } + } + free_json(txjson); + } + } + } + free_json(array); + } +} + +int64_t LP_dynamictrust(bits256 pubkey,int64_t kmdvalue) +{ + struct LP_pubswap *ptr,*tmp; struct LP_swapstats *sp; struct LP_pubkey_info *pubp; struct LP_address *ap; char coinaddr[64]; struct iguana_info *coin; int64_t swaps_kmdvalue = 0; + if ( (coin= LP_coinfind("KMD")) != 0 && (pubp= LP_pubkeyfind(pubkey)) != 0 ) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->pubsecp,33); + if ((ap= LP_address(coin,coinaddr)) != 0 )//&& ap->zeroconf_credits >= kmdvalue ) + { + DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && sp->finished == 0 && sp->expired == 0 ) + swaps_kmdvalue += LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis); + } + DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && sp->finished == 0 && sp->expired == 0 ) + swaps_kmdvalue += LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis); + } + //printf("%s zeroconf_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(ap->zeroconf_credits),dstr(swaps_kmdvalue),dstr(kmdvalue)); + //if ( ap->zeroconf_credits > swaps_kmdvalue+kmdvalue ) + return(ap->zeroconf_credits - (swaps_kmdvalue+kmdvalue)); + } + } + return(0); +} + diff --git a/iguana/exchanges/claim b/iguana/exchanges/claim new file mode 100755 index 000000000..20ec10c44 --- /dev/null +++ b/iguana/exchanges/claim @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"zeroconf_claim\",\"address\":\"$1\",\"expiration\":$2}" diff --git a/iguana/exchanges/deposit b/iguana/exchanges/deposit new file mode 100755 index 000000000..1fe7c6138 --- /dev/null +++ b/iguana/exchanges/deposit @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"zeroconf_deposit\",\"weeks\":0,\"amount\":10.0,\"broadcast\":1}" diff --git a/iguana/exchanges/deposit1 b/iguana/exchanges/deposit1 new file mode 100755 index 000000000..c82178e79 --- /dev/null +++ b/iguana/exchanges/deposit1 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"zeroconf_deposit\",\"weeks\":1,\"amount\":10.0,\"broadcast\":1}" diff --git a/iguana/exchanges/install b/iguana/exchanges/install index efb2c7a2e..d01b5dd4a 100755 --- a/iguana/exchanges/install +++ b/iguana/exchanges/install @@ -1,5 +1,5 @@ #!/bin/bash -cp invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts +cp tradesarray claim deposit invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts cp coins.json .. cd ../dexscripts #cp ../exchanges/passphrase ../exchanges/userpass . diff --git a/iguana/exchanges/mm.c b/iguana/exchanges/mm.c index a87481f15..f4d147131 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -881,6 +881,18 @@ int main(int argc, const char * argv[]) double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr; cJSON *retjson,*loginjson; int32_t i; OS_init(); + if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 ) + { + uint8_t addrtype,rmd160[20],rmd160b[20]; char coinaddr[64],coinaddr2[64]; + bitcoin_addr2rmd160(0,&addrtype,rmd160,(char *)argv[1]); + bitcoin_address(coinaddr,0,60,rmd160,20); + bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr); + bitcoin_address(coinaddr2,0,0,rmd160b,20); + printf("(%s) -> %s -> %s\n",(char *)argv[1],coinaddr,coinaddr2); + if ( strcmp((char *)argv[1],coinaddr2) != 0 ) + printf("ERROR\n"); + exit(0); + } sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname); diff --git a/iguana/exchanges/stats.c b/iguana/exchanges/stats.c index 681da52d2..a3232b1e6 100644 --- a/iguana/exchanges/stats.c +++ b/iguana/exchanges/stats.c @@ -33,7 +33,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char char *stats_validmethods[] = { "psock", "getprices", "notify", "getpeers", // from issue_ "uitem", "listunspent", - "orderbook", "help", "getcoins", "pricearray", "balance", "tradestatus" + "orderbook", "help", "getcoins", "pricearray", "balance", "tradesarray" }; int32_t LP_valid_remotemethod(cJSON *argjson) @@ -310,7 +310,7 @@ cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr) jaddstr(json,key,value); else jaddistr(array,key); len += (n + 1); - if ( strcmp(key,"Content-Length") == 0 && (datalen= atoi(value)) > 0 ) + if ( (strcmp(key,"Content-Length") == 0 || strcmp(key,"content-length") == 0) && (datalen= atoi(value)) > 0 ) { data = &urlstr[totallen - datalen]; data[-1] = 0; @@ -329,8 +329,7 @@ extern void *bitcoin_ctx(); char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port) { static void *ctx; - cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0; - //printf("rpcparse.(%s)\n",urlstr); + cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr=0,*filestr,*token = 0; int32_t i,j,n,num=0; if ( ctx == 0 ) ctx = bitcoin_ctx(); for (i=0; i 0 ) - { - cJSON *retitem,*retarray = cJSON_CreateArray(); - origargjson = argjson; - symbol[0] = 0; - for (i=0; i 0 ) { - argjson = jitem(origargjson,i); - if ( userpass != 0 && jstr(argjson,"userpass") == 0 ) - jaddstr(argjson,"userpass",userpass); - //printf("after urlconv.(%s) argjson.(%s)\n",jprint(json,0),jprint(argjson,0)); -#ifdef FROM_MARKETMAKER - if ( strcmp(remoteaddr,"127.0.0.1") == 0 || LP_valid_remotemethod(argjson) > 0 ) + cJSON *retitem,*retarray = cJSON_CreateArray(); + origargjson = argjson; + symbol[0] = 0; + for (i=0; i 0 ) + { + if ( (retstr= stats_JSON(ctx,myipaddr,-1,argjson,remoteaddr,port)) != 0 ) + { + if ( (retitem= cJSON_Parse(retstr)) != 0 ) + jaddi(retarray,retitem); + free(retstr); + } + } else retstr = clonestr("{\"error\":\"invalid remote method\"}"); +#else if ( (retstr= stats_JSON(ctx,myipaddr,-1,argjson,remoteaddr,port)) != 0 ) { if ( (retitem= cJSON_Parse(retstr)) != 0 ) jaddi(retarray,retitem); free(retstr); } - } else retstr = clonestr("{\"error\":\"invalid remote method\"}"); -#else - if ( (retstr= stats_JSON(ctx,myipaddr,-1,argjson,remoteaddr,port)) != 0 ) - { - if ( (retitem= cJSON_Parse(retstr)) != 0 ) - jaddi(retarray,retitem); - free(retstr); - } #endif - //printf("(%s) {%s} -> (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),jprint(json,0),*postflagp,retstr); + //printf("(%s) {%s} -> (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),jprint(json,0),*postflagp,retstr); + } + free_json(origargjson); + retstr = jprint(retarray,1); } - free_json(origargjson); - retstr = jprint(retarray,1); - } - else - { - cJSON *arg; - if ( jstr(argjson,"agent") != 0 && strcmp(jstr(argjson,"agent"),"bitcoinrpc") != 0 && jobj(argjson,"params") != 0 ) + else { - arg = jobj(argjson,"params"); - if ( is_cJSON_Array(arg) != 0 && cJSON_GetArraySize(arg) == 1 ) - arg = jitem(arg,0); - } else arg = argjson; - //printf("ARGJSON.(%s)\n",jprint(arg,0)); - if ( userpass != 0 && jstr(arg,"userpass") == 0 ) - jaddstr(arg,"userpass",userpass); + cJSON *arg; + if ( jstr(argjson,"agent") != 0 && strcmp(jstr(argjson,"agent"),"bitcoinrpc") != 0 && jobj(argjson,"params") != 0 ) + { + arg = jobj(argjson,"params"); + if ( is_cJSON_Array(arg) != 0 && cJSON_GetArraySize(arg) == 1 ) + arg = jitem(arg,0); + } else arg = argjson; + //printf("ARGJSON.(%s)\n",jprint(arg,0)); + if ( userpass != 0 && jstr(arg,"userpass") == 0 ) + jaddstr(arg,"userpass",userpass); #ifdef FROM_MARKETMAKER - if ( strcmp(remoteaddr,"127.0.0.1") == 0 || LP_valid_remotemethod(arg) > 0 ) - retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port); - else retstr = clonestr("{\"error\":\"invalid remote method\"}"); + if ( strcmp(remoteaddr,"127.0.0.1") == 0 || LP_valid_remotemethod(arg) > 0 ) + retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port); + else retstr = clonestr("{\"error\":\"invalid remote method\"}"); #else - retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port); + retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port); #endif + } + free_json(argjson); } - free_json(argjson); free_json(json); if ( tmpjson != 0 ) free(tmpjson); @@ -562,15 +568,17 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po } free_json(argjson); if ( tmpjson != 0 ) - free(tmpjson); + free_json(tmpjson); + if ( tokens != 0 ) + free_json(tokens); *jsonflagp = 1; return(clonestr("{\"error\":\"couldnt process packet\"}")); } int32_t iguana_getcontentlen(char *buf,int32_t recvlen) { - char *str,*clenstr = "Content-Length: "; int32_t len = -1; - if ( (str= strstr(buf,clenstr)) != 0 ) + char *str,*clenstr = "Content-Length: ",*clenstr2 = "content-length: "; int32_t len = -1; + if ( (str= strstr(buf,clenstr)) != 0 || (str= strstr(buf,clenstr2)) != 0 ) { //printf("strstr.(%s)\n",str); str += strlen(clenstr); @@ -597,15 +605,16 @@ void LP_rpc_processreq(void *_ptr) static uint32_t spawned,maxspawned; 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; struct rpcrequest_info *req = _ptr; + char helpname[512],remoteaddr[64],*buf,*retstr,space[8192],space2[32786],*jsonbuf; struct rpcrequest_info *req = _ptr; uint32_t ipbits,i,size = IGUANA_MAXPACKETSIZE + 512; ipbits = req->ipbits;; expand_ipbits(remoteaddr,ipbits); sock = req->sock; recvlen = flag = 0; retstr = 0; - space = calloc(1,size); + //space = calloc(1,size); jsonbuf = calloc(1,size); + //printf("alloc jsonbuf.%p\n",jsonbuf); remains = size-1; buf = jsonbuf; spawned++; @@ -624,10 +633,12 @@ void LP_rpc_processreq(void *_ptr) printf("EAGAIN for len %d, remains.%d\n",len,remains); usleep(10000); } + //printf("errno.%d len.%d remains.%d\n",errno,len,remains); break; } else { + //printf("received len.%d\n%s\n",len,buf); if ( len > 0 ) { buf[len] = 0; @@ -694,16 +705,23 @@ void LP_rpc_processreq(void *_ptr) //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); + if ( strlen(retstr)+1024+1+1 < sizeof(space2) ) + response = space2; + else + { + response = malloc(strlen(retstr)+1024+1+1); + printf("alloc response.%p\n",response); + } 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 ) + { + //printf("free retstr0.%p\n",retstr); free(retstr); + } retstr = response; //printf("RET.(%s)\n",retstr); } @@ -727,16 +745,28 @@ void LP_rpc_processreq(void *_ptr) printf("iguana sent.%d remains.%d of recvlen.%d (%s)\n",numsent,remains,recvlen,jsonbuf); } } - if ( retstr != space) + if ( retstr != space && retstr != space2 ) + { + //printf("free retstr.%p\n",retstr); free(retstr); + } } - free(space); + //free(space); + //printf("free jsonbuf.%p\n",jsonbuf); free(jsonbuf); closesocket(sock); - portable_mutex_lock(&LP_gcmutex); - DL_APPEND(LP_garbage_collector,req); + if ( 1 ) + { + portable_mutex_lock(&LP_gcmutex); + DL_APPEND(LP_garbage_collector,req); + portable_mutex_unlock(&LP_gcmutex); + } + else + { + //printf("free req.%p\n",req); + free(req); + } spawned--; - portable_mutex_unlock(&LP_gcmutex); } extern int32_t IAMLP; @@ -787,10 +817,12 @@ void stats_rpcloop(void *args) memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); if ( port == RPC_port && ipbits != localhostbits ) { + //printf("port.%u RPC_port.%u ipbits %x != %x\n",port,RPC_port,ipbits,localhostbits); closesocket(sock); continue; } req = calloc(1,sizeof(*req)); + //printf("alloc req.%p\n",req); req->sock = sock; req->ipbits = ipbits; req->port = port; diff --git a/iguana/exchanges/tradesarray b/iguana/exchanges/tradesarray new file mode 100755 index 000000000..982bdca7c --- /dev/null +++ b/iguana/exchanges/tradesarray @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"tradesarray\",\"base\":\"REVS\",\"rel\":\"KMD\",\"timescale\":3600}" diff --git a/iguana/main.c b/iguana/main.c index 85510c3fb..b89521a04 100755 --- a/iguana/main.c +++ b/iguana/main.c @@ -793,7 +793,7 @@ void iguana_launchdaemons(struct supernet_info *myinfo) if ( COMMANDLINE_ARGFILE == 0 ) iguana_launch(0,"rpcloop",iguana_rpcloop,myinfo,IGUANA_PERMTHREAD); // limit to oneprocess printf("launch mainloop\n"); - OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo); + // disable basilisk: OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo); OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)jumblr_loop,(void *)myinfo); OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_psockloop,(void *)myinfo); mainloop(myinfo);