diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index 298c9e52d..77e8c3a71 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -35,46 +35,163 @@ struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srch return(rp); } -struct LP_utxoinfo *LP_orderbook(char *base,char *rel) +double LP_pricequery(uint64_t *destsatoshisp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 txid,int32_t vout) { - struct LP_peerinfo *peer,*tmp; char *utxostr; cJSON *array,*reqjson,*item; int32_t i,n; + cJSON *reqjson; struct LP_peerinfo *peer; int32_t i,pushsock = -1; double price = 0.; + if ( ipaddr != 0 && port >= 1000 ) + { + if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),port)) == 0 ) + peer = LP_addpeer(1,0,-1,ipaddr,port,port+1,port+2,0,0,0); + if ( peer != 0 ) + { + if ( (pushsock= peer->pushsock) >= 0 ) + { + reqjson = cJSON_CreateObject(); + jaddbits256(reqjson,"txid",txid); + jaddnum(reqjson,"vout",vout); + jaddstr(reqjson,"base",base); + jaddstr(reqjson,"rel",rel); + jaddstr(reqjson,"method","price"); + LP_send(pushsock,jprint(reqjson,1),1); + for (i=0; i<10; i++) + { + if ( (price= LP_pricecache(destsatoshisp,base,rel,txid,vout)) != 0. ) + break; + usleep(100000); + } + } else printf("no pushsock for peer.%s:%u\n",ipaddr,port); + } else printf("cant find/create peer.%s:%u\n",ipaddr,port); + } + return(price); +} + +/* + //5.9.253.196:7779 [{"ipaddr":"5.9.253.196","port":7779,"profit":0.01064000,"coin":"KMD","address":"RFQn4gNG555woQWQV1wPseR47spCduiJP5","script":"76a914434009423522682bd7cc1b18a614c3096d19683188ac","txid":"f5d5e2eb4ef85c78f95076d0d2d99af9e1b85968e57b3c7bdb282bd005f7c341","vout":1,"value":100,"deposit":"07902a65d11f0f577a0346432bcd2b6b53de5554c314209d1964693962524d69","dvout":1,"dvalue":120}] + + LP_send(peer->pushsock,jprint(reqjson,0),1); + jdelete(reqjson,"method"); + jaddstr(reqjson,"method","request"); + LP_send(peer->pushsock,jprint(reqjson,0),1); + jdelete(reqjson,"method"); + jaddstr(reqjson,"method","connect"); + LP_send(peer->pushsock,jprint(reqjson,0),1); + + //SENT.({"base":"KMD","rel":"BTC","timestamp":1496076137,"price":0.00021791,"txid":"f5d5e2eb4ef85c78f95076d0d2d99af9e1b85968e57b3c7bdb282bd005f7c341","srchash":"2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74","txfee":"100000","satoshis":"9999900000","destsatoshis":"2179101","result":"reserved","pending":1496076197} +*/ +int32_t LP_sizematch(uint64_t mysatoshis,uint64_t othersatoshis) +{ + if ( mysatoshis >= othersatoshis ) + return(0); + else return(-1); +} + +cJSON *LP_tradecandidates(struct LP_utxoinfo *myutxo,char *base) +{ + struct LP_peerinfo *peer,*tmp; char *utxostr,coinstr[16]; cJSON *array,*icopy,*retarray=0,*item; int32_t i,n; double price; int64_t estimatedbase; uint64_t destsatoshis; + if ( (price= LP_price(base,myutxo->coin)) == .0 ) + return(0); + estimatedbase = myutxo->satoshis / price; + if ( estimatedbase <= 0 ) + return(0); + printf("%s -> %s price %.8f mysatoshis %llu estimated base %llu\n",base,myutxo->coin,price,(long long)myutxo->satoshis,(long long)estimatedbase); HASH_ITER(hh,LP_peerinfos,peer,tmp) { - if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,"KMD",10)) != 0 ) + if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) { printf("%s:%u %s\n",peer->ipaddr,peer->port,utxostr); - if ( 0 && (array= cJSON_Parse(utxostr)) != 0 ) + if ( (array= cJSON_Parse(utxostr)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { - for (i=0; i<1; i++) + retarray = cJSON_CreateArray(); + for (i=0; ipushsock,jprint(reqjson,0),1); - jdelete(reqjson,"method"); - jaddstr(reqjson,"method","request"); - LP_send(peer->pushsock,jprint(reqjson,0),1); - jdelete(reqjson,"method"); - jaddstr(reqjson,"method","connect"); - LP_send(peer->pushsock,jprint(reqjson,0),1); - - //SENT.({"base":"KMD","rel":"BTC","timestamp":1496076137,"price":0.00021791,"txid":"f5d5e2eb4ef85c78f95076d0d2d99af9e1b85968e57b3c7bdb282bd005f7c341","srchash":"2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74","txfee":"100000","satoshis":"9999900000","destsatoshis":"2179101","result":"reserved","pending":1496076197} + safecopy(coinstr,jstr(item,"coin"),sizeof(coinstr)); + if ( strcmp(coinstr,base) == 0 && LP_sizematch(estimatedbase,j64bits(item,"satoshis")) == 0 ) + { + icopy = 0; + if ( (price= LP_pricecache(&destsatoshis,base,myutxo->coin,jbits256(item,"txid"),jint(item,"vout"))) != 0. ) + { + if ( LP_sizematch(myutxo->satoshis,destsatoshis) == 0 ) + icopy = jduplicate(item); + } else icopy = jduplicate(item); + if ( icopy != 0 ) + { + jaddnum(icopy,"price",price); + jaddi(retarray,icopy); + } + } } } free_json(array); } free(utxostr); } + if ( retarray != 0 ) + break; + } + return(retarray); +} + +cJSON *LP_bestprice(struct LP_utxoinfo *utxo,char *base) +{ + int32_t i,n,besti; cJSON *array,*item,*bestitem=0; double bestmetric,metric,bestprice=0.,price,prices[100]; uint64_t destsatoshis[100]; + bestprice = 0.; + if ( (array= LP_tradecandidates(utxo,base)) != 0 ) + { + printf("%s %.8f -> (%s)\n",utxo->coin,dstr(utxo->satoshis),jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + memset(prices,0,sizeof(prices)); + memset(destsatoshis,0,sizeof(destsatoshis)); + for (i=0; icoin,jbits256(item,"txid"),jint(item,"vout")); + if ( destsatoshis[i] != 0 && (double)j64bits(item,"satoshis")/destsatoshis[i] > price ) + price = (double)j64bits(item,"satoshis")/destsatoshis[i]; + } + if ( (prices[i]= price) != 0. && (bestprice == 0. || price < bestprice) ) + bestprice = price; + } + if ( bestprice != 0. ) + { + bestmetric = 0.; + besti = -1; + for (i=0; i 0.9 ) + { + metric = destsatoshis[i] / metric * metric * metric; + if ( metric > bestmetric ) + { + besti = i; + bestmetric = metric; + } + } + } + } + if ( besti >= 0 ) + bestitem = jduplicate(jitem(array,besti)); + } + free_json(array); + } } - return(0); + return(bestitem); +} + +char *LP_quote(uint32_t reserved,char *base,char *rel,bits256 txid,int32_t vout,double price,uint64_t satoshis) +{ + struct LP_cacheinfo *ptr; + if ( (ptr= LP_cacheadd(base,rel,txid,vout,price,satoshis)) != 0 ) + return(clonestr("{\"result\":\"updated\"}")); + else return(clonestr("{\"error\":\"nullptr\"}")); } void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) @@ -110,15 +227,18 @@ void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_ if ( (txfee= LP_getestimatedrate(base)*LP_AVETXSIZE) < 10000 ) txfee = 10000; jadd64bits(retjson,"txfee",txfee); + if ( (desttxfee= LP_getestimatedrate(rel) * LP_AVETXSIZE) < 10000 ) + desttxfee = 10000; + jadd64bits(retjson,"desttxfee",desttxfee); jadd64bits(retjson,"satoshis",utxo->satoshis - txfee); - jadd64bits(retjson,"destsatoshis",price * (utxo->satoshis-txfee)); + jadd64bits(retjson,"destsatoshis",price * (utxo->satoshis-txfee) + desttxfee); if ( strcmp(method,"request") == 0 ) { utxo->swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); utxo->otherpubkey = jbits256(argjson,"pubkey"); - jaddstr(retjson,"result","reserved"); + jaddstr(retjson,"method","reserved"); jaddnum(retjson,"pending",utxo->swappending); - } + } else jaddstr(retjson,"method","quote"); retstr = jprint(retjson,1); LP_send(pubsock,retstr,1); } else printf("null price\n"); @@ -132,8 +252,8 @@ void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_ { price *= (1. + profitmargin); txfee = j64bits(argjson,"txfee"); + desttxfee = j64bits(argjson,"desttxfee"); satoshis = j64bits(argjson,"satoshis"); - desttxfee = LP_getestimatedrate(rel) * LP_AVETXSIZE; desttxid = jbits256(argjson,"desttxid"); destvout = jint(argjson,"destvout"); timestamp = juint(argjson,"timestamp"); @@ -198,6 +318,7 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port { if ( strcmp(ipaddr,"127.0.0.1") != 0 && port >= 1000 ) { + amclient = 0; if ( (pushport= juint(argjson,"push")) == 0 ) pushport = argport + 1; if ( (subport= juint(argjson,"sub")) == 0 ) @@ -212,20 +333,21 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port peer->numutxos = othernumutxos; } //printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0)); - } else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); - amclient = 0; + } else LP_addpeer(amclient,LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); } else amclient = 1; } - if ( strcmp(method,"getpeers") == 0 ) + if ( strcmp(method,"quote") == 0 || strcmp(method,"reserved") == 0 ) + retstr = LP_quote(juint(argjson,"pending"),jstr(argjson,"base"),jstr(argjson,"rel"),jbits256(argjson,"txid"),jint(argjson,"vout"),jdouble(argjson,"price"),j64bits(argjson,"satoshis")); + else if ( strcmp(method,"getpeers") == 0 ) retstr = LP_peers(); - else if ( strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 ) + else if ( strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"base")) != 0 ) retstr = LP_utxos(LP_mypeer,coin,jint(argjson,"lastn")); else if ( strcmp(method,"notify") == 0 ) retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); else if ( strcmp(method,"notifyutxo") == 0 ) { printf("utxonotify.(%s)\n",jprint(argjson,0)); - LP_addutxo(amclient,LP_mypeer,LP_mypubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),SATOSHIDEN * jdouble(argjson,"value"),jbits256(argjson,"deposit"),jint(argjson,"dvout"),SATOSHIDEN * jdouble(argjson,"dvalue"),jstr(argjson,"script"),jstr(argjson,"address"),jstr(argjson,"ipaddr"),juint(argjson,"port"),jdouble(argjson,"profit")); + LP_addutxo(amclient,LP_mypeer,LP_mypubsock,jstr(argjson,"base"),jbits256(argjson,"txid"),jint(argjson,"vout"),SATOSHIDEN * jdouble(argjson,"value"),jbits256(argjson,"deposit"),jint(argjson,"dvout"),SATOSHIDEN * jdouble(argjson,"dvalue"),jstr(argjson,"script"),jstr(argjson,"address"),jstr(argjson,"ipaddr"),juint(argjson,"port"),jdouble(argjson,"profit")); retstr = clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"); } } diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 7df5192aa..3a01c34e0 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -26,6 +26,7 @@ #define LP_RESERVETIME 60 #define LP_AVETXSIZE 500 +#define LP_CACHEDURATION 60 #define BASILISK_DEFAULT_NUMCONFIRMS 5 #define DEX_SLEEP 3 diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 5b220285f..d5fbf7f27 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -24,9 +24,12 @@ #define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid +char *activecoins[] = { "BTC", "KMD", "LTC", "USD", "REVS", "JUMBLR" }; + char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", "5.9.253.204" }; -portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex; +portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex,LP_cachemutex; int32_t LP_mypubsock = -1; +int32_t Client_connections; struct LP_peerinfo { @@ -52,6 +55,78 @@ struct LP_utxoinfo uint16_t port; } *LP_utxoinfos; +struct LP_cacheinfo +{ + UT_hash_handle hh; + uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(int32_t)]; + double price; + uint64_t satoshis,destsatoshis; + uint32_t timestamp; +} *LP_cacheinfos; + +int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout) +{ + uint64_t basebits,relbits; int32_t offset = 0; + basebits = stringbits(base); + relbits = stringbits(rel); + memcpy(&key[offset],&basebits,sizeof(basebits)), offset += sizeof(basebits); + memcpy(&key[offset],&relbits,sizeof(relbits)), offset += sizeof(relbits); + memcpy(&key[offset],&txid,sizeof(txid)), offset += sizeof(txid); + memcpy(&key[offset],&vout,sizeof(vout)), offset += sizeof(vout); + return(offset); +} + +struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout) +{ + struct LP_cacheinfo *ptr=0; uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(vout)]; + if ( LP_cachekey(key,base,rel,txid,vout) == sizeof(key) ) + { + portable_mutex_lock(&LP_cachemutex); + HASH_FIND(hh,LP_cacheinfos,key,sizeof(key),ptr); + portable_mutex_unlock(&LP_cachemutex); + } else printf("LP_cachefind keysize mismatch?\n"); + if ( ptr->timestamp != 0 && ptr->timestamp < time(NULL)-LP_CACHEDURATION ) + { + printf("expire price %.8f\n",ptr->price); + ptr->price = 0.; + ptr->destsatoshis = 0; + ptr->timestamp = 0; + } + return(ptr); +} + +struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,double price,uint64_t satoshis) +{ + struct LP_cacheinfo *ptr=0; + if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 ) + { + ptr = calloc(1,sizeof(*ptr)); + if ( LP_cachekey(ptr->key,base,rel,txid,vout) == sizeof(ptr->key) ) + { + portable_mutex_lock(&LP_cachemutex); + HASH_ADD(hh,LP_cacheinfos,key,sizeof(ptr->key),ptr); + portable_mutex_unlock(&LP_cachemutex); + } else printf("LP_cacheadd keysize mismatch?\n"); + } + ptr->price = price; + ptr->satoshis = satoshis; + ptr->destsatoshis = satoshis * price; + ptr->timestamp = (uint32_t)time(NULL); + printf("updated %s/%s %llu price %.8f\n",base,rel,(long long)satoshis,price); + return(ptr); +} + +double LP_pricecache(uint64_t *destsatoshisp,char *base,char *rel,bits256 txid,int32_t vout) +{ + struct LP_cacheinfo *ptr; + if ( (ptr= LP_cachefind(base,rel,txid,vout)) != 0 ) + { + *destsatoshisp = ptr->destsatoshis; + return(ptr->price); + } else *destsatoshisp = 0; + return(0.); +} + struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) { struct LP_peerinfo *peer=0; uint64_t ip_port; @@ -88,7 +163,7 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo) jaddstr(item,"ipaddr",utxo->ipaddr); jaddnum(item,"port",utxo->port); jaddnum(item,"profit",utxo->profitmargin); - jaddstr(item,"coin",utxo->coin); + jaddstr(item,"base",utxo->coin); jaddstr(item,"address",utxo->coinaddr); jaddstr(item,"script",utxo->spendscript); jaddbits256(item,"txid",utxo->txid); @@ -129,9 +204,9 @@ char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) return(jprint(utxosjson,1)); } -struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) +struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) { - uint32_t ipbits; int32_t pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; + uint32_t ipbits; int32_t pushsock,subsock,timeout,enabled; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; ipbits = (uint32_t)calc_ipbits(ipaddr); expand_ipbits(checkip,ipbits); if ( strcmp(checkip,ipaddr) == 0 ) @@ -151,22 +226,32 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char peer = calloc(1,sizeof(*peer)); peer->pushsock = peer->subsock = pushsock = subsock = -1; strcpy(peer->ipaddr,ipaddr); - if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) + if ( amclient == 0 ) + enabled = 1; + else enabled = (rand() % (1 << Client_connections)) == 0; + if ( enabled != 0 && pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) { - if ( (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) + timeout = 1000; + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + nanomsg_tcpname(pushaddr,peer->ipaddr,pushport); + if ( nn_connect(peer->pushsock,pushaddr) >= 0 ) { - timeout = 1000; - nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); + printf("connected to push.(%s) %d\n",pushaddr,peer->pushsock); + peer->connected = (uint32_t)time(NULL); peer->pushsock = pushsock; - peer->subsock = subsock; - nanomsg_tcpname(pushaddr,peer->ipaddr,pushport); - nanomsg_tcpname(subaddr,peer->ipaddr,subport); - printf("adding (%s and %s) %d %d\n",pushaddr,subaddr,peer->pushsock,peer->subsock); - if ( nn_connect(peer->pushsock,pushaddr) >= 0 && nn_connect(peer->subsock,subaddr) >= 0 ) - peer->connected = (uint32_t)time(NULL); + if ( enabled != 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) + { + timeout = 1; + nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); + nanomsg_tcpname(subaddr,peer->ipaddr,subport); + if ( nn_connect(peer->subsock,subaddr) >= 0 ) + { + peer->subsock = subsock; + printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); + Client_connections += amclient; + } else nn_close(subsock); + } } else nn_close(pushsock); } peer->profitmargin = profitmargin; @@ -246,7 +331,7 @@ struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32 return(utxo); } -int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) { struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; if ( (array= cJSON_Parse(retstr)) != 0 ) @@ -264,7 +349,7 @@ int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa subport = argport + 2; argipbits = (uint32_t)calc_ipbits(argipaddr); if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) - peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); + peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); if ( peer != 0 ) { peer->lasttime = now; @@ -282,6 +367,11 @@ int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) { struct LP_peerinfo *peer,*destpeer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; + if ( amclient != 0 ) + { + printf("LP_utxosparse not for clientside\n"); + return(-1); + } if ( (array= cJSON_Parse(retstr)) != 0 ) { if ( (n= cJSON_GetArraySize(array)) > 0 ) @@ -297,11 +387,11 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs subport = argport + 2; argipbits = (uint32_t)calc_ipbits(argipaddr); if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) - peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); + peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); if ( jobj(item,"txid") != 0 ) { txid = jbits256(item,"txid"); - utxo = LP_addutxo(amclient,mypeer,mypubsock,jstr(item,"coin"),txid,jint(item,"vout"),SATOSHIDEN*jdouble(item,"value"),jbits256(item,"deposit"),jint(item,"dvout"),SATOSHIDEN * jdouble(item,"dvalue"),jstr(item,"script"),jstr(item,"address"),argipaddr,argport,jdouble(item,"profit")); + utxo = LP_addutxo(amclient,mypeer,mypubsock,jstr(item,"base"),txid,jint(item,"vout"),SATOSHIDEN*jdouble(item,"value"),jbits256(item,"deposit"),jint(item,"dvout"),SATOSHIDEN * jdouble(item,"dvalue"),jstr(item,"script"),jstr(item,"address"),argipaddr,argport,jdouble(item,"profit")); if ( utxo != 0 ) utxo->lasttime = now; } @@ -361,7 +451,7 @@ char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utx return(issue_curl(url)); } -void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) +void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) { char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); @@ -371,7 +461,7 @@ void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr { //printf("got.(%s)\n",retstr); now = (uint32_t)time(NULL); - LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now); + LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); free(retstr); if ( mypeer != 0 ) { @@ -395,6 +485,11 @@ void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit) { char *retstr; struct LP_utxoinfo *utxo,*tmp; struct LP_peerinfo *peer; int32_t i,firsti; uint32_t now,flag = 0; + if ( amclient != 0 ) + { + printf("LP_utxosquery not for clientside\n"); + return; + } peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); if ( (peer != 0 && peer->errors > 0) || mypeer == 0 ) return; @@ -630,7 +725,7 @@ struct iguana_info *LP_coinfind(char *symbol) if ( strcmp(symbol,"BTC") == 0 ) { cdata.txfee = 50000; - cdata.estimatedrate = 200; + cdata.estimatedrate = 300; cdata.p2shtype = 5; cdata.wiftype = 128; LP_userpass(cdata.userpass,symbol,"","bitcoin"); @@ -730,47 +825,80 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb return(total); } +void LP_privkey_updates(struct LP_peerinfo *mypeer,int32_t pubsock,char *passphrase,int32_t amclient) +{ + int32_t i; + for (i=0; i 25 ) - continue; - LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer!=0?mypeer->ipaddr:"127.0.0.1",myport,profitmargin); + for (i=0; i 25 ) + continue; + LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,mypeer!=0?mypeer->ipaddr:"127.0.0.1",myport,profitmargin); + } + } + else + { + OS_randombytes((void *)&r,sizeof(r)); + for (j=0; jipaddr:"127.0.0.1",myport,profitmargin); + } } if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) { printf("error launching stats rpcloop for port.%u\n",myport); exit(-1); } - LP_coinfind("BTC"); LP_coinfind("LTC"); LP_coinfind("KMD"); - LP_coinfind("USD"); LP_coinfind("REVS"); LP_coinfind("JUMBLR"); + for (i=0; isubsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 ) + { + nonz++; + if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) + { + portable_mutex_lock(&LP_commandmutex); + if ( (retstr= stats_JSON(argjson,"127.0.0.1",mypubport)) != 0 ) + { + printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); + free(retstr); + } + portable_mutex_unlock(&LP_commandmutex); + free_json(argjson); + } else printf("error parsing.(%s)\n",(char *)ptr); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; + } + } + if ( nonz == 0 ) + sleep(n + 1); } } else { - counter = 0; while ( 1 ) { nonz = 0; if ( (counter++ % 60) == 0 ) - { - LP_privkey_init(mypeer,pubsock,"BTC",passphrase,"",amclient); - LP_privkey_init(mypeer,pubsock,"KMD",passphrase,"",amclient); - LP_privkey_init(mypeer,pubsock,"LTC",passphrase,"",amclient); - LP_privkey_init(mypeer,pubsock,"USD",passphrase,"",amclient); - LP_privkey_init(mypeer,pubsock,"REVS",passphrase,"",amclient); - LP_privkey_init(mypeer,pubsock,"JUMBLR",passphrase,"",amclient); - } + LP_privkey_updates(mypeer,pubsock,passphrase,amclient); HASH_ITER(hh,LP_peerinfos,peer,tmp) { if ( peer->numpeers != mypeer->numpeers || (rand() % 10) == 0 ) @@ -778,7 +906,7 @@ void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,i if ( peer->numpeers != mypeer->numpeers ) printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,mypeer->numpeers); if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) - LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin); + LP_peersquery(amclient,mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin); } if ( peer->numutxos != mypeer->numutxos ) { @@ -835,6 +963,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit portable_mutex_init(&LP_peermutex); portable_mutex_init(&LP_utxomutex); portable_mutex_init(&LP_commandmutex); + portable_mutex_init(&LP_cachemutex); if ( amclient == 0 ) { if ( profitmargin == 0. || profitmargin == 0.01 ) @@ -875,7 +1004,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit } } else printf("error getting sockets %d %d\n",pullsock,pubsock); LP_mypubsock = pubsock; - LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0); + LP_mypeer = mypeer = LP_addpeer(amclient,mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0); //printf("my ipaddr.(%s) peers.(%s)\n",ipaddr,retstr!=0?retstr:""); } else printf("error getting myipaddr\n"); } else printf("error issuing curl\n"); diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 691325cc4..33bc6f897 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -20,6 +20,8 @@ double LP_kmdbtc; + + // very, very simple for now void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]) diff --git a/iguana/exchanges/mm.c b/iguana/exchanges/mm.c index 4f9d3e0b1..34312e13a 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -819,7 +819,7 @@ int main(int argc, const char * argv[]) { char *base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr,theoretical = 0.; - cJSON *retjson,*loginjson; int32_t i; + cJSON *retjson,*loginjson,*matchjson; int32_t i; if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 ) { if ( (passphrase= jstr(retjson,"passphrase")) == 0 ) @@ -834,6 +834,15 @@ int main(int argc, const char * argv[]) { theoretical = marketmaker_updateprice("komodo","KMD","BTC",theoretical,&incr); sleep(30); + if ( jint(retjson,"client") != 0 ) + { + struct LP_utxoinfo *utxo,*utmp; + HASH_ITER(hh,LP_utxoinfos,utxo,utmp) + { + if ( (matchjson= LP_bestprice(utxo,"KMD")) != 0 ) + printf("bestprice (%s)\n",jprint(matchjson,1)); + } + } } profitmargin = jdouble(retjson,"profitmargin"); minask = jdouble(retjson,"minask");