Browse Source

Merge branch 'dev' of https://github.com/jl777/SuperNET into dev-decker-dev

etomic
DeckerSU 7 years ago
parent
commit
a51bd62cb9
  1. 4
      iguana/exchanges/LP_cache.c
  2. 17
      iguana/exchanges/LP_include.h
  3. 16
      iguana/exchanges/LP_nativeDEX.c
  4. 36
      iguana/exchanges/LP_network.c
  5. 388
      iguana/exchanges/LP_ordermatch.c
  6. 2
      iguana/exchanges/LP_rpc.c
  7. 11
      iguana/exchanges/LP_signatures.c
  8. 10
      iguana/exchanges/LP_socket.c
  9. 35
      iguana/exchanges/LP_statemachine.c
  10. 12
      iguana/exchanges/LP_swap.c
  11. 41
      iguana/exchanges/LP_transaction.c
  12. 247
      iguana/exchanges/LP_utxo.c
  13. 54
      iguana/exchanges/LP_utxos.c

4
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; i<numvins; i++)
{
@ -76,7 +76,7 @@ struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 tx
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);
}

17
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 <emscripten.h>
@ -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
@ -81,7 +82,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 1000
#define LP_MINCLIENTVOL 100
#define LP_MINSIZE_TXFEEMULT 10
#define LP_REQUIRED_TXFEE 0.8
@ -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);

16
iguana/exchanges/LP_nativeDEX.c

@ -17,8 +17,10 @@
// LP_nativeDEX.c
// marketmaker
//
// single utxo allocations, reject result, latency
// single utxo allocations alice, reject result, latency
// alice waiting for bestprice
//if ( G.LP_pendingswaps != 0 )
//return(-1);
// bot safe to exit?
//
// BCH signing
@ -78,7 +80,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];
@ -87,6 +89,7 @@ struct LP_forwardinfo *LP_forwardinfos;
struct iguana_info *LP_coins;
struct LP_pubkeyinfo *LP_pubkeyinfos;
struct rpcrequest_info *LP_garbage_collector;
struct LP_address_utxo *LP_garbage_collector2;
//uint32_t LP_deadman_switch;
@ -312,8 +315,9 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,
}
//printf("%.3f %s LP_command_process\n",OS_milliseconds()-millis,jstr(argjson,"method"));
}
free_json(argjson);
}
if ( argjson != 0 )
free_json(argjson);
}
} //else printf("DUPLICATE.(%s)\n",(char *)ptr);
portable_mutex_unlock(&LP_commandmutex);
@ -335,6 +339,7 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
pfd.events = NN_POLLIN;
if ( nn_poll(&pfd,1,1) != 1 )
break;
ptr = 0;
if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
methodstr[0] = 0;
@ -384,9 +389,9 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
free(str);
}
}
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
}
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
}
}
return(nonz);
@ -923,6 +928,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);

36
iguana/exchanges/LP_network.c

@ -267,9 +267,9 @@ int32_t LP_peerindsock(int32_t *peerindp)
void gc_loop(void *arg)
{
struct rpcrequest_info *req,*rtmp; int32_t flag = 0;
uint32_t now; struct LP_address_utxo *up,*utmp; struct rpcrequest_info *req,*rtmp; int32_t flag = 0;
strcpy(LP_gcloop_stats.name,"gc_loop");
LP_gcloop_stats.threshold = 1100.;
LP_gcloop_stats.threshold = 11000.;
while ( 1 )
{
flag = 0;
@ -282,10 +282,21 @@ void gc_loop(void *arg)
free(req);
flag++;
}
now = (uint32_t)time(NULL);
DL_FOREACH_SAFE(LP_garbage_collector2,up,utmp)
{
if ( now > (uint32_t)up->spendheight+120 )
{
DL_DELETE(LP_garbage_collector2,up);
//char str[65]; printf("garbage collect %s/v%d lag.%d\n",bits256_str(str,up->U.txid),up->U.vout,now-up->spendheight);
free(up);
}
flag++;
}
portable_mutex_unlock(&LP_gcmutex);
if ( 0 && flag != 0 )
printf("gc_loop.%d\n",flag);
sleep(1);
sleep(10);
}
}
@ -563,12 +574,19 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w
else if ( (pfds[n].revents & POLLIN) != 0 )
{
printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr);
buf = 0;
if ( (size= nn_recv(ptr->publicsock,&buf,NN_MSG,0)) > 0 )
{
ptr->lasttime = now;
sendsock = ptr->sendsock;
break;
}
else if ( buf != 0 )
{
nn_freemsg(buf);
buf = 0;
size = 0;
}
}
}
n++;
@ -595,12 +613,12 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w
sendsock = ptr->publicsock;
break;
}
else
{
nn_freemsg(buf);
buf = 0;
size = 0;
}
}
if ( buf != 0 )
{
nn_freemsg(buf);
buf = 0;
size = 0;
}
}
}

388
iguana/exchanges/LP_ordermatch.c

@ -275,7 +275,7 @@ int32_t LP_nanobind(void *ctx,char *pairstr)
int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_address_utxo **utxos,int32_t n,uint64_t targetval)
{
int32_t i,mini = -1; struct LP_address_utxo *up; struct electrum_info *backupep=0,*ep; int64_t dist; uint64_t mindist = (1LL << 60);
int32_t i,replacei,bestheight,mini = -1; struct LP_address_utxo *up,*bestup; struct electrum_info *backupep=0,*ep; int64_t dist,bestdist; uint64_t mindist = (1LL << 60);
if ( (ep= coin->electrum) != 0 )
{
if ( (backupep= ep->prev) == 0 )
@ -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;
@ -299,70 +299,49 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_a
}
}
}
//printf("return mini.%d\n",mini);
return(mini);
}
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);
if ( relvolume > dstr(desttxfee) && price > SMALLVAL )
return(SATOSHIDEN * (relvolume / price) + 2*txfee);
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_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 ( mini >= 0 && (bestup= utxos[mini]) != 0 )
{
if ( (m= LP_address_utxo_ptrs(coin,iambob,utxos,max,ap,coinaddr)) > 1 )
bestdist = (bestup->U.value - targetval);
replacei = -1;
bestheight = bestup->U.height;
for (i=0; i<n; i++)
{
if ( 0 )
if ( i != mini && (up= utxos[i]) != 0 )
{
int32_t i;
for (i=0; i<m; i++)
printf("%.8f ",dstr(utxos[i]->U.value));
printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s\n",dstr(targetval),relvolume,price,dstr(txfee),coinaddr);
}
mini = -1;
if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval)) >= 0 )
{
up = utxos[mini];
utxos[mini] = 0;
//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 )
dist = (up->U.value - targetval);
if ( dist > 0 && up->U.height < bestheight )
{
if ( (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,(targetval2+2*txfee) * 1.01)) >= 0 )
if ( (double)dist/bestdist < sqrt(bestheight - up->U.height) )
{
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 )
{
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);
}
}
} //else printf("cant find targetval2 %.8f\n",dstr(targetval2));
} //else printf("failed ratio test %.8f\n",(double)up->U.value/targetval);
} else if ( targetval != 0 && mini >= 0 )
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 )
replacei = i;
bestheight = up->U.height;
} //else printf("almost ratio %.3f dist %.8f vs best %.8f, ht %d vs best ht %d\n",(double)dist/bestdist,dstr(dist),dstr(bestdist),up->U.height,bestheight);
}
}
}
if ( replacei >= 0 )
{
utxo->S.satoshis = targetval;
printf("backup method found utxo!\n");
return(utxo);
printf("REPLACE bestdist %.8f height %d with dist %.8f height %d\n",dstr(bestdist),bestup->U.height,dstr(utxos[replacei]->U.value - targetval),utxos[replacei]->U.height);
return(replacei);
}
}*/
return(0);
}
//printf("return mini.%d\n",mini);
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)
@ -399,18 +378,75 @@ void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP
}
}
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)
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);
if ( relvolume > dstr(desttxfee) && price > SMALLVAL )
return(SATOSHIDEN * (relvolume / price) + 2*txfee);
else return(0);
}
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;
memset(butxo,0,sizeof(*butxo));
targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee);
targetval2 = (targetval / 8) * 9 + 2*txfee;
if ( coin != 0 && (ap= LP_address(coin,coinaddr)) != 0 )
{
if ( (m= LP_address_utxo_ptrs(coin,iambob,utxos,max,ap,coinaddr)) > 1 )
{
if ( 1 )
{
int32_t i;
for (i=0; i<m; i++)
if ( utxos[i]->U.value >= targetval )
printf("%.8f ",dstr(utxos[i]->U.value));
printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s %s\n",dstr(targetval),relvolume,price,dstr(txfee),coin->symbol,coinaddr);
}
mini = -1;
if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval)) >= 0 )
{
up = utxos[mini];
utxos[mini] = 0;
//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 )
{
if ( (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,(targetval2+2*txfee) * 1.01)) >= 0 )
{
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 )
{
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(butxo);
}*/
LP_butxo_set(butxo,coin,up,up2,targetval);
return(butxo);
}
} else printf("cant find targetval2 %.8f\n",dstr(targetval2));
} else printf("failed ratio test %.8f\n",(double)up->U.value/targetval);
} else if ( targetval != 0 && mini >= 0 )
printf("targetval %.8f mini.%d\n",dstr(targetval),mini);
} else printf("no %s utxos pass LP_address_utxo_ptrs filter\n",coinaddr);
} else printf("address_myutxopair couldnt find %s %s\n",coin->symbol,coinaddr);
return(0);
}
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 +457,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 +519,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);
}
@ -510,13 +543,10 @@ 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*1.005 )
if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice )
{
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 +573,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 +594,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 +614,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 +631,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 +655,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 +673,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 +694,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; i<n; i++)
{
item = jitem(array,i);
@ -665,7 +703,7 @@ int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag)
value = LP_value_extract(item,0);
height = LP_txheight(coin,txid);
//char str[65]; printf("LP_listunspent_both: %s/v%d ht.%d %.8f\n",bits256_str(str,txid),v,height,dstr(value));
LP_address_utxoadd("LP_listunspent_both",coin,coinaddr,txid,v,value,height,-1);
LP_address_utxoadd(now,"LP_listunspent_both",coin,coinaddr,txid,v,value,height,-1);
}
}
}
@ -713,7 +751,7 @@ int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
{
char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t aliceid,value,value2; cJSON *retjson; double qprice,range,bestprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t r,counter,retval = -1,recalc,max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t aliceid; cJSON *retjson; double qprice,range,bestprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t r,counter,retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"reserved") == 0 ||strcmp(method,"connected") == 0 || strcmp(method,"request") == 0 || strcmp(method,"connect") == 0) )
{
// LP_checksig
@ -761,7 +799,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
return(retval);
}
LP_aliceid(Q.tradeid,Q.aliceid,"reserved",0,0);
printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
//printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
if ( (retstr= LP_quotereceived(argjson)) != 0 )
free(retstr);
LP_reserved(ctx,myipaddr,pubsock,&Q);
@ -801,7 +839,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
return(retval);
}
price = ask;
printf("MYPRICE %s/%s %.8f vs qprice %.8f\n",Q.srccoin,Q.destcoin,price,qprice);
//printf("MYPRICE %s/%s %.8f vs qprice %.8f\n",Q.srccoin,Q.destcoin,price,qprice);
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));
@ -819,9 +857,8 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
}
if ( strcmp(method,"request") == 0 )
{
char str[65];//,str2[65];
recalc = 0;
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 )
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);
@ -831,30 +868,6 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
memset(&Q.txid,0,sizeof(Q.txid));
memset(&Q.txid2,0,sizeof(Q.txid2));
Q.vout = Q.vout2 = -1;
recalc = 1;
}
else if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL )
recalc = 1;
else if ( price < qprice )
{
char tmp[64];
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;
//printf("price %.8f qprice %.8f\n",price,qprice);
if ( recalc == 0 )
{
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,Q.satoshis)) == 0 )
recalc = 1;
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);
if ( qprice > price )
{
@ -863,45 +876,38 @@ 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);
}
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 )
{
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 %.8f -> relvol %.8f\n",(long long)aliceid,Q.srccoin,Q.destcoin,dstr(LP_basesatoshis(dstr(Q.destsatoshis),price,Q.txfee,Q.desttxfee)),dstr(Q.destsatoshis));
return(retval);
}
}
else // "connect"
else if ( strcmp(method,"connect") == 0 )
{
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 ( bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 || bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 )
return(retval);
}
if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 )
{
@ -923,55 +929,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 *astr = jprint(argjson,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,astr);
free(astr);
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 ( 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 +1073,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 +1109,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 +1148,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 +1190,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
}

2
iguana/exchanges/LP_rpc.c

@ -544,7 +544,7 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
return(retjson);
}
}
printf("couldnt find %s (%s) %s/v%d\n",symbol,coinaddr,bits256_str(str,txid),vout);
//printf("couldnt find %s (%s) %s/v%d\n",symbol,coinaddr,bits256_str(str,txid),vout);
return(cJSON_Parse("{\"error\":\"couldnt get tx\"}"));
}
}

11
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");

10
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);
}
}
}
@ -578,8 +578,8 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON
cJSON *retjson=0; char *retstr; struct LP_address *ap; struct iguana_info *coin; int32_t updatedflag,height,usecache=1;
if ( (coin= LP_coinfind(symbol)) == 0 )
return(0);
//if ( strcmp(addr,INSTANTDEX_KMD) == 0 )
// return(cJSON_Parse("[]"));
if ( strcmp(addr,INSTANTDEX_KMD) == 0 )
return(cJSON_Parse("[]"));
if ( ep == 0 || ep->heightp == 0 )
height = coin->longestchain;
else height = *(ep->heightp);

35
iguana/exchanges/LP_statemachine.c

@ -1704,6 +1704,41 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu
}
portable_mutex_unlock(&myinfo->DEX_swapmutex);
}*/
/*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);
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;
}
else if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL )
recalc = 1;
else if ( price < qprice )
{
char tmp[64];
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;
//printf("price %.8f qprice %.8f\n",price,qprice);
if ( recalc == 0 )
{
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,Q.satoshis)) == 0 )
recalc = 1;
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);*/
/*int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double origprice)
{

12
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

41
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; i<n; i++)
{
//{"tx_hash":"38d1b7c73015e1b1d6cb7fc314cae402a635b7d7ea294970ab857df8777a66f4","tx_pos":0,"height":577975,"value":238700}
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
LP_address_utxoadd("withdraw",coin,coin->smartaddr,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,8 +1047,13 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
return(0);
}
}
if ( (ap= LP_address_utxo_reset(coin)) == 0 )
return(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 )
{

247
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; i<LP_numinuse; i++)
if ( vout == LP_inuse[i].vout && bits256_cmp(LP_inuse[i].txid,txid) == 0 )
return(&LP_inuse[i]);
}
return(0);
}
int32_t _LP_inuse_delete(bits256 txid,int32_t vout)
{
struct LP_inuse_info *lp; int32_t ind;
if ( (lp= _LP_inuse_find(txid,vout)) != 0 )
{
ind = lp->ind;
*lp = LP_inuse[--LP_numinuse];
lp->ind = ind;
memset(&LP_inuse[LP_numinuse],0,sizeof(struct LP_inuse_info));
for (ind=0; ind<LP_numinuse; ind++)
if ( LP_inuse[ind].ind != ind )
printf("ind.%d of %d: mismatched ind.%d\n",ind,LP_numinuse,LP_inuse[ind].ind);
}
//char str[65]; printf("_LP_inuse_delete cant find %s/v%d\n",bits256_str(str,txid),vout);
return(-1);
}
struct LP_inuse_info *_LP_inuse_add(uint32_t expiration,bits256 otherpub,bits256 txid,int32_t vout)
{
struct LP_inuse_info *lp;
if ( bits256_nonz(txid) != 0 && LP_numinuse < sizeof(LP_inuse)/sizeof(*LP_inuse) )
{
if ( (lp= _LP_inuse_find(txid,vout)) == 0 )
{
lp = &LP_inuse[LP_numinuse];
memset(lp,0,sizeof(*lp));
lp->txid = 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,43 +234,16 @@ 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);
portable_mutex_lock(&LP_utxomutex);
//LP_listunspent_issue(coin->symbol,coin->smartaddr,2);
//portable_mutex_lock(&LP_utxomutex);
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
//char str[65]; printf("LP_address_utxo_ptrs %s n.%d %.8f %s v%d spendheight.%d allocated.%p\n",ap->coinaddr,n,dstr(up->U.value),bits256_str(str,up->U.txid),up->U.vout,up->spendheight,LP_allocated(up->U.txid,up->U.vout));
//char str[65]; printf("LP_address_utxo_ptrs %s n.%d %.8f %s v%d spendheight.%d allocated.%d\n",ap->coinaddr,n,dstr(up->U.value),bits256_str(str,up->U.txid),up->U.vout,up->spendheight,LP_allocated(up->U.txid,up->U.vout));
if ( up->spendheight <= 0 && LP_RTmetrics_avoidtxid(up->U.txid) < 0 )
{
if ( coin->electrum == 0 )
@ -189,12 +280,12 @@ 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 )
break;
}
} //else printf("LP_allocated skip\n");
}
else
{
@ -202,8 +293,8 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a
tx->outpoints[up->U.vout].spendheight = 1;
}
}
portable_mutex_unlock(&LP_utxomutex);
//printf("return n.%d\n",n);
//portable_mutex_unlock(&LP_utxomutex);
//printf("return n.%d for %s %s\n",n,coin->symbol,coinaddr);
return(n);
}
@ -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,7 +353,8 @@ 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;
//printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
//up->timestamp = timestamp;
//char str[65]; printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
break;
}
}
@ -272,7 +364,7 @@ int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,b
{
if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) == 0 )
{
//printf("prevent utxoadd since gettxout %s %s %s/v%d missing\n",coin->symbol,coinaddr,bits256_str(str,txid),vout);
//char str[65]; printf("prevent utxoadd since gettxout %s %s %s/v%d missing\n",coin->symbol,coinaddr,bits256_str(str,txid),vout);
return(0);
} else free_json(txobj);
}
@ -282,21 +374,79 @@ 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));
}
char str[65];
if ( 0 && strcmp(coin->smartaddr,coinaddr) == 0 && strcmp("KMD",coin->symbol) == 0 )
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_address(coin,coin->smartaddr);
LP_listunspent_issue(coin->symbol,coin->smartaddr,2);
if ( (ap= LP_addressfind(coin,coin->smartaddr)) == 0 )
{
printf("LP_address_utxo_reset: cant find address data\n");
return(0);
}
if ( (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 )
{
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
portable_mutex_lock(&coin->addrmutex);
DL_DELETE(ap->utxos,up);
portable_mutex_unlock(&coin->addrmutex);
portable_mutex_lock(&LP_gcmutex);
up->spendheight = (int32_t)time(NULL);
DL_APPEND(LP_garbage_collector2,up);
portable_mutex_unlock(&LP_gcmutex);
}
now = (uint32_t)time(NULL);
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
char str[65];
for (i=0; i<n; i++)
{
//{"tx_hash":"38d1b7c73015e1b1d6cb7fc314cae402a635b7d7ea294970ab857df8777a66f4","tx_pos":0,"height":577975,"value":238700}
item = jitem(array,i);
if ( coin->electrum != 0 )
{
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
}
else
{
txid = jbits256(item,"txid");
vout = juint(item,"vout");
value = LP_value_extract(item,0);
height = LP_txheight(coin,txid);
}
LP_address_utxoadd(now,"withdraw",coin,coin->smartaddr,txid,vout,value,height,-1);
if ( (up= LP_address_utxofind(coin,coin->smartaddr,txid,vout)) == 0 )
printf("couldnt find just added %s/%d ht.%d %.8f\n",bits256_str(str,txid),vout,height,dstr(value));
}
//printf("added %d from listunspents\n",n);
}
free_json(array);
}
return(ap);
}
cJSON *LP_address_item(struct iguana_info *coin,struct LP_address_utxo *up,int32_t electrumret)
{
cJSON *item = cJSON_CreateObject();
@ -345,7 +495,10 @@ cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrum
}
if ( up->spendheight <= 0 && up->U.value != 0 )
{
if ( coin->electrum == 0 || up->SPV > 0 )
char str[65];
if ( LP_allocated(up->U.txid,up->U.vout) != 0 )
printf("%s %s/v%d allocated\n",coin->symbol,bits256_str(str,up->U.txid),up->U.vout);
else if ( coin->electrum == 0 || up->SPV > 0 )
{
jaddi(array,LP_address_item(coin,up,electrumret));
n++;
@ -422,7 +575,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 +595,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 +609,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 +733,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 +755,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);
}

54
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 )
@ -492,7 +516,7 @@ cJSON *LP_inventory(char *symbol)
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2));
//printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2));
continue;
}
//if ( iambob != 0 )

Loading…
Cancel
Save