From 9a2f5c735cc2f3ba4d1f4b0e9d08d3513b4fa5b0 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 30 Sep 2017 13:34:18 +0300 Subject: [PATCH] fixes detect port conflicts on enable check for completed swap tx being spent prevent autxo reuse add extra hash to keypair25519 --- iguana/exchanges/LP_coins.c | 13 +++ iguana/exchanges/LP_commands.c | 10 ++- iguana/exchanges/LP_include.h | 12 ++- iguana/exchanges/LP_nativeDEX.c | 13 +-- iguana/exchanges/LP_ordermatch.c | 125 +++++++++++++++-------------- iguana/exchanges/LP_prices.c | 46 +++++++++++ iguana/exchanges/LP_statemachine.c | 20 +++++ iguana/exchanges/LP_swap.c | 3 +- iguana/exchanges/LP_utxo.c | 37 +++++---- iguana/exchanges/LP_utxos.c | 49 ++++------- 10 files changed, 204 insertions(+), 124 deletions(-) diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index f9ae0c9a8..bf02bc11a 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -201,6 +201,19 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) return(item); } +struct iguana_info *LP_conflicts_find(struct iguana_info *refcoin) +{ + struct iguana_info *coin=0,*tmp; + HASH_ITER(hh,LP_coins,coin,tmp) + { + if ( coin->inactive != 0 || coin->electrum != 0 || coin == refcoin ) + continue; + if ( strcmp(coin->serverport,refcoin->serverport) == 0 ) + break; + } + return(coin); +} + cJSON *LP_coinsjson(int32_t showwif) { struct iguana_info *coin,*tmp; cJSON *array = cJSON_CreateArray(); diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index df62ebfb1..bb7d1e49b 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -112,7 +112,7 @@ getcoins()\n\ getcoin(coin)\n\ portfolio()\n\ getpeers()\n\ -passphrase(passphrase)\n\ +passphrase(passphrase, gui)\n\ listunspent(coin, address)\n\ orderbook(base, rel, duration=3600)\n\ getprices(base, rel)\n\ @@ -166,7 +166,7 @@ dividends(coin, height, )\n\ } else if ( strcmp(method,"passphrase") == 0 ) { - if ( LP_passphrase_init(jstr(argjson,"passphrase")) < 0 ) + if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 ) return(clonestr("{\"error\":\"couldnt change passphrase\"}")); { retjson = cJSON_CreateObject(); @@ -253,7 +253,11 @@ dividends(coin, height, )\n\ if ( strcmp(method,"enable") == 0 ) { if ( (ptr= LP_coinsearch(coin)) != 0 ) - ptr->inactive = 0; + { + if ( LP_conflicts_find(ptr) == 0 ) + ptr->inactive = 0; + else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}")); + } return(jprint(LP_coinsjson(0),1)); } else if ( strcmp(method,"disable") == 0 ) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index fa0eb746d..233c1a70e 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -212,7 +212,7 @@ struct LP_utxoinfo int32_t iambob,iamlp; uint8_t key[sizeof(bits256) + sizeof(int32_t)]; uint8_t key2[sizeof(bits256) + sizeof(int32_t)]; - char coin[16],coinaddr[64],spendscript[256],gui[16]; + char coin[16],coinaddr[64],gui[16];//spendscript[256]; }; struct LP_address_utxo @@ -226,9 +226,11 @@ struct LP_address { UT_hash_handle hh; struct LP_address_utxo *utxos; + bits256 pubkey; int64_t balance,total; uint32_t timestamp,n; char coinaddr[40]; + uint8_t pubsecp[33],pad; }; struct LP_peerinfo @@ -297,8 +299,10 @@ int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32); char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price); uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee); struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr); +struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr); +struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr); int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson); -void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo); +//void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo); int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration); struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid); cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj); @@ -310,10 +314,12 @@ cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout); void LP_postutxos(char *symbol,char *coinaddr); int32_t LP_listunspent_both(char *symbol,char *coinaddr); uint16_t LP_randpeer(char *destip); -int32_t LP_butxo_findeither(bits256 txid,int32_t vout); +//int32_t LP_butxo_findeither(bits256 txid,int32_t vout); cJSON *LP_listunspent(char *symbol,char *coinaddr); int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid); double LP_getestimatedrate(struct iguana_info *coin); +struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout); +struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 25b34acd7..945c2a1d8 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -20,14 +20,17 @@ // marketmaker // // new features: +// sign, spv check // bittrex balancing -// detect port conflicts on enable // stats +// -detect port conflicts on enable +// -check for completed one being spent +// -prevent autxo reuse +// -add extra hash to keypair25519 + // unduplicated bugs: // swap cancel should cleanly cancel -// check for completed one being spent -// prevent autxo reuse, add extra hash to keypair25519, sign, spv check #include #include "LP_include.h" @@ -64,7 +67,7 @@ struct LP_globals uint8_t LP_myrmd160[20],LP_pubsecp[33]; uint32_t LP_sessionid,counter; int32_t LP_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting; - char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41]; + char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16]; struct LP_privkey LP_privkeys[100]; } G; @@ -693,7 +696,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu printf("initcoins\n"); LP_initcoins(ctx,pubsock,jobj(argjson,"coins")); G.waiting = 1; - LP_passphrase_init(passphrase); + LP_passphrase_init(passphrase,jstr(argjson,"gui")); if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 ) { printf("error launching LP_psockloop for (%s)\n",myipaddr); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index 98676988f..02b67ddf9 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -435,7 +435,7 @@ int32_t LP_nanobind(void *ctx,char *pairstr) return(pairsock); } -struct LP_utxoinfo BUTXOS[100]; +/*struct LP_utxoinfo BUTXOS[100]; int32_t LP_butxo_findeither(bits256 txid,int32_t vout) { @@ -452,7 +452,7 @@ int32_t LP_butxo_findeither(bits256 txid,int32_t vout) } portable_mutex_unlock(&LP_butxomutex); return(retval); -} +}*/ int32_t LP_nearest_utxovalue(struct LP_address_utxo **utxos,int32_t n,uint64_t targetval) { @@ -481,12 +481,12 @@ uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t d else return(0); } -struct LP_utxoinfo *LP_address_utxopair(struct LP_utxoinfo *utxo,struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double volume,double price,int32_t avoidflag,uint64_t desttxfee) +struct LP_utxoinfo *LP_address_utxopair(struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double volume,double price,uint64_t desttxfee) { - struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; + struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; struct LP_utxoinfo *utxo = 0; if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 ) { - if ( (m= LP_address_utxo_ptrs(utxos,max,ap,avoidflag)) > 1 ) + if ( (m= LP_address_utxo_ptrs(utxos,max,ap)) > 1 ) { targetval = LP_basesatoshis(volume,price,txfee,desttxfee); if ( 0 ) @@ -505,18 +505,12 @@ struct LP_utxoinfo *LP_address_utxopair(struct LP_utxoinfo *utxo,struct LP_addre { if ( up != 0 && (up2= utxos[mini]) != 0 ) { - safecopy(utxo->coin,coin->symbol,sizeof(utxo->coin)); - safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); - utxo->payment.txid = up->U.txid; - utxo->payment.vout = up->U.vout; - utxo->payment.value = up->U.value; - utxo->iambob = 1; - utxo->deposit.txid = up2->U.txid; - utxo->deposit.vout = up2->U.vout; - utxo->deposit.value = up2->U.value; - utxo->S.satoshis = targetval; - printf("targetval %.8f, found val %.8f | targetval2 %.8f val2 %.8f\n",dstr(targetval),dstr(up->U.value),dstr(targetval2),dstr(up2->U.value)); - return(utxo); + if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0)) != 0 ) + { + utxo->S.satoshis = targetval; + printf("targetval %.8f, found val %.8f | targetval2 %.8f val2 %.8f\n",dstr(targetval),dstr(up->U.value),dstr(targetval2),dstr(up2->U.value)); + return(utxo); + } } } } @@ -525,7 +519,7 @@ struct LP_utxoinfo *LP_address_utxopair(struct LP_utxoinfo *utxo,struct LP_addre return(0); } -struct LP_utxoinfo *_LP_butxo_find(struct LP_utxoinfo *butxo) +/*struct LP_utxoinfo *_LP_butxo_find(struct LP_utxoinfo *butxo) { int32_t i; struct LP_utxoinfo *utxo=0; uint32_t now = (uint32_t)time(NULL); //portable_mutex_lock(&LP_butxomutex); @@ -586,7 +580,7 @@ void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo) { LP_butxo_swapfields_copy(setutxo,butxo); } -} +}*/ void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp) { @@ -668,37 +662,49 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ nn_close(pair); LP_availableset(utxo); } else LP_unavailableset(utxo,utxo->S.otherpubkey); - LP_butxo_swapfields(utxo); + //LP_butxo_swapfields(utxo); return(retval); } char *LP_connectedalice(cJSON *argjson) // alice { - cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo A,B,*autxo,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; + cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; uint64_t value,value2; if ( LP_quoteparse(&Q,argjson) < 0 ) clonestr("{\"error\":\"cant parse quote\"}"); if ( bits256_cmp(Q.desthash,G.LP_mypub25519) != 0 ) return(clonestr("{\"result\",\"update stats\"}")); printf("CONNECTED.(%s) numpending.%d\n",jprint(argjson,0),G.LP_pendingswaps); - if ( G.LP_pendingswaps > 0 ) + /*if ( G.LP_pendingswaps > 0 ) { printf("swap already pending\n"); return(clonestr("{\"error\":\"swap already pending\"}")); - } - autxo = &A; - butxo = &B; - LP_abutxo_set(autxo,butxo,&Q); - /*if ( (autxo= LP_utxopairfind(0,Q.txid,Q.vout,Q.txid2,Q.vout2)) != 0 && autxo->S.swap != 0 ) + }*/ + if ( (autxo= LP_utxopairfind(1,Q.desttxid,Q.destvout,Q.feetxid,Q.feevout)) == 0 ) { - printf("swap already pending\n"); - return(clonestr("{\"error\":\"swap already pending\"}")); + printf("cant find autxo\n"); + return(clonestr("{\"error\":\"cant find autxo\"}")); } - autxo = LP_utxoadd(0,LP_mypubsock,Q.destcoin,Q.desttxid,Q.destvout,Q.destsatoshis,Q.feetxid,Q.feevout,0,"",Q.destaddr,Q.desthash,LP_gui,G.LP_sessionid); - if ( autxo == 0 ) + LP_abutxo_set(autxo,0,&Q); + if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 ) { - printf("couldnt create autxo\n"); - return(clonestr("{\"error\":\"couldnt create autxo\"}")); - }*/ + value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout); + value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2); + if ( value == 0 || value2 == 0 ) + { + printf("zero value %.8f or value2 %.8f\n",dstr(value),dstr(value2)); + return(clonestr("{\"error\":\"spent txid or txid2 for bob?\"}")); + } + if ( (butxo= LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0)) == 0 ) + { + printf("cant find or create butxo\n"); + return(clonestr("{\"error\":\"cant find or create butxo\"}")); + } + if ( value < Q.satoshis ) + { + printf("butxo value %.8f less satoshis %.8f\n",dstr(value),dstr(Q.satoshis)); + return(clonestr("{\"error\":\"butxo value less than satoshis\"}")); + } + } if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) { LP_availableset(autxo); @@ -713,7 +719,7 @@ char *LP_connectedalice(cJSON *argjson) // alice //G.LP_pendingswaps--; return(clonestr("{\"error\":\"no price set\"}")); } - printf("%s/%s bid %.8f ask %.8f\n",Q.srccoin,Q.destcoin,bid,ask); + printf("%s/%s bid %.8f ask %.8f values %.8f %.8f\n",Q.srccoin,Q.destcoin,bid,ask,dstr(butxo->payment.value),dstr(butxo->deposit.value)); price = bid; if ( (coin= LP_coinfind(Q.destcoin)) == 0 ) { @@ -813,22 +819,26 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, price = ask; autxo = &A; butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); LP_abutxo_set(autxo,butxo,&Q); - LP_butxo_swapfields(butxo); + //LP_butxo_swapfields(butxo); if ( strcmp(method,"request") == 0 ) { - if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) + if ( LP_unallocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_unallocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) { LP_listunspent_both(Q.srccoin,Q.coinaddr); - butxo = LP_address_utxopair(butxo,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,1,Q.desttxfee); - Q.txid = butxo->payment.txid; - Q.vout = butxo->payment.vout; - Q.txid2 = butxo->deposit.txid; - Q.vout2 = butxo->deposit.vout; - LP_abutxo_set(0,butxo,&Q); - LP_butxo_swapfields(butxo); - } - } + if ( (butxo= LP_address_utxopair(utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) + { + Q.txid = butxo->payment.txid; + Q.vout = butxo->payment.vout; + Q.txid2 = butxo->deposit.txid; + Q.vout2 = butxo->deposit.vout; + } + //LP_abutxo_set(0,butxo,&Q); + //LP_butxo_swapfields(butxo); + } else butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); + } else butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 ) { char str[65]; printf("couldnt find bob utxos for autxo %s/v%d %.8f\n",bits256_str(str,autxo->payment.txid),autxo->payment.vout,dstr(autxo->S.satoshis)); @@ -869,7 +879,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, msg2 = clonestr(msg); LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,zero,msg); LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg2); - LP_butxo_swapfields_set(butxo); + //LP_butxo_swapfields_set(butxo); printf("return after RESERVED\n"); return(2); } @@ -882,12 +892,12 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, { // validate SPV alice LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q); - LP_butxo_swapfields_set(butxo); + //LP_butxo_swapfields_set(butxo); return(3); } else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); } - LP_butxo_swapfields_set(butxo); + //LP_butxo_swapfields_set(butxo); } } return(retval); @@ -925,8 +935,6 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q if ( aliceutxo->S.swap != 0 ) break; sleep(3); - //price = LP_query(ctx,myipaddr,mypubsock,"connect",qp); - //LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); } if ( aliceutxo->S.swap == 0 ) { @@ -957,7 +965,7 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q return(jprint(bestitem,0)); } -struct LP_utxoinfo *LP_buyutxo(struct LP_utxoinfo *space,double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,char *gui,bits256 *avoids,int32_t numavoids) +struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,char *gui,bits256 *avoids,int32_t numavoids) { bits256 pubkey; char *obookstr,coinaddr[64],str[65]; cJSON *orderbook,*asks,*item; int32_t i,j,n,numasks,max = 10000; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; struct iguana_info *basecoin; uint64_t basesatoshis; struct LP_utxoinfo *bestutxo = 0; *ordermatchpricep = 0.; @@ -996,7 +1004,7 @@ struct LP_utxoinfo *LP_buyutxo(struct LP_utxoinfo *space,double *ordermatchprice if ( n > 1 ) { basesatoshis = LP_basesatoshis(dstr(autxo->S.satoshis),price,txfee,desttxfee); - if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(space,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,0,desttxfee)) != 0 ) + if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 ) { bestutxo->pubkey = pubp->pubkey; safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui)); @@ -1031,7 +1039,7 @@ struct LP_utxoinfo *LP_buyutxo(struct LP_utxoinfo *space,double *ordermatchprice char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui) { - uint64_t desttxfee,txfee; int32_t numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct LP_utxoinfo *autxo,_bestB,_bestA,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100]; + uint64_t desttxfee,txfee; int32_t numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100]; printf("LP_autobuy %s/%s price %.8f vol %.8f\n",base,rel,maxprice,relvolume); if ( duration <= 0 ) duration = LP_ORDERBOOK_DURATION; @@ -1041,18 +1049,14 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel return(clonestr("{\"error\":\"invalid parameter\"}")); memset(pubkeys,0,sizeof(pubkeys)); LP_txfees(&txfee,&desttxfee,base,rel); - memset(&_bestA,0,sizeof(_bestA)); - memset(&_bestB,0,sizeof(_bestB)); destsatoshis = SATOSHIDEN * relvolume + 2*desttxfee; if ( (autxo= LP_utxo_bestfit(rel,destsatoshis)) == 0 ) return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); - _bestA = *autxo; - autxo = &_bestA; if ( destsatoshis < autxo->S.satoshis ) autxo->S.satoshis = destsatoshis; while ( 1 ) { - if ( (bestutxo= LP_buyutxo(&_bestB,&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) { printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); @@ -1064,9 +1068,8 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); if ( (qprice= LP_quote_validate(autxo,0,&Q,0)) <= SMALLVAL ) { - printf("quote validate error %.0f\n",qprice); + printf("continue searching, quote validate error %.0f\n",qprice); continue; - //return(clonestr("{\"error\":\"quote validation error\"}")); } break; } diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 0d9f82450..bf347411d 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -126,6 +126,52 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout return(ptr); } +struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) +{ + struct LP_pubkeyinfo *pubp=0,*tmp; + portable_mutex_lock(&LP_pubkeymutex); + HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) + { + if ( memcmp(rmd160,pubp->rmd160,sizeof(pubp->rmd160)) == 0 ) + break; + pubp = 0; + } + portable_mutex_unlock(&LP_pubkeymutex); + return(pubp); +} + +struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) +{ + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); + if ( bits256_nonz(ap->pubkey) == 0 ) + { + bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); + if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 ) + { + ap->pubkey = pubp->pubkey; + memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp)); + } + } + return(ap); +} + +struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) +{ + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + ap = calloc(1,sizeof(*ap)); + safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); + bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); + if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 ) + { + ap->pubkey = pubp->pubkey; + memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp)); + } + //printf("LP_ADDRESS %s ADD.(%s)\n",coin->symbol,coinaddr); + HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap); + return(ap); +} + struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) { struct LP_pubkeyinfo *pubp=0; diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index b70c7342a..073832675 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -1608,6 +1608,26 @@ int32_t LP_utxopurge(int32_t allutxos) portable_mutex_unlock(&LP_utxomutex); return(n); } +struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) +{ + struct LP_utxoinfo *utxo; + if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) + { + printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); + return(0); + } + portable_mutex_lock(&LP_UTXOmutex); + utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jstr(argjson,"gui"),juint(argjson,"session")); + if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) + { + utxo->T.lasttime = (uint32_t)time(NULL); + printf("set lasttime!\n"); + } + portable_mutex_unlock(&LP_UTXOmutex); + return(utxo); +} + + int32_t LP_utxosparse(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; bits256 txid; struct LP_utxoinfo *utxo; diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 90e565c6d..6300e0dbf 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -123,7 +123,8 @@ void basilisk_swap_finished(struct basilisk_swap *swap) if ( swap->utxo != 0 && swap->sentflag == 0 ) { LP_availableset(swap->utxo); - LP_butxo_swapfields_set(swap->utxo); + swap->utxo = 0; + //LP_butxo_swapfields_set(swap->utxo); } swap->I.finished = (uint32_t)time(NULL); // save to permanent storage diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index a38aef168..6cd607f4b 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -69,23 +69,6 @@ int32_t LP_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj) return(retval); } -struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); - return(ap); -} - -struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - ap = calloc(1,sizeof(*ap)); - safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); - //printf("LP_ADDRESS %s ADD.(%s)\n",coin->symbol,coinaddr); - HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap); - return(ap); -} - struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr) { struct LP_address *ap = 0; @@ -138,14 +121,29 @@ int32_t LP_address_minmax(uint64_t *minp,uint64_t *maxp,struct LP_address *ap) return(n); } -int32_t LP_address_utxo_ptrs(struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap,int32_t avoidflag) +struct LP_utxoinfo *LP_unallocated(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo; + if ( (utxo= _LP_utxofind(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + return(0); + if ( (utxo= _LP_utxo2find(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + return(0); + if ( (utxo= _LP_utxofind(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + return(0); + if ( (utxo= _LP_utxo2find(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + return(0); + return(utxo); +} + +int32_t LP_address_utxo_ptrs(struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap) { struct LP_address_utxo *up,*tmp; int32_t n = 0; + portable_mutex_lock(&LP_utxomutex); DL_FOREACH_SAFE(ap->utxos,up,tmp) { if ( up->spendheight <= 0 ) { - if ( avoidflag == 0 || LP_butxo_findeither(up->U.txid,up->U.vout) == 0 ) + if ( LP_unallocated(up->U.txid,up->U.vout) != 0 ) { utxos[n++] = up; if ( n >= max ) @@ -153,6 +151,7 @@ int32_t LP_address_utxo_ptrs(struct LP_address_utxo **utxos,int32_t max,struct L } } } + portable_mutex_unlock(&LP_utxomutex); return(n); } diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index 990c5f4d1..94487dc3b 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -206,7 +206,7 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo) jaddbits256(item,"pubkey",utxo->pubkey); //jaddnum(item,"profit",utxo->S.profitmargin); jaddstr(item,"base",utxo->coin); - jaddstr(item,"script",utxo->spendscript); + //jaddstr(item,"script",utxo->spendscript); return(item); } @@ -278,12 +278,12 @@ char *LP_spentcheck(cJSON *argjson) return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); } -struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid) +struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid) { uint64_t val,val2=0,tmpsatoshis,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; - if ( symbol == 0 || symbol[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 || sessionid == 0 ) + if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 || sessionid == 0 ) { - printf("session.%u malformed addutxo %d %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); + printf("session.%u malformed addutxo %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); return(0); } if ( iambob != 0 ) @@ -343,7 +343,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis)); } 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(symbol,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) + 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(symbol,utxo->coin) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) { utxo->T.errors++; char str[65],str2[65],str3[65],str4[65],str5[65],str6[65]; @@ -353,7 +353,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit // utxo->T.spentflag = (uint32_t)time(NULL); printf("original utxo pair not valid\n"); if ( dispflag != 0 ) - printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.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(symbol,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); + printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.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(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); utxo = 0; } } @@ -373,7 +373,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit safecopy(utxo->gui,gui,sizeof(utxo->gui)); safecopy(utxo->coin,symbol,sizeof(utxo->coin)); safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); - safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); + //safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); utxo->payment.txid = txid; utxo->payment.vout = vout; utxo->payment.value = value; @@ -418,25 +418,6 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit return(utxo); } -struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) -{ - struct LP_utxoinfo *utxo; - if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) - { - printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); - return(0); - } - portable_mutex_lock(&LP_UTXOmutex); - utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jstr(argjson,"gui"),juint(argjson,"session")); - if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) - { - utxo->T.lasttime = (uint32_t)time(NULL); - printf("set lasttime!\n"); - } - portable_mutex_unlock(&LP_UTXOmutex); - return(utxo); -} - cJSON *LP_inventory(char *symbol) { struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; @@ -610,14 +591,14 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri portable_mutex_lock(&LP_UTXOmutex); if ( iambob != 0 ) { - if ( (utxo= LP_utxoadd(1,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) + if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) { } } else { //printf("call utxoadd\n"); - if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) + if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) { } } @@ -742,9 +723,10 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan } else free_json(retjson); } } - G.LP_mypub25519 = *pubkeyp = curve25519(privkey,curve25519_basepoint9()); - G.LP_mypriv25519 = privkey; - //printf("privkey.(%s) -> LP_mypub25519.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypub25519)); + vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey)); + checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64; + G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9()); + G.LP_mypriv25519 = checkkey; return(privkey); } @@ -772,7 +754,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) } } -int32_t LP_passphrase_init(char *passphrase) +int32_t LP_passphrase_init(char *passphrase,char *gui) { static void *ctx; struct LP_utxoinfo *utxo,*tmp; if ( ctx == 0 ) @@ -780,6 +762,8 @@ int32_t LP_passphrase_init(char *passphrase) if ( G.LP_pendingswaps != 0 ) return(-1); G.initializing = 1; + if ( gui == 0 ) + gui = "cli"; while ( G.waiting == 0 ) { printf("waiting for G.waiting\n"); @@ -805,6 +789,7 @@ int32_t LP_passphrase_init(char *passphrase) LP_privkey_updates(ctx,LP_mypubsock,passphrase); init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20); G.LP_sessionid = (uint32_t)time(NULL); + safecopy(G.gui,gui,sizeof(G.gui)); return(0); }