diff --git a/iguana/exchanges/LP_cache.c b/iguana/exchanges/LP_cache.c index e4727a333..95fbe6f99 100644 --- a/iguana/exchanges/LP_cache.c +++ b/iguana/exchanges/LP_cache.c @@ -45,9 +45,9 @@ struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 tx vins = jarray(&numvins,txobj,"vin"); vouts = jarray(&numvouts,txobj,"vout"); tx = LP_transactionadd(coin,txid,height,numvouts,numvins); - tx->serialized = 0; + tx->serialized = serialized; + //free(serialized); tx->fpos = fpos; - free(serialized); tx->len = tx->len; tx->SPV = tx->height = height; //printf("tx.%s numvins.%d numvouts.%d\n",bits256_str(str,txid),numvins,numvouts); @@ -228,12 +228,12 @@ bits256 LP_merkleroot(struct iguana_info *coin,struct electrum_info *ep,int32_t return(merkleroot); } -int32_t LP_merkleproof(struct iguana_info *coin,struct electrum_info *ep,bits256 txid,int32_t height) +int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height) { struct LP_transaction *tx=0; cJSON *merkobj,*merkles,*retjson; bits256 roothash,merkleroot; int32_t m,SPV = 0; - if ( height < 0 ) + if ( height <= 0 ) return(0); - if ( (tx= LP_transactionfind(coin,txid)) == 0) + if ( (tx= LP_transactionfind(coin,txid)) == 0 && strcmp(coinaddr,coin->smartaddr) == 0 ) { if ( (retjson= electrum_transaction(coin->symbol,ep,&retjson,txid)) != 0 ) free_json(retjson); diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 980c8aeb2..3922708ed 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -23,7 +23,7 @@ #define LP_MAJOR_VERSION "0" #define LP_MINOR_VERSION "1" -#define LP_BUILD_NUMBER "11843" +#define LP_BUILD_NUMBER "14288" #ifdef FROM_JS #include @@ -43,7 +43,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define LP_MAXVINS 64 #define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL) -#define LP_AUTOTRADE_TIMEOUT 30 +#define LP_AUTOTRADE_TIMEOUT 40 #define ELECTRUM_TIMEOUT 7 #define LP_ELECTRUM_KEEPALIVE 60 #define LP_ELECTRUM_MAXERRORS 777 @@ -428,7 +428,9 @@ int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,cha struct iguana_info *LP_coinfind(char *symbol); int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32); char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price); -int32_t LP_merkleproof(struct iguana_info *coin,struct electrum_info *ep,bits256 txid,int32_t height); +int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height); +int32_t _LP_utxos_remove(bits256 txid,int32_t vout); +int32_t LP_utxos_remove(bits256 txid,int32_t vout); struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins); void LP_tradebot_finished(uint32_t tradeid,uint32_t requestid,uint32_t quoteid); uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen); diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 76c75db1c..279276789 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -18,10 +18,8 @@ // LP_nativeDEX.c // marketmaker // -// version info +// immediate "request", actual auction // previously, it used to show amount, kmd equiv, perc -// swap started, pending, locked, finished, ... -// aliceid //there is still a pending one with `-1 wait for bobpayment bYoNxkfvwQ42Yufry8J5y8BYi6mQxokvW9 numconfs.1 MNZ c0ea4aa808a653222a15122d96692fecf734dbbacfb9a54cb4711306ea0c3cef`, but that tx is already spent including 6 confirmation // bot safe to exit? // @@ -457,7 +455,7 @@ void command_rpcloop(void *myipaddr) void utxosQ_loop(void *myipaddr) { strcpy(utxosQ_loop_stats.name,"utxosQ_loop"); - utxosQ_loop_stats.threshold = 500.; + utxosQ_loop_stats.threshold = 5000.; while ( 1 ) { LP_millistats_update(&utxosQ_loop_stats); @@ -468,7 +466,7 @@ void utxosQ_loop(void *myipaddr) void LP_coinsloop(void *_coins) { - struct LP_address *ap=0,*atmp; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins; + struct LP_address *ap=0; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins; if ( strcmp("BTC",coins) == 0 ) { strcpy(LP_coinsloopBTC_stats.name,"BTC coin loop"); @@ -519,6 +517,8 @@ void LP_coinsloop(void *_coins) //HASH_ITER(hh,coin->addresses,ap,atmp) if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) { + if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) + free_json(retjson); DL_FOREACH_SAFE(ap->utxos,up,tmp) { break; @@ -527,7 +527,7 @@ void LP_coinsloop(void *_coins) if ( up->SPV == 0 ) { nonz++; - up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height); + up->SPV = LP_merkleproof(coin,coin->smartaddr,backupep,up->U.txid,up->U.height); if ( up->SPV > 0 ) { if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && tx->SPV == 0 ) @@ -544,7 +544,7 @@ void LP_coinsloop(void *_coins) oldht = up->U.height; LP_txheight_check(coin,ap->coinaddr,up); if ( oldht != up->U.height ) - up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height); + up->SPV = LP_merkleproof(coin,coin->smartaddr,backupep,up->U.txid,up->U.height); if ( up->SPV <= 0 ) up->SPV = -2; else printf("%s %s: corrected SPV.%d\n",coin->symbol,bits256_str(str,up->U.txid),up->SPV); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index c9cf68261..c2eba14fb 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -115,7 +115,7 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str { if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 ) { - char str[65]; printf("alice not eligible (%.8f %.8f) %s/v%d\n",dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout); + char str[65]; printf("alice not eligible destsatoshis %.8f (%.8f %.8f) %s/v%d\n",dstr(qp->destsatoshis),dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout); return(-3); } if ( (txout= LP_gettxout(qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout)) != 0 ) @@ -269,12 +269,13 @@ uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t d struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double relvolume,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_utxoinfo *utxo = 0; + struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; struct LP_utxoinfo *utxo = 0;//,*utmp; + targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee); + targetval2 = (targetval / 8) * 9 + 2*txfee; if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 ) { if ( (m= LP_address_utxo_ptrs(coin,iambob,utxos,max,ap,coinaddr)) > 1 ) { - targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee); if ( 0 ) { int32_t i; @@ -287,7 +288,6 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo ** { up = utxos[mini]; utxos[mini] = 0; - targetval2 = (targetval / 8) * 9 + 2*txfee; //printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval); if ( (double)up->U.value/targetval < LP_MINVOL-1 ) @@ -296,7 +296,7 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo ** { if ( up != 0 && (up2= utxos[mini]) != 0 ) { - 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 ) + 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,targetval)) != 0 ) { utxo->S.satoshis = targetval; char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid)); @@ -309,6 +309,15 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo ** printf("targetval %.8f mini.%d\n",dstr(targetval),mini); } //else printf("no %s utxos pass LP_address_utxo_ptrs filter\n",coinaddr); } else printf("couldnt find %s %s\n",coin->symbol,coinaddr); + /*HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,utmp) + { + if ( LP_isavailable(utxo) != 0 && utxo->payment.value >= targetval && targetval >= utxo->payment.value/2 && utxo->deposit.value >= targetval2 ) + { + utxo->S.satoshis = targetval; + printf("backup method found utxo!\n"); + return(utxo); + } + }*/ return(0); } @@ -359,7 +368,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ privkey = LP_privkey(utxo->coinaddr,coin->taddr); if ( bits256_nonz(privkey) != 0 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 ) //qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && { - LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-2*qp->txfee,rel,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); + LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp)) == 0 ) { printf("cant initialize swap\n"); @@ -416,6 +425,8 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q return(clonestr("{\"error\":\"cant find alice utxopair\"}")); } price = 0.; + memset(qp->txid.bytes,0,sizeof(qp->txid)); + qp->txid2 = qp->txid; qp->aliceid = LP_aliceid_calc(qp->desttxid,qp->destvout,qp->feetxid,qp->feevout); qp->tradeid = tradeid; LP_query(ctx,myipaddr,mypubsock,"request",qp); @@ -426,7 +437,7 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q int32_t LP_quotecmp(struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2) { - if ( bits256_cmp(qp->srchash,qp2->srchash) == 0 && bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee ) + if ( bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee ) //bits256_cmp(qp->srchash,qp2->srchash) == 0 && return(0); else return(-1); } @@ -449,14 +460,15 @@ void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo if ( LP_alice_eligible() > 0 && LP_quotecmp(qp,&LP_Alicequery) == 0 ) { price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); - if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice ) + if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice*1.005 ) { qp->tradeid = LP_Alicequery.tradeid; memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); LP_Alicemaxprice = 0.; Alice_expiration = 0; + printf("send CONNECT\n"); LP_query(ctx,myipaddr,mypubsock,"connect",qp); - } + } else printf("LP_reserved price %.8f vs maxprice %.8f\n",price,maxprice*1.005); } else printf("probably a timeout, reject reserved due to not eligible.%d or mismatched quote price %.8f vs maxprice %.8f\n",LP_alice_eligible(),price,maxprice); } @@ -506,7 +518,7 @@ char *LP_connectedalice(cJSON *argjson) // alice } if ( LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin) <= SMALLVAL || bid <= SMALLVAL ) { - printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); + //printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); LP_availableset(autxo); LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0); return(clonestr("{\"error\":\"no price set\"}")); @@ -522,7 +534,7 @@ char *LP_connectedalice(cJSON *argjson) // alice if ( bits256_nonz(Q.privkey) != 0 )//&& Q.quotetime >= Q.timestamp-3 ) { retjson = cJSON_CreateObject(); - LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); + LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q)) == 0 ) { jaddstr(retjson,"error","couldnt swapinit"); @@ -647,7 +659,7 @@ int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout) return(-1); if ( (backupep= ep->prev) == 0 ) backupep = ep; - up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height); + up->SPV = LP_merkleproof(coin,coinaddr,backupep,up->U.txid,up->U.height); if ( up->SPV <= 0 ) return(-1); } @@ -662,14 +674,26 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, { // LP_checksig LP_quoteparse(&Q,argjson); - LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); + LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); LP_tradecommand_log(argjson); //printf("LP_tradecommand: check received method %s aliceid.%llx\n",method,(long long)Q.aliceid); retval = 1; + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,&Q); if ( strcmp(method,"reserved") == 0 ) { + if ( LP_Alicemaxprice == 0. ) + return(retval); if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && LP_alice_eligible() > 0 ) { + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) + { + printf("reserved quote validate error %.0f\n",qprice); + return(retval); + } if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 ) { printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); @@ -692,6 +716,11 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, { if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 ) { + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(retval); + } if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 ) { printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); @@ -708,149 +737,169 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, } return(retval); } - if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 ) + if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) { - if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) - { - printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); - return(retval); - } - if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 ) - { - printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid)); - return(retval); - } - else if (LP_validSPV(Q.destcoin,Q.destaddr,Q.feetxid,Q.feevout) < 0 ) - { - printf("%s dexfee %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.feetxid)); - return(retval); - } - price = ask; - /*if ( coin->electrum != 0 ) - { - printf("electrum can only be for alice\n"); - return(retval); - }*/ - if ( LP_aliceonly(Q.srccoin) > 0 ) - { - printf("{\"error\":\"GAME can only be alice coin\"}\n"); - return(retval); - } - if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 ) + //printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); + return(retval); + } + if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 ) + { + printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid)); + return(retval); + } + else if (LP_validSPV(Q.destcoin,Q.destaddr,Q.feetxid,Q.feevout) < 0 ) + { + printf("%s dexfee %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.feetxid)); + return(retval); + } + price = ask; + if ( LP_aliceonly(Q.srccoin) > 0 ) + { + printf("{\"error\":\"GAME can only be alice coin\"}\n"); + return(retval); + } + if ( strcmp(method,"request") == 0 ) + { + char str[65],str2[65]; + //printf("address.(%s/%s) request.(%s)\n",Q.coinaddr,coin->smartaddr,jprint(argjson,0)); + recalc = 0; + if ( bits256_cmp(Q.srchash,G.LP_mypub25519) != 0 || strcmp(butxo->coinaddr,coin->smartaddr) != 0 ) { - printf("bob is patching Q.coinaddr %s mismatch != %s\n",Q.coinaddr,coin->smartaddr); + strcpy(Q.gui,G.gui); strcpy(Q.coinaddr,coin->smartaddr); + strcpy(butxo->coinaddr,coin->smartaddr); + Q.srchash = G.LP_mypub25519; + memset(&Q.txid,0,sizeof(Q.txid)); + memset(&Q.txid2,0,sizeof(Q.txid2)); + Q.vout = Q.vout2 = -1; + recalc = 1; } - autxo = &A; - butxo = &B; - memset(autxo,0,sizeof(*autxo)); - memset(butxo,0,sizeof(*butxo)); - LP_abutxo_set(autxo,butxo,&Q); - if ( strcmp(method,"request") == 0 ) + else if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL ) + recalc = 1; + else { - char str[65],str2[65]; - printf("address.(%s/%s) request.(%s)\n",Q.coinaddr,coin->smartaddr,jprint(argjson,0)); - recalc = 0; - if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL ) - recalc = 1; - else + char tmp[64]; + price = (qprice * 0.5) + (0.5 * price); + if ( bits256_nonz(Q.txid) != 0 ) + LP_utxos_remove(Q.txid,Q.vout); + else recalc = 1; + if ( bits256_nonz(Q.txid2) != 0 ) + LP_utxos_remove(Q.txid2,Q.vout2); + else recalc = 1; + if ( recalc == 0 ) { - char tmp[64]; value = LP_txvalue(tmp,Q.srccoin,Q.txid,Q.vout); value2 = LP_txvalue(tmp,Q.srccoin,Q.txid2,Q.vout2); - printf("call LP_utxoadd.(%s) %.8f %.8f\n",Q.coinaddr,dstr(value),dstr(value2)); - if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,G.gui,0)) == 0 ) + //printf("call LP_utxoadd.(%s) %.8f %.8f\n",Q.coinaddr,dstr(value),dstr(value2)); + if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,G.gui,0,Q.satoshis)) == 0 ) recalc = 1; } - if ( recalc != 0 ) + else { - LP_RTmetrics_update(Q.srccoin,Q.destcoin); - if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 ) - { - printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); - return(retval); - } - printf("butxo.%p recalc path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1)); - LP_listunspent_both(Q.srccoin,Q.coinaddr,0); - if ( (butxo= LP_address_utxopair(1,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; - printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis)); - } - else - { - printf("cant find utxopair\n"); - return(retval); - } + if ( bits256_cmp(Q.txid,butxo->payment.txid) != 0 || Q.vout != butxo->payment.vout || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 || Q.vout2 != butxo->deposit.vout ) + recalc = 1; } } - else // "connect" - { - butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); - } - char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0)); - 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],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis)); - return(retval); - } - if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) - { - printf("quote validate error %.0f\n",qprice); - return(-3); - } - if ( qprice < (price - 0.00000001) * 0.9999 ) - { - printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); - return(-4); - } - if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending ) - butxo->T.swappending = 0; - if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's + if ( recalc != 0 ) { - if ( LP_isavailable(butxo) > 0 ) + LP_RTmetrics_update(Q.srccoin,Q.destcoin); + if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 ) { - autxo->T.swappending = butxo->T.swappending = Q.timestamp + LP_RESERVETIME; - retjson = LP_quotejson(&Q); - butxo->S.otherpubkey = jbits256(argjson,"desthash"); - LP_unavailableset(butxo,butxo->S.otherpubkey); - jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); - jaddnum(retjson,"pending",butxo->T.swappending); - jaddbits256(retjson,"desthash",butxo->S.otherpubkey); - jaddbits256(retjson,"pubkey",butxo->S.otherpubkey); - jaddstr(retjson,"method","reserved"); - msg = jprint(retjson,0); - butxo->T.lasttime = (uint32_t)time(NULL); - printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg); - // LP_addsig - //msg2 = clonestr(msg); - LP_reserved_msg(1,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,clonestr(msg)); - sleep(1); - bits256 zero; - memset(zero.bytes,0,sizeof(zero)); - LP_reserved_msg(1,Q.srccoin,Q.destcoin,zero,msg); - //LP_broadcast_message(LP_mypubsock,Q.srccoin,Q.destcoin,Q.desthash,jprint(retjson,0)); - free_json(retjson); + printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); return(retval); - } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); - } - else if ( strcmp(method,"connect") == 0 ) // bob - { - retval = 4; - if ( butxo->S.swap == 0 && butxo->T.swappending != 0 ) + } + //printf("butxo.%p recalc path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1)); + LP_listunspent_both(Q.srccoin,Q.coinaddr,0); + if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) + { + strcpy(Q.gui,G.gui); + strcpy(Q.coinaddr,coin->smartaddr); + Q.srchash = G.LP_mypub25519; + Q.txid = butxo->payment.txid; + Q.vout = butxo->payment.vout; + Q.txid2 = butxo->deposit.txid; + Q.vout2 = butxo->deposit.vout; + butxo->S.satoshis = Q.satoshis; + printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis)); + } + else { - // validate SPV alice - LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q); - //LP_butxo_swapfields_set(butxo); + //printf("cant find utxopair\n"); return(retval); } - 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); } + else // "connect" + { + if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 ) + { + butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); // better work! + } else return(retval); + } + if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 ) + { + printf("bob is patching Q.coinaddr %s mismatch != %s\n",Q.coinaddr,coin->smartaddr); + strcpy(Q.coinaddr,coin->smartaddr); + } + 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],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis)); + return(retval); + } + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(-3); + } + if ( qprice < (price - 0.00000001) * 0.998 ) + { + printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); + return(retval); + } + char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0)); + if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending ) + butxo->T.swappending = 0; + if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's + { + if ( LP_isavailable(butxo) > 0 ) + { + autxo->T.swappending = butxo->T.swappending = Q.timestamp + LP_RESERVETIME; + retjson = LP_quotejson(&Q); + butxo->S.otherpubkey = jbits256(argjson,"desthash"); + LP_unavailableset(butxo,butxo->S.otherpubkey); + jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); + jaddnum(retjson,"pending",butxo->T.swappending); + jaddbits256(retjson,"desthash",butxo->S.otherpubkey); + jaddbits256(retjson,"pubkey",butxo->S.otherpubkey); + jaddstr(retjson,"method","reserved"); + msg = jprint(retjson,0); + butxo->T.lasttime = (uint32_t)time(NULL); + printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg); + // LP_addsig + //msg2 = clonestr(msg); + LP_reserved_msg(1,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,clonestr(msg)); + sleep(1); + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(1,Q.srccoin,Q.destcoin,zero,msg); + //LP_broadcast_message(LP_mypubsock,Q.srccoin,Q.destcoin,Q.desthash,jprint(retjson,0)); + free_json(retjson); + return(retval); + } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); + } + else if ( strcmp(method,"connect") == 0 ) // bob + { + retval = 4; + if ( butxo->S.swap == 0 && butxo->T.swappending != 0 ) + { + // validate SPV alice + LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q); + //LP_butxo_swapfields_set(butxo); + return(retval); + } + 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); } return(retval); } @@ -888,7 +937,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i else max = LP_MAXDESIRED_UTXOS; utxos = calloc(max,sizeof(*utxos)); LP_txfees(&txfee,&desttxfee,base,autxo->coin); - //printf("LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f\n",maxprice,dstr(autxo->S.satoshis),base,autxo->coin,dstr(txfee),dstr(desttxfee)); + printf("LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f\n",maxprice,dstr(autxo->S.satoshis),base,autxo->coin,dstr(txfee),dstr(desttxfee)); if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 ) { if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) @@ -901,9 +950,9 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i { item = jitem(asks,i); price = jdouble(item,"price"); - if ( price < maxprice && price > maxprice*0.8) - price = price * 0.9 + 0.1 * maxprice; - else price *= 1.005; + //if ( price < maxprice && price > maxprice*0.8) + // price = price * 0.9 + 0.1 * maxprice; + //else price *= 1.005; pubkey = jbits256(item,"pubkey"); if ( bits256_nonz(destpubkey) != 0 && bits256_cmp(destpubkey,pubkey) != 0 ) continue; @@ -927,7 +976,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i LP_listunspent_query(base,coinaddr); for (j=0; jpubkey,gui)) != 0 ) + if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,maxprice*.999,txfee,desttxfee,pubp->pubkey,gui)) != 0 ) { //printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee)); break; @@ -1028,6 +1077,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel return(clonestr("{\"error\":\"cant find alice utxo that is small enough\"}")); } LP_RTmetrics_update(base,rel); + //return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid)); while ( 1 ) { if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index ed2a52b8f..66bb2fdc3 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -813,13 +813,17 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) for (i=n=0; inumutxos < 3 ) + if ( suppress_prefetch == 0 && n < 3 && bids[i]->numutxos == 0 ) { //printf("bid ping %s %s\n",rel,bids[i]->coinaddr); LP_address(relcoin,bids[i]->coinaddr); if ( relcoin->electrum == 0 ) + { LP_listunspent_issue(rel,bids[i]->coinaddr,0); - LP_listunspent_query(rel,bids[i]->coinaddr); + //else if ( (tmpjson= LP_listunspent(rel,bids[i]->coinaddr)) != 0 ) + // free_json(tmpjson); + LP_listunspent_query(rel,bids[i]->coinaddr); + } n++; } free(bids[i]); @@ -833,13 +837,17 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) for (i=n=0; inumutxos < 3 ) + if ( suppress_prefetch == 0 && n < 3 && asks[i]->numutxos == 0 ) { //printf("ask ping %s %s\n",base,asks[i]->coinaddr); LP_address(basecoin,asks[i]->coinaddr); if ( basecoin->electrum == 0 ) + { LP_listunspent_issue(base,asks[i]->coinaddr,0); - LP_listunspent_query(base,asks[i]->coinaddr); + //else if ( (tmpjson= LP_listunspent(base,asks[i]->coinaddr)) != 0 ) + // free_json(tmpjson); + LP_listunspent_query(base,asks[i]->coinaddr); + } n++; } free(asks[i]); diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index b1a72bc5d..5be93ba33 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -329,7 +329,8 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep tx->height = ht; if ( ep != 0 && coin != 0 && tx->SPV == 0 ) { - tx->SPV = LP_merkleproof(coin,ep,txid,tx->height); + if ( strcmp(coinaddr,coin->smartaddr) == 0 ) + tx->SPV = LP_merkleproof(coin,coin->smartaddr,ep,txid,tx->height); //printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height); } } @@ -419,16 +420,11 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch //printf("%s %s",symbol,stratumreq); memset(ep->buf,0,ep->bufsize); sitem = electrum_sitem(ep,stratumreq,timeout,retjsonp); - /*sitem = (struct stritem *)queueitem(stratumreq); - sitem->expiration = timeout; - sitem->DL.type = ep->stratumid++; - sitem->retptrp = (void **)retjsonp;*/ -//portable_mutex_lock(&ep->mutex); - //queue_enqueue("sendQ",&ep->sendQ,&sitem->DL); + portable_mutex_lock(&ep->mutex); // this helps performance! expiration = (uint32_t)time(NULL) + timeout + 1; while ( *retjsonp == 0 && time(NULL) <= expiration ) usleep(15000); -//portable_mutex_unlock(&ep->mutex); + portable_mutex_unlock(&ep->mutex); if ( *retjsonp == 0 || jobj(*retjsonp,"error") != 0 ) { if ( ++ep->numerrors >= LP_ELECTRUM_MAXERRORS ) diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 8671759fc..f923ad161 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -556,7 +556,7 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat 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) { - bits256 otherhash,myhash,txid; int64_t txfee; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits; + bits256 otherhash,myhash,txid; int64_t txfee,val; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits; for (i=0; i<32; i++) otherhash.bytes[i] = recvbuf[offset++]; for (i=0; i<32; i++) @@ -626,7 +626,10 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba txfee = swap->I.Atxfee; else txfee = LP_MIN_TXFEE; } - if ( j64bits(vout,"satoshis") >= rawtx->I.amount-txfee && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) + if ( rawtx->I.amount > 2*txfee) + val = rawtx->I.amount-2*txfee; + else val = 1; + if ( j64bits(vout,"satoshis") >= val && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) { if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) { diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 91bdb2f2d..d9939432d 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -1805,7 +1805,10 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d } } if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 && swap->myfee.I.datalen != 0 && swap->myfee.I.spendlen > 0 ) + { + printf("fee sent\n"); return(0); + } return(-1); } @@ -1820,7 +1823,7 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data diff = swap->otherfee.I.locktime - (swap->I.started+1); if ( diff < 0 ) diff = -diff; - if ( diff == 0 ) + if ( diff < 10 ) printf("dexfee verified\n"); else printf("locktime mismatch in otherfee, reject %u vs %u\n",swap->otherfee.I.locktime,swap->I.started+1); return(0); diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 097478910..e76b74a54 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -141,7 +141,7 @@ struct LP_utxoinfo *LP_allocated(bits256 txid,int32_t vout) int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap,char *coinaddr) { - struct LP_address_utxo *up,*tmp; struct LP_transaction *tx; cJSON *txout; int32_t n = 0; char str[65]; + struct LP_address_utxo *up,*tmp; struct LP_transaction *tx; cJSON *txout; int32_t n = 0; //printf("LP_address_utxo_ptrs for (%s).(%s)\n",ap->coinaddr,coinaddr); if ( strcmp(ap->coinaddr,coinaddr) != 0 ) printf("UNEXPECTED coinaddr mismatch (%s) != (%s)\n",ap->coinaddr,coinaddr); @@ -157,7 +157,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a { if ( LP_value_extract(txout,0) == 0 ) { - printf("LP_address_utxo_ptrs skip zero value %s/v%d\n",bits256_str(str,up->U.txid),up->U.vout); + //printf("LP_address_utxo_ptrs skip zero value %s/v%d\n",bits256_str(str,up->U.txid),up->U.vout); free_json(txout); up->spendheight = 1; if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts ) @@ -179,13 +179,13 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a { if ( up->SPV < 0 || up->U.height == 0 ) { -printf("LP_address_utxo_ptrs skips %s/v%u due to SPV.%d ht.%d\n",bits256_str(str,up->U.txid),up->U.vout,up->SPV,up->U.height); +//printf("LP_address_utxo_ptrs skips %s/v%u due to SPV.%d ht.%d\n",bits256_str(str,up->U.txid),up->U.vout,up->SPV,up->U.height); if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts ) tx->outpoints[up->U.vout].spendheight = 1; continue; } } - if ( LP_allocated(up->U.txid,up->U.vout) == 0 ) + if ( LP_allocated(up->U.txid,up->U.vout) == 0 && _LP_utxofind(iambob,up->U.txid,up->U.vout) == 0 && _LP_utxo2find(iambob,up->U.txid,up->U.vout) == 0 ) { utxos[n++] = up; if ( n >= max ) @@ -468,26 +468,24 @@ void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t 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)]; - /*if ( iambob != 0 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - printf("_LP_utxofind deprecated iambob\n"); - return(0); - }*/ LP_utxosetkey(key,txid,vout); - HASH_FIND(hh,G.LP_utxoinfos[iambob],key,sizeof(key),utxo); + HASH_FIND(hh,G.LP_utxoinfos[iambob!=0],key,sizeof(key),utxo); return(utxo); } +void _LP_utxo_delete(int32_t iambob,struct LP_utxoinfo *utxo) +{ + HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo); +} + +void _LP_utxo2_delete(int32_t iambob,struct LP_utxoinfo *utxo) +{ + HASH_DELETE(hh,G.LP_utxoinfos2[iambob],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)]; - /*if ( iambob != 0 ) - { - printf("_LP_utxo2find deprecated iambob\n"); - return(0); - }*/ LP_utxosetkey(key2,txid2,vout2); HASH_FIND(hh2,G.LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); return(utxo); @@ -781,7 +779,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2) { - uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct LP_transaction *tx; struct LP_address_utxo *up; struct iguana_info *coin = LP_coinfind(symbol); + uint64_t val,val2=0,txfee,threshold=0; cJSON *txobj; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct LP_transaction *tx; struct LP_address_utxo *up; struct iguana_info *coin = LP_coinfind(symbol); if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 ) { printf("null txid not eligible\n"); @@ -814,25 +812,37 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol strcpy(destaddr,destaddr2); if ( coin != 0 ) { - if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts && tx->outpoints[vout].spendheight > 0 ) + if ( coin->electrum != 0 ) { - //printf("txid spent\n"); - return(0); - } - if ( (tx= LP_transactionfind(coin,txid2)) != 0 && vout2 < tx->numvouts && tx->outpoints[vout2].spendheight > 0 ) - { - //printf("txid2 spent\n"); - return(0); - } - if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 ) - { - //printf("txid %s spentB\n",destaddr); - return(0); + if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts && tx->outpoints[vout].spendheight > 0 ) + { + //printf("txid spent\n"); + return(0); + } + if ( (tx= LP_transactionfind(coin,txid2)) != 0 && vout2 < tx->numvouts && tx->outpoints[vout2].spendheight > 0 ) + { + //printf("txid2 spent\n"); + return(0); + } + if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 ) + { + //printf("txid %s spentB\n",destaddr); + return(0); + } + if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 ) + { + //printf("txid2 %s spentB\n",destaddr); + return(0); + } } - if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 ) + else { - //printf("txid2 %s spentB\n",destaddr); - return(0); + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) + return(0); + else free_json(txobj); + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) + return(0); + else free_json(txobj); } } return(1); diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index 8b7313630..e82541a63 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -286,9 +286,9 @@ void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) utxo->T.spentflag = (uint32_t)time(NULL); } -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) +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 satoshis) { - 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; + uint64_t val,val2=0,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 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 ) { char str[65],str2[65]; printf("REJECT (%s) iambob.%d %s utxoadd.(%.8f %.8f) %s/v%d %s/v%d\n",coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2); @@ -301,7 +301,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t return(0); } txfee = LP_txfeecalc(coin,0,0); - if ( iambob != 0 && value2 < 9 * (value >> 3) + 2*txfee ) // big txfee padding + /*if ( iambob != 0 && value2 < 9 * (satoshis >> 3) + 2*txfee ) // big txfee padding { if ( value2 > 2*txfee ) tmpsatoshis = (((value2 - 2*txfee) / 9) << 3); @@ -310,7 +310,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t printf("value2 %.8f <= 2 * %.8f\n",dstr(value2),dstr(txfee)); return(0); } - } else tmpsatoshis = (value - txfee); + } else tmpsatoshis = (satoshis - txfee);*/ char str[65],str2[65],dispflag = 0;//(iambob == 0); if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 ) { @@ -319,11 +319,11 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t } if ( coin->inactive == 0 ) { - if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 ) + if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,satoshis,txid2,vout2) <= 0 ) { static uint32_t counter; if ( counter++ < 3 ) - printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis)); + printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(satoshis)); return(0); } if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,vout,0)) <= 0 ) @@ -351,10 +351,10 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t if ( 0 && LP_ismine(utxo) == 0 ) { char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); - 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)); + printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(satoshis),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(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 || satoshis != 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]; @@ -364,7 +364,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t // 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 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)); + 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,satoshis != 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; } } @@ -389,7 +389,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t utxo->payment.txid = txid; utxo->payment.vout = vout; utxo->payment.value = value; - utxo->S.satoshis = tmpsatoshis; + utxo->S.satoshis = satoshis; if ( (utxo->iambob= iambob) != 0 ) { utxo->deposit.txid = txid2; @@ -430,6 +430,46 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t return(utxo); } +int32_t _LP_utxos_remove(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo,*utxo2; int32_t retval = 0,iambob = 1; + utxo = utxo2 = 0; + if ( (utxo= _LP_utxofind(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + retval = -1; + else + { + if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + retval = -1; + else + { + _LP_utxo_delete(iambob,utxo); + _LP_utxo2_delete(iambob,utxo2); + } + } + } + } + else if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo2) == 0 ) + retval = -1; + else _LP_utxo2_delete(iambob,utxo2); + } + return(retval); +} + +int32_t LP_utxos_remove(bits256 txid,int32_t vout) +{ + int32_t retval; + portable_mutex_lock(&LP_utxomutex); + retval = _LP_utxos_remove(txid,vout); + portable_mutex_unlock(&LP_utxomutex); + return(retval); +} + 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; struct iguana_info *coin; @@ -618,14 +658,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,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,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,value)) != 0 ) { } } else { //printf("call utxoadd\n"); - if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,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,value)) != 0 ) { } }