diff --git a/iguana/coins/genltc b/iguana/coins/genltc index 9994529e0..ea034ed80 100755 --- a/iguana/coins/genltc +++ b/iguana/coins/genltc @@ -1,4 +1,4 @@ #!/bin/bash -curl --url "http://127.0.0.1:7776" --data "{\"RELAY\":1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":68,\"endpend\":68,\"services\":129,\"maxpeers\":256,\"newcoin\":\"LTC\",\"name\":\"Litecoin\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fbc0b6db\",\"p2p\":9333,\"rpc\":9332,\"pubval\":48,\"p2shval\":5,\"wifval\":176,\"txfee_satoshis\":\"100000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2\",\"genesis\":{\"version\":1,\"timestamp\":1317972665,\"nBits\":\"1e0ffff0\",\"nonce\":2084524493,\"merkle_root\":\"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9\"},\"alertpubkey\":\"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9\",\"protover\":70002}" +curl --url "http://127.0.0.1:7778" --data "{\"RELAY\":1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":68,\"endpend\":68,\"services\":129,\"maxpeers\":256,\"newcoin\":\"LTC\",\"name\":\"Litecoin\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fbc0b6db\",\"p2p\":9333,\"rpc\":9332,\"pubval\":48,\"p2shval\":5,\"wifval\":176,\"txfee_satoshis\":\"100000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2\",\"genesis\":{\"version\":1,\"timestamp\":1317972665,\"nBits\":\"1e0ffff0\",\"nonce\":2084524493,\"merkle_root\":\"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9\"},\"alertpubkey\":\"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9\",\"protover\":70002}" diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index e2951dad5..c06acd1a1 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -185,6 +185,7 @@ void LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetnam coin->pubtype = pubtype; coin->p2shtype = p2shtype; coin->wiftype = wiftype; + coin->inactive = (uint32_t)time(NULL); LP_userpass(coin->userpass,symbol,assetname,name); } @@ -256,7 +257,7 @@ struct iguana_info *LP_coinfind(char *symbol) struct iguana_info *LP_coincreate(cJSON *item) { - struct iguana_info cdata,*coin; int32_t isPoS,longestchain = 1000000; uint16_t port; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*symbol,*assetname; + struct iguana_info cdata,*coin=0; int32_t isPoS,longestchain = 1000000; uint16_t port; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*symbol,*assetname; if ( (symbol= jstr(item,"coin")) != 0 && symbol[0] != 0 && strlen(symbol) < 16 && LP_coinfind(symbol) == 0 && (port= juint(item,"rpcport")) != 0 ) { isPoS = jint(item,"isPoS"); @@ -275,9 +276,10 @@ struct iguana_info *LP_coincreate(cJSON *item) else if ( (name= jstr(item,"name")) == 0 ) name = symbol; LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain); - if ( (coin= LP_coinadd(&cdata)) != 0 ) - coin->inactive = !jint(item,"active"); + coin = LP_coinadd(&cdata); } + if ( coin != 0 && item != 0 ) + coin->inactive = (strcmp("KMD",coin->symbol) == 0) ? 0 : !jint(item,"active"); return(0); } diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index 6e2410209..5972a432a 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -18,71 +18,159 @@ // marketmaker // -double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub) +double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub) { - cJSON *reqjson; struct LP_peerinfo *peer; int32_t i,flag = 0,pushsock = -1; double price = 0.; - if ( ipaddr != 0 && port >= 1000 ) + cJSON *reqjson; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo; + qp->desthash = mypub; + strcpy(qp->srccoin,base); + strcpy(qp->destcoin,rel); + if ( strcmp(method,"request") == 0 ) { - 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 ) + qp->quotetime = (uint32_t)time(NULL); + if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) + LP_unavailableset(utxo,qp->srchash); + else { - if ( (pushsock= peer->pushsock) >= 0 ) + printf("couldnt find my txid to make request\n"); + return(0.); + } + } + reqjson = LP_quotejson(qp); + if ( bits256_nonz(qp->desthash) != 0 ) + flag = 1; + jaddstr(reqjson,"method",method); + if ( strcmp(method,"price") != 0 ) + printf("QUERY.(%s)\n",jprint(reqjson,0)); + LP_pubkey_send(qp->srchash,jprint(reqjson,1),1); + for (i=0; i<30; i++) + { + if ( (price= LP_pricecache(qp,base,rel,qp->txid,qp->vout)) != 0. ) + { + if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) { - qp->desthash = mypub; - strcpy(qp->srccoin,base); - strcpy(qp->destcoin,rel); - if ( strcmp(method,"request") == 0 ) - qp->quotetime = (uint32_t)time(NULL); - reqjson = LP_quotejson(qp); - if ( bits256_nonz(qp->desthash) != 0 ) - flag = 1; - jaddstr(reqjson,"method",method); - if ( strcmp(method,"price") != 0 ) - printf("QUERY.(%s)\n",jprint(reqjson,0)); - LP_send(pushsock,jprint(reqjson,1),1); - for (i=0; i<30; i++) - { - if ( (price= LP_pricecache(qp,base,rel,qp->txid,qp->vout)) != 0. ) - { - if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) - { - //printf("break out of loop.%d price %.8f\n",i,price); - 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); + //printf("break out of loop.%d price %.8f\n",i,price); + break; + } + } + usleep(100000); } return(price); } -int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) +int32_t LP_connectstart(int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *myipaddr,char *base,char *rel,double profitmargin) +{ + char *retstr,pairstr[512]; cJSON *retjson; double price; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; uint64_t destvalue; struct LP_quoteinfo Q; struct basilisk_swap *swap; + if ( (price= LP_price(base,rel)) != 0. ) + { + price *= (1. + profitmargin); + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + if ( LP_quoteparse(&Q,argjson) < 0 ) + return(-2); + //printf("connect with.(%s)\n",jprint(argjson,0)); + Q.destsatoshis = Q.satoshis * price; + privkey = LP_privkey(utxo->coinaddr); + if ( bits256_nonz(utxo->S.mypub) == 0 ) + utxo->S.mypub = LP_pubkey(privkey); + if ( LP_iseligible(1,Q.srccoin,Q.txid,Q.vout,Q.satoshis,Q.txid2,Q.vout2) == 0 ) + { + printf("not eligible\n"); + return(-1); + } + if ( bits256_nonz(privkey) != 0 && Q.quotetime >= Q.timestamp-3 && Q.quotetime < utxo->T.swappending && bits256_cmp(utxo->S.mypub,Q.srchash) == 0 && (destvalue= LP_txvalue(rel,Q.desttxid,Q.destvout)) >= price*Q.satoshis+Q.desttxfee && destvalue >= Q.destsatoshis+Q.desttxfee ) + { + nanomsg_tcpname(pairstr,myipaddr,10000+(rand() % 10000)); + if ( (pair= nn_socket(AF_SP,NN_PAIR)) < 0 ) + printf("error creating utxo->pair\n"); + else if ( nn_bind(pair,pairstr) >= 0 ) + { + LP_requestinit(&Q.R,Q.srchash,Q.desthash,base,Q.satoshis,rel,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); + swap = LP_swapinit(1,0,privkey,&Q.R,&Q); + swap->N.pair = pair; + utxo->S.swap = swap; + swap->utxo = utxo; + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)swap) == 0 ) + { + retjson = LP_quotejson(&Q); + jaddstr(retjson,"method","connected"); + jaddstr(retjson,"pair",pairstr); + jaddnum(retjson,"requestid",Q.R.requestid); + jaddnum(retjson,"quoteid",Q.R.quoteid); + retstr = jprint(retjson,1); + if ( pubsock >= 0 ) + LP_send(pubsock,retstr,1); + else LP_pubkey_send(utxo->S.otherpubkey,retstr,1); + retval = 0; + } else printf("error launching swaploop\n"); + } else printf("printf error nn_connect to %s\n",pairstr); + } + else + { + printf("dest %.8f < required %.8f (%d %d %d %d %d %d) %.8f %.8f\n",dstr(Q.satoshis),dstr(price*(utxo->S.satoshis-Q.txfee)),bits256_nonz(privkey) != 0 ,Q.timestamp == utxo->T.swappending-LP_RESERVETIME ,Q.quotetime >= Q.timestamp ,Q.quotetime < utxo->T.swappending ,bits256_cmp(utxo->S.mypub,Q.srchash) == 0 , LP_txvalue(rel,Q.desttxid,Q.destvout) >= price*Q.satoshis+Q.desttxfee,dstr(LP_txvalue(rel,Q.desttxid,Q.destvout)),dstr(price*Q.satoshis+Q.desttxfee)); + } + } else printf("no price for %s/%s\n",base,rel); + if ( retval < 0 ) + { + if ( pair >= 0 ) + nn_close(pair); + LP_availableset(utxo); + } + return(retval); +} + +char *LP_connected(cJSON *argjson) // alice +{ + cJSON *retjson; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *utxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; + retjson = cJSON_CreateObject(); + LP_quoteparse(&Q,argjson); + if ( IAMLP == 0 && bits256_cmp(Q.desthash,LP_mypubkey) == 0 && (utxo= LP_utxofind(0,Q.desttxid,Q.destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) + { + if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + jaddstr(retjson,"error","couldnt create pairsock"); + else if ( nn_connect(pairsock,pairstr) >= 0 ) + { + LP_unavailableset(utxo,Q.srchash); + Q.privkey = LP_privkey(Q.destaddr); + LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis,Q.destcoin,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); + swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q); + swap->N.pair = pairsock; + utxo->S.swap = swap; + swap->utxo = utxo; + printf("alice pairstr.(%s)\n",pairstr); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 ) + { + jaddstr(retjson,"result","success"); + jadd(retjson,"trade",LP_quotejson(&Q)); + jaddnum(retjson,"requestid",Q.R.requestid); + jaddnum(retjson,"quoteid",Q.R.quoteid); + } else jaddstr(retjson,"error","couldnt aliceloop"); + } + } else jaddstr(retjson,"result","update stats"); + return(jprint(retjson,1)); +} + +int32_t LP_tradecommand(char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) { - char *method,*base,*rel,*retstr,pairstr[512]; cJSON *retjson; double price; bits256 privkey,txid; struct LP_utxoinfo *utxo; int32_t retval = -1,DEXselector = 0; uint64_t destvalue; struct basilisk_request R; struct LP_quoteinfo Q; - if ( IAMCLIENT == 0 && (method= jstr(argjson,"method")) != 0 ) + char *method,*base,*rel,*retstr; cJSON *retjson; double price; bits256 txid; struct LP_utxoinfo *utxo; int32_t retval = -1; struct LP_quoteinfo Q; + if ( (method= jstr(argjson,"method")) != 0 ) { txid = jbits256(argjson,"txid"); - if ( (utxo= LP_utxofind(txid,jint(argjson,"vout"))) != 0 && strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port && (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 ) + if ( (utxo= LP_utxofind(1,txid,jint(argjson,"vout"))) != 0 && LP_ismine(utxo) != 0 && (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 ) { printf("LP_command.(%s)\n",jprint(argjson,0)); - if ( time(NULL) > utxo->swappending ) - utxo->swappending = 0; - if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) + if ( utxo->S.swap == 0 && time(NULL) > utxo->T.swappending ) + utxo->T.swappending = 0; + if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) // bob { retval = 1; - if ( utxo->swappending == 0 ) + if ( LP_isavailable(utxo) > 0 ) { - if ( strcmp(method,"request") == 0 && utxo->pair >= 0 ) - nn_close(utxo->pair), utxo->pair = -1; if ( (price= LP_price(base,rel)) != 0. ) { price *= (1. + profitmargin); if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) return(-1); - if ( LP_iseligible(Q.srccoin,Q.txid,Q.vout,Q.satoshis,Q.txid2,Q.vout2) == 0 ) + if ( LP_iseligible(1,Q.srccoin,Q.txid,Q.vout,Q.satoshis,Q.txid2,Q.vout2) == 0 ) { printf("not eligible\n"); return(-1); @@ -90,121 +178,40 @@ int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uin if ( strcmp(method,"price") == 0 ) Q.timestamp = (uint32_t)time(NULL); retjson = LP_quotejson(&Q); + utxo->S.otherpubkey = jbits256(argjson,"desthash"); if ( strcmp(method,"request") == 0 ) { retval |= 2; - utxo->swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); - utxo->otherpubkey = jbits256(argjson,"desthash"); + LP_unavailableset(utxo,jbits256(argjson,"desthash")); jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); - jaddnum(retjson,"pending",utxo->swappending); - jaddbits256(retjson,"desthash",utxo->otherpubkey); + jaddnum(retjson,"pending",utxo->T.swappending); + jaddbits256(retjson,"desthash",utxo->S.otherpubkey); jaddstr(retjson,"method","reserved"); } else jaddstr(retjson,"method","quote"); retstr = jprint(retjson,1); - LP_send(pubsock,retstr,1); - utxo->published = (uint32_t)time(NULL); + if ( pubsock >= 0 ) + LP_send(pubsock,retstr,1); + else LP_pubkey_send(utxo->S.otherpubkey,retstr,1); + utxo->T.published = (uint32_t)time(NULL); } else printf("null price\n"); - } else printf("swappending.%u pair.%d\n",utxo->swappending,utxo->pair); + } else printf("swappending.%u swap.%p\n",utxo->T.swappending,utxo->S.swap); } - else if ( strcmp(method,"connect") == 0 ) + else if ( strcmp(method,"connect") == 0 ) // bob { retval = 4; - if ( utxo->pair < 0 ) - { - if ( (price= LP_price(base,rel)) != 0. ) - { - price *= (1. + profitmargin); - if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) - return(-1); - if ( LP_quoteparse(&Q,argjson) < 0 ) - return(-2); - //printf("connect with.(%s)\n",jprint(argjson,0)); - Q.destsatoshis = Q.satoshis * price; - privkey = LP_privkey(utxo->coinaddr); - if ( bits256_nonz(utxo->mypub) == 0 ) - utxo->mypub = LP_pubkey(privkey); - if ( LP_iseligible(Q.srccoin,Q.txid,Q.vout,Q.satoshis,Q.txid2,Q.vout2) == 0 ) - { - printf("not eligible\n"); - return(-1); - } - if ( bits256_nonz(privkey) != 0 && Q.quotetime >= Q.timestamp-3 && Q.quotetime < utxo->swappending && bits256_cmp(utxo->mypub,Q.srchash) == 0 && (destvalue= LP_txvalue(rel,Q.desttxid,Q.destvout)) >= price*Q.satoshis+Q.desttxfee && destvalue >= Q.destsatoshis+Q.desttxfee ) - { - nanomsg_tcpname(pairstr,mypeer->ipaddr,10000+(rand() % 10000)); - if ( (utxo->pair= nn_socket(AF_SP,NN_PAIR)) < 0 ) - printf("error creating utxo->pair\n"); - else if ( nn_bind(utxo->pair,pairstr) >= 0 ) - { - LP_requestinit(&R,Q.srchash,Q.desthash,base,Q.satoshis,rel,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)utxo) == 0 ) - { - retjson = LP_quotejson(&Q); - jaddstr(retjson,"method","connected"); - jaddstr(retjson,"pair",pairstr); - jaddnum(retjson,"requestid",R.requestid); - jaddnum(retjson,"quoteid",R.quoteid); - retstr = jprint(retjson,1); - LP_send(pubsock,retstr,1); - utxo->swap = LP_swapinit(1,0,privkey,&R,&Q); - } - else - { - printf("error launching swaploop\n"); - free(utxo->swap); - utxo->swap = 0; - nn_close(utxo->pair); - utxo->pair = -1; - } - } - else - { - printf("printf error nn_connect to %s\n",pairstr); - nn_close(utxo->pair); - utxo->pair = -1; - } - } else printf("dest %.8f < required %.8f (%d %d %d %d %d %d) %.8f %.8f\n",dstr(Q.satoshis),dstr(price*(utxo->satoshis-Q.txfee)),bits256_nonz(privkey) != 0 ,Q.timestamp == utxo->swappending-LP_RESERVETIME ,Q.quotetime >= Q.timestamp ,Q.quotetime < utxo->swappending ,bits256_cmp(utxo->mypub,Q.srchash) == 0 , LP_txvalue(rel,Q.desttxid,Q.destvout) >= price*Q.satoshis+Q.desttxfee,dstr(LP_txvalue(rel,Q.desttxid,Q.destvout)),dstr(price*Q.satoshis+Q.desttxfee)); - } else printf("no price for %s/%s\n",base,rel); - } else printf("utxo->pair.%d when connect came in (%s)\n",utxo->pair,jprint(argjson,0)); + if ( utxo->T.swappending != 0 && utxo->S.swap == 0 ) + LP_connectstart(pubsock,utxo,argjson,myipaddr,base,rel,profitmargin); + else printf("swap %p when connect came in (%s)\n",utxo->S.swap,jprint(argjson,0)); } } } return(retval); } -char *LP_connected(cJSON *argjson) -{ - cJSON *retjson; int32_t pairsock = -1; char *pairstr; struct LP_quoteinfo *qp; int32_t DEXselector = 0; - retjson = cJSON_CreateObject(); - if ( IAMCLIENT == 0 ) - jaddstr(retjson,"result","update stats"); - else - { - if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) - jaddstr(retjson,"error","couldnt create pairsock"); - else if ( nn_connect(pairsock,pairstr) >= 0 ) - { - qp = calloc(1,sizeof(*qp)); - LP_quoteparse(qp,argjson); - qp->pair = pairsock; - qp->privkey = LP_privkey(qp->destaddr); - LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis,qp->destcoin,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector); - printf("alice pairstr.(%s)\n",pairstr); - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)qp) == 0 ) - { - jaddstr(retjson,"result","success"); - jadd(retjson,"trade",LP_quotejson(qp)); - } else jaddstr(retjson,"error","couldnt aliceloop"); - } - } - return(jprint(retjson,1)); -} - -// addcoin api - char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port { - char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport,pushport,subport; int32_t amclient,otherpeers,othernumutxos; struct LP_utxoinfo *utxo,*tmp; struct LP_peerinfo *peer; cJSON *retjson; struct iguana_info *ptr; + char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport,pushport,subport; int32_t otherpeers,othernumutxos; struct LP_utxoinfo *utxo,*tmp; struct LP_peerinfo *peer; cJSON *retjson; struct iguana_info *ptr; if ( (method= jstr(argjson,"method")) == 0 ) return(clonestr("{\"error\":\"need method in request\"}")); else if ( strcmp(method,"help") == 0 ) @@ -226,6 +233,9 @@ getutxos()\n\ getutxos(coin, lastn)\n\ orderbook(base, rel)\n\ getprice(base, rel)\n\ +register(pubkey,pushaddr)\n\ +lookup(pubkey)\n\ +forward(pubkey,hexstr)\n\ \"}")); if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) { @@ -250,9 +260,9 @@ getprice(base, rel)\n\ return(clonestr("{\"error\":\"couldnt set price\"}")); else { - if ( IAMCLIENT == 0 ) + if ( IAMLP != 0 ) { - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) { if ( LP_ismine(utxo) != 0 && (strcmp(utxo->coin,base) == 0 || strcmp(utxo->coin,rel) == 0) ) LP_priceping(LP_mypubsock,utxo,rel,LP_profitratio - 1.); @@ -294,10 +304,10 @@ getprice(base, rel)\n\ return(clonestr("{\"error\":\"coin is disabled\"}")); if ( strcmp(method,"inventory") == 0 ) { - LP_privkey_init(0,-1,coin,0,USERPASS_WIFSTR,1); - return(LP_inventory(coin)); + LP_privkey_init(-1,coin,0,USERPASS_WIFSTR,0); + return(LP_inventory(coin,jobj(argjson,"client") != 0 ? jint(argjson,"client") : 0)); } - else if ( IAMCLIENT != 0 && (strcmp(method,"candidates") == 0 || strcmp(method,"autotrade") == 0) ) + else if ( (strcmp(method,"candidates") == 0 || strcmp(method,"autotrade") == 0) ) { bits256 txid; int32_t vout; struct LP_utxoinfo *utxo; txid = jbits256(argjson,"txid"); @@ -306,7 +316,7 @@ getprice(base, rel)\n\ if ( jobj(argjson,"vout") == 0 ) return(clonestr("{\"error\":\"missing vout\"}")); vout = jint(argjson,"vout"); - if ( (utxo= LP_utxofind(txid,vout)) == 0 ) + if ( (utxo= LP_utxofind(1,txid,vout)) == 0 ) return(clonestr("{\"error\":\"txid/vout not found\"}")); if ( strcmp(method,"candidates") == 0 ) return(jprint(LP_tradecandidates(coin),1)); @@ -325,7 +335,6 @@ getprice(base, rel)\n\ return(clonestr("{\"error\":\"at least one of coins disabled\"}")); if ( LP_isdisabled(jstr(argjson,"coin"),0) != 0 ) return(clonestr("{\"error\":\"coin is disabled\"}")); - amclient = (LP_mypeer == 0); if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) { if ( strcmp(ipaddr,"127.0.0.1") != 0 && port >= 1000 ) @@ -344,7 +353,7 @@ getprice(base, rel)\n\ 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(amclient,LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); + } else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); } } //printf("CMD.(%s)\n",jprint(argjson,0)); @@ -362,21 +371,30 @@ getprice(base, rel)\n\ retstr = LP_orderbook(jstr(argjson,"base"),jstr(argjson,"rel")); else if ( strcmp(method,"getpeers") == 0 ) retstr = LP_peers(); - else if ( IAMCLIENT == 0 && strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 ) - { - retstr = LP_utxos(LP_mypeer,coin,jint(argjson,"lastn")); - //printf("RETURN. %d utxos\n",cJSON_GetArraySize(cJSON_Parse(retstr))); - } - else if ( IAMCLIENT == 0 && strcmp(method,"notify") == 0 ) - retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); - else if ( IAMCLIENT == 0 && strcmp(method,"notified") == 0 ) + else if ( IAMLP != 0 ) { - if ( juint(argjson,"timestamp") > time(NULL)-60 ) + if ( strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 ) { - printf("utxonotify.(%s)\n",jprint(argjson,0)); - LP_addutxo(amclient,LP_mypeer,LP_mypubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"valuesats"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"valuesats2"),jstr(argjson,"script"),jstr(argjson,"address"),jstr(argjson,"ipaddr"),juint(argjson,"port"),jdouble(argjson,"profit")); + retstr = LP_utxos(1,LP_mypeer,coin,jint(argjson,"lastn")); + //printf("RETURN. %d utxos\n",cJSON_GetArraySize(cJSON_Parse(retstr))); + } + else if ( strcmp(method,"register") == 0 ) + retstr = LP_register(jbits256(argjson,"pubkey"),jstr(argjson,"pushaddr")); + else if ( strcmp(method,"lookup") == 0 ) + retstr = LP_lookup(jbits256(argjson,"pubkey")); + else if ( strcmp(method,"forward") == 0 ) + retstr = LP_forward(jbits256(argjson,"pubkey"),jstr(argjson,"hexstr")); + else if ( strcmp(method,"notify") == 0 ) + retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); + else if ( strcmp(method,"notified") == 0 ) + { + if ( juint(argjson,"timestamp") > time(NULL)-60 ) + { + printf("utxonotify.(%s)\n",jprint(argjson,0)); + LP_addutxo(1,LP_mypubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"valuesats"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"valuesats2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jdouble(argjson,"profit")); + } + retstr = clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"); } - retstr = clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"); } if ( retstr != 0 ) return(retstr); diff --git a/iguana/exchanges/LP_forwarding.c b/iguana/exchanges/LP_forwarding.c new file mode 100644 index 000000000..2dd260294 --- /dev/null +++ b/iguana/exchanges/LP_forwarding.c @@ -0,0 +1,165 @@ + +/****************************************************************************** + * 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_forwarding.c +// marketmaker +// + +struct LP_forwardinfo +{ + UT_hash_handle hh; + bits256 pubkey; + char pushaddr[64]; + int32_t pushsock; + uint32_t lasttime; +} *LP_forwardinfos; +#define LP_KEEPALIVE 300 + +struct LP_forwardinfo *LP_forwardfind(bits256 pubkey) +{ + struct LP_forwardinfo *ptr=0; + portable_mutex_lock(&LP_forwardmutex); + HASH_FIND(hh,LP_forwardinfos,&pubkey,sizeof(pubkey),ptr); + portable_mutex_unlock(&LP_forwardmutex); + if ( ptr != 0 && ptr->lasttime > time(NULL)-LP_KEEPALIVE ) + return(ptr); + else return(0); +} + +char *LP_lookup(bits256 pubkey) +{ + if ( LP_forwardfind(pubkey) != 0 ) + return(clonestr("{\"result\":\"success\",\"forwarding\":1}")); + else return(clonestr("{\"error\":\"notfound\"}")); +} + +char *LP_register(bits256 pubkey,char *pushaddr) +{ + struct LP_forwardinfo *ptr=0; int32_t pushsock; + if ( is_ipaddr(pushaddr) == 0 ) + return(clonestr("{\"error\":\"illegal ipaddr\"}")); + if ( (ptr= LP_forwardfind(pubkey)) != 0 ) + { + ptr->lasttime = (uint32_t)time(NULL); + return(clonestr("{\"error\":\"already registered\"}")); + } + else if ( (pushsock= nn_socket(AF_SP,NN_PUSH)) < 0 ) + return(clonestr("{\"error\":\"out of sockets\"}")); + else if ( nn_connect(pushsock,pushaddr) < 0 ) + { + nn_close(pushsock); + return(clonestr("{\"error\":\"cant connect\"}")); + } + else + { + ptr = calloc(1,sizeof(*ptr)); + ptr->pubkey = pubkey; + strcpy(ptr->pushaddr,pushaddr); + ptr->pushsock = pushsock; + ptr->lasttime = (uint32_t)time(NULL); + portable_mutex_lock(&LP_forwardmutex); + HASH_ADD_KEYPTR(hh,LP_forwardinfos,&ptr->pubkey,sizeof(ptr->pubkey),ptr); + portable_mutex_unlock(&LP_forwardmutex); + return(LP_lookup(pubkey)); + } +} + +char *LP_forward(bits256 pubkey,char *hexstr) +{ + struct LP_forwardinfo *ptr=0; uint8_t *data; int32_t datalen=0,sentbytes=0; cJSON *retjson; + if ( hexstr == 0 || hexstr[0] == 0 ) + return(clonestr("{\"error\":\"nohex\"}")); + if ( (ptr= LP_forwardfind(pubkey)) != 0 ) + { + if ( ptr->pushsock >= 0 ) + { + datalen = (int32_t)strlen(hexstr) >> 1; + data = malloc(datalen); + decode_hex(data,datalen,hexstr); + sentbytes = LP_send(ptr->pushsock,(char *)data,1); + } + retjson = cJSON_CreateObject(); + if ( sentbytes == datalen ) + { + jaddstr(retjson,"result","success"); + jaddnum(retjson,"forwarded",sentbytes); + return(jprint(retjson,1)); + } + else + { + jaddstr(retjson,"error","send error"); + jaddnum(retjson,"sentbytes",sentbytes); + jaddnum(retjson,"datalen",datalen); + return(jprint(retjson,1)); + } + } else return(clonestr("{\"error\":\"notfound\"}")); +} + +void LP_forwarding_register(bits256 pubkey,char *pushaddr) +{ + char *retstr; cJSON *retjson; struct LP_peerinfo *peer,*tmp; int32_t retval = -1; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( (retstr= issue_LP_register(peer->ipaddr,peer->port,pubkey,pushaddr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jint(retjson,"registered") != 0 ) + retval = 0; + free_json(retjson); + } + free(retstr); + } + if ( retval == 0 ) + break; + } +} + +int32_t LP_pubkey_send(bits256 pubkey,char *jsonstr,int32_t freeflag) +{ + struct LP_forwardinfo *ptr; struct LP_peerinfo *peer,*tmp; char *hexstr,*retstr; int32_t len,retval = -1; cJSON *retjson; + if ( IAMLP != 0 && (ptr= LP_forwardfind(pubkey)) != 0 && ptr->pushsock >= 0 && ptr->lasttime > time(NULL)-LP_KEEPALIVE ) + { + return(LP_send(ptr->pushsock,jsonstr,1)); + } + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( (retstr= issue_LP_lookup(peer->ipaddr,peer->port,pubkey)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jint(retjson,"forwarding") != 0 ) + retval = 0; + free_json(retjson); + } + free(retstr); + } + if ( retval == 0 ) + { + len = (int32_t)strlen(jsonstr) + 1; + hexstr = malloc(len*2 + 1); + init_hexbytes_noT(hexstr,(uint8_t *)jsonstr,len); + if ( freeflag != 0 ) + free(jsonstr); + if ( peer->pushsock >= 0 ) + return(LP_send(peer->pushsock,hexstr,1)); + } + } + return(-1); +} + + + diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index b75202a12..dd2422cdf 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -46,7 +46,7 @@ #define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) extern char GLOBAL_DBDIR[],USERPASS[],USERPASS_WIFSTR[]; -extern int32_t IAMCLIENT,USERPASS_COUNTER; +extern int32_t IAMLP,USERPASS_COUNTER; struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; @@ -139,42 +139,34 @@ struct basilisk_swapinfo struct iguana_info { - uint64_t txfee; double estimatedrate; + uint64_t txfee; double estimatedrate,profitmargin; int32_t longestchain; uint32_t counter,inactive; uint8_t pubtype,p2shtype,isPoS,wiftype; char symbol[16],smartaddr[64],userpass[1024],serverport[128]; }; -struct basilisk_swap -{ - void *ctx; struct iguana_info bobcoin,alicecoin; - void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob); - int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted; - FILE *fp; - bits256 persistent_privkey,persistent_pubkey; - struct basilisk_swapinfo I; - struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; - bits256 privkeys[INSTANTDEX_DECKSIZE]; - struct basilisk_swapmessage *messages; int32_t nummessages; - char Bdeposit[64],Bpayment[64]; - uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; - uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; - -}; +struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; }; + +struct LP_utxostats { uint32_t lasttime,errors,swappending,published,spentflag,lastspentcheck; }; + +struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; }; + +struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; }; + +struct LP_utxoswap { bits256 otherpubkey,mypub; void *swap; uint64_t satoshis; double profitmargin; }; struct LP_utxoinfo { UT_hash_handle hh,hh2; - bits256 txid,txid2,feetxid,otherpubkey,mypub; - void *swap; - uint64_t value,satoshis,value2; + bits256 pubkey; + struct _LP_utxoinfo payment,deposit,fee; + struct LP_utxostats T; + struct LP_utxoswap S; + //struct LP_utxonetwork N; + int32_t iambob,iamlp; uint8_t key[sizeof(bits256) + sizeof(int32_t)]; uint8_t key2[sizeof(bits256) + sizeof(int32_t)]; - int32_t vout,vout2,pair; - uint32_t lasttime,errors,swappending,published,spentflag,lastspentcheck; - double profitmargin; - char ipaddr[64],coinaddr[64],spendscript[256],coin[16]; - uint16_t port; + char coin[16],coinaddr[64],spendscript[256]; }; struct LP_peerinfo @@ -197,13 +189,33 @@ struct LP_quoteinfo char srccoin[16],coinaddr[64],destcoin[16],destaddr[64]; }; +struct LP_endpoint { int32_t pair; char ipaddr[64]; uint16_t port; }; + +struct basilisk_swap +{ + void *ctx; struct iguana_info bobcoin,alicecoin; struct LP_utxoinfo *utxo; + struct LP_endpoint N; + void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob); + int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted; + FILE *fp; + bits256 persistent_privkey,persistent_pubkey; + struct basilisk_swapinfo I; + struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; + bits256 privkeys[INSTANTDEX_DECKSIZE]; + struct basilisk_swapmessage *messages; int32_t nummessages; + char Bdeposit[64],Bpayment[64]; + uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; + uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; + +}; + 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); 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 *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub); +double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub); int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys); void LP_quotesinit(char *base,char *rel); diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 754ca56bc..b2d4e7369 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -17,13 +17,13 @@ // LP_nativeDEX.c // marketmaker // -// jl777: fix price calcs based on specific txfees +// jl777: profitmargin per coin, ignore peers with errors #include #include "LP_include.h" #include "LP_network.c" -struct LP_utxoinfo *LP_utxoinfos,*LP_utxoinfos2; +struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; struct LP_peerinfo *LP_peerinfos,*LP_mypeer; char *activecoins[] = { "BTC", "KMD" }; @@ -32,11 +32,11 @@ char USERPASS[65],USERPASS_WIFSTR[64],USERHOME[512] = { "/root" }; char *default_LPnodes[] = { "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" }; //"5.9.253.195", -portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex; +portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex; int32_t LP_mypubsock = -1; -int32_t Client_connections; -int32_t USERPASS_COUNTER,IAMCLIENT = 0; +int32_t USERPASS_COUNTER,IAMLP = 0; double LP_profitratio = 1.; +bits256 LP_mypubkey; // stubs int32_t basilisk_istrustedbob(struct basilisk_swap *swap) @@ -76,26 +76,124 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_peers.c" #include "LP_utxos.c" #include "LP_quotes.c" +#include "LP_forwarding.c" #include "LP_commands.c" -void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,int32_t pullsock,uint16_t myport,int32_t amclient,char *passphrase,double profitmargin,cJSON *coins) +int32_t LP_pullsock_check(char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin) { - //static uint16_t tmpport; - char *retstr; uint8_t r; int32_t i,n,j,len,recvsize,counter=0,nonz,lastn; struct LP_peerinfo *peer,*tmp; uint32_t now; struct LP_utxoinfo *utxo,*utmp; void *ptr; cJSON *argjson,*item; - //if ( amclient != 0 ) - // myport += amclient * 10; + int32_t recvsize,len,datalen,nonz = 0; void *ptr; char *retstr,*jsonstr=0; cJSON *argjson; + while ( (recvsize= nn_recv(pullsock,&ptr,NN_MSG,0)) >= 0 ) + { + nonz++; + if ( (datalen= is_hexstr((char *)ptr,0)) > 0 ) + { + datalen >>= 1; + jsonstr = malloc(datalen + 1); + decode_hex((void *)jsonstr,datalen,(char *)ptr); + jsonstr[datalen] = 0; + } else jsonstr = (char *)ptr; + if ( (argjson= cJSON_Parse(jsonstr)) != 0 ) + { + len = (int32_t)strlen(jsonstr) + 1; + portable_mutex_lock(&LP_commandmutex); + if ( LP_tradecommand(myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvsize - len,profitmargin) == 0 ) + { + if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) + { + printf("%s PULL.[%d] %s\n",myipaddr != 0 ? myipaddr : "127.0.0.1",recvsize,(char *)ptr); + free(retstr); + } + } + portable_mutex_unlock(&LP_commandmutex); + free_json(argjson); + } + if ( (void *)jsonstr != ptr ) + free(jsonstr); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; + } + return(nonz); +} + +int32_t LP_subsock_check(struct LP_peerinfo *peer) +{ + int32_t recvsize,nonz = 0; char *retstr; void *ptr; cJSON *argjson; + while ( peer->subsock >= 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",0)) != 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; + } + return(nonz); +} + +void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo,double profitmargin) +{ + struct _LP_utxoinfo u; char str[65]; uint32_t now = (uint32_t)time(NULL); + //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck); + if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) + { + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + utxo->T.lastspentcheck = now; + if ( LP_txvalue(utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 ) + { + printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value)); + LP_spentnotify(utxo,0); + } + else if ( LP_txvalue(utxo->coin,u.txid,u.vout) == 0 ) + { + printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value)); + LP_spentnotify(utxo,1); + } + else if ( LP_ismine(utxo) != 0 ) + { + if ( strcmp(utxo->coin,"KMD") == 0 ) + LP_priceping(pubsock,utxo,"BTC",profitmargin); + else LP_priceping(pubsock,utxo,"KMD",profitmargin); + } + } +} + +void LP_utxo_updates(int32_t pubsock,char *passphrase,double profitmargin) +{ + int32_t iambob; struct LP_utxoinfo *utxo,*tmp; + LP_utxopurge(0); + for (iambob=0; iambob<=1; iambob++) + { + LP_privkey_updates(pubsock,passphrase,iambob); + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + { + LP_utxo_spentcheck(pubsock,utxo,profitmargin); + } + } +} + +void LP_mainloop(char *myipaddr,struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,char *pushaddr,int32_t pullsock,uint16_t myport,char *passphrase,double profitmargin,cJSON *coins) +{ + char *retstr; uint8_t r; int32_t i,n,j,counter=0,nonz,lastn; struct LP_peerinfo *peer,*tmp; uint32_t now,lastforward = 0; cJSON *item; if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) { printf("error launching stats rpcloop for port.%u\n",myport); exit(-1); } - if ( amclient == 0 ) + if ( IAMLP != 0 ) { for (i=0; i 25 ) continue; - LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); + LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); } } else @@ -104,12 +202,9 @@ void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,i for (j=0; jipaddr,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1") != 0 ) { - printf("query utxo from %s\n",peer->ipaddr); - LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",100,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); + //printf("query utxo from %s\n",peer->ipaddr); + LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",100,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); } } - if ( amclient != 0 ) + if ( IAMLP == 0 ) { while ( 1 ) { + now = (uint32_t)time(NULL); + if ( lastforward < now-LP_KEEPALIVE ) + { + LP_forwarding_register(LP_mypubkey,pushaddr); + lastforward = now; + } nonz = n = 0; - if ( (++counter % 3600) == 0 ) - LP_privkey_updates(mypeer,pubsock,passphrase,amclient); + if ( (++counter % 5000) == 0 ) + LP_utxo_updates(pubsock,passphrase,profitmargin); HASH_ITER(hh,LP_peerinfos,peer,tmp) { - n++; - while ( peer->subsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 ) + nonz += LP_subsock_check(peer); + } + if ( pullsock >= 0 ) + { + if ( (n= LP_pullsock_check(myipaddr,pubsock,pullsock,profitmargin)) > 0 ) { - nonz++; - if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) - { - portable_mutex_lock(&LP_commandmutex); - if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) - { - //printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); - free(retstr); - } - portable_mutex_unlock(&LP_commandmutex); - //printf("subloop.(%s)\n",jprint(argjson,0)); - free_json(argjson); - } else printf("error parsing.(%s)\n",(char *)ptr); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; + nonz += n; + lastforward = now; } } if ( nonz == 0 ) @@ -173,41 +265,8 @@ void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,i while ( 1 ) { nonz = 0; - if ( (++counter % 2000) == 0 ) - { - LP_privkey_updates(mypeer,pubsock,passphrase,amclient); - } if ( (counter % 500) == 0 ) - { - char str[65]; - //printf("start utxos updates\n"); - HASH_ITER(hh,LP_utxoinfos,utxo,utmp) - { - now = (uint32_t)time(NULL); - //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck); - if ( utxo->spentflag == 0 && now > utxo->lastspentcheck+60 ) - { - utxo->lastspentcheck = now; - if ( LP_txvalue(utxo->coin,utxo->txid,utxo->vout) == 0 ) - { - printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->txid),utxo->vout,dstr(utxo->value)); - LP_spentnotify(utxo,0); - } - else if ( LP_txvalue(utxo->coin,utxo->txid2,utxo->vout2) == 0 ) - { - printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->txid2),utxo->vout2,dstr(utxo->value2)); - LP_spentnotify(utxo,1); - } - else if ( LP_ismine(utxo) != 0 ) - { - if ( strcmp(utxo->coin,"KMD") == 0 ) - LP_priceping(pubsock,utxo,"BTC",profitmargin); - else LP_priceping(pubsock,utxo,"KMD",profitmargin); - } - } - } - //printf("done utxos updates\n"); - } + LP_utxo_updates(pubsock,passphrase,profitmargin); now = (uint32_t)time(NULL); //printf("start peers updates\n"); HASH_ITER(hh,LP_peerinfos,peer,tmp) @@ -219,7 +278,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(amclient,mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin); + LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin); } if ( peer->numutxos != mypeer->numutxos && now > peer->lastutxos+60 ) { @@ -229,47 +288,12 @@ void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,i lastn = LP_PROPAGATION_SLACK * 2; printf("%s numutxos.%d vs %d lastn.%d\n",peer->ipaddr,peer->numutxos,mypeer->numutxos,lastn); if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) - LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer->ipaddr,myport,profitmargin); - } - while ( peer->subsock >= 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",0)) != 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; + LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer->ipaddr,myport,profitmargin); } + nonz += LP_subsock_check(peer); } - while ( pullsock >= 0 && (recvsize= nn_recv(pullsock,&ptr,NN_MSG,0)) >= 0 ) - { - nonz++; - if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) - { - len = (int32_t)strlen((char *)ptr) + 1; - portable_mutex_lock(&LP_commandmutex); - if ( LP_command(mypeer,pubsock,argjson,&((uint8_t *)ptr)[len],recvsize - len,profitmargin) == 0 ) - { - if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) - { - printf("%s PULL.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); - free(retstr); - } - } - portable_mutex_unlock(&LP_commandmutex); - free_json(argjson); - } - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; - } + if ( pullsock >= 0 ) + nonz += LP_pullsock_check(myipaddr,pubsock,pullsock,profitmargin); if ( nonz == 0 ) usleep(100000); //printf("nonz.%d in mainloop\n",nonz); @@ -280,7 +304,7 @@ void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,i void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson) { char *myipaddr=0; long filesize,n; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128]; - IAMCLIENT = amclient; + IAMLP = !amclient; LP_profitratio += profitmargin; OS_randombytes((void *)&n,sizeof(n)); srand((int32_t)n); @@ -291,58 +315,70 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit portable_mutex_init(&LP_commandmutex); portable_mutex_init(&LP_swaplistmutex); portable_mutex_init(&LP_cachemutex); - if ( amclient == 0 ) + portable_mutex_init(&LP_forwardmutex); + if ( profitmargin == 0. || profitmargin == 0.01 ) { - if ( profitmargin == 0. || profitmargin == 0.01 ) + profitmargin = 0.01 + (double)(rand() % 100)/100000; + printf("default profit margin %f\n",profitmargin); + } + if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) + { + if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) + { + n = strlen(myipaddr); + if ( myipaddr[n-1] == '\n' ) + myipaddr[--n] = 0; + } else printf("error getting myipaddr\n"); + } else printf("error issuing curl\n"); + nanomsg_tcpname(pushaddr,myipaddr,mypullport); + if ( (pullsock= nn_socket(AF_SP,NN_PULL)) >= 0 ) + { + if ( nn_bind(pullsock,pushaddr) >= 0 ) { - profitmargin = 0.01 + (double)(rand() % 100)/100000; - printf("default profit margin %f\n",profitmargin); + timeout = 1; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + timeout = 1; + maxsize = 1024 * 1024; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); } - if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) + } + if ( IAMLP != 0 ) + { + if ( myipaddr != 0 ) { - if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) + pubsock = -1; + nanomsg_tcpname(subaddr,myipaddr,mypubport); + printf(">>>>>>>>> myipaddr.%s (%s %s)\n",myipaddr,pushaddr,subaddr); + if ( (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) { - n = strlen(myipaddr); - if ( myipaddr[n-1] == '\n' ) - myipaddr[--n] = 0; - pullsock = pubsock = -1; - nanomsg_tcpname(pushaddr,myipaddr,mypullport); - nanomsg_tcpname(subaddr,myipaddr,mypubport); - printf(">>>>>>>>> myipaddr.%s (%s %s)\n",myipaddr,pushaddr,subaddr); - if ( (pullsock= nn_socket(AF_SP,NN_PULL)) >= 0 && (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) + if ( nn_bind(pubsock,subaddr) >= 0 ) + { + timeout = 10; + nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + } + else { - if ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 ) - { - timeout = 10; - nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - maxsize = 1024 * 1024; - nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); - } - else - { - printf("error binding to (%s).%d (%s).%d\n",pushaddr,pullsock,subaddr,pubsock); - if ( pullsock >= 0 ) - nn_close(pullsock), pullsock = -1; - if ( pubsock >= 0 ) - nn_close(pubsock), pubsock = -1; - } - } else printf("error getting sockets %d %d\n",pullsock,pubsock); - LP_mypubsock = pubsock; - 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"); + printf("error binding to (%s).%d (%s).%d\n",pushaddr,pullsock,subaddr,pubsock); + if ( pubsock >= 0 ) + nn_close(pubsock), pubsock = -1; + } + } 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); + //printf("my ipaddr.(%s) peers.(%s)\n",ipaddr,retstr!=0?retstr:""); + } if ( myipaddr == 0 || mypeer == 0 ) { printf("couldnt get myipaddr or null mypeer.%p\n",mypeer); exit(-1); } - //printf("utxos.(%s)\n",LP_utxos(mypeer,"",10000)); } - LP_mainloop(mypeer,mypubport,pubsock,pullsock,myport,amclient,passphrase,profitmargin,jobj(argjson,"coins")); + else if ( myipaddr == 0 ) + { + printf("couldnt get myipaddr\n"); + exit(-1); + } +LP_mainloop(myipaddr,mypeer,mypubport,pubsock,pushaddr,pullsock,myport,passphrase,profitmargin,jobj(argjson,"coins")); } diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c index 1cd4c9056..2309e5c20 100644 --- a/iguana/exchanges/LP_peers.c +++ b/iguana/exchanges/LP_peers.c @@ -47,13 +47,9 @@ char *LP_peers() return(jprint(peersjson,1)); } -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) +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) { - uint32_t ipbits; int32_t pushsock,subsock,timeout,enabled; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; - /*if ( strcmp(ipaddr,"173.208.149.42") == 0 ) - return(0); - if ( strncmp(ipaddr,"5.9.253",strlen("5.9.253")) != 0 ) - return(0);*/ + uint32_t ipbits; int32_t pushsock,subsock,timeout; 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 ) @@ -73,9 +69,6 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32 peer = calloc(1,sizeof(*peer)); peer->pushsock = peer->subsock = pushsock = subsock = -1; strcpy(peer->ipaddr,ipaddr); - if ( amclient == 0 ) - enabled = 1; - else enabled = 1;//(rand() % (1 << Client_connections)) == 0; if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) { timeout = 1000; @@ -86,7 +79,7 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32 printf("connected to push.(%s) %d\n",pushaddr,pushsock); peer->connected = (uint32_t)time(NULL); peer->pushsock = pushsock; - if ( enabled != 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) + if ( (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) { timeout = 1; nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); @@ -96,7 +89,6 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32 { peer->subsock = subsock; printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); - Client_connections += amclient; } else nn_close(subsock); } } @@ -125,7 +117,7 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32 return(peer); } -int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +int32_t LP_peersparse(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 ) @@ -144,7 +136,7 @@ int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs argipbits = (uint32_t)calc_ipbits(argipaddr); if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) { - peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); + peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); } if ( peer != 0 ) { @@ -160,7 +152,7 @@ int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs return(n); } -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) +void LP_peersquery(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); @@ -170,9 +162,9 @@ void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock { //printf("got.(%s)\n",retstr); now = (uint32_t)time(NULL); - LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now); free(retstr); - if ( amclient == 0 ) + if ( IAMLP != 0 ) { HASH_ITER(hh,LP_peerinfos,peer,tmp) { diff --git a/iguana/exchanges/LP_quotes.c b/iguana/exchanges/LP_quotes.c index 943b103e2..7f7b7ade9 100644 --- a/iguana/exchanges/LP_quotes.c +++ b/iguana/exchanges/LP_quotes.c @@ -125,13 +125,13 @@ int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char * safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < 10000 ) qp->txfee = 10000; - if ( qp->txfee >= utxo->satoshis || qp->txfee >= utxo->value2 || utxo->value2 < LP_DEPOSITSATOSHIS(utxo->satoshis) ) + if ( utxo->iambob == 0 || qp->txfee >= utxo->S.satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(utxo->S.satoshis) ) return(-1); - qp->txid = utxo->txid; - qp->vout = utxo->vout; - qp->txid2 = utxo->txid2; - qp->vout2 = utxo->vout2; - qp->satoshis = utxo->satoshis - qp->txfee; + qp->txid = utxo->payment.txid; + qp->vout = utxo->payment.vout; + qp->txid2 = utxo->deposit.txid; + qp->vout2 = utxo->deposit.vout; + qp->satoshis = utxo->S.satoshis - qp->txfee; qp->destsatoshis = qp->satoshis * price; if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < 10000 ) qp->desttxfee = 10000; @@ -140,7 +140,7 @@ int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char * qp->destsatoshis -= qp->desttxfee; safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); - qp->srchash = LP_pubkey(LP_privkey(utxo->coinaddr)); + qp->srchash = utxo->pubkey; return(0); } @@ -224,7 +224,7 @@ cJSON *LP_tradecandidates(char *base) safecopy(coinstr,jstr(item,"base"),sizeof(coinstr)); if ( strcmp(coinstr,base) == 0 ) { - if ( LP_iseligible(Q.srccoin,Q.txid,Q.vout,Q.satoshis,Q.txid2,Q.vout2) != 0 ) + if ( LP_iseligible(1,Q.srccoin,Q.txid,Q.vout,Q.satoshis,Q.txid2,Q.vout2) != 0 ) { if ( LP_arrayfind(retarray,Q.txid,Q.vout) < 0 ) { @@ -265,8 +265,8 @@ void LP_quotesinit(char *base,char *rel) item = jitem(array,i); LP_quoteparse(&Q,item); if ( iter == 0 ) - LP_query("price",&Q,jstr(item,"ipaddr"),jint(item,"port"),base,rel,zero); - else LP_query("price",&Q,jstr(item,"ipaddr"),jint(item,"port"),rel,base,zero); + LP_query("price",&Q,base,rel,zero); + else LP_query("price",&Q,rel,base,zero); } } free_json(array); @@ -293,7 +293,7 @@ cJSON *LP_autotrade(struct LP_utxoinfo *myutxo,char *base,double maxprice) LP_quoteparse(&Q[i],item); if ( (price= jdouble(item,"price")) == 0. ) { - price = LP_query("price",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,zero); + price = LP_query("price",&Q[i],base,myutxo->coin,zero); Q[i].destsatoshis = price * Q[i].satoshis; } if ( (prices[i]= price) != 0. && (bestprice == 0. || price < bestprice) ) @@ -306,7 +306,7 @@ cJSON *LP_autotrade(struct LP_utxoinfo *myutxo,char *base,double maxprice) besti = -1; for (i=0; isatoshis >= Q[i].destsatoshis+Q[i].desttxfee ) + if ( (price= prices[i]) != 0. && myutxo->S.satoshis >= Q[i].destsatoshis+Q[i].desttxfee ) { metric = price / bestprice; printf("%f %f %f %f ",price,metric,dstr(Q[i].destsatoshis),metric * metric * metric); @@ -320,7 +320,7 @@ cJSON *LP_autotrade(struct LP_utxoinfo *myutxo,char *base,double maxprice) bestmetric = metric; } } - } else printf("(%f %f) ",dstr(myutxo->satoshis),dstr(Q[i].destsatoshis)); + } else printf("(%f %f) ",dstr(myutxo->S.satoshis),dstr(Q[i].destsatoshis)); } printf("metrics, best %f\n",bestmetric); if ( besti >= 0 )//&& bits256_cmp(myutxo->mypub,otherpubs[besti]) == 0 ) @@ -332,23 +332,23 @@ cJSON *LP_autotrade(struct LP_utxoinfo *myutxo,char *base,double maxprice) printf("bestprice %f vs maxprice %f\n",bestprice,maxprice); if ( maxprice == 0. || bestprice <= maxprice ) { - Q[i].desttxid = myutxo->txid; - Q[i].destvout = myutxo->vout; - Q[i].feetxid = myutxo->txid2; - Q[i].feevout = myutxo->vout2; + Q[i].desttxid = myutxo->payment.txid; + Q[i].destvout = myutxo->payment.vout; + Q[i].feetxid = myutxo->fee.txid; + Q[i].feevout = myutxo->fee.vout; strcpy(Q[i].destaddr,myutxo->coinaddr); - price = LP_query("request",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); + price = LP_query("request",&Q[i],base,myutxo->coin,myutxo->S.mypub); if ( jobj(bestitem,"price") != 0 ) jdelete(bestitem,"price"); jaddnum(bestitem,"price",prices[i]); if ( price <= maxprice ) { - Q[i].desttxid = myutxo->txid; - Q[i].destvout = myutxo->vout; - Q[i].feetxid = myutxo->txid2; - Q[i].feevout = myutxo->vout2; + Q[i].desttxid = myutxo->payment.txid; + Q[i].destvout = myutxo->payment.vout; + Q[i].feetxid = myutxo->fee.txid; + Q[i].feevout = myutxo->fee.vout; strcpy(Q[i].destaddr,myutxo->coinaddr); - price = LP_query("connect",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); + price = LP_query("connect",&Q[i],base,myutxo->coin,myutxo->S.mypub); LP_requestinit(&R,Q[i].srchash,Q[i].desthash,base,Q[i].satoshis,Q[i].destcoin,Q[i].destsatoshis,Q[i].timestamp,Q[i].quotetime,DEXselector); jaddstr(bestitem,"status","connected"); jaddnum(bestitem,"requestid",R.requestid); @@ -376,9 +376,9 @@ cJSON *LP_autotrade(struct LP_utxoinfo *myutxo,char *base,double maxprice) int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double profitmargin) { double price,bid,ask; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; - if ( (now= (uint32_t)time(NULL)) > utxo->swappending ) - utxo->swappending = 0; - if ( now > utxo->published+60 && utxo->swappending == 0 && utxo->pair < 0 && utxo->swap == 0 && (price= LP_myprice(&bid,&ask,utxo->coin,rel)) != 0. ) + if ( (now= (uint32_t)time(NULL)) > utxo->T.swappending ) + utxo->T.swappending = 0; + if ( now > utxo->T.published+60 && utxo->T.swappending == 0 && utxo->S.swap == 0 && (price= LP_myprice(&bid,&ask,utxo->coin,rel)) != 0. ) { if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) return(-1); @@ -388,7 +388,7 @@ int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double p retstr = jprint(retjson,1); //printf("PING.(%s)\n",retstr); LP_send(pubsock,retstr,1); - utxo->published = now; + utxo->T.published = now; return(0); } return(-1); diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index 31e1e0255..f5e915a70 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -52,12 +52,28 @@ char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port, char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) { char url[4096],str[65],str2[65]; - sprintf(url,"http://%s:%u/api/stats/notified?ipaddr=%s&port=%u&profit=%.6f&coin=%s&txid=%s&vout=%d&valuesats=%llu&txid2=%s&vout2=%d&valuesats2=%llu&script=%s&address=%s×tamp=%u",destip,destport,utxo->ipaddr,utxo->port,utxo->profitmargin,utxo->coin,bits256_str(str,utxo->txid),utxo->vout,(long long)utxo->value,bits256_str(str2,utxo->txid2),utxo->vout2,(long long)utxo->value2,utxo->spendscript,utxo->coinaddr,(uint32_t)time(NULL)); + sprintf(url,"http://%s:%u/api/stats/notified?pubkey=%s&profit=%.6f&coin=%s&txid=%s&vout=%d&valuesats=%llu&txid2=%s&vout2=%d&valuesats2=%llu&script=%s&address=%s×tamp=%u",destip,destport,bits256_str(str2,utxo->pubkey),utxo->S.profitmargin,utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,(long long)utxo->payment.value,bits256_str(str2,utxo->deposit.txid),utxo->deposit.vout,(long long)utxo->deposit.value,utxo->spendscript,utxo->coinaddr,(uint32_t)time(NULL)); if ( strlen(url) > 1024 ) printf("WARNING long url.(%s)\n",url); return(issue_curl(url)); } +char *issue_LP_register(char *destip,uint16_t destport,bits256 pubkey,char *pushaddr) +{ + char url[512],str[65]; + sprintf(url,"http://%s:%u/api/stats/register?pubkey=%s&pushaddr=%s",destip,destport,bits256_str(str,pubkey),pushaddr); + //printf("getutxo.(%s)\n",url); + return(issue_curl(url)); +} + +char *issue_LP_lookup(char *destip,uint16_t destport,bits256 pubkey) +{ + char url[512],str[65]; + sprintf(url,"http://%s:%u/api/stats/register?pubkey=%s",destip,destport,bits256_str(str,pubkey)); + //printf("getutxo.(%s)\n",url); + return(issue_curl(url)); +} + cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) { char *retstr; cJSON *retjson = 0; diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 35ce8f62f..fa674cf7a 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -17,22 +17,12 @@ // LP_swap.c // marketmaker // + /* - resume handling: list of tx broadcast, tx pending + required items, reconnect state machine or have statemachine assume off by one or state/otherstate specific handling make sure to broadcast deposit before claiming refund, or to just skip it if neither is done */ -// Todo: monitor blockchains, ie complete extracting scriptsig -// mode to autocreate required outputs -// more better LP commands - -// depends on just three external functions: -// - basilisk_sendrawtransaction(coin,signedtx); -// - basilisk_value(rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0) -// basilisk_bitcoinrawtx(rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V) - - // included from basilisk.c /* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271 https://bitcointalk.org/index.php?topic=1364951 @@ -148,6 +138,10 @@ void basilisk_swap_finished(struct basilisk_swap *swap) free(swap->messages[i].data), swap->messages[i].data = 0; free(swap->messages), swap->messages = 0; swap->nummessages = 0; + if ( swap->N.pair >= 0 ) + nn_close(swap->N.pair); + if ( swap->utxo != 0 ) + swap->utxo->S.swap = 0; } uint32_t basilisk_quoteid(struct basilisk_request *rp) @@ -575,7 +569,7 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba 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) { - uint8_t sendbuf[32768]; int32_t sendlen; + uint8_t sendbuf[32768]; int32_t sendlen,retval = -1; if ( LP_swapdata_rawtx(swap,data,maxlen,rawtx) != 0 ) { if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) @@ -603,7 +597,15 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 basilisk_dontforget_update(swap,rawtx); //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen); if ( suppress_swapsend == 0 ) - return(LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs)); + { + retval = LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs); + if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.signedtxid,10) < 0 ) + { + char str[65]; printf("failed to find %s %s in the mempool?\n",rawtx->name,bits256_str(str,rawtx->I.actualtxid)); + retval = -1; + } + return(retval); + } else { printf("suppress swapsend %x\n",msgbits); @@ -645,22 +647,20 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t } else return(-1); } -void LP_bobloop(void *_utxo) +void LP_bobloop(void *_swap) { - uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; + uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap = _swap; fprintf(stderr,"start swap iambob\n"); maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); expiration = (uint32_t)time(NULL) + 10; - while ( (swap= utxo->swap) == 0 && time(NULL) < expiration ) - sleep(1); - if ( (utxo->swap= swap) != 0 ) + if ( swap != 0 ) { - if ( LP_waitsend("pubkeys",10,utxo->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + if ( LP_waitsend("pubkeys",10,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) printf("error waitsend pubkeys\n"); - else if ( LP_waitsend("choosei",10,utxo->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) + else if ( LP_waitsend("choosei",10,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) printf("error waitsend choosei\n"); - else if ( LP_waitsend("mostprivs",10,utxo->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) + else if ( LP_waitsend("mostprivs",10,swap->N.pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) printf("error waitsend mostprivs\n"); else if ( basilisk_bobscripts_set(swap,1,1) < 0 ) printf("error bobscripts deposit\n"); @@ -671,11 +671,11 @@ void LP_bobloop(void *_utxo) basilisk_bobdeposit_refund(swap,swap->I.putduration); //printf("depositlen.%d\n",swap->bobdeposit.I.datalen); LP_swapsfp_update(&swap->I.req); - if ( LP_waitfor(utxo->pair,swap,10,LP_verify_otherfee) < 0 ) + if ( LP_waitfor(swap->N.pair,swap,10,LP_verify_otherfee) < 0 ) printf("error waiting for alicefee\n"); - else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) + else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) printf("error sending bobdeposit\n"); - else if ( LP_waitfor(utxo->pair,swap,10,LP_verify_alicepayment) < 0 ) + else if ( LP_waitfor(swap->N.pair,swap,10,LP_verify_alicepayment) < 0 ) printf("error waiting for alicepayment\n"); else { @@ -689,45 +689,41 @@ void LP_bobloop(void *_utxo) } if ( basilisk_bobscripts_set(swap,0,1) < 0 ) printf("error bobscripts payment\n"); - else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 ) + else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 ) printf("error sending bobpayment\n"); LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,600); } } basilisk_swap_finished(swap); - free(utxo->swap); + free(swap); } else printf("swap timed out\n"); - utxo->swap = 0; - nn_close(utxo->pair); - utxo->pair = -1; } -void LP_aliceloop(void *_qp) +void LP_aliceloop(void *_swap) { - uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap = 0; struct LP_quoteinfo *qp = _qp; - fprintf(stderr,"start swap iamalice pair.%d\n",qp->pair); + uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap = _swap; maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); expiration = (uint32_t)time(NULL) + 10; - swap = LP_swapinit(0,0,qp->privkey,&qp->R,qp); if ( swap != 0 ) { - if ( LP_sendwait("pubkeys",10,qp->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + fprintf(stderr,"start swap iamalice pair.%d\n",swap->N.pair); + if ( LP_sendwait("pubkeys",10,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) printf("error LP_sendwait pubkeys\n"); - else if ( LP_sendwait("choosei",10,qp->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) + else if ( LP_sendwait("choosei",10,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) printf("error LP_sendwait choosei\n"); - else if ( LP_sendwait("mostprivs",10,qp->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) + else if ( LP_sendwait("mostprivs",10,swap->N.pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) printf("error LP_sendwait mostprivs\n"); - else if ( basilisk_alicetxs(qp->pair,swap,data,maxlen) != 0 ) + else if ( basilisk_alicetxs(swap->N.pair,swap,data,maxlen) != 0 ) printf("basilisk_alicetxs error\n"); else { LP_swapsfp_update(&swap->I.req); - if ( LP_swapdata_rawtxsend(qp->pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) + if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) printf("error sending alicefee\n"); - else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobdeposit) < 0 ) + else if ( LP_waitfor(swap->N.pair,swap,10,LP_verify_bobdeposit) < 0 ) printf("error waiting for bobdeposit\n"); - else if ( LP_swapdata_rawtxsend(qp->pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) + else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) printf("error sending alicepayment\n"); else { @@ -736,7 +732,7 @@ void LP_aliceloop(void *_qp) printf("waiting for alicepayment to confirm\n"); sleep(3); } - if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobpayment) < 0 ) + if ( LP_waitfor(swap->N.pair,swap,10,LP_verify_bobpayment) < 0 ) printf("error waiting for bobpayment\n"); else { @@ -745,7 +741,7 @@ void LP_aliceloop(void *_qp) printf("waiting for bobpayment to confirm\n"); sleep(3); } - if ( LP_swapdata_rawtxsend(qp->pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 ) + if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 ) printf("error sending alicespend\n"); while ( LP_numconfirms(swap,&swap->alicespend) < 1 ) { @@ -759,8 +755,8 @@ void LP_aliceloop(void *_qp) basilisk_swap_finished(swap); free(swap); } - nn_close(qp->pair); - free(qp); + free(data); + nn_close(swap->N.pair); } bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 5c0c05dfd..a2ccbc9d5 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -189,35 +189,52 @@ int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 se else return(0); } -int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) +int32_t LP_mempoolscan(char *symbol,bits256 txid) { - int32_t numconfirms = 100; -#ifndef BASILISK_DISABLEWAITTX - cJSON *txobj,*array; int32_t i,n; - numconfirms = -1; - if ( (txobj= LP_gettx(rawtx->coin->symbol,rawtx->I.signedtxid)) != 0 ) - { - numconfirms = jint(txobj,"confirmations"); - free_json(txobj); - } - else if ( (array= LP_getmempool(rawtx->coin->symbol)) != 0 ) + int32_t i,n; cJSON *array; + if ( (array= LP_getmempool(symbol)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { for (i=0; iI.signedtxid,jbits256i(array,i)) == 0 ) + if ( bits256_cmp(txid,jbits256i(array,i)) == 0 ) { - numconfirms = 0; printf("found tx in mempool slot.%d\n",i); - break; + return(i); } } free_json(array); } + return(-1); +} + +int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) +{ + int32_t numconfirms = 100; +#ifndef BASILISK_DISABLEWAITTX + cJSON *txobj; + numconfirms = -1; + if ( (txobj= LP_gettx(rawtx->coin->symbol,rawtx->I.signedtxid)) != 0 ) + { + numconfirms = jint(txobj,"confirmations"); + free_json(txobj); + } else if ( LP_mempoolscan(rawtx->coin->symbol,rawtx->I.signedtxid) >= 0 ) + numconfirms = 0; #endif return(numconfirms); } +int32_t LP_waitmempool(char *symbol,bits256 txid,int32_t duration) +{ + uint32_t expiration = (uint32_t)time(NULL) + duration; + while ( time(NULL) < expiration ) + { + if ( LP_mempoolscan(symbol,txid) >= 0 ) + return(0); + } + return(-1); +} + int32_t iguana_msgtx_Vset(uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,struct vin_info *V) { int32_t vini,j,scriptlen,p2shlen,userdatalen,siglen,plen,need_op0=0,len = 0; uint8_t *script,*redeemscript=0,*userdata=0; struct vin_info *vp; @@ -1530,7 +1547,7 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da printf("%02x",swap->aliceclaim.txbytes[i]); printf(" <- aliceclaim\n"); //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); - return(retval); + return(LP_waitmempool(swap->bobcoin.symbol,swap->bobdeposit.I.signedtxid,10)); } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr); } printf("error with bobdeposit\n"); @@ -1548,7 +1565,8 @@ int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) swap->aliceunconf = 1; basilisk_dontforget_update(swap,&swap->alicepayment); - printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr); + return(LP_waitmempool(swap->alicecoin.symbol,swap->alicepayment.I.signedtxid,10)); + //printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr); //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.p2shaddr); return(0); } @@ -1594,8 +1612,7 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da printf("%02x",swap->alicespend.txbytes[i]); printf(" <- alicespend\n\n"); swap->I.alicespent = 1; - //basilisk_txlog(swap,&swap->alicespend,-1); - return(retval); + return(LP_waitmempool(swap->bobcoin.symbol,swap->bobpayment.I.signedtxid,10)); } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->alicespend.I.suppress_pubkeys,swap->bobpayment.I.destaddr); } printf("error validating bobpayment\n"); diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index 02db3e90c..b0713e810 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -20,75 +20,212 @@ int32_t LP_ismine(struct LP_utxoinfo *utxo) { - if ( strcmp(utxo->ipaddr,"127.0.0.1") == 0 ) + if ( bits256_cmp(utxo->pubkey,LP_mypubkey) != 0 ) return(1); else if ( LP_mypeer == 0 ) return(0); - else if ( strcmp(utxo->ipaddr,LP_mypeer->ipaddr) == 0 && utxo->port == LP_mypeer->port )\ + else return(0); +} + +int32_t LP_isavailable(struct LP_utxoinfo *utxo) +{ + if ( utxo->T.swappending == 0 && utxo->S.swap == 0 ) return(1); else return(0); } int32_t LP_isunspent(struct LP_utxoinfo *utxo) { - if ( utxo->spentflag == 0 && utxo->swappending == 0 ) + if ( utxo->T.spentflag == 0 && LP_isavailable(utxo) > 0 ) return(1); else return(0); } -struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout) +void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) { - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; memcpy(key,txid.bytes,sizeof(txid)); memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); +} + +struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; + LP_utxosetkey(key,txid,vout); + HASH_FIND(hh,LP_utxoinfos[iambob],key,sizeof(key),utxo); + return(utxo); +} + +struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)]; + LP_utxosetkey(key2,txid2,vout2); + HASH_FIND(hh2,LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); + return(utxo); +} + +struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; portable_mutex_lock(&LP_utxomutex); - HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo); + utxo = _LP_utxofind(iambob,txid,vout); portable_mutex_unlock(&LP_utxomutex); return(utxo); } -struct LP_utxoinfo *_LP_utxo2find(bits256 txid,int32_t vout) +struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) { - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); - HASH_FIND(hh2,LP_utxoinfos2,key,sizeof(key),utxo); + struct LP_utxoinfo *utxo=0; + portable_mutex_lock(&LP_utxomutex); + utxo = _LP_utxo2find(iambob,txid2,vout2); + portable_mutex_unlock(&LP_utxomutex); return(utxo); } -struct LP_utxoinfo *LP_utxo2find(bits256 txid,int32_t vout) +int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo) { - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); + int32_t i; + for (i=0; ipayment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee; + if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + } portable_mutex_unlock(&LP_utxomutex); - return(utxo); + if ( n > 0 ) + printf("LP_utxocollisions n.%d\n",n); + return(n); +} + +void _LP_availableset(struct LP_utxoinfo *utxo) +{ + if ( utxo != 0 ) + { + memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey)); + utxo->S.swap = 0; + utxo->T.swappending = 0; + } +} + +void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) +{ + if ( utxo != 0 ) + { + utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); + utxo->S.otherpubkey = otherpubkey; + } +} + +void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) +{ + struct LP_utxoinfo *ptrs[8]; int32_t i,n; + memset(ptrs,0,sizeof(ptrs)); + if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) + { + for (i=0; ipayment.txid),utxo->payment.vout,n); + _LP_unavailableset(utxo,otherpubkey); +} + +void LP_availableset(struct LP_utxoinfo *utxo) +{ + struct LP_utxoinfo *ptrs[8]; int32_t i,n; + memset(ptrs,0,sizeof(ptrs)); + if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) + { + for (i=0; ipayment.txid),utxo->payment.vout,n); + _LP_availableset(utxo); +} + +int32_t LP_utxopurge(int32_t allutxos) +{ + struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; + portable_mutex_lock(&LP_utxomutex); + for (iambob=0; iambob<=1; iambob++) + { + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + { + if ( allutxos != 0 || LP_ismine(utxo) == 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + { + HASH_DELETE(hh,LP_utxoinfos[iambob],utxo); + free(utxo); + } else n++; + } else n++; + } + HASH_ITER(hh,LP_utxoinfos2[iambob],utxo,tmp) + { + if ( allutxos != 0 || LP_ismine(utxo) == 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + { + HASH_DELETE(hh,LP_utxoinfos2[iambob],utxo); + free(utxo); + } else n++; + } else n++; + } + } + portable_mutex_unlock(&LP_utxomutex); + return(n); } cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) { + struct _LP_utxoinfo u; jaddstr(item,"coin",utxo->coin); jaddnum(item,"now",time(NULL)); jaddstr(item,"address",utxo->coinaddr); - jaddbits256(item,"txid",utxo->txid); - jaddnum(item,"vout",utxo->vout); - jadd64bits(item,"value",utxo->value); - jadd64bits(item,"satoshis",utxo->satoshis); - jaddbits256(item,"txid2",utxo->txid2); - jaddnum(item,"vout2",utxo->vout2); - jadd64bits(item,"value2",utxo->value2); - if ( utxo->swappending != 0 ) - jaddnum(item,"pending",utxo->swappending); - if ( bits256_nonz(utxo->otherpubkey) != 0 ) - jaddbits256(item,"desthash",utxo->otherpubkey); - if ( utxo->pair >= 0 ) - jaddnum(item,"socket",utxo->pair); - if ( utxo->swap != 0 ) + jaddbits256(item,"txid",utxo->payment.txid); + jaddnum(item,"vout",utxo->payment.vout); + jadd64bits(item,"value",utxo->payment.value); + jadd64bits(item,"satoshis",utxo->S.satoshis); + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + if ( bits256_nonz(u.txid) != 0 ) + { + jaddbits256(item,"txid2",u.txid); + jaddnum(item,"vout2",u.vout); + jadd64bits(item,"value2",u.value); + } + if ( utxo->T.swappending != 0 ) + jaddnum(item,"pending",utxo->T.swappending); + if ( utxo->iambob != 0 ) + { + jaddbits256(item,"srchash",LP_mypubkey); + if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) + jaddbits256(item,"desthash",utxo->S.otherpubkey); + } + else + { + jaddbits256(item,"desthash",LP_mypubkey); + if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) + jaddbits256(item,"srchash",utxo->S.otherpubkey); + } + if ( utxo->S.swap != 0 ) jaddstr(item,"swap","in progress"); - if ( utxo->spentflag != 0 ) - jaddnum(item,"spent",utxo->spentflag); + if ( utxo->T.spentflag != 0 ) + jaddnum(item,"spent",utxo->T.spentflag); return(item); } @@ -96,26 +233,25 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo) { cJSON *item = cJSON_CreateObject(); item = LP_inventoryjson(item,utxo); - jaddstr(item,"ipaddr",utxo->ipaddr); - jaddnum(item,"port",utxo->port); - jaddnum(item,"profit",utxo->profitmargin); + jaddbits256(item,"pubkey",utxo->pubkey); + jaddnum(item,"profit",utxo->S.profitmargin); jaddstr(item,"base",utxo->coin); jaddstr(item,"script",utxo->spendscript); return(item); } -char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) +char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *coin,int32_t lastn) { int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); i = 0; if ( lastn >= mypeer->numutxos ) firsti = -1; else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) { if ( i++ < firsti ) continue; - if ( (coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0) && utxo->spentflag == 0 )//&& LP_ismine(utxo) != 0 ) + if ( (coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0) && utxo->T.spentflag == 0 )//&& LP_ismine(utxo) != 0 ) { jaddi(utxosjson,LP_utxojson(utxo)); } @@ -125,20 +261,23 @@ char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) { - cJSON *argjson; - utxo->spentflag = (uint32_t)time(NULL); + cJSON *argjson; struct _LP_utxoinfo u; + utxo->T.spentflag = (uint32_t)time(NULL); if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) LP_mypeer->numutxos--; if ( LP_mypubsock >= 0 ) { argjson = cJSON_CreateObject(); jaddstr(argjson,"method","checktxid"); - jaddbits256(argjson,"txid",utxo->txid); - jaddnum(argjson,"vout",utxo->vout); + jaddbits256(argjson,"txid",utxo->payment.txid); + jaddnum(argjson,"vout",utxo->payment.vout); if ( selector != 0 ) { - jaddbits256(argjson,"checktxid",utxo->txid2); - jaddnum(argjson,"checkvout",utxo->vout2); + if ( bits256_nonz(utxo->deposit.txid) != 0 ) + u = utxo->deposit; + else u = utxo->fee; + jaddbits256(argjson,"checktxid",u.txid); + jaddnum(argjson,"checkvout",u.vout); } LP_send(LP_mypubsock,jprint(argjson,1),1); } @@ -146,35 +285,41 @@ void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) char *LP_spentcheck(cJSON *argjson) { - bits256 txid,checktxid; int32_t vout,checkvout; struct LP_utxoinfo *utxo; + bits256 txid,checktxid; int32_t vout,checkvout; struct LP_utxoinfo *utxo; int32_t iambob,retval = 0; txid = jbits256(argjson,"txid"); vout = jint(argjson,"vout"); - if ( (utxo= LP_utxofind(txid,vout)) != 0 && utxo->spentflag == 0 ) + for (iambob=0; iambob<=1; iambob++) { - if ( jobj(argjson,"check") == 0 ) - checktxid = txid, checkvout = vout; - else + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 && utxo->T.spentflag == 0 ) { - checktxid = jbits256(argjson,"checktxid"); - checkvout = jint(argjson,"checkvout"); + if ( jobj(argjson,"check") == 0 ) + checktxid = txid, checkvout = vout; + else + { + checktxid = jbits256(argjson,"checktxid"); + checkvout = jint(argjson,"checkvout"); + } + if ( LP_txvalue(utxo->coin,checktxid,checkvout) == 0 ) + { + //if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) + // LP_mypeer->numutxos--; + utxo->T.spentflag = (uint32_t)time(NULL); + retval++; + //printf("indeed txid was spent\n"); + } } - if ( LP_txvalue(utxo->coin,checktxid,checkvout) == 0 ) - { - if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) - LP_mypeer->numutxos--; - utxo->spentflag = (uint32_t)time(NULL); - //printf("indeed txid was spent\n"); - return(clonestr("{\"result\":\"marked as spent\"}")); - } else return(clonestr("{\"error\":\"txid is still unspent?\"}")); - } else return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); + } + if ( retval > 0 ) + return(clonestr("{\"result\":\"marked as spent\"}")); + return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); } -int32_t LP_iseligible(char *coin,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2) +int32_t LP_iseligible(int32_t iambob,char *coin,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2) { uint64_t val,val2,threshold; if ( (val= LP_txvalue(coin,txid,vout)) >= satoshis ) { - threshold = (IAMCLIENT == 0) ? LP_DEPOSITSATOSHIS(satoshis) : LP_DEXFEE(satoshis); + threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : LP_DEXFEE(satoshis); if ( (val2= LP_txvalue(coin,txid2,vout2)) >= threshold ) { //printf("val %.8f and val2 %.8f vs %.8f\n",dstr(val),dstr(val2),dstr(satoshis)); @@ -184,66 +329,65 @@ int32_t LP_iseligible(char *coin,bits256 txid,int32_t vout,uint64_t satoshis,bit return(0); } -struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin) +struct LP_utxoinfo *LP_addutxo(int32_t iambob,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,double profitmargin) { - uint64_t tmpsatoshis; struct LP_utxoinfo *utxo = 0; + uint64_t tmpsatoshis; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 ) { printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", coin == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); return(0); } - if ( IAMCLIENT == 0 && value2 < 9 * (value >> 3) + 100000 ) + if ( iambob != 0 && value2 < 9 * (value >> 3) + 100000 ) tmpsatoshis = (((value2-100000) / 9) << 3); else tmpsatoshis = value; - if ( LP_iseligible(coin,txid,vout,tmpsatoshis,txid2,vout2) <= 0 ) + if ( LP_iseligible(iambob,coin,txid,vout,tmpsatoshis,txid2,vout2) <= 0 ) { printf("LP_addutxo got spent txid value %.8f, value2 %.8f, tmpsatoshis %.8f\n",dstr(value),dstr(value2),dstr(tmpsatoshis)); return(0); } - if ( IAMCLIENT == 0 && strcmp(ipaddr,"127.0.0.1") == 0 ) - { - //printf("LP node got localhost utxo\n"); - return(0); - } - if ( (utxo= LP_utxofind(txid,vout)) != 0 || (utxo= LP_utxo2find(txid,vout)) != 0 ) + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) { //printf("%.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->value),dstr(utxo->value2),dstr(utxo->satoshis)); - if ( bits256_cmp(txid,utxo->txid) != 0 || bits256_cmp(txid2,utxo->txid2) != 0 || vout != utxo->vout || value != utxo->value || tmpsatoshis != utxo->satoshis || vout2 != utxo->vout2 || value2 != utxo->value2 || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port ) + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) { - utxo->errors++; - char str[65],str2[65]; printf("error on subsequent utxo add.(%s v %s) %d %d %d %d %d %d %d %d %d %d %d %d\n",bits256_str(str,txid),bits256_str(str2,utxo->txid),bits256_cmp(txid,utxo->txid) != 0,bits256_cmp(txid2,utxo->txid2) != 0,vout != utxo->vout,tmpsatoshis != utxo->satoshis,vout2 != utxo->vout2,value2 != utxo->value2,strcmp(coin,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,strcmp(ipaddr,utxo->ipaddr) != 0,port != utxo->port,value != utxo->value); + utxo->T.errors++; + char str[65],str2[65]; printf("error on subsequent utxo add.(%s v %s) %d %d %d %d %d %d %d %d %d %d %d\n",bits256_str(str,txid),bits256_str(str2,utxo->payment.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(coin,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value); } else if ( profitmargin != 0. ) - utxo->profitmargin = profitmargin; + utxo->S.profitmargin = profitmargin; } else { utxo = calloc(1,sizeof(*utxo)); - utxo->pair = -1; - utxo->profitmargin = profitmargin; - strcpy(utxo->ipaddr,ipaddr); - utxo->port = port; + utxo->S.profitmargin = profitmargin; + utxo->pubkey = pubkey; safecopy(utxo->coin,coin,sizeof(utxo->coin)); safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); - utxo->txid = txid; - utxo->vout = vout; - utxo->value = value; - utxo->satoshis = tmpsatoshis; - utxo->txid2 = txid2; - utxo->vout2 = vout2; - utxo->value2 = value2; - memcpy(utxo->key,txid.bytes,sizeof(txid)); - memcpy(&utxo->key[sizeof(txid)],&vout,sizeof(vout)); - memcpy(utxo->key2,txid2.bytes,sizeof(txid2)); - memcpy(&utxo->key2[sizeof(txid2)],&vout2,sizeof(vout2)); - char str[65],str2[65]; printf("amclient.%d %s:%u %s LP_addutxo.(%.8f %.8f) numutxos.%d %s %s\n",IAMCLIENT,ipaddr,port,utxo->coin,dstr(value),dstr(value2),mypeer!=0?mypeer->numutxos:0,bits256_str(str,utxo->txid),bits256_str(str2,txid2)); + utxo->payment.txid = txid; + utxo->payment.vout = vout; + utxo->payment.value = value; + utxo->S.satoshis = tmpsatoshis; + if ( (utxo->iambob= iambob) != 0 ) + { + utxo->deposit.txid = txid2; + utxo->deposit.vout = vout2; + utxo->deposit.value = value2; + } + else + { + utxo->fee.txid = txid2; + utxo->fee.vout = vout2; + utxo->fee.value = value2; + } + LP_utxosetkey(utxo->key,txid,vout); + LP_utxosetkey(utxo->key2,txid2,vout2); + char str[65],str2[65],str3[65]; printf("iambob.%d %s %s LP_addutxo.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,utxo->pubkey),utxo->coin,dstr(value),dstr(value2),bits256_str(str,utxo->payment.txid),bits256_str(str2,txid2)); portable_mutex_lock(&LP_utxomutex); - HASH_ADD_KEYPTR(hh,LP_utxoinfos,utxo->key,sizeof(utxo->key),utxo); - if ( _LP_utxo2find(txid2,vout2) == 0 ) - HASH_ADD_KEYPTR(hh2,LP_utxoinfos2,utxo->key2,sizeof(utxo->key2),utxo); - if ( mypeer != 0 ) - mypeer->numutxos++; + HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); + if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) + HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); portable_mutex_unlock(&LP_utxomutex); if ( mypubsock >= 0 ) LP_send(mypubsock,jprint(LP_utxojson(utxo),1),1); @@ -251,10 +395,10 @@ struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32 return(utxo); } -int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +int32_t LP_utxosparse(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 ) + struct LP_peerinfo *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 ( IAMLP == 0 ) { printf("LP_utxosparse not for clientside\n"); return(-1); @@ -273,16 +417,16 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs if ( (subport= juint(item,"sub")) == 0 ) subport = argport + 2; argipbits = (uint32_t)calc_ipbits(argipaddr); - if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) - peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); + //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")); if ( jobj(item,"txid") != 0 ) { txid = jbits256(item,"txid"); //printf("parse.(%s)\n",jprint(item,0)); - utxo = LP_addutxo(amclient,mypeer,mypubsock,jstr(item,"coin"),txid,jint(item,"vout"),j64bits(item,"value"),jbits256(item,"txid2"),jint(item,"vout2"),j64bits(item,"value2"),jstr(item,"script"),jstr(item,"address"),argipaddr,argport,jdouble(item,"profit")); + utxo = LP_addutxo(1,mypubsock,jstr(item,"coin"),txid,jint(item,"vout"),j64bits(item,"value"),jbits256(item,"txid2"),jint(item,"vout2"),j64bits(item,"value2"),jstr(item,"script"),jstr(item,"address"),jbits256(item,"pubkey"),jdouble(item,"profit")); if ( utxo != 0 ) { - utxo->lasttime = now; + utxo->T.lasttime = now; } } } // else printf("skip.(%s)\n",jprint(item,0)); @@ -297,10 +441,10 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs return(n); } -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) +void LP_utxosquery(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_peerinfo *peer; int32_t i,firsti; uint32_t now; - if ( amclient != 0 ) + if ( IAMLP == 0 ) { printf("LP_utxosquery not for clientside\n"); return; @@ -313,7 +457,7 @@ void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock if ( (retstr= issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 ) { now = (uint32_t)time(NULL); - LP_utxosparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + LP_utxosparse(mypeer,mypubsock,destipaddr,destport,retstr,now); free(retstr); i = 0; if ( lastn >= mypeer->numutxos ) @@ -337,16 +481,17 @@ void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock peer->errors++; } -char *LP_inventory(char *symbol) +char *LP_inventory(char *symbol,int32_t iambob) { - struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array = cJSON_CreateArray(); + struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array; + array = cJSON_CreateArray(); if ( LP_mypeer != 0 ) myipaddr = LP_mypeer->ipaddr; else myipaddr = "127.0.0.1"; - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) { //char str[65]; printf("iterate %s\n",bits256_str(str,utxo->txid)); - if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && (IAMCLIENT != 0 || LP_ismine(utxo) != 0) ) + if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) != 0 ) jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); } return(jprint(array,1)); @@ -381,10 +526,10 @@ int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval) return(mini); } -uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symbol,char *passphrase,char *wifstr,int32_t amclient) +uint64_t LP_privkey_init(int32_t mypubsock,char *symbol,char *passphrase,char *wifstr,int32_t iambob) { static uint32_t counter; - char *script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 userpass,userpub,txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol); + char *script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 userpass,userpub,txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey,mypub; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol); if ( coin == 0 ) { printf("cant add privkey for %s, coin not active\n",symbol); @@ -413,6 +558,7 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb } bitcoin_addr2rmd160(&tmptype,rmd160,coin->smartaddr); LP_privkeyadd(privkey,rmd160); + LP_mypubkey = mypub = curve25519(privkey,curve25519_basepoint9()); if ( coin->inactive == 0 && (array= LP_listunspent(symbol,coin->smartaddr)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) @@ -438,7 +584,7 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb script = jstr(item,"scriptPubKey"); depositval = values[i]; values[i] = 0, used++; - if ( amclient != 0 ) + if ( iambob == 0 ) targetval = (depositval / 776) + 100000; else targetval = (depositval / 9) * 8 + 100000; //printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); @@ -451,15 +597,19 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb { value = values[i]; values[i] = 0, used++; - if ( amclient == 0 ) + if ( iambob != 0 ) { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 ) - utxo->mypub = curve25519(privkey,curve25519_basepoint9()); + if ( (utxo= LP_addutxo(1,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_peerinfos[0].profitmargin)) != 0 ) + { + //utxo->S.mypub = curve25519(privkey,curve25519_basepoint9()); + } } else { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,"127.0.0.1",0,0)) != 0 ) - utxo->mypub = curve25519(privkey,curve25519_basepoint9()); + if ( (utxo= LP_addutxo(0,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,0)) != 0 ) + { + //utxo->S.mypub = curve25519(privkey,curve25519_basepoint9()); + } } total += value; } @@ -474,13 +624,13 @@ 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) +void LP_privkey_updates(int32_t pubsock,char *passphrase,int32_t iambob) { int32_t i; for (i=0; i