Browse Source

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

etomic
DeckerSU 7 years ago
parent
commit
3d76a624da
  1. 16
      iguana/exchanges/LP_commands.c
  2. 10
      iguana/exchanges/LP_include.h
  3. 44
      iguana/exchanges/LP_nativeDEX.c
  4. 109
      iguana/exchanges/LP_ordermatch.c
  5. 13
      iguana/exchanges/LP_portfolio.c
  6. 1
      iguana/exchanges/LP_prices.c
  7. 8
      iguana/exchanges/LP_remember.c
  8. 12
      iguana/exchanges/LP_rpc.c
  9. 52
      iguana/exchanges/LP_socket.c
  10. 257
      iguana/exchanges/LP_transaction.c
  11. 90
      iguana/exchanges/LP_utxo.c
  12. 3
      iguana/exchanges/LP_utxos.c
  13. 2
      iguana/exchanges/coins
  14. 4
      iguana/exchanges/coins.json
  15. 44
      iguana/exchanges/stats.c

16
iguana/exchanges/LP_commands.c

@ -69,12 +69,12 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport);
return(0);
}
/*if ( strcmp(method,"hello") == 0 )
{
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
return(0);
}
else*/ if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 )
if ( strcmp(method,"hello") == 0 )
{
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}"));
}
else if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 )
{
static char *laststr;
char *newstr; bits256 pubkey = jbits256(argjson,"pubkey");
@ -557,7 +557,9 @@ bot_resume(botid)\n\
//printf("network invoked\n");
LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519);
//LP_smartutxos_push(ptr);
return(jprint(LP_address_utxos(ptr,coinaddr,1),1));
if ( ptr->electrum != 0 )
return(LP_unspents_filestr(coin,ptr->smartaddr));
else return(jprint(LP_address_utxos(ptr,coinaddr,1),1));
}
else
{

10
iguana/exchanges/LP_include.h

@ -39,7 +39,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL)
#define LP_AUTOTRADE_TIMEOUT 20
#define ELECTRUM_TIMEOUT 10
#define ELECTRUM_TIMEOUT 5
#define LP_ELECTRUM_KEEPALIVE 60
#define LP_ELECTRUM_MAXERRORS 777
#define LP_MEMPOOL_TIMEINCR 10
@ -48,7 +48,8 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define LP_MAX_PEERS 32
#define LP_MAXDESIRED_UTXOS 128
#define LP_MINDESIRED_UTXOS 64
#define LP_MINDESIRED_UTXOS 32
#define LP_DUSTCOMBINE_THRESHOLD 1000000
// RTmetrics
#define LP_RTMETRICS_TOPGROUP 1.01
@ -254,7 +255,7 @@ struct iguana_info
portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses;
uint64_t txfee;
int32_t numutxos,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport;
uint32_t importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime;
uint32_t electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms;
char symbol[16],smartaddr[64],userpass[1024],serverport[128];
// portfolio
@ -408,6 +409,8 @@ struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coina
int32_t LP_destaddr(char *destaddr,cJSON *item);
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration);
char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey);
uint64_t LP_unspents_load(char *symbol,char *addr);
int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid);
cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj);
int32_t LP_mempoolscan(char *symbol,bits256 searchtxid);
@ -422,6 +425,7 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
void LP_postutxos(char *symbol,char *coinaddr);
int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag);
uint16_t LP_randpeer(char *destip);
char *LP_unspents_filestr(char *symbol,char *addr);
cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash);
//int32_t LP_butxo_findeither(bits256 txid,int32_t vout);
cJSON *LP_listunspent(char *symbol,char *coinaddr);

44
iguana/exchanges/LP_nativeDEX.c

@ -18,11 +18,9 @@
// LP_nativeDEX.c
// marketmaker
//
// autoadd dust utxo to vin for initial atomic tx
// verify portfolio, interest to KMD withdraw
// BCH signing
// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections
// bigendian architectures need to use little endian for sighash calcs
// BCH signing
#include <stdio.h>
struct LP_millistats
@ -593,6 +591,7 @@ void LP_coinsloop(void *_coins)
backupep = ep;
HASH_ITER(hh,coin->addresses,ap,atmp)
{
break; // causes timeouts probably due to too much usage, SPV validation done on tx spending
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
if ( up->U.height > 0 && up->spendheight < 0 )
@ -624,7 +623,7 @@ void LP_coinsloop(void *_coins)
if ( time(NULL) > ep->keepalive+LP_ELECTRUM_KEEPALIVE )
{
//printf("%s electrum.%p needs a keepalive: lag.%d\n",ep->symbol,ep,(int32_t)(time(NULL) - ep->keepalive));
if ( (retjson= electrum_donation(ep->symbol,ep,&retjson)) != 0 )
if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,coin->smartaddr,1)) != 0 )
free_json(retjson);
}
ep = ep->prev;
@ -828,13 +827,23 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint
void LP_pubkeysloop(void *ctx)
{
static uint32_t lasttime;
static uint32_t lasttime; cJSON *retjson; struct iguana_info *coin,*tmp;
strcpy(LP_pubkeysloop_stats.name,"LP_pubkeysloop");
LP_pubkeysloop_stats.threshold = 5000.;
sleep(10);
while ( 1 )
{
LP_millistats_update(&LP_pubkeysloop_stats);
HASH_ITER(hh,LP_coins,coin,tmp) // firstrefht,firstscanht,lastscanht
{
if ( coin->electrum != 0 && time(NULL) > coin->lastunspent+30 )
{
//printf("call electrum listunspent.%s\n",coin->symbol);
if ( (retjson= electrum_address_listunspent(coin->symbol,coin->electrum,&retjson,coin->smartaddr,2)) != 0 )
free_json(retjson);
coin->lastunspent = (uint32_t)time(NULL);
}
}
if ( time(NULL) > lasttime+60 )
{
//printf("LP_pubkeysloop %u\n",(uint32_t)time(NULL));
@ -1155,7 +1164,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
printf("error launching LP_swapsloop for port.%u\n",myport);
exit(-1);
}
int32_t nonz;
int32_t nonz; uint32_t lasthello = 0;
while ( 1 )
{
nonz = 0;
@ -1171,6 +1180,29 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
usleep(1000);
else if ( IAMLP == 0 )
usleep(1000);
if ( time(NULL) > lasthello+60 )
{
char *hellostr,*retstr; cJSON *retjson; int32_t allgood,sock = LP_bindsock;
allgood = 0;
if ( (retstr= issue_hello(myport)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (hellostr= jstr(retjson,"status")) != 0 && strcmp(hellostr,"got hello") == 0 )
allgood = 1;
else printf("strange return.(%s)\n",jprint(retjson,0));
free_json(retjson);
} else printf("couldnt parse hello return.(%s)\n",retstr);
free(retstr);
} else printf("issue_hello NULL return\n");
lasthello = (uint32_t)time(NULL);
if ( allgood == 0 )
{
printf("RPC port got stuck, close bindsocket\n");
LP_bindsock = -1;
closesocket(sock);
}
}
}
#endif
}

109
iguana/exchanges/LP_ordermatch.c

@ -83,7 +83,7 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str
{
if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 )
{
printf("bob not eligible %s\n",jprint(LP_quotejson(qp),1));
printf("bob not eligible %s (%.8f %.8f)\n",jprint(LP_quotejson(qp),1),dstr(srcvalue),dstr(srcvalue2));
return(-2);
}
if ( (txout= LP_gettxout(qp->srccoin,qp->coinaddr,qp->txid,qp->vout)) != 0 )
@ -246,7 +246,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 ( (coin->electrum == 0 || up->SPV > 0) && dist >= 0 && dist < mindist )
if ( dist >= 0 && dist < mindist ) //(coin->electrum == 0 || up->SPV > 0) &&
{
//printf("(%.8f %.8f %.8f).%d ",dstr(up->U.value),dstr(dist),dstr(mindist),mini);
mini = i;
@ -594,9 +594,29 @@ int32_t LP_aliceonly(char *symbol)
else return(0);
}
int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
{
struct electrum_info *ep,*backupep; struct LP_address_utxo *up; struct iguana_info *coin;
coin = LP_coinfind(symbol);
if ( coin != 0 && (ep= coin->electrum) != 0 )
{
if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 )
{
if ( up->SPV < 0 )
return(-1);
if ( (backupep= ep->prev) == 0 )
backupep = ep;
up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height);
if ( up->SPV <= 0 )
return(-1);
}
}
return(0);
}
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 value,value2; cJSON *retjson; double qprice,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 retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t value,value2; cJSON *retjson; double qprice,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 retval = -1,recalc,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
@ -605,8 +625,28 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
LP_tradecommand_log(argjson);
//printf("LP_tradecommand: check received method %s aliceid.%llx\n",method,(long long)Q.aliceid);
retval = 1;
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);
}
if ( strcmp(method,"reserved") == 0 )
{
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));
return(retval);
}
else if (LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 )
{
printf("%s src2 %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid2));
return(retval);
}
if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && LP_alice_eligible() > 0 )
{
printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
@ -620,7 +660,17 @@ 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 )
{
//printf("alice %s received CONNECTED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
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));
return(retval);
}
else if (LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 )
{
printf("%s src2 %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid2));
return(retval);
}
//printf("alice %s received CONNECTED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
if ( (retstr= LP_connectedalice(argjson)) != 0 )
free(retstr);
}
@ -633,6 +683,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin);
return(retval);
}
price = ask;
/*if ( coin->electrum != 0 )
{
printf("electrum can only be for alice\n");
@ -648,21 +699,28 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
printf("bob is patching Q.coinaddr %s mismatch != %s\n",Q.coinaddr,coin->smartaddr);
strcpy(Q.coinaddr,coin->smartaddr);
}
price = ask;
autxo = &A;
butxo = &B;
memset(autxo,0,sizeof(*autxo));
memset(butxo,0,sizeof(*butxo));
LP_abutxo_set(autxo,butxo,&Q);
printf("utxopairfind\n");
if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 )
butxo = &B;
//LP_butxo_swapfields(butxo);
if ( strcmp(method,"request") == 0 )
{
char str[65],str2[65];
printf("request.(%s)\n",jprint(argjson,0));
if ( 1 )//LP_allocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_allocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
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];
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 )
recalc = 1;
}
if ( recalc != 0 )
{
LP_RTmetrics_update(Q.srccoin,Q.destcoin);
if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 )
@ -670,7 +728,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash));
return(retval);
}
printf("butxo.%p replace 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));
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 )
{
@ -679,28 +737,17 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
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");
//LP_abutxo_set(0,butxo,&Q);
//LP_butxo_swapfields(butxo);
}
else
{
printf("other path %p %p %.8f\n",LP_allocated(butxo->payment.txid,butxo->payment.vout),LP_allocated(butxo->deposit.txid,butxo->deposit.vout), LP_quote_validate(autxo,butxo,&Q,1));
value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout);
value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2);
if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,G.LP_mypub25519,G.gui,0)) == 0 )
printf("couldnt create bob's utxopair\n");
else printf("created butxo.(%s %s)\n",bits256_str(str,butxo->payment.txid),bits256_str(str2,butxo->deposit.txid));
}
else
{
printf("cant find utxopair\n");
return(retval);
}
}
}
if ( butxo == 0 || butxo == &B )
butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2);
if ( butxo == 0 || bits256_cmp(Q.txid,butxo->payment.txid) != 0 || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 )
else // "connect"
{
printf("%s %s null butxo.%p case\n",Q.srccoin,Q.coinaddr,butxo);
value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout);
value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2);
butxo = LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0);
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 )

13
iguana/exchanges/LP_portfolio.c

@ -222,7 +222,7 @@ struct LP_autoprice_ref
int32_t LP_autoprice(char *base,char *rel,cJSON *argjson)
{
//curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}"
struct LP_priceinfo *basepp,*relpp; int32_t i; char *refbase,*refrel; double minprice,margin,offset,factor;
struct LP_priceinfo *basepp,*relpp; int32_t i; char *refbase,*refrel; double minprice,margin,offset,factor,fixedprice;
//printf("autoprice.(%s %s) %s\n",base,rel,jprint(argjson,0));
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
@ -232,6 +232,8 @@ int32_t LP_autoprice(char *base,char *rel,cJSON *argjson)
margin = jdouble(argjson,"margin");
offset = jdouble(argjson,"offset");
factor = jdouble(argjson,"factor");
fixedprice = jdouble(argjson,"fixed");
basepp->fixedprices[relpp->ind] = fixedprice;
basepp->minprices[relpp->ind] = minprice;
basepp->margins[relpp->ind] = margin;
basepp->offsets[relpp->ind] = offset;
@ -267,9 +269,16 @@ int32_t LP_autoprice(char *base,char *rel,cJSON *argjson)
void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP_priceinfo *relpp,double price,char *refbase,char *refrel)
{
static uint32_t lasttime;
double margin,minprice,newprice,oppomargin,factor,offset; double bid,ask; int32_t changed;
double margin,minprice,newprice,oppomargin,fixedprice,factor,offset; double bid,ask; int32_t changed;
margin = basepp->margins[relpp->ind];
oppomargin = relpp->margins[basepp->ind];
if ( (fixedprice= relpp->fixedprices[basepp->ind]) > SMALLVAL )
{
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,fixedprice);
printf("autoprice FIXED %s/%s <- %.8f\n",basepp->symbol,relpp->symbol,fixedprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,fixedprice);
return;
}
if ( margin != 0. || oppomargin != 0. )
{
offset = basepp->offsets[relpp->ind];

1
iguana/exchanges/LP_prices.c

@ -29,6 +29,7 @@ struct LP_priceinfo
double relvals[LP_MAXPRICEINFOS];
double myprices[LP_MAXPRICEINFOS];
double minprices[LP_MAXPRICEINFOS]; // autoprice
double fixedprices[LP_MAXPRICEINFOS]; // fixedprices
double margins[LP_MAXPRICEINFOS];
double offsets[LP_MAXPRICEINFOS];
double factors[LP_MAXPRICEINFOS];

8
iguana/exchanges/LP_remember.c

@ -937,7 +937,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
for (j=0; j<32; j++)
rev.bytes[j] = rswap.myprivs[0].bytes[31 - j];
if ( (rswap.txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(0,&signedtxid,rswap.Btxfee,"alicespend",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_ALICESPEND],0,0,rswap.bobpaymentaddr,1,bob->zcash)) != 0 )
if ( (rswap.txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"alicespend",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_ALICESPEND],0,0,rswap.bobpaymentaddr,1,bob->zcash)) != 0 )
printf("alicespend.(%s)\n",rswap.txbytes[BASILISK_ALICESPEND]);
}
LP_txbytes_update("alicespend",rswap.bobcoin,rswap.txbytes[BASILISK_ALICESPEND],&rswap.txids[BASILISK_ALICESPEND],&rswap.paymentspent,&rswap.sentflags[BASILISK_ALICESPEND]);
@ -967,7 +967,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( bits256_nonz(rswap.privBn) != 0 )
{
len = basilisk_swapuserdata(userdata,zero,1,rswap.myprivs[0],redeemscript,redeemlen);
if ( (rswap.txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(0,&signedtxid,rswap.Btxfee,"aliceclaim",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_ALICECLAIM],0,0,rswap.bobdepositaddr,1,bob->zcash)) != 0 )
if ( (rswap.txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"aliceclaim",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_ALICECLAIM],0,0,rswap.bobdepositaddr,1,bob->zcash)) != 0 )
printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICECLAIM]);
}
}
@ -1042,7 +1042,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( redeemlen > 0 )
{
len = basilisk_swapuserdata(userdata,zero,1,rswap.myprivs[1],redeemscript,redeemlen);
if ( (rswap.txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(0,&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[1],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_BOBRECLAIM],0,0,rswap.bobpaymentaddr,1,bob->zcash)) != 0 )
if ( (rswap.txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[1],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_BOBRECLAIM],0,0,rswap.bobpaymentaddr,1,bob->zcash)) != 0 )
{
int32_t z;
for (z=0; z<20; z++)
@ -1073,7 +1073,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
vcalc_sha256(0,rswap.secretBn256,rswap.privBn.bytes,sizeof(rswap.privBn));
redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,rswap.dlocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,rswap.privAm,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256);
len = basilisk_swapuserdata(userdata,rswap.privBn,0,rswap.myprivs[0],redeemscript,redeemlen);
if ( (rswap.txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(0,&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_BOBREFUND],0,0,rswap.bobdepositaddr,1,bob->zcash)) != 0 )
if ( (rswap.txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_BOBREFUND],0,0,rswap.bobdepositaddr,1,bob->zcash)) != 0 )
printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,rswap.pubB1),rswap.txbytes[BASILISK_BOBREFUND]);
}
LP_txbytes_update("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],&rswap.txids[BASILISK_BOBREFUND],&rswap.depositspent,&rswap.sentflags[BASILISK_BOBREFUND]);

12
iguana/exchanges/LP_rpc.c

@ -93,6 +93,14 @@ char *issue_LP_getprices(char *destip,uint16_t destport)
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_hello(uint16_t port)
{
char url[512];
sprintf(url,"http://127.0.0.1:%u/api/stats/hello",port);
//printf("getutxo.(%s)\n",url);
return(issue_curlt(url,60)); // might be starting a trade
}
char *issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr)
{
char url[512],*retstr;
@ -578,7 +586,7 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
return(retjson);
}
}
printf("couldnt find %s/v%d\n",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\"}"));
}
}
@ -686,7 +694,7 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr)
sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr);
return(bitcoin_json(coin,"listunspent",buf));
} else return(LP_address_utxos(coin,coinaddr,0));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,2));
}
int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag)

52
iguana/exchanges/LP_socket.c

@ -408,12 +408,12 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch
sitem->expiration = timeout;
sitem->DL.type = ep->stratumid++;
sitem->retptrp = (void **)retjsonp;*/
portable_mutex_lock(&ep->mutex);
//portable_mutex_lock(&ep->mutex);
//queue_enqueue("sendQ",&ep->sendQ,&sitem->DL);
expiration = (uint32_t)time(NULL) + timeout + 1;
while ( *retjsonp == 0 && time(NULL) <= expiration )
usleep(5000);
portable_mutex_unlock(&ep->mutex);
//portable_mutex_unlock(&ep->mutex);
if ( *retjsonp == 0 || jobj(*retjsonp,"error") != 0 )
{
if ( ++ep->numerrors >= LP_ELECTRUM_MAXERRORS )
@ -591,27 +591,44 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON
usecache = 0;
}
//printf("electrum.%s/%s listunspent last.(%s lag %d)\n",ep->symbol,coin->symbol,coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime));
if ( usecache == 0 )
if ( usecache == 0 || electrumflag > 1 )
{
if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.listunspent",addr,ELECTRUM_TIMEOUT)) != 0 )
{
//printf("%s.%d u.%u/%d t.%ld %s LISTUNSPENT.(%d)\n",coin->symbol,height,ap->unspenttime,ap->unspentheight,time(NULL),addr,(int32_t)strlen(jprint(retjson,0)));
updatedflag = 0;
if ( electrum_process_array(coin,ep,addr,retjson,electrumflag) != 0 )
LP_postutxos(coin->symbol,addr), updatedflag = 1;
if ( strcmp(addr,coin->smartaddr) == 0 )
if ( jobj(retjson,"error") == 0 && is_cJSON_Array(retjson) != 0 )
{
retstr = jprint(retjson,0);
LP_unspents_cache(coin->symbol,coin->smartaddr,retstr,updatedflag);
free(retstr);
if ( 0 && electrumflag > 1 )
printf("%s.%d u.%u/%d t.%ld %s LISTUNSPENT.(%d)\n",coin->symbol,height,ap->unspenttime,ap->unspentheight,time(NULL),addr,(int32_t)strlen(jprint(retjson,0)));
updatedflag = 0;
if ( electrum_process_array(coin,ep,addr,retjson,electrumflag) != 0 )
LP_postutxos(coin->symbol,addr), updatedflag = 1;
if ( strcmp(addr,coin->smartaddr) == 0 )
{
retstr = jprint(retjson,0);
LP_unspents_cache(coin->symbol,coin->smartaddr,retstr,1);
free(retstr);
}
if ( ap != 0 )
{
ap->unspenttime = (uint32_t)time(NULL);
ap->unspentheight = height;
}
}
if ( ap != 0 )
else
{
ap->unspenttime = (uint32_t)time(NULL);
ap->unspentheight = height;
free_json(retjson);
retjson = 0;
}
}
} else retjson = LP_address_utxos(coin,addr,1);
}
if ( retjson == 0 )
{
if ( strcmp(addr,coin->smartaddr) == 0 && (retstr= LP_unspents_filestr(symbol,coin->smartaddr)) != 0 )
{
retjson = LP_address_utxos(coin,addr,1);
free(retstr);
} else retjson = LP_address_utxos(coin,addr,1);
}
return(retjson);
}
@ -1024,7 +1041,8 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
struct electrum_info *ep; int32_t already; cJSON *retjson;
if ( ipaddr == 0 || ipaddr[0] == 0 || port == 0 )
{
coin->electrum = 0;
//coin->electrum = 0;
printf("would have disabled %s electrum here\n",coin->symbol);
return(cJSON_Parse("{\"result\":\"success\",\"status\":\"electrum mode disabled, now in native coin mode\"}"));
}
retjson = cJSON_CreateObject();
@ -1044,7 +1062,7 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
}
else
{
printf("launched electrum.(%s:%u)\n",ep->ipaddr,ep->port);
printf("launched %s electrum.(%s:%u)\n",coin->symbol,ep->ipaddr,ep->port);
jaddstr(retjson,"result","success");
ep->prev = coin->electrum;
coin->electrum = ep;

257
iguana/exchanges/LP_transaction.c

@ -603,9 +603,9 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_
return(complete);
}
char *basilisk_swap_bobtxspend(int32_t dustcombine,bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t utxovout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys,int32_t zcash)
char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t utxovout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys,int32_t zcash)
{
char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *items[2],*txobj,*vins,*obj,*vouts,*item,*privkeys; int32_t i,completed,spendlen,n,ignore_cltverr=1; struct vin_info V[8]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin;
char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*obj,*vouts,*item,*privkeys; int32_t completed,spendlen,n,ignore_cltverr=1; struct vin_info V[8]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin;
LP_mark_spent(symbol,utxotxid,utxovout);
if ( txfee > 0 && txfee < 10000 )
txfee = 10000;
@ -635,22 +635,6 @@ char *basilisk_swap_bobtxspend(int32_t dustcombine,bits256 *signedtxidp,uint64_t
printf("basilisk_swap_bobtxspend.%s %s utxo.(%s).v%d already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid),utxovout);
return(0);
}
if ( coin->electrum != 0 || coin->numutxos < LP_MINDESIRED_UTXOS )
dustcombine = 0;
else if ( coin->numutxos >= LP_MINDESIRED_UTXOS )
dustcombine = 2;
if ( dustcombine != 0 )
{
uint64_t more;
if ( privkey2p != 0 )
dustcombine = 1;
memset(items,0,sizeof(items));
more = LP_dustcombine(items,dustcombine,coin);
if ( more != 0 )
printf("%s dustcombine.%d -> %.8f (%s) + (%s)\n",coin->symbol,dustcombine,dstr(more),items[0] != 0 ? jprint(items[0],0) : "",items[1] != 0 ? jprint(items[1],0) : "");
value += more;
dustcombine = (items[0] != 0) + (items[1] != 0);
}
#endif
}
if ( satoshis != 0 )
@ -710,13 +694,6 @@ char *basilisk_swap_bobtxspend(int32_t dustcombine,bits256 *signedtxidp,uint64_t
jaddistr(privkeys,wifstr);
V[0].suppress_pubkeys = suppress_pubkeys;
V[0].ignore_cltverr = ignore_cltverr;
for (i=0; i<dustcombine; i++) // must be simple standard vin
{
V[i+1].signers[0].privkey = privkey;
V[i+1].suppress_pubkeys = 0;
V[i+1].ignore_cltverr = 0;
V[i+1].N = V[i+1].M = 1;
}
if ( redeemlen != 0 )
memcpy(V[0].p2shscript,redeemscript,redeemlen), V[0].p2shlen = redeemlen;
txobj = bitcoin_txcreate(symbol,isPoS,locktime,1,timestamp);
@ -747,9 +724,6 @@ char *basilisk_swap_bobtxspend(int32_t dustcombine,bits256 *signedtxidp,uint64_t
jaddnum(item,"suppress",suppress_pubkeys);
jaddnum(item,"sequence",sequenceid);
jaddi(vins,item);
for (i=0; i<dustcombine; i++)
if ( items[i] != 0 )
jaddi(vins,items[i]);
jdelete(txobj,"vin");
jadd(txobj,"vin",vins);
if ( destaddr == 0 )
@ -878,34 +852,114 @@ int64_t LP_komodo_interest(bits256 txid,int64_t value)
return(interest);
}
int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_t amount,struct vin_info *V,struct LP_address_utxo **utxos,int32_t numunspents,int32_t suppress_pubkeys,int32_t ignore_cltverr,bits256 privkey,cJSON *privkeys,cJSON *vins,uint8_t *script,int32_t scriptlen)
int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_t amount,struct vin_info *V,struct LP_address_utxo **utxos,int32_t numunspents,int32_t suppress_pubkeys,int32_t ignore_cltverr,bits256 privkey,cJSON *privkeys,cJSON *vins,uint8_t *script,int32_t scriptlen,bits256 utxotxid,int32_t utxovout,int32_t dustcombine)
{
char wifstr[128],spendscriptstr[128]; int32_t i,n,ind,abovei,belowi,maxmode=0; struct vin_info *vp; struct LP_address_utxo *up; int64_t interest,interestsum,above,below,remains = amount,total = 0;
char wifstr[128],spendscriptstr[128],str[65]; int32_t i,j,n,numpre,ind,abovei,belowi,maxmode=0; struct vin_info *vp; cJSON *txobj; struct LP_address_utxo *up,*min0,*min1,*preselected[3]; int64_t value,interest,interestsum,above,below,remains = amount,total = 0;
*totalp = 0;
interestsum = 0;
init_hexbytes_noT(spendscriptstr,script,scriptlen);
bitcoin_priv2wif(coin->wiftaddr,wifstr,privkey,coin->wiftype);
for (i=n=0; i<numunspents; i++)
n = 0;
min0 = min1 = 0;
memset(preselected,0,sizeof(preselected));
for (j=numpre=0; j<numunspents; j++)
{
//printf("vinselect.%d of %d: remain %.8f amount %.8f\n",i,numunspents,dstr(remains),dstr(amount));
below = above = 0;
abovei = belowi = -1;
if ( LP_vin_select(&abovei,&above,&belowi,&below,utxos,numunspents,remains,maxmode) < 0 )
up = utxos[j];
if ( utxovout == up->U.vout && bits256_cmp(utxotxid,up->U.txid) == 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,numunspents,dstr(remains),dstr(amount));
return(0);
preselected[numpre++] = up;
printf("found utxotxid in slot.%d\n",j);
utxos[j] = 0;
continue;
}
if ( up->spendheight <= 0 && up->U.height > 0 && up->U.value != 0 )
{
if ( (txobj= LP_gettxout(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout)) == 0 )
{
up->spendheight = 1;
utxos[j] = 0;
}
else
{
if ( LP_inventory_prevent(1,coin->symbol,up->U.txid,up->U.vout) == 0 )
{
if ( min1 == 0 || up->U.value < min1->U.value )
{
if ( min0 == 0 || up->U.value < min0->U.value )
{
min1 = min0;
min0 = up;
} else min1 = up;
}
} else utxos[j] = 0;
if ( 0 && utxos[j] != 0 )
printf("gettxout j.%d %s/v%d (%s)\n",j,bits256_str(str,up->U.txid),up->U.vout,jprint(txobj,0));
free_json(txobj);
}
} else utxos[j] = 0;
}
if ( bits256_nonz(utxotxid) != 0 && numpre == 0 )
{
up = LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout);
printf("have utxotxid but wasnt found up.%p\n",up);
if ( up == 0 )
{
value = LP_txvalue(coin->smartaddr,coin->symbol,utxotxid,utxovout);
LP_address_utxoadd("withdraw",coin,coin->smartaddr,utxotxid,utxovout,value,1,-1);
printf("added after not finding\n");
}
if ( belowi < 0 || abovei >= 0 )
ind = abovei;
else ind = belowi;
if ( ind < 0 )
if ( (up= LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout)) != 0 )
preselected[numpre++] = up;
else
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,numunspents,dstr(remains),dstr(amount),abovei,belowi,ind);
printf("couldnt add address_utxo after not finding\n");
return(0);
}
up = utxos[ind];
utxos[ind] = utxos[--numunspents];
utxos[numunspents] = 0;
}
if ( dustcombine >= 1 && min0 != 0 && min0->U.value < LP_DUSTCOMBINE_THRESHOLD && (coin->electrum == 0 || min0->SPV > 0) )
preselected[numpre++] = min0;
else min0 = 0;
if ( dustcombine >= 2 && min1 != 0 && min1->U.value < LP_DUSTCOMBINE_THRESHOLD && (coin->electrum == 0 || min1->SPV > 0) )
preselected[numpre++] = min1;
else min1 = 0;
printf("dustcombine.%d numpre.%d min0.%p min1.%p numutxos.%d\n",dustcombine,numpre,min0,min1,numunspents);
for (i=0; i<numunspents+numpre; i++)
{
if ( i < numpre )
{
up = preselected[i];
char str[65]; printf("preselected[%d]: %s/v%d %.8f\n",i,bits256_str(str,up->U.txid),up->U.vout,dstr(up->U.value));
}
else
{
below = above = 0;
abovei = belowi = -1;
if ( LP_vin_select(&abovei,&above,&belowi,&below,utxos,numunspents,remains,maxmode) < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,numunspents,dstr(remains),dstr(amount));
return(0);
}
if ( belowi < 0 || abovei >= 0 )
ind = abovei;
else ind = belowi;
if ( ind < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,numunspents,dstr(remains),dstr(amount),abovei,belowi,ind);
return(0);
}
up = utxos[ind];
utxos[ind] = utxos[--numunspents];
utxos[numunspents] = 0;
for (j=0; j<numpre; j++)
if ( up == preselected[j] )
break;
if ( j < numpre )
continue;
if ( LP_validSPV(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout) < 0 )
continue;
}
up->spendheight = 1;
total += up->U.value;
remains -= up->U.value;
if ( up->U.height < 7777777 && strcmp(coin->symbol,"KMD") == 0 )
@ -924,9 +978,7 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_
vp->suppress_pubkeys = suppress_pubkeys;
vp->ignore_cltverr = ignore_cltverr;
jaddi(vins,LP_inputjson(up->U.txid,up->U.vout,spendscriptstr));
//printf("wif.%s i.%d privkeys.%s vins.%s %p %p\n",wifstr,i,jprint(privkeys,0),jprint(vins,0),privkeys,vins);
//printf("%s value %.8f -> remains %.8f\n",coinaddr,dstr(value),dstr(remains));
if ( remains <= 0 )
if ( remains <= 0 && i >= numpre-1 )
break;
if ( numunspents == 0 )
{
@ -938,10 +990,10 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_
return(n);
}
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)
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;
cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[64]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp,locktime; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[256]; struct LP_address *ap;
cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[256]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,dustcombine,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[256]; struct LP_address *ap;
if ( ctx == 0 )
ctx = bitcoin_ctx();
*numvinsp = 0;
@ -956,6 +1008,11 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
printf("LP_createrawtransaction: illegal coin.%p outputs.%p or arraysize.%d, error\n",coin,outputs,numvouts);
return(0);
}
if ( coin->numutxos < LP_MINDESIRED_UTXOS )
dustcombine = 0;
else if ( coin->numutxos >= LP_MINDESIRED_UTXOS )
dustcombine = 2;
else dustcombine = 1;
amount = txfee;
for (i=0; i<numvouts; i++)
{
@ -990,12 +1047,12 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,max,ap,coin->smartaddr)) <= 0 )
{
printf("LP_createrawtransaction: address_utxo_ptrs %d, error\n",numutxos);
return(0);
//return(0);
}
ignore_cltverr = 0;
suppress_pubkeys = 1;
scriptlen = bitcoin_standardspend(script,0,G.LP_myrmd160);
numvins = LP_vins_select(ctx,coin,&total,amount,V,utxos,numutxos,suppress_pubkeys,ignore_cltverr,privkey,privkeys,vins,script,scriptlen);
numvins = LP_vins_select(ctx,coin,&total,amount,V,utxos,numutxos,suppress_pubkeys,ignore_cltverr,privkey,privkeys,vins,script,scriptlen,utxotxid,utxovout,dustcombine);
if ( total < amount )
{
printf("change %.8f = total %.8f - amount %.8f, adjust %.8f numvouts.%d, txfee %.8f\n",dstr(change),dstr(total),dstr(amount),dstr(adjust),numvouts,dstr(txfee));
@ -1004,9 +1061,8 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
}
change = (total - amount);
timestamp = (uint32_t)time(NULL);
if ( strcmp("KMD",coin->symbol) == 0 )
if ( locktime == 0 && strcmp("KMD",coin->symbol) == 0 )
locktime = timestamp - 777;
else locktime = 0;
txobj = bitcoin_txcreate(coin->symbol,coin->isPoS,locktime,1,timestamp);
jdelete(txobj,"vin");
jadd(txobj,"vin",jduplicate(vins));
@ -1027,7 +1083,9 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
return(0);
}
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr);
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
if ( addrtype == coin->pubtype )
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
else spendlen = bitcoin_p2shspend(spendscript,0,rmd160);
txobj = bitcoin_txoutput(txobj,spendscript,spendlen,value + adjust);
}
else
@ -1048,17 +1106,26 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
{
static void *ctx;
int32_t iter,completed=0,maxV,numvins,numvouts,datalen,suppress_pubkeys; bits256 privkey; char changeaddr[64],vinaddr[64],str[65],*signedtx=0,*rawtx=0; struct vin_info *V; cJSON *retjson,*outputs,*vins=0,*txobj=0,*privkeys=0; struct iguana_msgtx msgtx; bits256 signedtxid; uint64_t txfee,newtxfee=10000;
int32_t iter,utxovout,autofee,completed=0,maxV,numvins,numvouts,datalen,suppress_pubkeys; bits256 privkey; char changeaddr[64],vinaddr[64],str[65],*signedtx=0,*rawtx=0; struct vin_info *V; uint32_t locktime; cJSON *retjson,*outputs,*vins=0,*txobj=0,*privkeys=0; struct iguana_msgtx msgtx; bits256 utxotxid,signedtxid; uint64_t txfee,newtxfee=10000;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( (outputs= jarray(&numvouts,argjson,"outputs")) == 0 )
{
printf("no outputs in argjson (%s)\n",jprint(argjson,0));
return(clonestr("{\"error\":\"no outputs specified\"}"));
}
txfee = coin->txfee;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( txfee > 0 && txfee < 10000 )
txfee = 10000;
utxotxid = jbits256(argjson,"utxotxid");
utxovout = jint(argjson,"utxovout");
locktime = juint(argjson,"locktime");
txfee = juint(argjson,"txfee");
autofee = (strcmp(coin->symbol,"BTC") == 0);
if ( txfee == 0 )
{
autofee = 1;
txfee = coin->txfee;
if ( txfee > 0 && txfee < 10000 )
txfee = 10000;
} else autofee = 0;
suppress_pubkeys = 0;
memset(signedtxid.bytes,0,sizeof(signedtxid));
safecopy(changeaddr,coin->smartaddr,sizeof(changeaddr));
@ -1071,7 +1138,7 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
privkeys = cJSON_CreateArray();
vins = cJSON_CreateArray();
memset(V,0,sizeof(*V) * maxV);
if ( (rawtx= LP_createrawtransaction(&txobj,&numvins,coin,V,maxV,privkey,outputs,vins,privkeys,iter == 0 ? txfee : newtxfee)) != 0 )
if ( (rawtx= LP_createrawtransaction(&txobj,&numvins,coin,V,maxV,privkey,outputs,vins,privkeys,iter == 0 ? txfee : newtxfee,utxotxid,utxovout,locktime)) != 0 )
{
completed = 0;
memset(&msgtx,0,sizeof(msgtx));
@ -1118,6 +1185,43 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr)
{
struct iguana_info *coin; int32_t len,retval=-1; char *retstr,*hexstr; cJSON *argjson,*outputs,*item,*retjson,*obj;
if ( (coin= rawtx->coin) == 0 )
return(-1);
if ( strcmp(coin->smartaddr,vinaddr) != 0 )
{
printf("basilisk_rawtx_gen mismatched vinaddr.%s != %s\n",vinaddr,coin->smartaddr);
return(-1);
}
argjson = cJSON_CreateObject();
jaddbits256(argjson,"utxotxid",rawtx->utxotxid);
jaddnum(argjson,"utxovout",rawtx->utxovout);
jaddnum(argjson,"locktime",locktime);
jadd64bits(argjson,"txfee",txfee);
outputs = cJSON_CreateArray();
item = cJSON_CreateObject();
jaddnum(item,rawtx->I.destaddr,dstr(rawtx->I.amount));
jaddi(outputs,item);
jadd(argjson,"outputs",outputs);
if ( (retstr= LP_withdraw(coin,argjson)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (obj= jobj(retjson,"complete")) != 0 && is_cJSON_True(obj) != 0 && (hexstr= jstr(retjson,"hex")) != 0 && (len= is_hexstr(hexstr,0)) > 16 )
{
rawtx->I.datalen = len >> 1;
decode_hex(rawtx->txbytes,rawtx->I.datalen,hexstr);
rawtx->I.completed = 1;
rawtx->I.signedtxid = jbits256(retjson,"txid");
retval = 0;
}
free_json(retjson);
}
free(retstr);
}
free_json(argjson);
return(retval);
#ifdef old
int32_t retval=-1,iter; char *signedtx,*changeaddr = 0,_changeaddr[64]; struct iguana_info *coin; int64_t newtxfee=0,destamount;
char str2[65]; printf("%s rawtxgen.(%s/v%d)\n",rawtx->name,bits256_str(str2,rawtx->utxotxid),rawtx->utxovout);
if ( (coin= rawtx->coin) == 0 )
@ -1133,7 +1237,7 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub
txfee = LP_MIN_TXFEE;
for (iter=0; iter<2; iter++)
{
if ( (signedtx= basilisk_swap_bobtxspend(1,&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys,coin->zcash)) != 0 )
if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys,coin->zcash)) != 0 )
{
rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1;
if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) )
@ -1152,6 +1256,7 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub
break;
}
return(retval);
#endif
}
int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr,int32_t zcash)
@ -1172,7 +1277,7 @@ int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t
}
for (iter=0; iter<2; iter++)
{
if ( (signedtx= basilisk_swap_bobtxspend(0,&dest->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,rawtx->redeemscript,rawtx->I.redeemlen,userdata,userdatalen,dest->utxotxid,dest->utxovout,dest->I.destaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,dest->I.suppress_pubkeys,zcash)) != 0 )
if ( (signedtx= basilisk_swap_bobtxspend(&dest->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,rawtx->redeemscript,rawtx->I.redeemlen,userdata,userdatalen,dest->utxotxid,dest->utxovout,dest->I.destaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,dest->I.suppress_pubkeys,zcash)) != 0 )
{
dest->I.datalen = (int32_t)strlen(signedtx) >> 1;
if ( dest->I.datalen <= sizeof(dest->txbytes) )
@ -1219,20 +1324,12 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wifta
//printf("pubAm.(%s)\n",bits256_str(str,pubAm));
//printf("pubBn.(%s)\n",bits256_str(str,pubBn));
spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,taddr,p2shtype,pubAm,pubBn);
//char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen);
/*rev = privAm;
for (i=0; i<32; i++)
privAm.bytes[i] = rev.bytes[31 - i];
rev = privBn;
for (i=0; i<32; i++)
privBn.bytes[i] = rev.bytes[31 - i];*/
if ( (txfee= Atxfee) == 0 )
{
if ( (txfee= LP_getestimatedrate(LP_coinfind(symbol)) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
}
//txfee = LP_txfee(symbol);
signedtx = basilisk_swap_bobtxspend(0,&signedtxid,txfee,name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,utxovout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,1,zcash);
signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,utxovout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,1,zcash);
LP_mark_spent(symbol,utxotxid,utxovout);
}
return(signedtx);
@ -1651,12 +1748,6 @@ void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,s
{
char coinaddr[64];
alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->taddr,coin->p2shtype,pubAm,pubBn);
/*for (i=0; i<33; i++)
printf("%02x",swap->persistent_pubkey33[i]);
printf(" pubkey33, ");
for (i=0; i<20; i++)
printf("%02x",swap->changermd160[i]);
printf(" rmd160, ");*/
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20);
//printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys);
basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,swap->I.Atxfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr);
@ -1686,7 +1777,7 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d
{
printf("generate fee %.8f\n",dstr(strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee));
bitcoin_address(coinaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->changermd160,20);
if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 )
if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,swap->myfee.I.locktime,swap->myfee.spendscript,swap->myfee.I.spendlen,strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 )
{
printf("rawtxsend %s %.8f\n",swap->myfee.coin->symbol,dstr(strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee));
swap->I.statebits |= LP_swapdata_rawtxsend(pairsock,swap,0x80,data,maxlen,&swap->myfee,0x40,0);
@ -1710,12 +1801,16 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d
int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
int32_t diff;
if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->otherfee,0,data,datalen,0) == 0 )
{
printf("otherfee amount %.8f -> %s vs %s locktime %u vs %u\n",dstr(swap->otherfee.I.amount),swap->otherfee.p2shaddr,swap->otherfee.I.destaddr,swap->otherfee.I.locktime,swap->I.started+1);
if ( strcmp(swap->otherfee.I.destaddr,swap->otherfee.p2shaddr) == 0 )
{
if ( swap->otherfee.I.locktime == swap->I.started+1 )
diff = swap->otherfee.I.locktime - (swap->I.started+1);
if ( diff < 0 )
diff = -diff;
if ( diff == 0 )
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);

90
iguana/exchanges/LP_utxo.c

@ -177,9 +177,9 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a
}
else
{
if ( up->SPV <= 0 || up->U.height == 0 )
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;
@ -472,13 +472,38 @@ cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrum
cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electrumret)
{
cJSON *array,*retjson; int32_t i,n; uint64_t balance = 0;
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
cJSON *array,*retjson,*item; int32_t i,n; uint64_t balance = 0;
if ( coin->electrum == 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
if ( (array= LP_listunspent(coin->symbol,coinaddr)) != 0 )
{
for (i=0; i<n; i++)
balance += j64bits(jitem(array,i),"value");
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
balance += LP_value_extract(item,1);
}
}
}
}
else
{
if ( strcmp(coin->smartaddr,coinaddr) == 0 )
balance = LP_unspents_load(coin->symbol,coinaddr);
else
{
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
balance += j64bits(item,"value");
}
}
}
}
}
retjson = cJSON_CreateObject();
@ -886,13 +911,25 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
if ( coin != 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);
}
}
return(1);
}
@ -965,13 +1002,13 @@ cJSON *LP_dustcombine_item(struct LP_address_utxo *up)
return(item);
}
uint64_t LP_dustcombine(cJSON *items[2],int32_t dustcombine,struct iguana_info *coin)
uint64_t LP_dustcombine(struct LP_address_utxo *ups[2],int32_t dustcombine,struct iguana_info *coin)
{
struct LP_address *ap=0; struct LP_address_utxo *up,*tmp,*min0,*min1; cJSON *txobj;
if ( coin == 0 || coin->electrum != 0 || dustcombine <= 0 || dustcombine > 2 )
return(0);
return(0);
min1 = min0 = 0;
ups[0] = ups[1] = 0;
if ( (ap= _LP_addressfind(coin,coin->smartaddr)) != 0 )
{
DL_FOREACH_SAFE(ap->utxos,up,tmp)
@ -983,7 +1020,7 @@ return(0);
else
{
free_json(txobj);
if ( LP_inventory_prevent(0,coin->symbol,up->U.txid,up->U.vout) == 0 && LP_inventory_prevent(1,coin->symbol,up->U.txid,up->U.vout) == 0 )
if ( LP_inventory_prevent(1,coin->symbol,up->U.txid,up->U.vout) == 0 )
{
if ( min1 == 0 || up->U.value < min1->U.value )
{
@ -1000,10 +1037,10 @@ return(0);
}
if ( min0 != 0 )
{
items[0] = LP_dustcombine_item(min0);
ups[0] = min0;
if ( dustcombine == 2 && min1 != 0 )
{
items[1] = LP_dustcombine_item(min1);
ups[1] = min1;
return(min0->U.value + min1->U.value);
} else return(min0->U.value);
}
@ -1050,25 +1087,38 @@ void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedfla
}
}
void LP_unspents_load(char *symbol,char *addr)
char *LP_unspents_filestr(char *symbol,char *addr)
{
char fname[1024],*arraystr; long fsize; struct iguana_info *coin; cJSON *retjson;
char fname[1024]; long fsize;
sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname);
return(OS_filestr(&fsize,fname));
}
uint64_t LP_unspents_load(char *symbol,char *addr)
{
char *arraystr; uint64_t balance = 0; int32_t i,n; cJSON *retjson,*item; struct iguana_info *coin;
if ( (coin= LP_coinfind(symbol)) != 0 )
{
sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname);
if ( (arraystr= OS_filestr(&fsize,fname)) != 0 )
if ( (arraystr= LP_unspents_filestr(symbol,addr)) != 0 )
{
if ( (retjson= cJSON_Parse(arraystr)) != 0 )
{
printf("PROCESS UNSPENTS %s\n",arraystr);
if ( electrum_process_array(coin,coin->electrum,coin->smartaddr,retjson,1) == 0 )
printf("error electrum_process_array\n");
else printf("processed %s\n",arraystr);
//printf("PROCESS UNSPENTS %s\n",arraystr);
if ( (n= cJSON_GetArraySize(retjson)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(retjson,i);
balance += j64bits(item,"value");
}
}
electrum_process_array(coin,coin->electrum,coin->smartaddr,retjson,1);
free_json(retjson);
}
free(arraystr);
}
}
return(balance);
}

3
iguana/exchanges/LP_utxos.c

@ -292,7 +292,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
uint64_t val,val2=0,tmpsatoshis,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0;
if ( symbol == 0 || symbol[0] == 0 || 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);
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);
printf("session.%u addutxo %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0);
return(0);
}
@ -826,6 +826,7 @@ int32_t LP_passphrase_init(char *passphrase,char *gui)
G.LP_sessionid = (uint32_t)time(NULL);
safecopy(G.gui,gui,sizeof(G.gui));
G.USERPASS_COUNTER = counter;
G.initializing = 0;
return(0);
}

2
iguana/exchanges/coins

File diff suppressed because one or more lines are too long

4
iguana/exchanges/coins.json

File diff suppressed because one or more lines are too long

44
iguana/exchanges/stats.c

@ -740,43 +740,62 @@ void LP_rpc_processreq(void *_ptr)
}
extern int32_t IAMLP;
int32_t LP_bindsock_reset,LP_bindsock = -1;
void stats_rpcloop(void *args)
{
static uint32_t counter;
uint16_t port; int32_t retval,sock,bindsock=-1; socklen_t clilen; struct sockaddr_in cli_addr; uint32_t ipbits,localhostbits; struct rpcrequest_info *req,*req2,*rtmp;
uint16_t port; int32_t retval,sock,initial_bindsock_reset; socklen_t clilen; struct sockaddr_in cli_addr; uint32_t ipbits,localhostbits; struct rpcrequest_info *req,*req2,*rtmp;
if ( (port= *(uint16_t *)args) == 0 )
port = 7779;
RPC_port = port;
localhostbits = (uint32_t)calc_ipbits("127.0.0.1");
while ( 1 )
initial_bindsock_reset = LP_bindsock_reset;
while ( LP_bindsock_reset == initial_bindsock_reset )
{
if ( bindsock < 0 )
//printf("LP_bindsock.%d\n",LP_bindsock);
if ( LP_bindsock < 0 )
{
while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 )
while ( (LP_bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 )
usleep(10000);
if ( counter++ < 1 )
printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock);
#ifndef _WIN32
fcntl(LP_bindsock, F_SETFL, fcntl(LP_bindsock, F_GETFL, 0) | O_NONBLOCK);
#endif
//if ( counter++ < 1 )
printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,LP_bindsock);
}
//printf("after LP_bindsock.%d\n",LP_bindsock);
clilen = sizeof(cli_addr);
sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen);
sock = accept(LP_bindsock,(struct sockaddr *)&cli_addr,&clilen);
#ifdef _WIN32
if ( sock < 0 )
{
printf("iguana_rpcloop ERROR on accept usock.%d errno %d %s\n",sock,errno,strerror(errno));
close(bindsock);
bindsock = -1;
closesocket(LP_bindsock);
LP_bindsock = -1;
continue;
}
#else
if ( sock < 0 )
{
//fprintf(stderr,".");
if ( IAMLP == 0 )
usleep(50000);
else usleep(2500);
continue;
}
#endif
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
req = calloc(1,sizeof(*req));
req->sock = sock;
req->ipbits = ipbits;
LP_rpc_processreq(req);
continue;
// this leads to cant open file errors
if ( (retval= OS_thread_create(&req->T,NULL,(void *)LP_rpc_processreq,req)) != 0 )
{
printf("error launching rpc handler on port %d, retval.%d\n",port,retval);
close(bindsock);
bindsock = -1;
closesocket(LP_bindsock);
LP_bindsock = -1;
portable_mutex_lock(&LP_gcmutex);
DL_FOREACH_SAFE(LP_garbage_collector,req2,rtmp)
{
@ -791,6 +810,7 @@ continue;
}
}
}
printf("i got killed\n");
}
#ifndef FROM_MARKETMAKER

Loading…
Cancel
Save