From c7d175dac94a82a86be3a85248827c806bafdfb7 Mon Sep 17 00:00:00 2001 From: jl777 Date: Tue, 14 Nov 2017 18:39:22 +0200 Subject: [PATCH] Dynamic inventory --- iguana/exchanges/LP_cache.c | 4 +- iguana/exchanges/LP_include.h | 15 +- iguana/exchanges/LP_nativeDEX.c | 3 +- iguana/exchanges/LP_ordermatch.c | 320 +++++++++++++++--------------- iguana/exchanges/LP_signatures.c | 11 +- iguana/exchanges/LP_socket.c | 6 +- iguana/exchanges/LP_swap.c | 12 +- iguana/exchanges/LP_transaction.c | 39 +--- iguana/exchanges/LP_utxo.c | 206 +++++++++++++++---- iguana/exchanges/LP_utxos.c | 52 +++-- 10 files changed, 405 insertions(+), 263 deletions(-) diff --git a/iguana/exchanges/LP_cache.c b/iguana/exchanges/LP_cache.c index 65140dc2c..a08828966 100644 --- a/iguana/exchanges/LP_cache.c +++ b/iguana/exchanges/LP_cache.c @@ -58,7 +58,7 @@ struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 tx tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest"); LP_destaddr(tx->outpoints[i].coinaddr,vout); //printf("from transaction init %s %s %s/v%d <- %.8f\n",coin->symbol,tx->outpoints[i].coinaddr,bits256_str(str,txid),i,dstr(tx->outpoints[i].value)); - LP_address_utxoadd("LP_create_transaction",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); + LP_address_utxoadd((uint32_t)time(NULL),"LP_create_transaction",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); } for (i=0; ioutpoints[spentvout].spendtxid = txid; tx->outpoints[spentvout].spendvini = i; tx->outpoints[spentvout].spendheight = height > 0 ? height : 1; - LP_address_utxoadd("LP_transactioninit iter1",coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1); + LP_address_utxoadd((uint32_t)time(NULL),"LP_transactioninit iter1",coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1); if ( 0 && strcmp(coin->symbol,"REVS") == 0 ) printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height); } diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 839333523..c24ad9bf4 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 "14336" +#define LP_BUILD_NUMBER "14414" #ifdef FROM_JS #include @@ -43,7 +43,8 @@ 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 60 +#define LP_AUTOTRADE_TIMEOUT 30 +#define LP_RESERVETIME (LP_AUTOTRADE_TIMEOUT * 2) #define ELECTRUM_TIMEOUT 7 #define LP_ELECTRUM_KEEPALIVE 60 #define LP_ELECTRUM_MAXERRORS 777 @@ -103,7 +104,6 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define LP_RPCPORT 7783 #define LP_PROPAGATION_SLACK 100 // txid ordering is not enforced, so getting extra recent txid -#define LP_RESERVETIME 60 #define LP_AVETXSIZE 256 #define LP_CACHEDURATION 60 #define BASILISK_DEFAULT_NUMCONFIRMS 1 @@ -288,7 +288,7 @@ struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; }; struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; }; -struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; }; +struct LP_utxoswap { bits256 otherpubkey; uint64_t satoshis; }; struct LP_utxoinfo { @@ -308,6 +308,7 @@ struct LP_address_utxo struct LP_address_utxo *next,*prev; struct _LP_utxoinfo U; int32_t SPV,spendheight; + uint32_t timestamp; }; struct LP_address @@ -346,7 +347,7 @@ struct LP_endpoint { int32_t pair; char ipaddr[64]; uint16_t port; }; struct basilisk_swap { - void *ctx; struct LP_utxoinfo *utxo; + void *ctx; //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; @@ -410,7 +411,7 @@ uint64_t LP_value_extract(cJSON *obj,int32_t addinterest); int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout); char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen); int64_t LP_komodo_interest(bits256 txid,int64_t value); -void LP_availableset(struct LP_utxoinfo *utxo); +void LP_availableset(bits256 txid,int32_t vout); int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2); int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock); void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag); @@ -452,7 +453,7 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid); int32_t LP_numpeers(); char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid); uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance); -int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight); +int32_t LP_address_utxoadd(uint32_t timestamp,char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight); void LP_smartutxos_push(struct iguana_info *coin); void LP_cacheptrs_init(struct iguana_info *coin); cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret); diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 455845d77..713e8e7de 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -78,7 +78,7 @@ void LP_millistats_update(struct LP_millistats *mp) } #include "LP_include.h" -portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex; +portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex; int32_t LP_canbind; char *Broadcaststr,*Reserved_msgs[2][1000]; int32_t num_Reserved_msgs[2],max_Reserved_msgs[2]; @@ -923,6 +923,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu portable_mutex_init(&LP_networkmutex); portable_mutex_init(&LP_gcmutex); portable_mutex_init(&LP_forwardmutex); + portable_mutex_init(&LP_inusemutex); portable_mutex_init(&LP_psockmutex); portable_mutex_init(&LP_coinmutex); portable_mutex_init(&LP_pubkeymutex); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index 7f7e946c1..0ef73ab65 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -290,7 +290,7 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_a //printf("nearest i.%d target %.8f val %.8f dist %.8f mindist %.8f mini.%d spent.%d\n",i,dstr(targetval),dstr(up->U.value),dstr(dist),dstr(mindist),mini,up->spendheight); if ( up->spendheight <= 0 ) { - if ( dist >= 0 && dist < mindist ) //(coin->electrum == 0 || up->SPV > 0) && + if ( dist >= 0 && dist < mindist ) { //printf("(%.8f %.8f %.8f).%d ",dstr(up->U.value),dstr(dist),dstr(mindist),mini); mini = i; @@ -303,6 +303,55 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_a return(mini); } +void LP_butxo_set(struct LP_utxoinfo *butxo,struct iguana_info *coin,struct LP_address_utxo *up,struct LP_address_utxo *up2,int64_t satoshis) +{ + butxo->pubkey = G.LP_mypub25519; + safecopy(butxo->coin,coin->symbol,sizeof(butxo->coin)); + safecopy(butxo->coinaddr,coin->smartaddr,sizeof(butxo->coinaddr)); + butxo->payment.txid = up->U.txid; + butxo->payment.vout = up->U.vout; + butxo->payment.value = up->U.value; + butxo->iambob = 1; + butxo->deposit.txid = up2->U.txid; + butxo->deposit.vout = up2->U.vout; + butxo->deposit.value = up2->U.value; + butxo->S.satoshis = satoshis; +} + +void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp) +{ + if ( butxo != 0 ) + { + memset(butxo,0,sizeof(*butxo)); + butxo->pubkey = qp->srchash; + safecopy(butxo->coin,qp->srccoin,sizeof(butxo->coin)); + safecopy(butxo->coinaddr,qp->coinaddr,sizeof(butxo->coinaddr)); + butxo->payment.txid = qp->txid; + butxo->payment.vout = qp->vout; + //butxo->payment.value = qp->value; + butxo->iambob = 1; + butxo->deposit.txid = qp->txid2; + butxo->deposit.vout = qp->vout2; + //butxo->deposit.value = up2->U.value; + butxo->S.satoshis = qp->satoshis; + } + if ( autxo != 0 ) + { + memset(autxo,0,sizeof(*autxo)); + autxo->pubkey = qp->desthash; + safecopy(autxo->coin,qp->destcoin,sizeof(autxo->coin)); + safecopy(autxo->coinaddr,qp->destaddr,sizeof(autxo->coinaddr)); + autxo->payment.txid = qp->desttxid; + autxo->payment.vout = qp->destvout; + //autxo->payment.value = qp->value; + autxo->iambob = 0; + autxo->fee.txid = qp->feetxid; + autxo->fee.vout = qp->feevout; + //autxo->deposit.value = up2->U.value; + autxo->S.satoshis = qp->destsatoshis; + } +} + uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t desttxfee) { //printf("basesatoshis %.8f (rel %.8f / price %.8f)\n",dstr(SATOSHIDEN * ((relvolume) / price) + 2*txfee),relvolume,price); @@ -311,9 +360,10 @@ uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t d else return(0); } -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_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,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;//,*utmp; + struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; + memset(butxo,0,sizeof(*butxo)); targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee); targetval2 = (targetval / 8) * 9 + 2*txfee; if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 ) @@ -340,12 +390,13 @@ 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,targetval)) != 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)); - return(utxo); - } + return(butxo); + }*/ + LP_butxo_set(butxo,coin,up,up2,targetval); } } //else printf("cant find targetval2 %.8f\n",dstr(targetval2)); } //else printf("failed ratio test %.8f\n",(double)up->U.value/targetval); @@ -353,64 +404,21 @@ 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); } -void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp) -{ - if ( butxo != 0 ) - { - memset(butxo,0,sizeof(*butxo)); - butxo->pubkey = qp->srchash; - safecopy(butxo->coin,qp->srccoin,sizeof(butxo->coin)); - safecopy(butxo->coinaddr,qp->coinaddr,sizeof(butxo->coinaddr)); - butxo->payment.txid = qp->txid; - butxo->payment.vout = qp->vout; - //butxo->payment.value = qp->value; - butxo->iambob = 1; - butxo->deposit.txid = qp->txid2; - butxo->deposit.vout = qp->vout2; - //butxo->deposit.value = up2->U.value; - butxo->S.satoshis = qp->satoshis; - } - if ( autxo != 0 ) - { - memset(autxo,0,sizeof(*autxo)); - autxo->pubkey = qp->desthash; - safecopy(autxo->coin,qp->destcoin,sizeof(autxo->coin)); - safecopy(autxo->coinaddr,qp->destaddr,sizeof(autxo->coinaddr)); - autxo->payment.txid = qp->desttxid; - autxo->payment.vout = qp->destvout; - //autxo->payment.value = qp->value; - autxo->iambob = 0; - autxo->fee.txid = qp->feetxid; - autxo->fee.vout = qp->feevout; - //autxo->deposit.value = up2->U.value; - autxo->S.satoshis = qp->destsatoshis; - } -} - -int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *base,char *rel,double price,struct LP_quoteinfo *qp) +int32_t LP_connectstartbob(void *ctx,int32_t pubsock,cJSON *argjson,char *base,char *rel,double price,struct LP_quoteinfo *qp) { char pairstr[512]; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin; printf("LP_connectstartbob.(%s) with.(%s) %s\n",LP_myipaddr,jprint(argjson,0),LP_myipaddr); qp->quotetime = (uint32_t)time(NULL); - if ( (coin= LP_coinfind(utxo->coin)) == 0 ) + if ( (coin= LP_coinfind(qp->srccoin)) == 0 ) { - printf("cant find coin.%s\n",utxo->coin); + printf("cant find coin.%s\n",qp->srccoin); return(-1); } - 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 && + privkey = LP_privkey(coin->smartaddr,coin->taddr); + if ( bits256_nonz(privkey) != 0 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 ) { 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 ) @@ -421,45 +429,37 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 ) { swap->N.pair = pair; - utxo->S.swap = swap; - swap->utxo = utxo; + //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(qp); jaddstr(retjson,"method","connected"); jaddstr(retjson,"pair",pairstr); - //jaddnum(retjson,"requestid",qp->R.requestid); - //jaddnum(retjson,"quoteid",qp->R.quoteid); - // LP_addsig - char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,utxo->S.otherpubkey)); - LP_reserved_msg(1,base,rel,utxo->S.otherpubkey,jprint(retjson,0)); + char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,qp->desthash)); + LP_reserved_msg(1,base,rel,qp->desthash,jprint(retjson,0)); sleep(1); bits256 zero; memset(zero.bytes,0,sizeof(zero)); LP_reserved_msg(1,base,rel,zero,jprint(retjson,0)); - //LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->desthash,jprint(retjson,0)); free_json(retjson); retval = 0; } else printf("error launching swaploop\n"); } else printf("couldnt bind to any port %s\n",pairstr); } - else - { - printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(G.LP_mypub25519,qp->srchash) == 0); - } if ( retval < 0 ) { if ( pair >= 0 ) nn_close(pair); - LP_availableset(utxo); - } else LP_unavailableset(utxo,utxo->S.otherpubkey); - //LP_butxo_swapfields(utxo); + LP_availableset(qp->txid,qp->vout); + LP_availableset(qp->txid2,qp->vout2); + } return(retval); } char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration,uint32_t tradeid,bits256 destpubkey) { - struct LP_utxoinfo *aliceutxo; double price; //cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap; + struct LP_utxoinfo *aliceutxo; double price; if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 ) { char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); @@ -491,15 +491,20 @@ int32_t LP_quotecmp(struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2) else return(-1); } +void LP_alicequery_clear() +{ + memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); + memset(&LP_Alicedestpubkey,0,sizeof(LP_Alicedestpubkey)); + LP_Alicemaxprice = 0.; + Alice_expiration = 0; +} + int32_t LP_alice_eligible() { if ( Alice_expiration != 0 && time(NULL) > Alice_expiration ) { printf("time expired for Alice_request\n"); - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - memset(&LP_Alicedestpubkey,0,sizeof(LP_Alicedestpubkey)); - LP_Alicemaxprice = 0.; - Alice_expiration = 0; + LP_alicequery_clear(); } return(Alice_expiration == 0 || time(NULL) < Alice_expiration); } @@ -513,10 +518,7 @@ void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice*1.005 ) { qp->tradeid = LP_Alicequery.tradeid; - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - memset(&LP_Alicedestpubkey,0,sizeof(LP_Alicedestpubkey)); - LP_Alicemaxprice = 0.; - Alice_expiration = 0; + LP_alicequery_clear(); 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); @@ -543,19 +545,20 @@ char *LP_connectedalice(cJSON *argjson) // alice LP_aliceid(Q.tradeid,Q.aliceid,"error2",0,0); return(clonestr("{\"error\":\"cant find autxo\"}")); } - if ( autxo->S.swap != 0 ) + /*if ( autxo->S.swap != 0 ) { printf("ignore duplicate swap\n"); LP_aliceid(Q.tradeid,Q.aliceid,"error3",0,0); return(clonestr("{\"error\":\"ignore duplicate swap\"}")); - } + }*/ LP_aliceid(Q.tradeid,Q.aliceid,"connected",Q.R.requestid,Q.R.quoteid); butxo = &B; memset(butxo,0,sizeof(*butxo)); LP_abutxo_set(0,butxo,&Q); if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) { - LP_availableset(autxo); + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); LP_aliceid(Q.tradeid,Q.aliceid,"error4",0,0); printf("quote validate error %.0f\n",qprice); return(clonestr("{\"error\":\"quote validation error\"}")); @@ -563,7 +566,8 @@ 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); - LP_availableset(autxo); + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0); return(clonestr("{\"error\":\"no price set\"}")); } @@ -582,7 +586,8 @@ char *LP_connectedalice(cJSON *argjson) // alice if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q)) == 0 ) { jaddstr(retjson,"error","couldnt swapinit"); - LP_availableset(autxo); + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); LP_aliceid(Q.tradeid,Q.aliceid,"error7",Q.R.requestid,Q.R.quoteid); return(jprint(retjson,1)); } @@ -598,8 +603,8 @@ char *LP_connectedalice(cJSON *argjson) // alice //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); swap->tradeid = Q.tradeid; swap->N.pair = pairsock; - autxo->S.swap = swap; - swap->utxo = autxo; + //autxo->S.swap = swap; + //swap->utxo = autxo; LP_aliceid(Q.tradeid,Q.aliceid,"started",Q.R.requestid,Q.R.quoteid); printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock); if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 ) @@ -622,12 +627,16 @@ char *LP_connectedalice(cJSON *argjson) // alice } printf("connected result.(%s)\n",jprint(retjson,0)); if ( jobj(retjson,"error") != 0 ) - LP_availableset(autxo); + { + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); + } return(jprint(retjson,1)); } else { - LP_availableset(autxo); + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); LP_aliceid(Q.tradeid,Q.aliceid,"error11",0,0); printf("no privkey found coin.%s %s taddr.%u\n",Q.destcoin,Q.destaddr,coin->taddr); return(clonestr("{\"error\",\"no privkey\"}")); @@ -636,7 +645,7 @@ char *LP_connectedalice(cJSON *argjson) // alice int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag) { - int32_t i,v,numconfs,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; struct iguana_info *coin = LP_coinfind(symbol); + int32_t i,v,numconfs,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; uint32_t now; struct iguana_info *coin = LP_coinfind(symbol); if ( coin != 0 )//&& (IAMLP != 0 || coin->inactive == 0) ) { if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 ) @@ -657,6 +666,7 @@ int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag) { if ( (n= cJSON_GetArraySize(array)) > 0 ) { + now = (uint32_t)time(NULL); for (i=0; icoinaddr,coin->smartaddr) != 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 ) + char str[65]; + if ( bits256_nonz(Q.srchash) == 0 || bits256_cmp(Q.srchash,G.LP_mypub25519) == 0 ) + { + qprice = (double)Q.destsatoshis / Q.satoshis; + 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; + } else return(retval); + /*if ( bits256_nonz(Q.srchash) == 0 || bits256_cmp(Q.srchash,G.LP_mypub25519) == 0 || strcmp(butxo->coinaddr,coin->smartaddr) != 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 ) { qprice = (double)Q.destsatoshis / Q.satoshis; strcpy(Q.gui,G.gui); @@ -855,7 +875,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, else 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 return(retval); + } else return(retval);*/ if ( qprice > price ) { r = (rand() % 100); @@ -863,45 +883,33 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, price += (r * range) / 100.; bestprice = LP_bob_competition(&counter,aliceid,price,0); printf(">>>>>>>>>>>>> price %.8f qprice %.8f r.%d range %.8f -> %.8f, bestprice %.8f counter.%d\n",ask,qprice,r,range,price,bestprice,counter); - if ( counter > 5 || price > bestprice*1.1 ) + if ( counter > 5 || price > bestprice*1.1 ) // skip if late or bad price return(retval); } else return(retval); - //printf("recalc.%d address.(%s/%s) price %.8f request.(%s)\n",recalc,Q.coinaddr,coin->smartaddr,price,jprint(argjson,0)); - if ( recalc != 0 ) + LP_RTmetrics_update(Q.srccoin,Q.destcoin); + if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 ) { - 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); - } - 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; - Q.satoshis = butxo->S.satoshis; - printf("found %.8f -> %.8f newprice %.8f vs ask %.8f += %.8f qprice %.8f\n",dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,ask,price,qprice); - //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 %s/%s\n",Q.srccoin,Q.destcoin); - return(retval); - } + printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); + return(retval); } - } - else // "connect" - { - if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 ) + LP_address_utxo_reset(coin); + if ( (butxo= LP_address_myutxopair(butxo,1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) { - butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); // better work! - } else return(retval); + 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; + Q.satoshis = butxo->S.satoshis; + printf("found %.8f -> %.8f newprice %.8f vs ask %.8f += %.8f qprice %.8f\n",dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,ask,price,qprice); + } + else + { + printf("cant find utxopair aliceid.%llu %s/%s\n",(long long)aliceid,Q.srccoin,Q.destcoin); + return(retval); + } } if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 ) { @@ -923,55 +931,46 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s %.8f < %.8f\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin,qprice,(ask - 0.00000001) * 0.998); 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; + char str[65],str2[65]; printf("(%s/v%d %s/v%d) TRADECOMMAND.(%s)\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,jprint(argjson,0)); if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's { - if ( LP_isavailable(butxo) > 0 ) + if ( LP_allocated(Q.txid,Q.vout) == 0 && LP_allocated(Q.txid2,Q.vout2) == 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); + LP_unavailableset(Q.txid,Q.vout,Q.timestamp + LP_RESERVETIME,Q.desthash); + LP_unavailableset(Q.txid2,Q.vout2,Q.timestamp + LP_RESERVETIME,Q.desthash); + jaddnum(retjson,"quotetime",Q.quotetime); + jaddnum(retjson,"pending",Q.timestamp + LP_RESERVETIME); + jaddbits256(retjson,"desthash",Q.desthash); 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,ask,msg); - // LP_addsig - //msg2 = clonestr(msg); - LP_reserved_msg(1,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,clonestr(msg)); + printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",Q.timestamp + LP_RESERVETIME,qprice,ask,msg); + LP_reserved_msg(1,Q.srccoin,Q.destcoin,Q.desthash,clonestr(msg)); sleep(1); bits256 zero; memset(zero.bytes,0,sizeof(zero)); LP_reserved_msg(1,Q.srccoin,Q.destcoin,zero,msg); - //LP_reserved_msg(0,Q.srccoin,Q.destcoin,zero,msg); - //LP_broadcast_message(LP_mypubsock,Q.srccoin,Q.destcoin,Q.desthash,jprint(retjson,0)); free_json(retjson); + butxo->T.lasttime = (uint32_t)time(NULL); return(retval); - } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); + } else printf("request processing selected ineligible utxos?\n"); } else if ( strcmp(method,"connect") == 0 ) // bob { retval = 4; - if ( butxo->S.swap == 0 && butxo->T.swappending != 0 ) + if ( bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 || bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 ) + return(retval); + else if ( LP_reservation_check(Q.txid,Q.vout,Q.desthash) == 0 && LP_reservation_check(Q.txid2,Q.vout2,Q.desthash) == 0 ) { - // validate SPV alice - LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q); - //LP_butxo_swapfields_set(butxo); + LP_connectstartbob(ctx,pubsock,argjson,Q.srccoin,Q.destcoin,qprice,&Q); return(retval); - } - else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); + } else printf("connect message from non-reserved (%s)\n",jprint(argjson,0)); } - //LP_butxo_swapfields_set(butxo); } return(retval); } +#ifdef oldway struct LP_utxoinfo *LP_ordermatch_iter(struct LP_address_utxo **utxos,int32_t max,double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct iguana_info *basecoin,char *coinaddr,uint64_t asatoshis,double price,uint64_t txfee,uint64_t desttxfee,bits256 pubkey,char *gui) { uint64_t basesatoshis; struct LP_utxoinfo *bestutxo; @@ -1076,10 +1075,11 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); return(bestutxo); } +#endif 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,uint32_t nonce,bits256 destpubkey,uint32_t tradeid) { - uint64_t desttxfee,txfee; uint32_t lastnonce; int32_t i,maxiters,numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,B,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100]; + uint64_t desttxfee,txfee; uint32_t lastnonce; int64_t bestsatoshis=0,destsatoshis; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,B; struct LP_quoteinfo Q; bits256 pubkeys[100]; basecoin = LP_coinfind(base); relcoin = LP_coinfind(rel); if ( gui == 0 ) @@ -1111,12 +1111,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel } if ( time(NULL) < Alice_expiration ) return(clonestr("{\"error\":\"only one pending request at a time\"}")); - else - { - Alice_expiration = 0; - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - LP_Alicemaxprice = 0.; - } + else LP_alicequery_clear(); if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) return(clonestr("{\"error\":\"invalid parameter\"}")); if ( strcmp("BTC",rel) == 0 ) @@ -1155,7 +1150,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel int32_t changed; LP_mypriceset(&changed,autxo->coin,base,1. / maxprice); return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey)); - +#ifdef oldway LP_RTmetrics_update(base,rel); while ( 1 ) { @@ -1197,6 +1192,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey)); } return(clonestr("{\"error\":\"cant get here\"}")); +#endif } diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c index 6b5643bb6..fee4a1189 100644 --- a/iguana/exchanges/LP_signatures.c +++ b/iguana/exchanges/LP_signatures.c @@ -658,7 +658,7 @@ char *LP_uitem_recv(cJSON *argjson) { //char str[65]; printf("uitem %s %s %s/v%d %.8f ht.%d\n",symbol,coinaddr,bits256_str(str,txid),vout,dstr(value),height); if ( strcmp(coin->smartaddr,coinaddr) != 0 ) - LP_address_utxoadd("LP_uitem_recv",coin,coinaddr,txid,vout,value,height,-1); + LP_address_utxoadd((uint32_t)time(NULL),"LP_uitem_recv",coin,coinaddr,txid,vout,value,height,-1); //else printf("ignore external uitem %s %s\n",symbol,coin->smartaddr); } return(clonestr("{\"result\":\"success\"}")); @@ -676,11 +676,14 @@ void LP_listunspent_query(char *symbol,char *coinaddr) void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp) { - cJSON *reqjson; bits256 zero; char *msg,*msg2; int32_t flag = 0; struct LP_utxoinfo *utxo; + cJSON *reqjson; bits256 zero; char *msg,*msg2; int32_t flag = 0; if ( strcmp(method,"request") == 0 ) { - if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) - LP_unavailableset(utxo,qp->srchash); + if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 ) + { + LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); + LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); + } else { printf("couldnt find my txid to make request\n"); diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index f345e9ab6..870543904 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -303,7 +303,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep else { //printf("external unspent has no gettxout\n"); - flag += LP_address_utxoadd("electrum process",coin,coinaddr,txid,v,value,0,1); + flag += LP_address_utxoadd((uint32_t)time(NULL),"electrum process",coin,coinaddr,txid,v,value,0,1); } } else @@ -345,7 +345,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep if ( tx->height > 0 ) { //printf("from electrum_process_array\n"); - flag += LP_address_utxoadd("electrum process2",coin,coinaddr,txid,v,value,tx->height,-1); + flag += LP_address_utxoadd((uint32_t)time(NULL),"electrum process2",coin,coinaddr,txid,v,value,tx->height,-1); } //printf("v.%d numvouts.%d %.8f (%s)\n",v,tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0)); } //else printf("cant find tx\n"); @@ -544,7 +544,7 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON * if ( tx->height > 0 && tx->height != height ) printf("update %s height.%d <- %d\n",bits256_str(str,txid),tx->height,height); tx->height = height; - LP_address_utxoadd("electrum history",coin,addr,txid,0,0,height,-1); + LP_address_utxoadd((uint32_t)time(NULL),"electrum history",coin,addr,txid,0,0,height,-1); } } } diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index ce1b725da..03d08d69e 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -120,11 +120,21 @@ void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) void basilisk_swap_finished(struct basilisk_swap *swap) { int32_t i; - if ( swap->utxo != 0 && swap->sentflag == 0 ) + /*if ( swap->utxo != 0 && swap->sentflag == 0 ) { LP_availableset(swap->utxo); swap->utxo = 0; //LP_butxo_swapfields_set(swap->utxo); + }*/ + if ( swap->I.iambob != 0 ) + { + LP_availableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout); + LP_availableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout); + } + else + { + LP_availableset(swap->alicepayment.utxotxid,swap->alicepayment.utxovout); + LP_availableset(swap->myfee.utxotxid,swap->myfee.utxovout); } swap->I.finished = (uint32_t)time(NULL); // save to permanent storage diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 6e4642f3e..4d9ee5fe1 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -911,7 +911,7 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ if ( up == 0 ) { value = LP_txvalue(0,coin->symbol,utxotxid,utxovout); - LP_address_utxoadd("withdraw",coin,coin->smartaddr,utxotxid,utxovout,value,1,-1); + LP_address_utxoadd((uint32_t)time(NULL),"withdraw",coin,coin->smartaddr,utxotxid,utxovout,value,1,-1); //printf("added after not finding\n"); } if ( (up= LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout)) != 0 ) @@ -999,36 +999,6 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ return(n); } -struct LP_address *LP_address_utxo_reset(struct iguana_info *coin) -{ - struct LP_address *ap; int32_t i,n; cJSON *array,*item; int64_t value; bits256 txid; int32_t vout,height; - LP_listunspent_issue(coin->symbol,coin->smartaddr,2); - if ( (ap= LP_addressfind(coin,coin->smartaddr)) == 0 ) - { - printf("LP_createrawtransaction: cant find address data\n"); - return(0); - } - if ( (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) - { - ap->utxos = 0; - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; ismartaddr,txid,vout,value,height,-1); - } - } - free_json(array); - } - return(ap); -} - char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_info *coin,struct vin_info *V,int32_t max,bits256 privkey,cJSON *outputs,cJSON *vins,cJSON *privkeys,int64_t txfee,bits256 utxotxid,int32_t utxovout,uint32_t locktime) { static void *ctx; @@ -1077,7 +1047,12 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf return(0); } } - if ( (ap= LP_address_utxo_reset(coin)) == 0 ) + if ( bits256_nonz(utxotxid) == 0 ) + { + if ( (ap= LP_address_utxo_reset(coin)) == 0 ) + return(0); + } + else if ( (ap= LP_address(coin,coin->smartaddr)) == 0 ) return(0); memset(utxos,0,sizeof(utxos)); if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,max,ap,coin->smartaddr)) <= 0 ) diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 3257f6096..f8fab79a7 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -18,6 +18,124 @@ // marketmaker // + +struct LP_inuse_info +{ + bits256 txid,otherpub; + uint32_t expiration; + int32_t vout,ind; +} LP_inuse[1024]; +int32_t LP_numinuse; + +struct LP_inuse_info *_LP_inuse_find(bits256 txid,int32_t vout) +{ + int32_t i; + if ( bits256_nonz(txid) != 0 ) + { + for (i=0; iind; + *lp = LP_inuse[--LP_numinuse]; + lp->ind = ind; + memset(&LP_inuse[LP_numinuse],0,sizeof(struct LP_inuse_info)); + for (ind=0; indtxid = txid; + lp->vout = vout; + lp->expiration = expiration; + lp->otherpub = otherpub; + lp->ind = LP_numinuse++; + } + else + { + if ( bits256_nonz(otherpub) != 0 ) + lp->otherpub = otherpub; + if ( expiration > lp->expiration || expiration == 0 ) + lp->expiration = expiration; + } + return(lp); + } else printf("_LP_inuse_add [%d] overflow\n",LP_numinuse); + return(0); +} + +int32_t LP_reservation_check(bits256 txid,int32_t vout,bits256 pubkey) +{ + struct LP_inuse_info *lp; int32_t retval = -1; + if ( bits256_nonz(pubkey) != 0 ) + { + portable_mutex_lock(&LP_inusemutex); + if ( (lp= _LP_inuse_find(txid,vout)) != 0 ) + { + if ( bits256_cmp(lp->otherpub,pubkey) == 0 ) + retval = 0; + } + portable_mutex_unlock(&LP_inusemutex); + } + return(retval); +} + +uint32_t LP_allocated(bits256 txid,int32_t vout) +{ + struct LP_inuse_info *lp; uint32_t now,duration = 0; + now = (uint32_t)time(NULL); + portable_mutex_lock(&LP_inusemutex); + if ( (lp= _LP_inuse_find(txid,vout)) != 0 ) + { + if ( lp->expiration != 0 && now < lp->expiration ) + duration = (lp->expiration - now); + } + portable_mutex_unlock(&LP_inusemutex); + return(duration); +} + +void LP_unavailableset(bits256 txid,int32_t vout,uint32_t expiration,bits256 otherpub) +{ + portable_mutex_lock(&LP_inusemutex); + _LP_inuse_add(expiration,otherpub,txid,vout); + portable_mutex_unlock(&LP_inusemutex); +} + +void LP_availableset(bits256 txid,int32_t vout) +{ + portable_mutex_lock(&LP_inusemutex); + _LP_inuse_delete(txid,vout); + portable_mutex_unlock(&LP_inusemutex); +} + +int32_t LP_isavailable(struct LP_utxoinfo *utxo) +{ + struct _LP_utxoinfo u; + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + if ( LP_allocated(utxo->payment.txid,utxo->payment.vout) == 0 && LP_allocated(u.txid,u.vout) == 0 ) + return(1); + else return(0); +} + uint64_t LP_value_extract(cJSON *obj,int32_t addinterest) { double val = 0.; uint64_t value = 0; int32_t electrumflag; @@ -116,36 +234,9 @@ int32_t LP_address_minmax(uint64_t *balancep,uint64_t *minp,uint64_t *maxp,struc return(n); } -struct LP_utxoinfo *LP_allocated(bits256 txid,int32_t vout) -{ - struct LP_utxoinfo *utxo; - if ( (utxo= _LP_utxofind(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) - { - //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); - return(utxo); - } - if ( (utxo= _LP_utxo2find(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) - { - //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); - return(utxo); - } - if ( (utxo= _LP_utxofind(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) - { - //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); - return(utxo); - } - if ( (utxo= _LP_utxo2find(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) - { - //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); - return(utxo); - } - return(0); -} - 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; - //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); LP_listunspent_issue(coin->symbol,coin->smartaddr,2); @@ -189,7 +280,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a continue; } } - if ( LP_allocated(up->U.txid,up->U.vout) == 0 )//&& (iambob == 0 || (_LP_utxofind(iambob,up->U.txid,up->U.vout) == 0 && _LP_utxo2find(iambob,up->U.txid,up->U.vout) == 0)) ) + if ( LP_allocated(up->U.txid,up->U.vout) == 0 ) { utxos[n++] = up; if ( n >= max ) @@ -239,7 +330,7 @@ void LP_mark_spent(char *symbol,bits256 txid,int32_t vout) } } -int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight) +int32_t LP_address_utxoadd(uint32_t timestamp,char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight) { struct LP_address *ap; cJSON *txobj; struct LP_transaction *tx; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; //char str[65]; if ( coin == 0 ) @@ -262,6 +353,7 @@ int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,b up->spendheight = spendheight, flag |= 4; if ( value != 0 && up->U.value == 0 && up->U.value != value ) up->U.value = value, flag |= 8; + up->timestamp = timestamp; //printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value)); break; } @@ -282,21 +374,61 @@ int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,b up->U.height = height; up->U.value = value; up->spendheight = spendheight; - portable_mutex_lock(&coin->addrmutex); - DL_APPEND(ap->utxos,up); - portable_mutex_unlock(&coin->addrmutex); + up->timestamp = timestamp; retval = 1; if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->SPV > 0 ) { up->SPV = tx->SPV; //printf("%s ADD UTXO >> %s %s %s/v%d ht.%d %.8f\n",debug,coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value)); } + portable_mutex_lock(&coin->addrmutex); + DL_APPEND(ap->utxos,up); + portable_mutex_unlock(&coin->addrmutex); } } // else printf("cant get ap %s %s\n",coin->symbol,coinaddr); //printf("done %s add addr.%s ht.%d\n",coin->symbol,coinaddr,height); return(retval); } +struct LP_address *LP_address_utxo_reset(struct iguana_info *coin) +{ + struct LP_address *ap; struct LP_address_utxo *up,*tmp; int32_t i,n,vout,height; cJSON *array,*item; int64_t value; bits256 txid; uint32_t now; + LP_listunspent_issue(coin->symbol,coin->smartaddr,2); + if ( (ap= LP_addressfind(coin,coin->smartaddr)) == 0 ) + { + printf("LP_createrawtransaction: cant find address data\n"); + return(0); + } + if ( (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) + { + //ap->utxos = 0; + now = (uint32_t)time(NULL); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ismartaddr,txid,vout,value,height,-1); + } + } + free_json(array); + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( up->timestamp < now ) + { + char str[65]; printf("purge %s/v%d as it wasnt in listunspent\n",bits256_str(str,up->U.txid),up->U.vout); + up->spendheight = 1; + } + } + } + return(ap); +} + cJSON *LP_address_item(struct iguana_info *coin,struct LP_address_utxo *up,int32_t electrumret) { cJSON *item = cJSON_CreateObject(); @@ -422,7 +554,7 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) { - int32_t i,n,v,ht,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid; + int32_t i,n,v,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid; if ( (n= cJSON_GetArraySize(array)) <= 0 ) return(0); //printf("%s %s LP_unspents.(%s)\n",coin->symbol,coinaddr,jprint(array,0)); @@ -442,7 +574,7 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) char str[65]; printf("REJECT %s %s/v%d value.%llu vs %llu (%s)\n",coin->symbol,bits256_str(str,txid),v,(long long)value,(long long)val,jprint(txobj,0)); errs++; } - ht = LP_txheight(coin,txid); + //ht = LP_txheight(coin,txid); //if ( coin->height != 0 ) // ht = LP_getheight(coin) - jint(txobj,"confirmations") + 1; //else ht = 0; @@ -456,7 +588,7 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) if ( errs == 0 ) { //printf("from LP_unspents_array\n"); - LP_address_utxoadd("LP_unspents_array",coin,coinaddr,txid,v,val,height,-1); + LP_address_utxoadd((uint32_t)time(NULL),"LP_unspents_array",coin,coinaddr,txid,v,val,height,-1); count++; } } @@ -580,7 +712,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest"); LP_destaddr(tx->outpoints[i].coinaddr,vout); //printf("from transaction init %s %s %s/v%d <- %.8f\n",coin->symbol,tx->outpoints[i].coinaddr,bits256_str(str,txid),i,dstr(tx->outpoints[i].value)); - LP_address_utxoadd("LP_transactioninit iter0",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); + LP_address_utxoadd((uint32_t)time(NULL),"LP_transactioninit iter0",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); } //printf("numvouts.%d\n",numvouts); } @@ -602,7 +734,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS tx->outpoints[spentvout].spendtxid = txid; tx->outpoints[spentvout].spendvini = i; tx->outpoints[spentvout].spendheight = height > 0 ? height : 1; - LP_address_utxoadd("LP_transactioninit iter1",coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1); + LP_address_utxoadd((uint32_t)time(NULL),"LP_transactioninit iter1",coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1); if ( 0 && strcmp(coin->symbol,"REVS") == 0 ) printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height); } diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index b24c47ff3..c09e7e6c4 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -19,8 +19,6 @@ // - - int32_t LP_ismine(struct LP_utxoinfo *utxo) { if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 0 ) @@ -28,15 +26,6 @@ int32_t LP_ismine(struct LP_utxoinfo *utxo) else return(0); } -int32_t LP_isavailable(struct LP_utxoinfo *utxo) -{ - if ( time(NULL) > utxo->T.swappending ) - utxo->T.swappending = 0; - if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 ) - return(1); - else return(0); -} - int32_t LP_isunspent(struct LP_utxoinfo *utxo) { struct LP_address_utxo *up; struct _LP_utxoinfo u; struct iguana_info *coin; @@ -88,6 +77,41 @@ int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo * return(n); } +/*uint32_t LP_allocated(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo; + if ( (utxo= _LP_utxofind(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxofind(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + return(0); +} + +int32_t LP_isavailable(struct LP_utxoinfo *utxo) +{ + if ( time(NULL) > utxo->T.swappending ) + utxo->T.swappending = 0; + if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 ) + return(1); + else return(0); +} + int32_t LP_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo) { int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u; @@ -170,6 +194,7 @@ void LP_availableset(struct LP_utxoinfo *utxo) } } } +*/ cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) { @@ -208,8 +233,8 @@ cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) 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->S.swap != 0 ) + // jaddstr(item,"swap","in progress"); if ( utxo->T.spentflag != 0 ) jaddnum(item,"spent",utxo->T.spentflag); jaddnum(item,"session",utxo->T.sessionid); @@ -235,7 +260,6 @@ struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) printf("LP_utxo_bestfit error symbol.%p %.8f\n",symbol,dstr(destsatoshis)); return(0); } - // jl777 remove mempool HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) { if ( strcmp(symbol,utxo->coin) != 0 )