Browse Source

Merge pull request #466 from jl777/spvdex

Spvdex
etomic
jl777 7 years ago
committed by GitHub
parent
commit
100bf3b5ea
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      iguana/exchanges/LP_cache.c
  2. 8
      iguana/exchanges/LP_include.h
  3. 14
      iguana/exchanges/LP_nativeDEX.c
  4. 330
      iguana/exchanges/LP_ordermatch.c
  5. 16
      iguana/exchanges/LP_prices.c
  6. 12
      iguana/exchanges/LP_socket.c
  7. 7
      iguana/exchanges/LP_swap.c
  8. 5
      iguana/exchanges/LP_transaction.c
  9. 78
      iguana/exchanges/LP_utxo.c
  10. 64
      iguana/exchanges/LP_utxos.c

10
iguana/exchanges/LP_cache.c

@ -45,9 +45,9 @@ struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 tx
vins = jarray(&numvins,txobj,"vin");
vouts = jarray(&numvouts,txobj,"vout");
tx = LP_transactionadd(coin,txid,height,numvouts,numvins);
tx->serialized = 0;
tx->serialized = serialized;
//free(serialized);
tx->fpos = fpos;
free(serialized);
tx->len = tx->len;
tx->SPV = tx->height = height;
//printf("tx.%s numvins.%d numvouts.%d\n",bits256_str(str,txid),numvins,numvouts);
@ -228,12 +228,12 @@ bits256 LP_merkleroot(struct iguana_info *coin,struct electrum_info *ep,int32_t
return(merkleroot);
}
int32_t LP_merkleproof(struct iguana_info *coin,struct electrum_info *ep,bits256 txid,int32_t height)
int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height)
{
struct LP_transaction *tx=0; cJSON *merkobj,*merkles,*retjson; bits256 roothash,merkleroot; int32_t m,SPV = 0;
if ( height < 0 )
if ( height <= 0 )
return(0);
if ( (tx= LP_transactionfind(coin,txid)) == 0)
if ( (tx= LP_transactionfind(coin,txid)) == 0 && strcmp(coinaddr,coin->smartaddr) == 0 )
{
if ( (retjson= electrum_transaction(coin->symbol,ep,&retjson,txid)) != 0 )
free_json(retjson);

8
iguana/exchanges/LP_include.h

@ -23,7 +23,7 @@
#define LP_MAJOR_VERSION "0"
#define LP_MINOR_VERSION "1"
#define LP_BUILD_NUMBER "11843"
#define LP_BUILD_NUMBER "14288"
#ifdef FROM_JS
#include <emscripten.h>
@ -43,7 +43,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define LP_MAXVINS 64
#define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL)
#define LP_AUTOTRADE_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 40
#define ELECTRUM_TIMEOUT 7
#define LP_ELECTRUM_KEEPALIVE 60
#define LP_ELECTRUM_MAXERRORS 777
@ -428,7 +428,9 @@ int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,cha
struct iguana_info *LP_coinfind(char *symbol);
int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32);
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price);
int32_t LP_merkleproof(struct iguana_info *coin,struct electrum_info *ep,bits256 txid,int32_t height);
int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height);
int32_t _LP_utxos_remove(bits256 txid,int32_t vout);
int32_t LP_utxos_remove(bits256 txid,int32_t vout);
struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins);
void LP_tradebot_finished(uint32_t tradeid,uint32_t requestid,uint32_t quoteid);
uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen);

14
iguana/exchanges/LP_nativeDEX.c

@ -18,10 +18,8 @@
// LP_nativeDEX.c
// marketmaker
//
// version info
// immediate "request", actual auction
// previously, it used to show amount, kmd equiv, perc
// swap started, pending, locked, finished, ...
// aliceid
//there is still a pending one with `-1 wait for bobpayment bYoNxkfvwQ42Yufry8J5y8BYi6mQxokvW9 numconfs.1 MNZ c0ea4aa808a653222a15122d96692fecf734dbbacfb9a54cb4711306ea0c3cef`, but that tx is already spent including 6 confirmation
// bot safe to exit?
//
@ -457,7 +455,7 @@ void command_rpcloop(void *myipaddr)
void utxosQ_loop(void *myipaddr)
{
strcpy(utxosQ_loop_stats.name,"utxosQ_loop");
utxosQ_loop_stats.threshold = 500.;
utxosQ_loop_stats.threshold = 5000.;
while ( 1 )
{
LP_millistats_update(&utxosQ_loop_stats);
@ -468,7 +466,7 @@ void utxosQ_loop(void *myipaddr)
void LP_coinsloop(void *_coins)
{
struct LP_address *ap=0,*atmp; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins;
struct LP_address *ap=0; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins;
if ( strcmp("BTC",coins) == 0 )
{
strcpy(LP_coinsloopBTC_stats.name,"BTC coin loop");
@ -519,6 +517,8 @@ void LP_coinsloop(void *_coins)
//HASH_ITER(hh,coin->addresses,ap,atmp)
if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 )
{
if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 )
free_json(retjson);
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
break;
@ -527,7 +527,7 @@ void LP_coinsloop(void *_coins)
if ( up->SPV == 0 )
{
nonz++;
up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height);
up->SPV = LP_merkleproof(coin,coin->smartaddr,backupep,up->U.txid,up->U.height);
if ( up->SPV > 0 )
{
if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && tx->SPV == 0 )
@ -544,7 +544,7 @@ void LP_coinsloop(void *_coins)
oldht = up->U.height;
LP_txheight_check(coin,ap->coinaddr,up);
if ( oldht != up->U.height )
up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height);
up->SPV = LP_merkleproof(coin,coin->smartaddr,backupep,up->U.txid,up->U.height);
if ( up->SPV <= 0 )
up->SPV = -2;
else printf("%s %s: corrected SPV.%d\n",coin->symbol,bits256_str(str,up->U.txid),up->SPV);

330
iguana/exchanges/LP_ordermatch.c

@ -115,7 +115,7 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str
{
if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 )
{
char str[65]; printf("alice not eligible (%.8f %.8f) %s/v%d\n",dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout);
char str[65]; printf("alice not eligible destsatoshis %.8f (%.8f %.8f) %s/v%d\n",dstr(qp->destsatoshis),dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout);
return(-3);
}
if ( (txout= LP_gettxout(qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout)) != 0 )
@ -269,12 +269,13 @@ uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t d
struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double relvolume,double price,uint64_t desttxfee)
{
struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; struct LP_utxoinfo *utxo = 0;
struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; struct LP_utxoinfo *utxo = 0;//,*utmp;
targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee);
targetval2 = (targetval / 8) * 9 + 2*txfee;
if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( (m= LP_address_utxo_ptrs(coin,iambob,utxos,max,ap,coinaddr)) > 1 )
{
targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee);
if ( 0 )
{
int32_t i;
@ -287,7 +288,6 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **
{
up = utxos[mini];
utxos[mini] = 0;
targetval2 = (targetval / 8) * 9 + 2*txfee;
//printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval);
if ( (double)up->U.value/targetval < LP_MINVOL-1 )
@ -296,7 +296,7 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **
{
if ( up != 0 && (up2= utxos[mini]) != 0 )
{
if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0)) != 0 )
if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0,targetval)) != 0 )
{
utxo->S.satoshis = targetval;
char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid));
@ -309,6 +309,15 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **
printf("targetval %.8f mini.%d\n",dstr(targetval),mini);
} //else printf("no %s utxos pass LP_address_utxo_ptrs filter\n",coinaddr);
} else printf("couldnt find %s %s\n",coin->symbol,coinaddr);
/*HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,utmp)
{
if ( LP_isavailable(utxo) != 0 && utxo->payment.value >= targetval && targetval >= utxo->payment.value/2 && utxo->deposit.value >= targetval2 )
{
utxo->S.satoshis = targetval;
printf("backup method found utxo!\n");
return(utxo);
}
}*/
return(0);
}
@ -359,7 +368,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
privkey = LP_privkey(utxo->coinaddr,coin->taddr);
if ( bits256_nonz(privkey) != 0 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 ) //qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending &&
{
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-2*qp->txfee,rel,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp)) == 0 )
{
printf("cant initialize swap\n");
@ -416,6 +425,8 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
}
price = 0.;
memset(qp->txid.bytes,0,sizeof(qp->txid));
qp->txid2 = qp->txid;
qp->aliceid = LP_aliceid_calc(qp->desttxid,qp->destvout,qp->feetxid,qp->feevout);
qp->tradeid = tradeid;
LP_query(ctx,myipaddr,mypubsock,"request",qp);
@ -426,7 +437,7 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
int32_t LP_quotecmp(struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2)
{
if ( bits256_cmp(qp->srchash,qp2->srchash) == 0 && bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee )
if ( bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee ) //bits256_cmp(qp->srchash,qp2->srchash) == 0 &&
return(0);
else return(-1);
}
@ -449,14 +460,15 @@ void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo
if ( LP_alice_eligible() > 0 && LP_quotecmp(qp,&LP_Alicequery) == 0 )
{
price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout);
if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice )
if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice*1.005 )
{
qp->tradeid = LP_Alicequery.tradeid;
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
Alice_expiration = 0;
printf("send CONNECT\n");
LP_query(ctx,myipaddr,mypubsock,"connect",qp);
}
} else printf("LP_reserved price %.8f vs maxprice %.8f\n",price,maxprice*1.005);
} else printf("probably a timeout, reject reserved due to not eligible.%d or mismatched quote price %.8f vs maxprice %.8f\n",LP_alice_eligible(),price,maxprice);
}
@ -506,7 +518,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
}
if ( LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin) <= SMALLVAL || bid <= SMALLVAL )
{
printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask);
//printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask);
LP_availableset(autxo);
LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0);
return(clonestr("{\"error\":\"no price set\"}"));
@ -522,7 +534,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
if ( bits256_nonz(Q.privkey) != 0 )//&& Q.quotetime >= Q.timestamp-3 )
{
retjson = cJSON_CreateObject();
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q)) == 0 )
{
jaddstr(retjson,"error","couldnt swapinit");
@ -647,7 +659,7 @@ int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
return(-1);
if ( (backupep= ep->prev) == 0 )
backupep = ep;
up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height);
up->SPV = LP_merkleproof(coin,coinaddr,backupep,up->U.txid,up->U.height);
if ( up->SPV <= 0 )
return(-1);
}
@ -662,14 +674,26 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
{
// LP_checksig
LP_quoteparse(&Q,argjson);
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
LP_tradecommand_log(argjson);
//printf("LP_tradecommand: check received method %s aliceid.%llx\n",method,(long long)Q.aliceid);
retval = 1;
autxo = &A;
butxo = &B;
memset(autxo,0,sizeof(*autxo));
memset(butxo,0,sizeof(*butxo));
LP_abutxo_set(autxo,butxo,&Q);
if ( strcmp(method,"reserved") == 0 )
{
if ( LP_Alicemaxprice == 0. )
return(retval);
if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && LP_alice_eligible() > 0 )
{
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL )
{
printf("reserved quote validate error %.0f\n",qprice);
return(retval);
}
if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 )
{
printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid));
@ -692,6 +716,11 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
{
if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 )
{
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(retval);
}
if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 )
{
printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid));
@ -708,149 +737,169 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
}
return(retval);
}
if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 )
if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL )
{
if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL )
{
printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin);
return(retval);
}
if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 )
{
printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid));
return(retval);
}
else if (LP_validSPV(Q.destcoin,Q.destaddr,Q.feetxid,Q.feevout) < 0 )
{
printf("%s dexfee %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.feetxid));
return(retval);
}
price = ask;
/*if ( coin->electrum != 0 )
{
printf("electrum can only be for alice\n");
return(retval);
}*/
if ( LP_aliceonly(Q.srccoin) > 0 )
{
printf("{\"error\":\"GAME can only be alice coin\"}\n");
return(retval);
}
if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 )
//printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin);
return(retval);
}
if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 )
{
printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid));
return(retval);
}
else if (LP_validSPV(Q.destcoin,Q.destaddr,Q.feetxid,Q.feevout) < 0 )
{
printf("%s dexfee %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.feetxid));
return(retval);
}
price = ask;
if ( LP_aliceonly(Q.srccoin) > 0 )
{
printf("{\"error\":\"GAME can only be alice coin\"}\n");
return(retval);
}
if ( strcmp(method,"request") == 0 )
{
char str[65],str2[65];
//printf("address.(%s/%s) request.(%s)\n",Q.coinaddr,coin->smartaddr,jprint(argjson,0));
recalc = 0;
if ( bits256_cmp(Q.srchash,G.LP_mypub25519) != 0 || strcmp(butxo->coinaddr,coin->smartaddr) != 0 )
{
printf("bob is patching Q.coinaddr %s mismatch != %s\n",Q.coinaddr,coin->smartaddr);
strcpy(Q.gui,G.gui);
strcpy(Q.coinaddr,coin->smartaddr);
strcpy(butxo->coinaddr,coin->smartaddr);
Q.srchash = G.LP_mypub25519;
memset(&Q.txid,0,sizeof(Q.txid));
memset(&Q.txid2,0,sizeof(Q.txid2));
Q.vout = Q.vout2 = -1;
recalc = 1;
}
autxo = &A;
butxo = &B;
memset(autxo,0,sizeof(*autxo));
memset(butxo,0,sizeof(*butxo));
LP_abutxo_set(autxo,butxo,&Q);
if ( strcmp(method,"request") == 0 )
else if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL )
recalc = 1;
else
{
char str[65],str2[65];
printf("address.(%s/%s) request.(%s)\n",Q.coinaddr,coin->smartaddr,jprint(argjson,0));
recalc = 0;
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL )
recalc = 1;
else
char tmp[64];
price = (qprice * 0.5) + (0.5 * price);
if ( bits256_nonz(Q.txid) != 0 )
LP_utxos_remove(Q.txid,Q.vout);
else recalc = 1;
if ( bits256_nonz(Q.txid2) != 0 )
LP_utxos_remove(Q.txid2,Q.vout2);
else recalc = 1;
if ( recalc == 0 )
{
char tmp[64];
value = LP_txvalue(tmp,Q.srccoin,Q.txid,Q.vout);
value2 = LP_txvalue(tmp,Q.srccoin,Q.txid2,Q.vout2);
printf("call LP_utxoadd.(%s) %.8f %.8f\n",Q.coinaddr,dstr(value),dstr(value2));
if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,G.gui,0)) == 0 )
//printf("call LP_utxoadd.(%s) %.8f %.8f\n",Q.coinaddr,dstr(value),dstr(value2));
if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,G.gui,0,Q.satoshis)) == 0 )
recalc = 1;
}
if ( recalc != 0 )
else
{
LP_RTmetrics_update(Q.srccoin,Q.destcoin);
if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 )
{
printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash));
return(retval);
}
printf("butxo.%p recalc path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1));
LP_listunspent_both(Q.srccoin,Q.coinaddr,0);
if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 )
{
Q.txid = butxo->payment.txid;
Q.vout = butxo->payment.vout;
Q.txid2 = butxo->deposit.txid;
Q.vout2 = butxo->deposit.vout;
printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis));
}
else
{
printf("cant find utxopair\n");
return(retval);
}
if ( bits256_cmp(Q.txid,butxo->payment.txid) != 0 || Q.vout != butxo->payment.vout || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 || Q.vout2 != butxo->deposit.vout )
recalc = 1;
}
}
else // "connect"
{
butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2);
}
char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0));
if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 )
{
char str[65],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis));
return(retval);
}
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(-3);
}
if ( qprice < (price - 0.00000001) * 0.9999 )
{
printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin);
return(-4);
}
if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending )
butxo->T.swappending = 0;
if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's
if ( recalc != 0 )
{
if ( LP_isavailable(butxo) > 0 )
LP_RTmetrics_update(Q.srccoin,Q.destcoin);
if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 )
{
autxo->T.swappending = butxo->T.swappending = Q.timestamp + LP_RESERVETIME;
retjson = LP_quotejson(&Q);
butxo->S.otherpubkey = jbits256(argjson,"desthash");
LP_unavailableset(butxo,butxo->S.otherpubkey);
jaddnum(retjson,"quotetime",juint(argjson,"quotetime"));
jaddnum(retjson,"pending",butxo->T.swappending);
jaddbits256(retjson,"desthash",butxo->S.otherpubkey);
jaddbits256(retjson,"pubkey",butxo->S.otherpubkey);
jaddstr(retjson,"method","reserved");
msg = jprint(retjson,0);
butxo->T.lasttime = (uint32_t)time(NULL);
printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg);
// LP_addsig
//msg2 = clonestr(msg);
LP_reserved_msg(1,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,clonestr(msg));
sleep(1);
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(1,Q.srccoin,Q.destcoin,zero,msg);
//LP_broadcast_message(LP_mypubsock,Q.srccoin,Q.destcoin,Q.desthash,jprint(retjson,0));
free_json(retjson);
printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash));
return(retval);
} else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap);
}
else if ( strcmp(method,"connect") == 0 ) // bob
{
retval = 4;
if ( butxo->S.swap == 0 && butxo->T.swappending != 0 )
}
//printf("butxo.%p recalc path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1));
LP_listunspent_both(Q.srccoin,Q.coinaddr,0);
if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 )
{
strcpy(Q.gui,G.gui);
strcpy(Q.coinaddr,coin->smartaddr);
Q.srchash = G.LP_mypub25519;
Q.txid = butxo->payment.txid;
Q.vout = butxo->payment.vout;
Q.txid2 = butxo->deposit.txid;
Q.vout2 = butxo->deposit.vout;
butxo->S.satoshis = Q.satoshis;
printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis));
}
else
{
// validate SPV alice
LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q);
//LP_butxo_swapfields_set(butxo);
//printf("cant find utxopair\n");
return(retval);
}
else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0));
}
//LP_butxo_swapfields_set(butxo);
}
else // "connect"
{
if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 )
{
butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); // better work!
} else return(retval);
}
if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 )
{
printf("bob is patching Q.coinaddr %s mismatch != %s\n",Q.coinaddr,coin->smartaddr);
strcpy(Q.coinaddr,coin->smartaddr);
}
if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 )
{
char str[65],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis));
return(retval);
}
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(-3);
}
if ( qprice < (price - 0.00000001) * 0.998 )
{
printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin);
return(retval);
}
char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0));
if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending )
butxo->T.swappending = 0;
if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's
{
if ( LP_isavailable(butxo) > 0 )
{
autxo->T.swappending = butxo->T.swappending = Q.timestamp + LP_RESERVETIME;
retjson = LP_quotejson(&Q);
butxo->S.otherpubkey = jbits256(argjson,"desthash");
LP_unavailableset(butxo,butxo->S.otherpubkey);
jaddnum(retjson,"quotetime",juint(argjson,"quotetime"));
jaddnum(retjson,"pending",butxo->T.swappending);
jaddbits256(retjson,"desthash",butxo->S.otherpubkey);
jaddbits256(retjson,"pubkey",butxo->S.otherpubkey);
jaddstr(retjson,"method","reserved");
msg = jprint(retjson,0);
butxo->T.lasttime = (uint32_t)time(NULL);
printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg);
// LP_addsig
//msg2 = clonestr(msg);
LP_reserved_msg(1,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,clonestr(msg));
sleep(1);
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(1,Q.srccoin,Q.destcoin,zero,msg);
//LP_broadcast_message(LP_mypubsock,Q.srccoin,Q.destcoin,Q.desthash,jprint(retjson,0));
free_json(retjson);
return(retval);
} else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap);
}
else if ( strcmp(method,"connect") == 0 ) // bob
{
retval = 4;
if ( butxo->S.swap == 0 && butxo->T.swappending != 0 )
{
// validate SPV alice
LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q);
//LP_butxo_swapfields_set(butxo);
return(retval);
}
else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0));
}
//LP_butxo_swapfields_set(butxo);
}
return(retval);
}
@ -888,7 +937,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
else max = LP_MAXDESIRED_UTXOS;
utxos = calloc(max,sizeof(*utxos));
LP_txfees(&txfee,&desttxfee,base,autxo->coin);
//printf("LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f\n",maxprice,dstr(autxo->S.satoshis),base,autxo->coin,dstr(txfee),dstr(desttxfee));
printf("LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f\n",maxprice,dstr(autxo->S.satoshis),base,autxo->coin,dstr(txfee),dstr(desttxfee));
if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 )
{
if ( (orderbook= cJSON_Parse(obookstr)) != 0 )
@ -901,9 +950,9 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
{
item = jitem(asks,i);
price = jdouble(item,"price");
if ( price < maxprice && price > maxprice*0.8)
price = price * 0.9 + 0.1 * maxprice;
else price *= 1.005;
//if ( price < maxprice && price > maxprice*0.8)
// price = price * 0.9 + 0.1 * maxprice;
//else price *= 1.005;
pubkey = jbits256(item,"pubkey");
if ( bits256_nonz(destpubkey) != 0 && bits256_cmp(destpubkey,pubkey) != 0 )
continue;
@ -927,7 +976,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
LP_listunspent_query(base,coinaddr);
for (j=0; j<maxiters; j++)
{
if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,price,txfee,desttxfee,pubp->pubkey,gui)) != 0 )
if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,maxprice*.999,txfee,desttxfee,pubp->pubkey,gui)) != 0 )
{
//printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee));
break;
@ -1028,6 +1077,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
return(clonestr("{\"error\":\"cant find alice utxo that is small enough\"}"));
}
LP_RTmetrics_update(base,rel);
//return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid));
while ( 1 )
{
if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )

16
iguana/exchanges/LP_prices.c

@ -813,13 +813,17 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
for (i=n=0; i<numbids; i++)
{
jaddi(array,LP_orderbookjson(rel,bids[i]));
if ( suppress_prefetch == 0 && n < 7 && bids[i]->numutxos < 3 )
if ( suppress_prefetch == 0 && n < 3 && bids[i]->numutxos == 0 )
{
//printf("bid ping %s %s\n",rel,bids[i]->coinaddr);
LP_address(relcoin,bids[i]->coinaddr);
if ( relcoin->electrum == 0 )
{
LP_listunspent_issue(rel,bids[i]->coinaddr,0);
LP_listunspent_query(rel,bids[i]->coinaddr);
//else if ( (tmpjson= LP_listunspent(rel,bids[i]->coinaddr)) != 0 )
// free_json(tmpjson);
LP_listunspent_query(rel,bids[i]->coinaddr);
}
n++;
}
free(bids[i]);
@ -833,13 +837,17 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
for (i=n=0; i<numasks; i++)
{
jaddi(array,LP_orderbookjson(base,asks[i]));
if ( suppress_prefetch == 0 && n < 7 && asks[i]->numutxos < 3 )
if ( suppress_prefetch == 0 && n < 3 && asks[i]->numutxos == 0 )
{
//printf("ask ping %s %s\n",base,asks[i]->coinaddr);
LP_address(basecoin,asks[i]->coinaddr);
if ( basecoin->electrum == 0 )
{
LP_listunspent_issue(base,asks[i]->coinaddr,0);
LP_listunspent_query(base,asks[i]->coinaddr);
//else if ( (tmpjson= LP_listunspent(base,asks[i]->coinaddr)) != 0 )
// free_json(tmpjson);
LP_listunspent_query(base,asks[i]->coinaddr);
}
n++;
}
free(asks[i]);

12
iguana/exchanges/LP_socket.c

@ -329,7 +329,8 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
tx->height = ht;
if ( ep != 0 && coin != 0 && tx->SPV == 0 )
{
tx->SPV = LP_merkleproof(coin,ep,txid,tx->height);
if ( strcmp(coinaddr,coin->smartaddr) == 0 )
tx->SPV = LP_merkleproof(coin,coin->smartaddr,ep,txid,tx->height);
//printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height);
}
}
@ -419,16 +420,11 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch
//printf("%s %s",symbol,stratumreq);
memset(ep->buf,0,ep->bufsize);
sitem = electrum_sitem(ep,stratumreq,timeout,retjsonp);
/*sitem = (struct stritem *)queueitem(stratumreq);
sitem->expiration = timeout;
sitem->DL.type = ep->stratumid++;
sitem->retptrp = (void **)retjsonp;*/
//portable_mutex_lock(&ep->mutex);
//queue_enqueue("sendQ",&ep->sendQ,&sitem->DL);
portable_mutex_lock(&ep->mutex); // this helps performance!
expiration = (uint32_t)time(NULL) + timeout + 1;
while ( *retjsonp == 0 && time(NULL) <= expiration )
usleep(15000);
//portable_mutex_unlock(&ep->mutex);
portable_mutex_unlock(&ep->mutex);
if ( *retjsonp == 0 || jobj(*retjsonp,"error") != 0 )
{
if ( ++ep->numerrors >= LP_ELECTRUM_MAXERRORS )

7
iguana/exchanges/LP_swap.c

@ -556,7 +556,7 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys)
{
bits256 otherhash,myhash,txid; int64_t txfee; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits;
bits256 otherhash,myhash,txid; int64_t txfee,val; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits;
for (i=0; i<32; i++)
otherhash.bytes[i] = recvbuf[offset++];
for (i=0; i<32; i++)
@ -626,7 +626,10 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba
txfee = swap->I.Atxfee;
else txfee = LP_MIN_TXFEE;
}
if ( j64bits(vout,"satoshis") >= rawtx->I.amount-txfee && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
if ( rawtx->I.amount > 2*txfee)
val = rawtx->I.amount-2*txfee;
else val = 1;
if ( j64bits(vout,"satoshis") >= val && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
{
if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) )
{

5
iguana/exchanges/LP_transaction.c

@ -1805,7 +1805,10 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d
}
}
if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 && swap->myfee.I.datalen != 0 && swap->myfee.I.spendlen > 0 )
{
printf("fee sent\n");
return(0);
}
return(-1);
}
@ -1820,7 +1823,7 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data
diff = swap->otherfee.I.locktime - (swap->I.started+1);
if ( diff < 0 )
diff = -diff;
if ( diff == 0 )
if ( diff < 10 )
printf("dexfee verified\n");
else printf("locktime mismatch in otherfee, reject %u vs %u\n",swap->otherfee.I.locktime,swap->I.started+1);
return(0);

78
iguana/exchanges/LP_utxo.c

@ -141,7 +141,7 @@ struct LP_utxoinfo *LP_allocated(bits256 txid,int32_t vout)
int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap,char *coinaddr)
{
struct LP_address_utxo *up,*tmp; struct LP_transaction *tx; cJSON *txout; int32_t n = 0; char str[65];
struct LP_address_utxo *up,*tmp; struct LP_transaction *tx; cJSON *txout; int32_t n = 0;
//printf("LP_address_utxo_ptrs for (%s).(%s)\n",ap->coinaddr,coinaddr);
if ( strcmp(ap->coinaddr,coinaddr) != 0 )
printf("UNEXPECTED coinaddr mismatch (%s) != (%s)\n",ap->coinaddr,coinaddr);
@ -157,7 +157,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a
{
if ( LP_value_extract(txout,0) == 0 )
{
printf("LP_address_utxo_ptrs skip zero value %s/v%d\n",bits256_str(str,up->U.txid),up->U.vout);
//printf("LP_address_utxo_ptrs skip zero value %s/v%d\n",bits256_str(str,up->U.txid),up->U.vout);
free_json(txout);
up->spendheight = 1;
if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts )
@ -179,13 +179,13 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a
{
if ( up->SPV < 0 || up->U.height == 0 )
{
printf("LP_address_utxo_ptrs skips %s/v%u due to SPV.%d ht.%d\n",bits256_str(str,up->U.txid),up->U.vout,up->SPV,up->U.height);
//printf("LP_address_utxo_ptrs skips %s/v%u due to SPV.%d ht.%d\n",bits256_str(str,up->U.txid),up->U.vout,up->SPV,up->U.height);
if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts )
tx->outpoints[up->U.vout].spendheight = 1;
continue;
}
}
if ( LP_allocated(up->U.txid,up->U.vout) == 0 )
if ( LP_allocated(up->U.txid,up->U.vout) == 0 && _LP_utxofind(iambob,up->U.txid,up->U.vout) == 0 && _LP_utxo2find(iambob,up->U.txid,up->U.vout) == 0 )
{
utxos[n++] = up;
if ( n >= max )
@ -468,26 +468,24 @@ void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout)
struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)];
/*if ( iambob != 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("_LP_utxofind deprecated iambob\n");
return(0);
}*/
LP_utxosetkey(key,txid,vout);
HASH_FIND(hh,G.LP_utxoinfos[iambob],key,sizeof(key),utxo);
HASH_FIND(hh,G.LP_utxoinfos[iambob!=0],key,sizeof(key),utxo);
return(utxo);
}
void _LP_utxo_delete(int32_t iambob,struct LP_utxoinfo *utxo)
{
HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo);
}
void _LP_utxo2_delete(int32_t iambob,struct LP_utxoinfo *utxo)
{
HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo);
}
struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2)
{
struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)];
/*if ( iambob != 0 )
{
printf("_LP_utxo2find deprecated iambob\n");
return(0);
}*/
LP_utxosetkey(key2,txid2,vout2);
HASH_FIND(hh2,G.LP_utxoinfos2[iambob],key2,sizeof(key2),utxo);
return(utxo);
@ -781,7 +779,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2)
{
uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct LP_transaction *tx; struct LP_address_utxo *up; struct iguana_info *coin = LP_coinfind(symbol);
uint64_t val,val2=0,txfee,threshold=0; cJSON *txobj; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct LP_transaction *tx; struct LP_address_utxo *up; struct iguana_info *coin = LP_coinfind(symbol);
if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 )
{
printf("null txid not eligible\n");
@ -814,25 +812,37 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
strcpy(destaddr,destaddr2);
if ( coin != 0 )
{
if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts && tx->outpoints[vout].spendheight > 0 )
if ( coin->electrum != 0 )
{
//printf("txid spent\n");
return(0);
}
if ( (tx= LP_transactionfind(coin,txid2)) != 0 && vout2 < tx->numvouts && tx->outpoints[vout2].spendheight > 0 )
{
//printf("txid2 spent\n");
return(0);
}
if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 )
{
//printf("txid %s spentB\n",destaddr);
return(0);
if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts && tx->outpoints[vout].spendheight > 0 )
{
//printf("txid spent\n");
return(0);
}
if ( (tx= LP_transactionfind(coin,txid2)) != 0 && vout2 < tx->numvouts && tx->outpoints[vout2].spendheight > 0 )
{
//printf("txid2 spent\n");
return(0);
}
if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 )
{
//printf("txid %s spentB\n",destaddr);
return(0);
}
if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 )
{
//printf("txid2 %s spentB\n",destaddr);
return(0);
}
}
if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 )
else
{
//printf("txid2 %s spentB\n",destaddr);
return(0);
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 )
return(0);
else free_json(txobj);
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 )
return(0);
else free_json(txobj);
}
}
return(1);

64
iguana/exchanges/LP_utxos.c

@ -286,9 +286,9 @@ void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
utxo->T.spentflag = (uint32_t)time(NULL);
}
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid)
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid,uint64_t satoshis)
{
uint64_t val,val2=0,tmpsatoshis,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0;
uint64_t val,val2=0,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0;
if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 )
{
char str[65],str2[65]; printf("REJECT (%s) iambob.%d %s utxoadd.(%.8f %.8f) %s/v%d %s/v%d\n",coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2);
@ -301,7 +301,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
return(0);
}
txfee = LP_txfeecalc(coin,0,0);
if ( iambob != 0 && value2 < 9 * (value >> 3) + 2*txfee ) // big txfee padding
/*if ( iambob != 0 && value2 < 9 * (satoshis >> 3) + 2*txfee ) // big txfee padding
{
if ( value2 > 2*txfee )
tmpsatoshis = (((value2 - 2*txfee) / 9) << 3);
@ -310,7 +310,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
printf("value2 %.8f <= 2 * %.8f\n",dstr(value2),dstr(txfee));
return(0);
}
} else tmpsatoshis = (value - txfee);
} else tmpsatoshis = (satoshis - txfee);*/
char str[65],str2[65],dispflag = 0;//(iambob == 0);
if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 )
{
@ -319,11 +319,11 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
}
if ( coin->inactive == 0 )
{
if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 )
if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,satoshis,txid2,vout2) <= 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis));
printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(satoshis));
return(0);
}
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,vout,0)) <= 0 )
@ -351,10 +351,10 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
if ( 0 && LP_ismine(utxo) == 0 )
{
char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis));
printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(satoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis));
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 )
if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || satoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 )
{
utxo->T.errors++;
char str[65],str2[65],str3[65],str4[65],str5[65],str6[65];
@ -364,7 +364,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
// utxo->T.spentflag = (uint32_t)time(NULL);
printf("original utxo pair not valid\n");
if ( dispflag != 0 )
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey));
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,satoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey));
utxo = 0;
}
}
@ -389,7 +389,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
utxo->payment.txid = txid;
utxo->payment.vout = vout;
utxo->payment.value = value;
utxo->S.satoshis = tmpsatoshis;
utxo->S.satoshis = satoshis;
if ( (utxo->iambob= iambob) != 0 )
{
utxo->deposit.txid = txid2;
@ -430,6 +430,46 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
return(utxo);
}
int32_t _LP_utxos_remove(bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo,*utxo2; int32_t retval = 0,iambob = 1;
utxo = utxo2 = 0;
if ( (utxo= _LP_utxofind(iambob,txid,vout)) != 0 )
{
if ( LP_isavailable(utxo) == 0 )
retval = -1;
else
{
if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 )
{
if ( LP_isavailable(utxo) == 0 )
retval = -1;
else
{
_LP_utxo_delete(iambob,utxo);
_LP_utxo2_delete(iambob,utxo2);
}
}
}
}
else if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 )
{
if ( LP_isavailable(utxo2) == 0 )
retval = -1;
else _LP_utxo2_delete(iambob,utxo2);
}
return(retval);
}
int32_t LP_utxos_remove(bits256 txid,int32_t vout)
{
int32_t retval;
portable_mutex_lock(&LP_utxomutex);
retval = _LP_utxos_remove(txid,vout);
portable_mutex_unlock(&LP_utxomutex);
return(retval);
}
cJSON *LP_inventory(char *symbol)
{
struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; struct iguana_info *coin;
@ -618,14 +658,14 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri
portable_mutex_lock(&LP_UTXOmutex);
if ( iambob != 0 )
{
if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 )
if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,value)) != 0 )
{
}
}
else
{
//printf("call utxoadd\n");
if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 )
if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,value)) != 0 )
{
}
}

Loading…
Cancel
Save