Browse Source

Merge pull request #491 from jl777/spvdex

dynamictrust
etomic
jl777 7 years ago
committed by GitHub
parent
commit
a53621829c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      crypto777/bitcoind_RPC.c
  2. 2
      iguana/dpow/dpow_network.c
  3. 50
      iguana/exchanges/LP_RTmetrics.c
  4. 28
      iguana/exchanges/LP_bitcoin.c
  5. 2
      iguana/exchanges/LP_cache.c
  6. 14
      iguana/exchanges/LP_coins.c
  7. 150
      iguana/exchanges/LP_commands.c
  8. 45
      iguana/exchanges/LP_include.h
  9. 186
      iguana/exchanges/LP_nativeDEX.c
  10. 116
      iguana/exchanges/LP_network.c
  11. 19
      iguana/exchanges/LP_ordermatch.c
  12. 2
      iguana/exchanges/LP_portfolio.c
  13. 66
      iguana/exchanges/LP_prices.c
  14. 17
      iguana/exchanges/LP_remember.c
  15. 107
      iguana/exchanges/LP_rpc.c
  16. 20
      iguana/exchanges/LP_signatures.c
  17. 7
      iguana/exchanges/LP_socket.c
  18. 23
      iguana/exchanges/LP_statemachine.c
  19. 304
      iguana/exchanges/LP_stats.c
  20. 21
      iguana/exchanges/LP_swap.c
  21. 2
      iguana/exchanges/LP_tradebots.c
  22. 27
      iguana/exchanges/LP_transaction.c
  23. 24
      iguana/exchanges/LP_utxo.c
  24. 41
      iguana/exchanges/LP_utxos.c
  25. 278
      iguana/exchanges/LP_zeroconf.c
  26. 3
      iguana/exchanges/claim
  27. 3
      iguana/exchanges/deposit
  28. 3
      iguana/exchanges/deposit1
  29. 2
      iguana/exchanges/install
  30. 12
      iguana/exchanges/mm.c
  31. 64
      iguana/exchanges/stats.c
  32. 3
      iguana/exchanges/tradesarray
  33. 2
      iguana/main.c

18
crypto777/bitcoind_RPC.c

@ -96,6 +96,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL )
{
retstr = jprint(result,0);
//printf("%s %s rpc retstr.%p\n",command,params,retstr);
len = strlen(retstr);
if ( retstr[0] == '"' && retstr[len-1] == '"' )
{
@ -112,7 +113,10 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
rpcstr = 0;
}
if ( rpcstr != 0 )
{
//printf("free rpcstr.%p\n",rpcstr);
free(rpcstr);
}
} else retstr = rpcstr;
free_json(json);
//fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
@ -231,30 +235,30 @@ try_again:
free(databuf);
databuf = 0;
}
retstr = chunk.memory; // retstr = s.ptr;
if ( res != CURLE_OK )
{
numretries++;
if ( specialcase != 0 || timeout != 0 )
{
//printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
free(chunk.memory); //free(s.ptr);
//printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,retstr,res);
free(retstr);
return(0);
}
else if ( numretries >= 4 )
{
printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
//printf("Maximum number of retries exceeded!\n");
free(chunk.memory);//free(s.ptr);
free(retstr);
return(0);
}
free(chunk.memory);//free(s.ptr);
free(retstr);
sleep((1<<numretries));
goto try_again;
}
else
{
retstr = chunk.memory; // retstr = s.ptr;
if ( command != 0 && specialcase == 0 )
{
count++;
@ -279,9 +283,6 @@ try_again:
return(retstr);
}
}
//printf("bitcoind_RPC: impossible case\n");
//free(s.ptr);
//return(0);
}
/************************************************************************
@ -337,6 +338,7 @@ static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data)
{
//printf("curl needs %d more\n",(int32_t)realsize);
mem->memory = (ptr != 0) ? realloc(mem->memory,needed) : malloc(needed);
//printf("mem->memory.%p len.%d\n",mem->memory,(int32_t)needed);
mem->allocsize = needed;
}
//mem->memory = (ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1);

2
iguana/dpow/dpow_network.c

@ -584,6 +584,8 @@ char *dex_response(int32_t *broadcastflagp,struct supernet_info *myinfo,struct d
{
char buf[65],*retstr = 0; int32_t i,datalen; bits256 hash2; cJSON *retjson=0; struct iguana_info *coin; struct dex_request dexreq;
*broadcastflagp = 0;
return(clonestr("{\"error\":\"basilisk disabled\"}"));
if ( strcmp(dexp->handler,"request") == 0 )
{
datalen = dex_rwrequest(0,dexp->packet,&dexreq);

50
iguana/exchanges/LP_RTmetrics.c

@ -27,11 +27,13 @@ struct LP_metricinfo
int32_t ind,numutxos,age,pendingswaps;
};
#define LP_NUMRT 1024
struct LP_RTmetrics_pendings
{
char refbase[65],refrel[65];
int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[1024];
bits256 avoidtxids[8192],whitelist[1024],blacklist[1024],pending_pubkeys[1024];
char refbase[128],refrel[128];
int64_t pending_kmdvalue[LP_NUMRT];
int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[LP_NUMRT];
bits256 avoidtxids[8192],whitelist[LP_NUMRT],blacklist[LP_NUMRT],pending_pubkeys[LP_NUMRT];
} LP_RTmetrics;
int32_t LP_bits256_find(bits256 *list,int32_t num,bits256 val)
@ -72,11 +74,14 @@ int32_t LP_RTmetrics_blacklistadd(bits256 pubkey)
return(LP_bits256_add("LP_RTmetrics_blacklistadd blacklist",LP_RTmetrics.blacklist,&LP_RTmetrics.numblacklist,(int32_t)(sizeof(LP_RTmetrics.blacklist)/sizeof(*LP_RTmetrics.blacklist)),pubkey));
}
int32_t LP_RTmetrics_pendingswap(bits256 pubkey)
int32_t LP_RTmetrics_pendingswap(bits256 pubkey,int64_t kmdvalue)
{
int32_t ind;
if ( (ind= LP_bits256_add("LP_RTmetrics_pendingswap",LP_RTmetrics.pending_pubkeys,&LP_RTmetrics.numpendings,(int32_t)(sizeof(LP_RTmetrics.pending_pubkeys)/sizeof(*LP_RTmetrics.pending_pubkeys)),pubkey)) >= 0 )
{
LP_RTmetrics.pending_swaps[ind]++;
LP_RTmetrics.pending_kmdvalue[ind] += kmdvalue;
}
return(ind);
}
@ -113,7 +118,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums
base = "";
if ( (rel= jstr(item,"rel")) == 0 )
rel = "";
if ( strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 )
if ( refbase[0] != 0 && strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 )
continue;
if ( refrel[0] != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 )
continue;
aliceid = j64bits(item,"aliceid");
basesatoshis = SATOSHIDEN * jdouble(item,"basevol");
@ -123,8 +130,8 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums
price = jdouble(item,"price");
requestid = juint(item,"requestid");
quoteid = juint(item,"quoteid");
LP_RTmetrics_pendingswap(srcpub);
LP_RTmetrics_pendingswap(destpub);
LP_RTmetrics_pendingswap(srcpub,LP_kmdvalue(base,basesatoshis));
LP_RTmetrics_pendingswap(destpub,LP_kmdvalue(rel,relsatoshis));
if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) // no need for this
{
if ( (swapjson= cJSON_Parse(retstr)) != 0 )
@ -142,9 +149,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums
}
}
void LP_RTmetrics_update(char *base,char *rel)
/*void LP_RTmetrics_init()
{
struct LP_pubkeyinfo *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 zero; char *retstr; cJSON *statsjson,*swaps;
struct LP_pubkey_info *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 pubkey,zero; cJSON *statsjson,*swaps;
memset(&LP_RTmetrics,0,sizeof(LP_RTmetrics));
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
@ -152,31 +159,38 @@ void LP_RTmetrics_update(char *base,char *rel)
LP_RTmetrics_whitelistadd(pubp->pubkey);
else if ( pubp->istrusted < 0 )
LP_RTmetrics_blacklistadd(pubp->pubkey);
pubp->swaps_kmdvalue = 0;
}
futuretime = (uint32_t)time(NULL) + 3600*100;
memset(zero.bytes,0,sizeof(zero));
if ( (retstr= LP_statslog_disp(100,futuretime,futuretime,"",zero)) != 0 )
{
if ( (statsjson= cJSON_Parse(retstr)) != 0 )
if ( (statsjson= LP_statslog_disp(futuretime,futuretime,"",zero,0,0)) != 0 )
{
if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 )
{
//printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0));
if ( numswaps > 0 )
LP_RTmetrics_swapsinfo(base,rel,swaps,numswaps);
LP_RTmetrics_swapsinfo("","",swaps,numswaps);
}
free_json(statsjson);
}
free(retstr);
}
for (i=0; i<LP_RTmetrics.numpendings; i++)
{
pubkey = LP_RTmetrics.pending_pubkeys[i];
if ( LP_RTmetrics.pending_swaps[i] > LP_MAXPENDING_SWAPS )
{
char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,LP_RTmetrics.pending_pubkeys[i]),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS);
LP_RTmetrics_blacklistadd(LP_RTmetrics.pending_pubkeys[i]);
char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS);
LP_RTmetrics_blacklistadd(pubkey);
}
else if ( (pubp= LP_pubkeyfind(pubkey)) != 0 )
{
char str[65]; printf("%s has %d pending swaps %.8f kmdvalue\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],dstr(LP_RTmetrics.pending_kmdvalue[i]));
pubp->swaps_kmdvalue = LP_RTmetrics.pending_kmdvalue[i];
}
}
//printf("%d pubkeys have pending swaps, whitelist.%d blacklist.%d avoidtxids.%d\n",LP_RTmetrics.numpendings,LP_RTmetrics.numwhitelist,LP_RTmetrics.numblacklist,LP_RTmetrics.numavoidtxids);
}
}*/
double _LP_RTmetric_calc(struct LP_metricinfo *mp,double bestprice,double maxprice,double relvolume)
{

28
iguana/exchanges/LP_bitcoin.c

@ -1959,13 +1959,13 @@ int32_t bitcoin_timelockspend(uint8_t *script,int32_t n,uint8_t rmd160[20],uint3
return(n);
}
int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t cltv_rmd160[20],uint8_t anytime_rmd160[20])
int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t *cltvpub33,uint8_t *elsepub33)
{
script[n++] = SCRIPT_OP_IF;
n = bitcoin_checklocktimeverify(script,n,unlocktimestamp);
n = bitcoin_standardspend(script,n,cltv_rmd160);
n = bitcoin_pubkeyspend(script,n,cltvpub33);
script[n++] = SCRIPT_OP_ELSE;
n = bitcoin_standardspend(script,n,anytime_rmd160);
n = bitcoin_pubkeyspend(script,n,elsepub33);
script[n++] = SCRIPT_OP_ENDIF;
calc_rmd160_sha256(p2sh_rmd160,script,n);
return(n);
@ -3309,9 +3309,9 @@ bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2sht
dest.vins[i].userdatalen = 0;
}
len = iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys,zcash);
for (i=0; i<len; i++)
printf("%02x",serialized[i]);
printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen);
//for (i=0; i<len; i++)
// printf("%02x",serialized[i]);
//printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen);
if ( len > 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 &&
{
#ifdef BTC2_VERSION
@ -3322,7 +3322,7 @@ bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2sht
revsigtxid = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31-i] = revsigtxid.bytes[i];
char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out);
//char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out);
}
free(dest.vins);
free(dest.vouts);
@ -3355,6 +3355,20 @@ int32_t iguana_rwjoinsplit(int32_t rwflag,uint8_t *serialized,struct iguana_msgj
return(len);
}
uint32_t LP_sighash(char *symbol,int32_t zcash)
{
uint32_t sighash;
sighash = SIGHASH_ALL;
if ( zcash == LP_IS_BITCOINCASH )
sighash |= SIGHASH_FORKID;
else if ( zcash == LP_IS_BITCOINGOLD )
{
sighash |= SIGHASH_FORKID;
sighash |= (LP_IS_BITCOINGOLD << 8);
}
return(sighash);
}
int32_t iguana_rwmsgtx(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash)
{
int32_t i,j,n,segtxlen,len = 0,extraused=0; uint32_t tmp,segitems; uint8_t *segtx=0,segwitflag=0,spendscript[IGUANA_MAXSCRIPTSIZE],*txstart = serialized,*sigser=0; char txidstr[65]; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid;

2
iguana/exchanges/LP_cache.c

@ -330,7 +330,7 @@ uint64_t LP_unspents_load(char *symbol,char *addr)
balance += j64bits(item,"value");
}
}
electrum_process_array(coin,coin->electrum,coin->smartaddr,retjson,1);
electrum_process_array(coin,coin->electrum,addr,retjson,1);
free_json(retjson);
}
free(arraystr);

14
iguana/exchanges/LP_coins.c

@ -286,20 +286,6 @@ cJSON *LP_coinsjson(int32_t showwif)
return(array);
}
uint32_t LP_sighash(char *symbol,int32_t zcash)
{
uint32_t sighash;
sighash = SIGHASH_ALL;
if ( zcash == LP_IS_BITCOINCASH )
sighash |= SIGHASH_FORKID;
else if ( zcash == LP_IS_BITCOINGOLD )
{
sighash |= SIGHASH_FORKID;
sighash |= (LP_IS_BITCOINGOLD << 8);
}
return(sighash);
}
char *LP_getcoin(char *symbol)
{
int32_t numenabled,numdisabled; struct iguana_info *coin,*tmp; cJSON *item=0,*retjson;

150
iguana/exchanges/LP_commands.c

@ -38,7 +38,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
method = jstr(argjson,"method");
if ( method != 0 && (strcmp(method,"addr_unspents") == 0 || strcmp(method,"uitem") == 0 || strcmp(method,"postutxos") == 0) )
return(0);
//printf("stats_JSON %s\n",method);
//printf("stats_JSON.(%s)\n",jprint(argjson,0));
/*if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) )
{
if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 )
@ -68,8 +68,16 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
}
if ( strcmp(method,"hello") == 0 )
{
//int32_t i; cJSON *array = cJSON_CreateArray();
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"status","got hello");
//for (i=0; i<10000; i++)
// jaddinum(array,i);
//jadd(retjson,"array",array);
return(jprint(retjson,1));
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}"));
//return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}"));
}
/*else if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 )
{
@ -94,8 +102,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
else if ( strcmp(method,"help") == 0 )
return(clonestr("{\"result\":\" \
available localhost RPC commands: \n \
pricearray(base, rel, starttime=0, endtime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
setprice(base, rel, price)\n\
setprice(base, rel, price, broadcast=1)\n\
autoprice(base, rel, fixed, minprice, margin, refbase, refrel, factor, offset)*\n\
goal(coin=*, val=<autocalc>)\n\
myprice(base, rel)\n\
@ -103,7 +110,9 @@ enable(coin)\n\
disable(coin)\n\
notarizations(coin)\n\
parselog()\n\
statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\
statsdisp(starttime=0, endtime=0, gui="", pubkey="", base="", rel="")\n\
tradesarray(base, rel, starttime=<now>-timescale*1024, endtime=<now>, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]\n\
pricearray(base, rel, starttime=0, endtime=0, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
getrawtransaction(coin, txid)\n\
inventory(coin, reset=0, [passphrase=])\n\
bestfit(rel, relvolume)\n\
@ -146,7 +155,8 @@ bot_settings(botid, newprice, newvolume)\n\
bot_status(botid)\n\
bot_stop(botid)\n\
bot_pause(botid)\n\
bot_resume(botid)\n\
zeroconf_deposit(weeks, amount, broadcast=0)\n\
zeroconf_claim(address, expiration=0)\n\
\"}"));
//sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\
@ -183,6 +193,26 @@ bot_resume(botid)\n\
return(jprint(retjson,1));
}
}
else if ( strcmp(method,"zeroconf_deposit") == 0 )
{
if ( (ptr= LP_coinsearch("KMD")) != 0 )
{
if ( jint(argjson,"weeks") < 0 || jdouble(argjson,"amount") < 10. )
return(clonestr("{\"error\":\"deposit_create needs to have weeks and amount\"}"));
else return(LP_zeroconf_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jint(argjson,"broadcast")));
}
return(clonestr("{\"error\":\"cant find KMD\"}"));
}
else if ( strcmp(method,"zeroconf_claim") == 0 )
{
if ( (ptr= LP_coinsearch("KMD")) != 0 )
{
if ( jstr(argjson,"address") == 0 )
return(clonestr("{\"error\":\"deposit_claim needs to have address\"}"));
else return(LP_zeroconf_claim(ptr,jstr(argjson,"address"),juint(argjson,"expiration")));
}
return(clonestr("{\"error\":\"cant find KMD\"}"));
}
/*else if ( strcmp(method,"sendmessage") == 0 )
{
if ( jobj(argjson,"method2") == 0 )
@ -242,14 +272,13 @@ bot_resume(botid)\n\
}
else if ( strcmp(method,"parselog") == 0 )
{
bits256 zero; int32_t n = LP_statslog_parse();
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
return(LP_statslog_disp(n,2000000000,2000000000,"",zero));
return(jprint(LP_statslog_disp(2000000000,2000000000,"",zero,0,0),1));
}
else if ( strcmp(method,"statsdisp") == 0 )
{
int32_t n = LP_statslog_parse();
return(LP_statslog_disp(n,juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey")));
return(jprint(LP_statslog_disp(juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"),jstr(argjson,"base"),jstr(argjson,"rel")),1));
}
else if ( strcmp(method,"secretaddresses") == 0 )
{
@ -262,13 +291,31 @@ bot_resume(botid)\n\
{
uint32_t requestid,quoteid;
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
{
return(basilisk_swapentry(requestid,quoteid));
}
else if ( coin[0] != 0 )
return(basilisk_swapentries(coin,0,jint(argjson,"limit")));
else if ( base[0] != 0 && rel[0] != 0 )
return(basilisk_swapentries(base,rel,jint(argjson,"limit")));
else return(basilisk_swaplist(0,0));
}
else if ( strcmp(method,"dynamictrust") == 0 )
{
struct LP_address *ap; char *coinaddr;
if ( (ptr= LP_coinsearch("KMD")) != 0 && (coinaddr= jstr(argjson,"address")) != 0 )
{
if ( (ap= LP_addressfind(ptr,coinaddr)) != 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"address",coinaddr);
jaddnum(retjson,"zcredits",dstr(ap->zeroconf_credits));
return(jprint(retjson,1));
}
}
return(clonestr("{\"error\":\"cant find address\"}"));
}
else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 )
return(retstr);
if ( base[0] != 0 && rel[0] != 0 )
@ -280,6 +327,20 @@ bot_resume(botid)\n\
return(clonestr("{\"error\":\"couldnt set autoprice\"}"));
else return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"pricearray") == 0 )
{
uint32_t firsttime;
if ( base[0] != 0 && rel[0] != 0 )
{
if ( (firsttime= juint(argjson,"starttime")) < time(NULL)-30*24*3600 )
firsttime = (uint32_t)(time(NULL)-30*24*3600);
return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"endtime"),jint(argjson,"timescale")),1));
} else return(clonestr("{\"error\":\"pricearray needs base and rel\"}"));
}
else if ( strcmp(method,"tradesarray") == 0 )
{
return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1));
}
if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"error\":\"at least one of coins disabled\"}"));
price = jdouble(argjson,"price");
@ -289,22 +350,10 @@ bot_resume(botid)\n\
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
// return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
}
else if ( strcmp(method,"pricearray") == 0 )
{
uint32_t firsttime;
if ( base[0] != 0 && rel[0] != 0 )
{
if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 )
firsttime = (uint32_t)(time(NULL)-30*24*3600);
return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1));
} else return(clonestr("{\"error\":\"pricearray needs base and rel\"}"));
else if ( jint(argjson,"broadcast") != 0 || jobj(argjson,"broadcast") == 0 )
return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
else return(clonestr("{\"result\":\"success\"}"));
}
/*else if ( strcmp(method,"pricearray") == 0 )
{
return(jprint(LP_pricearray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1));
}*/
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"myprice") == 0 )
@ -361,13 +410,19 @@ bot_resume(botid)\n\
{
ptr->inactive = 0;
cJSON *array;
if ( ptr->smartaddr[0] != 0 )
LP_unspents_load(coin,ptr->smartaddr);
if ( LP_getheight(ptr) <= 0 )
{
ptr->inactive = (uint32_t)time(NULL);
return(clonestr("{\"error\":\"coin cant be activated till synced\"}"));
} else LP_unspents_load(coin,ptr->smartaddr);
}
else
{
if ( ptr->smartaddr[0] != 0 )
LP_unspents_load(coin,ptr->smartaddr);
LP_unspents_load(coin,ptr->smartaddr);
if ( strcmp(ptr->symbol,"KMD") == 0 )
LP_importaddress("KMD",BOTS_BONDADDRESS);
}
array = cJSON_CreateArray();
jaddi(array,LP_coinjson(ptr,0));
return(jprint(array,1));
@ -397,20 +452,13 @@ bot_resume(botid)\n\
LP_address(ptr,coinaddr);
if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 )
{
LP_listunspent_issue(coin,coinaddr,2);
LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519);
//LP_smartutxos_push(ptr);
if ( ptr->electrum != 0 )
return(LP_unspents_filestr(coin,ptr->smartaddr));
else return(jprint(LP_address_utxos(ptr,coinaddr,1),1));
//LP_listunspent_issue(coin,coinaddr,2);
//LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519);
}
else
{
return(clonestr("{\"error\":\"not my address\"}"));
return(jprint(LP_listunspent(coin,coinaddr),1));
}
}
return(jprint(LP_address_utxos(ptr,coinaddr,1),1));
} else return(clonestr("{\"error\":\"no address specified\"}"));
return(clonestr("{\"error\":\"no address specified\"}"));
} else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"balance") == 0 )
@ -539,9 +587,22 @@ bot_resume(botid)\n\
}
argjson = reqjson;
}
if ( strcmp(method,"gettradestatus") == 0 )
retstr = clonestr("{\"result\":\"success\"}");
}
else
{
if ( strcmp(method,"gettradestatus") == 0 )
return(LP_gettradestatus(j64bits(argjson,"aliceid")));
else if ( strcmp(method,"tradesarray") == 0 )
{
return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1));
}
}
// received response
if ( strcmp(method,"postprice") == 0 )
if ( strcmp(method,"swapstatus") == 0 )
return(LP_swapstatus_recv(argjson));
else if ( strcmp(method,"postprice") == 0 )
return(LP_postprice_recv(argjson));
else if ( strcmp(method,"postutxos") == 0 )
return(LP_postutxos_recv(argjson));
@ -568,8 +629,15 @@ bot_resume(botid)\n\
else if ( strcmp(method,"tradestatus") == 0 )
{
bits256 zero; cJSON *tmpjson;
LP_tradecommand_log(argjson);
printf("GOT TRADESTATUS! %s\n",jprint(argjson,0));
//printf("GOT TRADESTATUS! %s\n",jprint(argjson,0));
if ( LP_statslog_parse() > 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (tmpjson= LP_statslog_disp(2000000000,2000000000,"",zero,0,0))) // pending swaps
free_json(tmpjson);
}
retstr = clonestr("{\"result\":\"success\"}");
}
else if ( strcmp(method,"wantnotify") == 0 )

45
iguana/exchanges/LP_include.h

@ -23,7 +23,7 @@
#define LP_MAJOR_VERSION "0"
#define LP_MINOR_VERSION "1"
#define LP_BUILD_NUMBER "15256"
#define LP_BUILD_NUMBER "15377"
#define LP_BARTERDEX_VERSION 1
#define LP_MAGICBITS 8
@ -49,6 +49,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define LP_ELECTRUM_KEEPALIVE 60
#define LP_ELECTRUM_MAXERRORS 777
#define LP_MEMPOOL_TIMEINCR 10
#define LP_SCREENWIDTH 1024
#define LP_MIN_PEERS 8
#define LP_MAX_PEERS 32
@ -82,7 +83,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 100
#define LP_MINCLIENTVOL 20
#define LP_MINSIZE_TXFEEMULT 10
#define LP_REQUIRED_TXFEE 0.8
@ -98,6 +99,10 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146"
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu"
#define INSTANTDEX_KMD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf"
#define BOTS_BONDADDRESS "RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P"
#define BOTS_BONDPUBKEY33 "03e641d22e1ff5a7d45c8880537e0b0a114d7b9fee2c18a6b4a8a80b6285292990"
#define LP_WEEKMULT (7 * 24 * 2600)
#define LP_FIRSTWEEKTIME 1510790400 // must be 0 mod LP_WEEKMULT
//#define BASILISK_DISABLEWAITTX
//#define BASILISK_DISABLESENDTX
@ -268,7 +273,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 loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime;
uint32_t loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime,electrumzeroconf;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms;
char symbol[128],smartaddr[64],userpass[1024],serverport[128];
// portfolio
@ -317,7 +322,7 @@ struct LP_address
UT_hash_handle hh;
struct LP_address_utxo *utxos;
bits256 pubkey;
int64_t balance,total;
int64_t balance,total,zeroconf_credits;
uint32_t timestamp,n,unspenttime;
int32_t unspentheight;
char coinaddr[40];
@ -373,14 +378,27 @@ struct LP_pubkey_quote
uint8_t baseind,relind,numutxos,scale;
};
struct LP_swapstats
{
UT_hash_handle hh;
struct LP_quoteinfo Q;
bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent;
double qprice;
uint64_t aliceid;
uint32_t ind,methodind,finished,expired,lasttime;
char alicegui[32],bobgui[32];
};
struct LP_pubswap { struct LP_pubswap *next,*prev; struct LP_swapstats *swap; };
#define LP_MAXPRICEINFOS 256
struct LP_pubkeyinfo
struct LP_pubkey_info
{
UT_hash_handle hh;
bits256 pubkey;
struct LP_pubkey_quote *quotes;
//float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS];
//uint32_t timestamps[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS];
struct LP_pubswap *bobswaps,*aliceswaps;
uint64_t dynamictrust;
uint32_t timestamp,numerrors,lasttime;
int32_t istrusted;
uint8_t rmd160[20],sig[65],pubsecp[33],siglen;
@ -400,7 +418,7 @@ struct electrum_info
};
uint32_t LP_sighash(char *symbol,int32_t zcash);
int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item);
int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item);
int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp);
int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson);
struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr);
@ -408,7 +426,7 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u
void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx);
uint32_t basilisk_requestid(struct basilisk_request *rp);
uint32_t basilisk_quoteid(struct basilisk_request *rp);
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp);
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust);
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params);
uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend);
//double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub);
@ -421,10 +439,12 @@ struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port);
uint64_t LP_value_extract(cJSON *obj,int32_t addinterest);
int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen);
int64_t LP_kmdvalue(char *symbol,int64_t satoshis);
int64_t LP_komodo_interest(bits256 txid,int64_t value);
void LP_availableset(bits256 txid,int32_t vout);
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2);
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock);
int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item);
void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag);
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
//void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
@ -440,6 +460,7 @@ 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,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height);
cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr);
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);
@ -453,7 +474,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_
struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout);
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);
cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel);
uint32_t LP_heighttime(char *symbol,int32_t height);
uint64_t LP_unspents_load(char *symbol,char *addr);
int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
@ -472,6 +493,8 @@ 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);
uint32_t LP_atomic_locktime(char *base,char *rel);
struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey);
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired);
char *LP_unspents_filestr(char *symbol,char *addr);
cJSON *bitcoin_data2json(char *symbol,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);
@ -481,6 +504,8 @@ int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid);
double LP_getestimatedrate(struct iguana_info *coin);
struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout);
struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout);
int64_t LP_dynamictrust(bits256 pubkey,int64_t kmdvalue);
struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr);
void LP_listunspent_query(char *symbol,char *coinaddr);
int32_t bitcoin_priv2wif(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype);

186
iguana/exchanges/LP_nativeDEX.c

@ -17,19 +17,20 @@
// LP_nativeDEX.c
// marketmaker
//
// feature requests:
// electrum memleak?
// alice waiting for bestprice
// MNZ getcoin strangeness
// [{"date":1405699200,"high":0.0045388,"low":0.00403001,"open":0.00404545,"close":0.00435873,"relvol":44.34555992,"basevol":10311.88079097,"aveprice":0.00430043}, // minute,
// trying to do bot_sell and the output he sent me is this
//{"base":"KMD","rel":"MNZ","basevolume":"0.08","minprice":5.608418011097937,"gui":"gecko","method":"bot_sell","userpass":"4011dddbfd920f9fab037907c2a13ba7eec207245487efa61cd0c484f8b1d607"}
//{"error":"not enough funds","coin":"KMD","abalance":0.00204856,"balance":9.9999,"relvolume":0.08,"txfees":0.001,"shortfall":-9.9189,"withdraw":
//i assume bot_sell detected he didn't had the proper utxos, tried to make some with the withdraw-method and failed with "not enough funds"
// the reason: bot_sell uses basevolume:0.08 and the withdraw-method uses relvolume:0.08
// USD paxprice based USDvalue in portfolio
// cancel bid/ask
// https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki for signing BCH/BTG
// improve critical section detection when parallel trades
// reduce mem: dont redundant store pubkey utxo info
//
// bugs, validations:
// waiting for alice and alice disconnects, can find bobpayment based on Q.txid
// portfolio value based on ask?
// disable basilisk
// verify encrypted destpubkey, broadcast:0 setprice
// improve critical section detection when parallel trades
// previously, it used to show amount, kmd equiv, perc
// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections
// bigendian architectures need to use little endian for sighash calcs
@ -89,21 +90,21 @@ void LP_millistats_update(struct LP_millistats *mp)
}
#include "LP_include.h"
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex;
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex,LP_logmutex;
int32_t LP_canbind;
char *Broadcaststr,*Reserved_msgs[2][1000];
int32_t num_Reserved_msgs[2],max_Reserved_msgs[2];
struct LP_peerinfo *LP_peerinfos,*LP_mypeer;
struct LP_forwardinfo *LP_forwardinfos;
struct iguana_info *LP_coins;
struct LP_pubkeyinfo *LP_pubkeyinfos;
struct LP_pubkey_info *LP_pubkeyinfos;
struct rpcrequest_info *LP_garbage_collector;
struct LP_address_utxo *LP_garbage_collector2;
//uint32_t LP_deadman_switch;
uint16_t LP_fixed_pairport,LP_publicport;
uint32_t LP_lastnonce,LP_counter,LP_swap_endcritical,LP_swap_critical;
uint32_t LP_lastnonce,LP_counter,LP_swap_endcritical,LP_swap_critical,LP_RTcount,LP_swapscount;
int32_t LP_mybussock = -1;
int32_t LP_mypubsock = -1;
int32_t LP_mypullsock = -1;
@ -181,6 +182,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_transaction.c"
#include "LP_stats.c"
#include "LP_remember.c"
#include "LP_zeroconf.c"
#include "LP_swap.c"
#include "LP_peers.c"
#include "LP_utxos.c"
@ -194,7 +196,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
{
char *retstr=0;
char *retstr=0; cJSON *retjson; bits256 zero;
if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 )
return(0);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 )
@ -205,7 +207,13 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson
//if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
//LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
}
} //else printf("finished tradecommand (%s)\n",jprint(argjson,0));
}
else if ( LP_statslog_parse() > 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (retjson= LP_statslog_disp(2000000000,2000000000,"",zero,0,0))) // pending swaps
free_json(retjson);
}
return(retstr);
}
@ -315,8 +323,8 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,
else
{
memset(zero.bytes,0,sizeof(zero));
/*if ( (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"request") == 0 || strcmp(method,"requested") == 0 || strcmp(method,"connect") == 0 || strcmp(method,"connected") == 0) )
printf("broadcast.(%s)\n",Broadcaststr);*/
if ( 0 && (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"tradestatus") == 0) )
printf("broadcast.(%s)\n",Broadcaststr);
LP_reserved_msg(0,"","",zero,jprint(reqjson,0));
}
retstr = clonestr("{\"result\":\"success\"}");
@ -538,6 +546,11 @@ void LP_coinsloop(void *_coins)
coin->longestchain = LP_getheight(coin);
if ( (ep= coin->electrum) != 0 )
{
if ( strcmp("KMD",coin->symbol) == 0 && coin->electrumzeroconf == 0 )
{
LP_zeroconf_deposits(coin);
coin->electrumzeroconf = (uint32_t)time(NULL);
}
if ( (backupep= ep->prev) == 0 )
backupep = ep;
if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 )
@ -547,8 +560,9 @@ void LP_coinsloop(void *_coins)
}
HASH_ITER(hh,coin->addresses,ap,atmp)
{
break;
//printf("call unspent %s\n",ap->coinaddr);
if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 )
if ( strcmp(coin->smartaddr,ap->coinaddr) != 0 && (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 )
free_json(retjson);
}
if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 )
@ -647,7 +661,7 @@ void LP_coinsloop(void *_coins)
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport)
{
static uint32_t counter;
static uint32_t counter,didzeroconf;
struct iguana_info *coin,*ctmp; char *origipaddr; uint32_t now; int32_t height,nonz = 0;
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
@ -656,6 +670,11 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
now = (uint32_t)time(NULL);
if ( coin->inactive == 0 && didzeroconf == 0 && strcmp("KMD",coin->symbol) == 0 )
{
LP_zeroconf_deposits(coin);
didzeroconf = now;
}
if ( (coin->addr_listunspent_requested != 0 && now > coin->lastpushtime+LP_ORDERBOOK_DURATION*.5) || now > coin->lastpushtime+LP_ORDERBOOK_DURATION*5 )
{
//printf("PUSH addr_listunspent_requested %u\n",coin->addr_listunspent_requested);
@ -694,7 +713,12 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins)
{
if ( LP_getheight(coin) <= 0 )
coin->inactive = (uint32_t)time(NULL);
else LP_unspents_load(coin->symbol,coin->smartaddr);
else
{
LP_unspents_load(coin->symbol,coin->smartaddr);
if ( strcmp(coin->symbol,"KMD") == 0 )
LP_importaddress("KMD",BOTS_BONDADDRESS);
}
if ( coin->txfee == 0 && strcmp(coin->symbol,"BTC") != 0 )
coin->txfee = LP_MIN_TXFEE;
}
@ -811,7 +835,7 @@ void LP_privkeysloop(void *ctx)
void LP_swapsloop(void *ignore)
{
char *retstr;
char *retstr; struct iguana_info *coin;
strcpy(LP_swapsloop_stats.name,"LP_swapsloop");
LP_swapsloop_stats.threshold = 605000.;
sleep(50);
@ -823,6 +847,124 @@ void LP_swapsloop(void *ignore)
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
free(retstr);
sleep(600);
if ( (coin= LP_coinfind("KMD")) != 0 )
LP_zeroconf_deposits(coin);
}
}
void gc_loop(void *arg)
{
uint32_t now; struct LP_address_utxo *up,*utmp; struct rpcrequest_info *req,*rtmp; int32_t flag = 0;
strcpy(LP_gcloop_stats.name,"gc_loop");
LP_gcloop_stats.threshold = 11000.;
while ( 1 )
{
flag = 0;
LP_millistats_update(&LP_gcloop_stats);
portable_mutex_lock(&LP_gcmutex);
DL_FOREACH_SAFE(LP_garbage_collector,req,rtmp)
{
DL_DELETE(LP_garbage_collector,req);
//printf("garbage collect ipbits.%x\n",req->ipbits);
free(req);
flag++;
}
now = (uint32_t)time(NULL);
DL_FOREACH_SAFE(LP_garbage_collector2,up,utmp)
{
if ( now > (uint32_t)up->spendheight+120 )
{
DL_DELETE(LP_garbage_collector2,up);
//char str[65]; printf("garbage collect %s/v%d lag.%d\n",bits256_str(str,up->U.txid),up->U.vout,now-up->spendheight);
free(up);
}
flag++;
}
portable_mutex_unlock(&LP_gcmutex);
if ( 0 && flag != 0 )
printf("gc_loop.%d\n",flag);
sleep(10);
}
}
void queue_loop(void *arg)
{
struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0;
strcpy(queue_loop_stats.name,"queue_loop");
queue_loop_stats.threshold = 1000.;
while ( 1 )
{
LP_millistats_update(&queue_loop_stats);
//printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0);
n = nonz = flag = 0;
DL_FOREACH_SAFE(LP_Q,ptr,tmp)
{
n++;
flag = 0;
if ( ptr->sock >= 0 )
{
if ( ptr->notready == 0 || (LP_rand() % ptr->notready) == 0 )
{
if ( LP_sockcheck(ptr->sock) > 0 )
{
bits256 magic;
magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256)));
memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic));
if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen )
printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen);
else flag++;
ptr->sock = -1;
if ( ptr->peerind > 0 )
ptr->starttime = (uint32_t)time(NULL);
}
else
{
if ( ptr->notready++ > 1000 )
flag = 1;
}
}
}
else if ( 0 && time(NULL) > ptr->starttime+13 )
{
LP_crc32find(&duplicate,-1,ptr->crc32);
if ( duplicate > 0 )
{
LP_Qfound++;
if ( (LP_Qfound % 100) == 0 )
printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound);
flag++;
}
else if ( 0 ) // too much beyond duplicate filter when network is busy
{
printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound);
ptr->peerind++;
if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 )
{
printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q);
flag++;
LP_Qerrors++;
}
}
}
if ( flag != 0 )
{
nonz++;
portable_mutex_lock(&LP_networkmutex);
DL_DELETE(LP_Q,ptr);
portable_mutex_unlock(&LP_networkmutex);
free(ptr);
ptr = 0;
break;
}
}
if ( arg == 0 )
break;
if ( nonz == 0 )
{
if ( IAMLP == 0 )
usleep(50000);
else usleep(10000);
}
}
}
@ -969,6 +1111,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
portable_mutex_init(&LP_nanorecvsmutex);
portable_mutex_init(&LP_tradebotsmutex);
portable_mutex_init(&LP_cJSONmutex);
portable_mutex_init(&LP_logmutex);
myipaddr = clonestr("127.0.0.1");
#ifndef _WIN32
#ifndef FROM_JS
@ -1125,6 +1268,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
exit(-1);
}
int32_t nonz;
LP_statslog_parse();
while ( 1 )
{
nonz = 0;

116
iguana/exchanges/LP_network.c

@ -265,122 +265,6 @@ int32_t LP_peerindsock(int32_t *peerindp)
return(-1);
}
void gc_loop(void *arg)
{
uint32_t now; struct LP_address_utxo *up,*utmp; struct rpcrequest_info *req,*rtmp; int32_t flag = 0;
strcpy(LP_gcloop_stats.name,"gc_loop");
LP_gcloop_stats.threshold = 11000.;
while ( 1 )
{
flag = 0;
LP_millistats_update(&LP_gcloop_stats);
portable_mutex_lock(&LP_gcmutex);
DL_FOREACH_SAFE(LP_garbage_collector,req,rtmp)
{
DL_DELETE(LP_garbage_collector,req);
//printf("garbage collect ipbits.%x\n",req->ipbits);
free(req);
flag++;
}
now = (uint32_t)time(NULL);
DL_FOREACH_SAFE(LP_garbage_collector2,up,utmp)
{
if ( now > (uint32_t)up->spendheight+120 )
{
DL_DELETE(LP_garbage_collector2,up);
//char str[65]; printf("garbage collect %s/v%d lag.%d\n",bits256_str(str,up->U.txid),up->U.vout,now-up->spendheight);
free(up);
}
flag++;
}
portable_mutex_unlock(&LP_gcmutex);
if ( 0 && flag != 0 )
printf("gc_loop.%d\n",flag);
sleep(10);
}
}
void queue_loop(void *arg)
{
struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0;
strcpy(queue_loop_stats.name,"queue_loop");
queue_loop_stats.threshold = 1000.;
while ( 1 )
{
LP_millistats_update(&queue_loop_stats);
//printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0);
n = nonz = flag = 0;
DL_FOREACH_SAFE(LP_Q,ptr,tmp)
{
n++;
flag = 0;
if ( ptr->sock >= 0 )
{
if ( ptr->notready == 0 || (LP_rand() % ptr->notready) == 0 )
{
if ( LP_sockcheck(ptr->sock) > 0 )
{
bits256 magic;
magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256)));
memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic));
if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen )
printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen);
else flag++;
ptr->sock = -1;
if ( ptr->peerind > 0 )
ptr->starttime = (uint32_t)time(NULL);
}
else
{
if ( ptr->notready++ > 1000 )
flag = 1;
}
}
}
else if ( 0 && time(NULL) > ptr->starttime+13 )
{
LP_crc32find(&duplicate,-1,ptr->crc32);
if ( duplicate > 0 )
{
LP_Qfound++;
if ( (LP_Qfound % 100) == 0 )
printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound);
flag++;
}
else if ( 0 ) // too much beyond duplicate filter when network is busy
{
printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound);
ptr->peerind++;
if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 )
{
printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q);
flag++;
LP_Qerrors++;
}
}
}
if ( flag != 0 )
{
nonz++;
portable_mutex_lock(&LP_networkmutex);
DL_DELETE(LP_Q,ptr);
portable_mutex_unlock(&LP_networkmutex);
free(ptr);
ptr = 0;
break;
}
}
if ( arg == 0 )
break;
if ( nonz == 0 )
{
if ( IAMLP == 0 )
usleep(50000);
else usleep(10000);
}
}
}
void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32_t msglen,int32_t needack)
{
int32_t maxind,peerind = 0; //sentbytes,

19
iguana/exchanges/LP_ordermatch.c

@ -454,7 +454,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,cJSON *argjson,char *base,c
printf("requestid.%u quoteid.%u is already in progres\n",qp->R.requestid,qp->R.quoteid);
return(-1);
}
if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp)) == 0 )
if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp,LP_dynamictrust(qp->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis)) > 0)) == 0 )
{
printf("cant initialize swap\n");
return(-1);
@ -614,6 +614,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0);
return(clonestr("{\"error\":\"no price set\"}"));
}
//LP_RTmetrics_update(Q.srccoin,Q.destcoin);
printf("%s/%s bid %.8f ask %.8f values %.8f %.8f\n",Q.srccoin,Q.destcoin,bid,ask,dstr(butxo->payment.value),dstr(butxo->deposit.value));
price = bid;
if ( (coin= LP_coinfind(Q.destcoin)) == 0 )
@ -625,7 +626,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
if ( bits256_nonz(Q.privkey) != 0 )//&& Q.quotetime >= Q.timestamp-3 )
{
retjson = cJSON_CreateObject();
if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q)) == 0 )
if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q,LP_dynamictrust(Q.srchash,LP_kmdvalue(Q.srccoin,Q.satoshis)) > 0)) == 0 )
{
jaddstr(retjson,"error","couldnt swapinit");
LP_availableset(Q.desttxid,Q.vout);
@ -733,7 +734,7 @@ char *LP_bestfit(char *rel,double relvolume)
if ( relvolume <= 0. || LP_priceinfofind(rel) == 0 )
return(clonestr("{\"error\":\"invalid parameter\"}"));
if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 )
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}"));
return(clonestr("{\"error\":\"cant find utxo that is close enough in size\"}"));
return(jprint(LP_utxojson(autxo),1));
}
@ -786,7 +787,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
LP_quoteparse(&Q,argjson);
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("(%-10u %10u) %12s aliceid.%22llu %5s/%-5s %12.8f -> %12.8f price %12.8f\n",Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis);
printf("(%-10u %10u) %12s aliceid.%22llu %5s/%-5s %12.8f -> %12.8f price %12.8f | RT.%d %d\n",Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,LP_RTcount,LP_swapscount);
retval = 1;
autxo = &A;
butxo = &B;
@ -907,7 +908,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
if ( counter > 3 || price > bestprice ) // skip if late or bad price
return(retval);
} else return(retval);
LP_RTmetrics_update(Q.srccoin,Q.destcoin);
//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));
@ -1019,7 +1020,7 @@ struct LP_utxoinfo *LP_ordermatch_iter(struct LP_address_utxo **utxos,int32_t ma
struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,char *gui,bits256 *avoids,int32_t numavoids,bits256 destpubkey)
{
bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*rawasks,*item; int32_t maxiters,i,j,numasks,max; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0;
bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*rawasks,*item; int32_t maxiters,i,j,numasks,max; struct LP_address_utxo **utxos; double price; struct LP_pubkey_info *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0;
maxiters = 100;
*ordermatchpricep = 0.;
*bestsatoshisp = *bestdestsatoshisp = 0;
@ -1149,9 +1150,9 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
memset(pubkeys,0,sizeof(pubkeys));
LP_txfees(&txfee,&desttxfee,base,rel);
destsatoshis = SATOSHIDEN * relvolume;
LP_address_utxo_reset(relcoin);
//LP_address_utxo_reset(relcoin);
if ( (autxo= LP_utxo_bestfit(rel,destsatoshis + 2*desttxfee)) == 0 )
return(clonestr("{\"error\":\"cant find alice utxo that is big enough\"}"));
return(clonestr("{\"error\":\"cant find alice utxo that is close enough in size\"}"));
//printf("bestfit selected alice (%.8f %.8f) for %.8f sats %.8f\n",dstr(autxo->payment.value),dstr(autxo->fee.value),dstr(destsatoshis),dstr(autxo->S.satoshis));
if ( destsatoshis - desttxfee < autxo->S.satoshis )
{
@ -1181,7 +1182,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
LP_mypriceset(&changed,autxo->coin,base,1. / maxprice);
return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey));
#ifdef oldway
LP_RTmetrics_update(base,rel);
//LP_RTmetrics_update(base,rel);
while ( 1 )
{
if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )

2
iguana/exchanges/LP_portfolio.c

@ -94,7 +94,7 @@ char *LP_portfolio()
if ( iter == 0 )
{
//printf("from portfolio\n");
LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519);
//LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519);
coin->balanceA = LP_balance(&coin->valuesumA,0,coin->symbol,coin->smartaddr);
coin->balanceB = LP_balance(&coin->valuesumB,1,coin->symbol,coin->smartaddr);
if ( strcmp(coin->symbol,"KMD") != 0 )

66
iguana/exchanges/LP_prices.c

@ -18,7 +18,15 @@
// marketmaker
//
struct LP_orderbookentry { bits256 pubkey; double price; uint64_t avesatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; };
struct LP_orderbookentry
{
bits256 pubkey;
double price;
uint64_t avesatoshis,maxsatoshis,depth,dynamictrust;
uint32_t timestamp;
int32_t numutxos;
char coinaddr[64];
};
struct LP_priceinfo
{
@ -49,7 +57,7 @@ struct LP_cacheinfo
} *LP_cacheinfos;
float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind)
float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind)
{
struct LP_pubkey_quote *pq,*tmp; int32_t scale; int64_t scale64;
*numutxosp = 0;
@ -75,7 +83,7 @@ float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatos
return(0);
}
void LP_pubkey_update(struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo)
void LP_pubkey_update(struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo)
{
struct LP_pubkey_quote *pq,*tmp; int64_t aveutxo,scale64,ave64,max64; int32_t scale;
DL_FOREACH_SAFE(pubp->quotes,pq,tmp)
@ -214,9 +222,9 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout
return(ptr);
}
struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20])
struct LP_pubkey_info *LP_pubkey_rmd160find(uint8_t rmd160[20])
{
struct LP_pubkeyinfo *pubp=0,*tmp;
struct LP_pubkey_info *pubp=0,*tmp;
portable_mutex_lock(&LP_pubkeymutex);
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
@ -230,7 +238,7 @@ struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20])
struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr)
{
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp;
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp;
HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap);
if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 )
{
@ -246,7 +254,7 @@ struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr)
struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr)
{
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp;
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp;
ap = calloc(1,sizeof(*ap));
safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr));
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr);
@ -260,18 +268,18 @@ struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr)
return(ap);
}
struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey)
struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp=0;
struct LP_pubkey_info *pubp=0;
portable_mutex_lock(&LP_pubkeymutex);
HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp);
portable_mutex_unlock(&LP_pubkeymutex);
return(pubp);
}
struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey)
struct LP_pubkey_info *LP_pubkeyadd(bits256 pubkey)
{
char str[65]; struct LP_pubkeyinfo *pubp=0;
char str[65]; struct LP_pubkey_info *pubp=0;
portable_mutex_lock(&LP_pubkeymutex);
HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp);
if ( pubp == 0 )
@ -294,7 +302,7 @@ struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey)
int32_t LP_pubkey_istrusted(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp;
struct LP_pubkey_info *pubp;
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
return(pubp->istrusted != 0);
return(0);
@ -302,7 +310,7 @@ int32_t LP_pubkey_istrusted(bits256 pubkey)
char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval)
{
struct LP_pubkeyinfo *pubp;
struct LP_pubkey_info *pubp;
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
pubp->istrusted = trustval;
@ -313,7 +321,7 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval)
char *LP_pubkey_trusted()
{
struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray();
struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray();
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
if ( pubp->istrusted != 0 )
@ -343,7 +351,7 @@ uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr)
return(metric);
}
cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
cJSON *LP_pubkeyjson(struct LP_pubkey_info *pubp)
{
int32_t baseid,relid,numutxos; int64_t avesatoshis,maxsatoshis; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj;
obj = cJSON_CreateObject();
@ -380,7 +388,7 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
char *LP_prices()
{
struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray();
struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray();
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
jaddi(array,LP_pubkeyjson(pubp));
@ -390,7 +398,7 @@ char *LP_prices()
/*void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj)
{
struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr; double askprice; uint32_t now;
struct LP_pubkey_info *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr; double askprice; uint32_t now;
now = (uint32_t)time(NULL);
pubkey = jbits256(obj,"pubkey");
if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
@ -555,7 +563,7 @@ char *LP_myprices()
int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
{
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp;
struct LP_priceinfo *basepp,*relpp; struct LP_pubkey_info *pubp;
*changedp = 0;
if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
@ -750,11 +758,12 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op)
jaddnum(item,"depth",dstr(op->depth)*0.8);
jaddbits256(item,"pubkey",op->pubkey);
jaddnum(item,"age",time(NULL)-op->timestamp);
jaddnum(item,"zcredits",dstr(op->dynamictrust));
}
return(item);
}
struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t avesatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance)
struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t avesatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance,uint64_t dynamictrust)
{
struct LP_orderbookentry *op;
if ( (op= calloc(1,sizeof(*op))) != 0 )
@ -767,13 +776,14 @@ struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,d
op->pubkey = pubkey;
op->timestamp = timestamp;
op->depth = balance;
op->dynamictrust = dynamictrust;
}
return(op);
}
void LP_pubkeys_query()
{
uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkeyinfo *pubp=0,*tmp;
uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkey_info *pubp=0,*tmp;
memset(zero.bytes,0,sizeof(zero));
memset(zeroes,0,sizeof(zeroes));
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
@ -792,7 +802,7 @@ void LP_pubkeys_query()
int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration)
{
char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis;
char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkey_info *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis;
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
baseid = basepp->ind;
else return(num);
@ -827,7 +837,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
}
//printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total));
}
if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance)) != 0 )
if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance,pubp->dynamictrust)) != 0 )
{
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1));
(*arrayp)[num++] = op;
@ -977,6 +987,16 @@ uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance)
return(KMDvalue);
}
int64_t LP_kmdvalue(char *symbol,int64_t satoshis)
{
struct iguana_info *coin; int64_t kmdvalue = 0;
if ( (coin= LP_coinfind(symbol)) != 0 )
kmdvalue = LP_KMDvalue(coin,satoshis);
if ( kmdvalue == 0 )
kmdvalue = satoshis;
return(kmdvalue);
}
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32])
{
LP_priceinfoupdate(base,rel,price);
@ -1112,7 +1132,7 @@ cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,i
void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,char *utxocoin,int32_t numrelutxos,int64_t balance,int64_t minutxo,int64_t maxutxo)
{
struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *pubp; char str[65],fname[512]; FILE *fp;
struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkey_info *pubp; char str[65],fname[512]; FILE *fp;
//printf("check PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey));
if ( LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{

17
iguana/exchanges/LP_remember.c

@ -389,6 +389,7 @@ uint32_t LP_extract(uint32_t requestid,uint32_t quoteid,char *rootfname,char *fi
t = (t << 8) | redeem[2];
//printf("extracted timestamp.%u\n",t);
}
free_json(json);
}
free(filestr);
}
@ -483,7 +484,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap)
if ( rswap->sentflags[i] != 0 )
jaddistr(array,txnames[i]);
if ( rswap->txbytes[i] != 0 )
free(rswap->txbytes[i]);
free(rswap->txbytes[i]), rswap->txbytes[i] = 0;
}
jadd(item,"sentflags",array);
array = cJSON_CreateArray();
@ -637,6 +638,7 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t
}
}
}
free_json(txobj);
}
rswap->origfinishedflag = basilisk_swap_isfinished(rswap->iambob,rswap->txids,rswap->sentflags,rswap->paymentspent,rswap->Apaymentspent,rswap->depositspent);
rswap->finishedflag = rswap->origfinishedflag;
@ -773,6 +775,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
//printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
}
}
free_json(txobj);
} //else printf("no symbol\n");
free(fstr);
} else if ( 0 && rswap->finishedflag == 0 )
@ -1140,6 +1143,8 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
jaddstr(item,"method","tradestatus");
jaddnum(item,"finishtime",rswap.finishtime);
jaddstr(item,"gui",G.gui);
//jaddbits256(item,"srchash",rswap.Q.srchash);
//jaddbits256(item,"desthash",rswap.desthash);
itemstr = jprint(item,0);
fprintf(fp,"%s\n",itemstr);
LP_tradecommand_log(item);
@ -1150,6 +1155,9 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
fclose(fp);
}
}
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
if ( rswap.txbytes[i] != 0 )
free(rswap.txbytes[i]), rswap.txbytes[i] = 0;
return(item);
}
@ -1234,13 +1242,6 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
else if ( Ktotal < 0 && Btotal > 0 )
jaddnum(retjson,"avesell",(double)-Btotal/Ktotal);
}
/*array = cJSON_CreateArray();
for (i=0; i<sizeof(myinfo->linfos)/sizeof(*myinfo->linfos); i++)
{
if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 )
jaddi(array,linfo_json(&myinfo->linfos[i]));
}
jadd(retjson,"quotes",array);*/
portable_mutex_unlock(&LP_swaplistmutex);
return(jprint(retjson,1));
}

107
iguana/exchanges/LP_rpc.c

@ -586,7 +586,7 @@ cJSON *LP_validateaddress(char *symbol,char *address)
}
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20);
jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse());
jadd(retjson,"iswatchonly",cJSON_CreateFalse());
jadd(retjson,"iswatchonly",cJSON_CreateTrue());
jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse());
return(retjson);
}
@ -599,12 +599,30 @@ cJSON *LP_validateaddress(char *symbol,char *address)
int32_t LP_address_ismine(char *symbol,char *address)
{
int32_t doneflag = 0; cJSON *retjson;
int32_t doneflag = 0; cJSON *retjson,*obj;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 )
if ( (obj= jobj(retjson,"ismine")) != 0 && is_cJSON_True(obj) != 0 )
{
doneflag = 1;
//printf("%s ismine (%s)\n",address,jprint(retjson,0));
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
}
return(doneflag);
}
int32_t LP_address_iswatched(char *symbol,char *address)
{
int32_t doneflag = 0; cJSON *retjson,*obj;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( (obj= jobj(retjson,"iswatched")) != 0 && is_cJSON_True(obj) != 0 )
{
doneflag = 1;
//printf("%s ismine (%s)\n",address,jprint(retjson,0));
@ -635,26 +653,76 @@ int32_t LP_address_isvalid(char *symbol,char *address)
cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
char buf[128]; cJSON *retjson; int32_t numconfs; struct iguana_info *coin;
char buf[128],*retstr; struct LP_address *ap; cJSON *retjson; int32_t numconfs,usecache=1; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum == 0 )
{
if ( LP_address_ismine(symbol,coinaddr) > 0 )
if ( (ap= LP_addressfind(coin,symbol)) != 0 )
{
if ( ap->unspenttime == 0 )
usecache = 0;
else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+30 )
usecache = 0;
if ( usecache != 0 && (retstr= LP_unspents_filestr(symbol,coinaddr)) != 0 )
{
retjson = cJSON_Parse(retstr);
free(retstr);
return(retjson);
}
}
if ( LP_address_ismine(symbol,coinaddr) > 0 || LP_address_iswatched(symbol,coinaddr) > 0 )
{
if ( strcmp(symbol,"BTC") == 0 )
numconfs = 0;
else numconfs = 1;
sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr);
return(bitcoin_json(coin,"listunspent",buf));
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
retjson = bitcoin_json(coin,"listunspent",buf);
retstr = jprint(retjson,0);
LP_unspents_cache(coin->symbol,coinaddr,retstr,1);
free(retstr);
if ( ap != 0 )
ap->unspenttime = (uint32_t)time(NULL);
return(retjson);
} else return(LP_address_utxos(coin,coinaddr,0));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1));
}
cJSON *LP_listreceivedbyaddress(char *symbol,char *coinaddr)
{
char buf[128],*addr; cJSON *retjson,*array,*item; int32_t i,n; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum == 0 )
{
sprintf(buf,"[1, false, true]");
if ( (array= bitcoin_json(coin,"listreceivedbyaddress",buf)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (addr= jstr(item,"address")) != 0 && strcmp(addr,coinaddr) == 0 )
{
retjson = jduplicate(jobj(item,"txids"));
free_json(array);
return(retjson);
}
}
}
}
return(cJSON_Parse("[]"));
} else return(electrum_address_gethistory(symbol,coin->electrum,&retjson,coinaddr));
}
int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag)
{
struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0;
@ -664,25 +732,16 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag)
{
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)) != 0 )
if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,fullflag)) != 0 )
{
n = cJSON_GetArraySize(retjson);
//printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0));
}
}
else
{
if ( strcmp(coin->smartaddr,coinaddr) == 0 )
{
retjson = LP_listunspent(symbol,coinaddr);
coin->numutxos = cJSON_GetArraySize(retjson);
//printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr);
}
else if ( IAMLP == 0 )
{
//printf("LP_listunspent_query.(%s %s)\n",symbol,coinaddr);
LP_listunspent_query(coin->symbol,coin->smartaddr);
}
if ( retjson != 0 )
{
n = cJSON_GetArraySize(retjson);
@ -998,17 +1057,19 @@ bits256 LP_getbestblockhash(struct iguana_info *coin)
char *LP_blockhashstr(char *symbol,int32_t height)
{
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin;
char params[64],*retstr; struct iguana_info *coin; //cJSON *array;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
coin = LP_coinfind(symbol);
if ( coin == 0 || coin->electrum != 0 )
return(0);
array = cJSON_CreateArray();
jaddinum(array,height);
paramstr = jprint(array,1);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",paramstr);
free(paramstr);
//array = cJSON_CreateArray();
//jaddinum(array,height);
//paramstr = jprint(array,1);
sprintf(params,"[%d]",height);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",params);
//free(paramstr);
//printf("blockhashstr.(%s)\n",retstr);
return(retstr);
}

20
iguana/exchanges/LP_signatures.c

@ -276,7 +276,7 @@ bits256 LP_utxos_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,bits
int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,bits256 utxoshash)
{
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkeyinfo *pubp;
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkey_info *pubp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
pubp = LP_pubkeyfind(pubkey);
@ -362,7 +362,7 @@ struct LP_utxos_qitem { struct queueitem DL; cJSON *argjson; };
char *LP_postutxos_recv(cJSON *argjson)
{
struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkeyinfo *pubp;
struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkey_info *pubp;
printf("LP_postutxos_recv deprecated\n");
pubkey = jbits256(argjson,"pubkey");
pubp = LP_pubkeyfind(pubkey);
@ -416,7 +416,7 @@ int32_t LP_utxosQ_process()
int32_t LP_price_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,char *base,char *rel,uint64_t price64)
{
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkeyinfo *pubp;
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkey_info *pubp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
pubp = LP_pubkeyfind(pubkey);
@ -454,7 +454,7 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
struct iguana_info *basecoin,*relcoin; struct LP_address *ap; char pubsecpstr[67]; uint32_t numutxos,timestamp; uint64_t price64,balance,minsize,maxsize; bits256 zero; cJSON *reqjson;
reqjson = cJSON_CreateObject();
// LP_addsig
if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 )//&& relcoin->electrum == 0 )
if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 )//&& basecoin->electrum == 0 )//&& relcoin->electrum == 0 )
{
memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
@ -521,7 +521,7 @@ int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub
return(LP_bitcoinsig_add(item,priv,pubsecp,sighash));
}
int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item)
{
int32_t i,len,siglen,retval=-1; uint8_t rmd160[20],checkrmd160[20],pubsecp[33],sig[65],zeroes[20]; char *sigstr,*hexstr,*pubsecpstr;
if ( (hexstr= jstr(item,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) )
@ -603,7 +603,7 @@ void LP_notify_pubkeys(void *ctx,int32_t pubsock)
char *LP_notify_recv(cJSON *argjson)
{
bits256 pub; struct LP_pubkeyinfo *pubp; char *ipaddr;
bits256 pub; struct LP_pubkey_info *pubp; char *ipaddr;
pub = jbits256(argjson,"pub");
if ( bits256_nonz(pub) != 0 )
{
@ -700,8 +700,8 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_
{
if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 )
{
LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash);
LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash);
LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash);
LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash);
}
else
{
@ -718,13 +718,15 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_
msg = jprint(reqjson,1);
msg2 = clonestr(msg);
printf("QUERY.(%s)\n",msg);
if ( bits256_nonz(qp->srchash) == 0 || strcmp(method,"request") != 0 )
{
memset(&zero,0,sizeof(zero));
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs[1] < sizeof(Reserved_msgs[1])/sizeof(*Reserved_msgs[1])-2 )
Reserved_msgs[1][num_Reserved_msgs[1]++] = msg;
if ( num_Reserved_msgs[0] < sizeof(Reserved_msgs[0])/sizeof(*Reserved_msgs[0])-2 )
Reserved_msgs[0][num_Reserved_msgs[0]++] = msg2;
//LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg2);
portable_mutex_unlock(&LP_reservedmutex);
} else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg2);
}

7
iguana/exchanges/LP_socket.c

@ -606,12 +606,9 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON
//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);
LP_unspents_cache(coin->symbol,addr,retstr,1);
free(retstr);
}
if ( ap != 0 )
{
ap->unspenttime = (uint32_t)time(NULL);
@ -627,7 +624,7 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON
}
if ( retjson == 0 )
{
if ( strcmp(addr,coin->smartaddr) == 0 && (retstr= LP_unspents_filestr(symbol,coin->smartaddr)) != 0 )
if ( (retstr= LP_unspents_filestr(symbol,addr)) != 0 )
{
retjson = cJSON_Parse(retstr);
free(retstr);

23
iguana/exchanges/LP_statemachine.c

@ -3039,6 +3039,29 @@ if ( (0) )
#undef aptr
#undef bptr
}*/
/*if ( (sobj= jobj(v,"scriptPubKey")) != 0 )
{
if ( (scriptstr= jstr(sobj,"hex")) != 0 )
{
printf("amount64 %.8f vout.%d (%s) weeki.%d %.8f (%s)\n",dstr(amount64),vout,jprint(v,0),weeki,dstr(satoshis),scriptstr);
len = (int32_t)strlen(scriptstr) >> 1;
if ( len <= sizeof(spendscript)/sizeof(*spendscript) )
{
decode_hex(spendscript,len,scriptstr);
if ( spendscript[11] == 33 )
{
pub33 = &spendscript[12];
redeemlen = LP_deposit_addr(p2shaddr,redeemscript,coin->taddr,coin->p2shtype,timestamp,pub33);
if ( len == redeemlen && (timestamp % LP_WEEKMULT) == 0 )
{
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pub33,33);
printf("%s -> matched %s script t.%u weeki.%d deposit %.8f\n",coinaddr,p2shaddr,timestamp,(timestamp-LP_FIRSTWEEKTIME)/LP_WEEKMULT,dstr(satoshis));
// add to pubp->credits;
}
}
}
}
}*/
/*portable_mutex_lock(&ep->pendingQ.mutex);
if ( ep->pendingQ.list != 0 )

304
iguana/exchanges/LP_stats.c

@ -20,32 +20,17 @@
#define LP_STATSLOG_FNAME "stats.log"
struct LP_swapstats
{
UT_hash_handle hh;
struct LP_quoteinfo Q;
bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent;
double qprice;
uint64_t aliceid;
uint32_t ind,methodind,finished,expired;
char alicegui[32],bobgui[32];
} *LP_swapstats;
struct LP_swapstats *LP_swapstats,*LP_RTstats;
int32_t LP_statslog_parsequote(char *method,cJSON *lineobj);
char *LP_stats_methods[] = { "unknown", "request", "reserved", "connect", "connected", "tradestatus" };
uint32_t LP_atomic_locktime(char *base,char *rel)
{
if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 )
return(INSTANTDEX_LOCKTIME);
else return(INSTANTDEX_LOCKTIME * 10);
}
static uint32_t LP_requests,LP_reserveds,LP_connects,LP_connecteds,LP_tradestatuses,LP_parse_errors,LP_unknowns,LP_duplicates,LP_aliceids;
void LP_tradecommand_log(cJSON *argjson)
{
static FILE *logfp; char *jsonstr;
portable_mutex_lock(&LP_logmutex);
if ( logfp == 0 )
{
if ( (logfp= fopen(LP_STATSLOG_FNAME,"rb+")) != 0 )
@ -59,6 +44,7 @@ void LP_tradecommand_log(cJSON *argjson)
free(jsonstr);
fflush(logfp);
}
portable_mutex_unlock(&LP_logmutex);
}
void LP_statslog_parseline(cJSON *lineobj)
@ -130,18 +116,22 @@ int32_t LP_statslog_parse()
struct LP_swapstats *LP_swapstats_find(uint64_t aliceid)
{
struct LP_swapstats *sp;
HASH_FIND(hh,LP_RTstats,&aliceid,sizeof(aliceid),sp);
if ( sp == 0 )
HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp);
return(sp);
}
struct LP_swapstats *LP_swapstats_add(uint64_t aliceid)
struct LP_swapstats *LP_swapstats_add(uint64_t aliceid,int32_t RTflag)
{
struct LP_swapstats *sp;
if ( (sp= LP_swapstats_find(aliceid)) == 0 )
{
sp = calloc(1,sizeof(*sp));
sp->aliceid = aliceid;
HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp);
if ( RTflag != 0 )
HASH_ADD(hh,LP_RTstats,aliceid,sizeof(aliceid),sp);
else HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp);
}
return(LP_swapstats_find(aliceid));
}
@ -180,6 +170,7 @@ bits256 LP_swapstats_txid(cJSON *argjson,char *name,bits256 oldtxid)
int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSON *lineobj)
{
char *statusstr,*base,*rel,gui[64]; uint32_t requestid,quoteid; uint64_t satoshis,destsatoshis;
sp->lasttime = (uint32_t)time(NULL);
safecopy(gui,sp->Q.gui,sizeof(gui));
if ( strcmp(LP_stats_methods[sp->methodind],"tradestatus") == 0 )
{
@ -189,7 +180,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
quoteid = juint(lineobj,"quoteid");
satoshis = jdouble(lineobj,"srcamount") * SATOSHIDEN;
destsatoshis = jdouble(lineobj,"destamount") * SATOSHIDEN;
if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && ((satoshis+2*sp->Q.txfee)|1) == (sp->Q.satoshis|1) && ((destsatoshis+2*sp->Q.desttxfee)|1) == (sp->Q.destsatoshis|1) )
if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && llabs((int64_t)(satoshis+2*sp->Q.txfee) - (int64_t)sp->Q.satoshis) <= sp->Q.txfee && llabs((int64_t)(destsatoshis+2*sp->Q.desttxfee) - (int64_t)sp->Q.destsatoshis) <= sp->Q.desttxfee )
{
sp->bobdeposit = LP_swapstats_txid(lineobj,"bobdeposit",sp->bobdeposit);
sp->alicepayment = LP_swapstats_txid(lineobj,"alicepayment",sp->alicepayment);
@ -208,7 +199,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
}
else
{
if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid )
//if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid )
printf("mismatched tradestatus aliceid.%22llu b%s/%s r%s/%s r%u/%u q%u/%u %.8f/%.8f -> %.8f/%.8f\n",(long long)sp->aliceid,base,sp->Q.srccoin,rel,sp->Q.destcoin,requestid,sp->Q.R.requestid,quoteid,sp->Q.R.quoteid,dstr(satoshis+2*sp->Q.txfee),dstr(sp->Q.satoshis),dstr(destsatoshis+2*sp->Q.desttxfee),dstr(sp->Q.destsatoshis));
return(-1);
}
@ -222,7 +213,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
{
static uint32_t unexpected;
struct LP_swapstats *sp,*tmp; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
struct LP_swapstats *sp,*tmp; struct LP_pubkey_info *pubp; struct LP_pubswap *ptr; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,RTflag,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *statusstr,*gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
memset(numtrades,0,sizeof(numtrades));
memset(basevols,0,sizeof(basevols));
memset(relvols,0,sizeof(relvols));
@ -242,8 +233,11 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
if ( (sp= LP_swapstats_find(aliceid)) != 0 )
{
sp->methodind = methodind;
sp->Q.R.requestid = requestid;
sp->Q.R.quoteid = quoteid;
if ( LP_swapstats_update(sp,&Q,lineobj) == 0 )
flag = 1;
//else printf("LP_swapstats_update error\n");
}
if ( flag == 0 )
{
@ -253,14 +247,16 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
{
sp->methodind = methodind;
if ( LP_swapstats_update(sp,&Q,lineobj) == 0 )
{
flag = 1;
else printf("error after delayed match\n");
break;
}
printf("error after delayed match\n");
}
}
}
if ( flag == 0 )
printf("unexpected.%d tradestatus.(%s)\n",unexpected++,jprint(lineobj,0));
printf("unexpected.%d tradestatus aliceid.%llu requestid.%u quoteid.%u\n",unexpected++,(long long)aliceid,requestid,quoteid);//,jprint(lineobj,0));
return(0);
}
if ( LP_quoteparse(&Q,lineobj) < 0 )
@ -290,6 +286,9 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
destvout = jint(lineobj,"destvout");
feetxid = jbits256(lineobj,"feetxid");
feevout = jint(lineobj,"feevout");
if ( (statusstr= jstr(lineobj,"status")) != 0 && strcmp(statusstr,"finished") == 0 )
RTflag = 0;
else RTflag = 1;
qprice = ((double)destsatoshis / (satoshis - txfee));
//printf("%s/v%d %s/v%d\n",bits256_str(str,desttxid),destvout,bits256_str(str2,feetxid),feevout);
aliceid = LP_aliceid_calc(desttxid,destvout,feetxid,feevout);
@ -305,16 +304,31 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
}
else
{
if ( (sp= LP_swapstats_add(aliceid)) != 0 )
//printf("create aliceid.%llu\n",(long long)aliceid);
if ( (sp= LP_swapstats_add(aliceid,RTflag)) != 0 )
{
sp->Q = Q;
sp->qprice = qprice;
sp->methodind = methodind;
sp->ind = LP_aliceids++;
sp->lasttime = (uint32_t)time(NULL);
strcpy(sp->bobgui,"nogui");
strcpy(sp->alicegui,"nogui");
//LP_swapstats_line(numtrades,basevols,relvols,line,sp);
//printf("%s\n",line);
if ( sp->finished == 0 && sp->expired == 0 )
{
if ( (pubp= LP_pubkeyadd(sp->Q.srchash)) != 0 )
{
ptr = calloc(1,sizeof(*ptr));
ptr->swap = sp;
DL_APPEND(pubp->bobswaps,ptr);
}
if ( (pubp= LP_pubkeyadd(sp->Q.desthash)) != 0 )
{
ptr = calloc(1,sizeof(*ptr));
ptr->swap = sp;
DL_APPEND(pubp->aliceswaps,ptr);
}
}
} else printf("unexpected LP_swapstats_add failure\n");
}
if ( sp != 0 )
@ -330,22 +344,69 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
return(duplicate == 0);
}
char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey)
cJSON *LP_swapstats_json(struct LP_swapstats *sp)
{
cJSON *retjson,*array,*item; struct LP_swapstats *sp,*tmp; int32_t i,dispflag,numtrades[LP_MAXPRICEINFOS]; char line[1024]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
if ( starttime > endtime )
starttime = endtime;
memset(basevols,0,sizeof(basevols));
memset(relvols,0,sizeof(relvols));
memset(numtrades,0,sizeof(numtrades));
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"newlines",n);
array = cJSON_CreateArray();
HASH_ITER(hh,LP_swapstats,sp,tmp)
cJSON *item = cJSON_CreateObject();
jaddnum(item,"timestamp",sp->Q.timestamp);
jadd64bits(item,"aliceid",sp->aliceid);
jaddbits256(item,"src",sp->Q.srchash);
jaddstr(item,"base",sp->Q.srccoin);
jaddnum(item,"basevol",dstr(sp->Q.satoshis));
jaddbits256(item,"dest",sp->Q.desthash);
jaddstr(item,"rel",sp->Q.destcoin);
jaddnum(item,"relvol",dstr(sp->Q.destsatoshis));
jaddnum(item,"price",sp->qprice);
jaddnum(item,"requestid",sp->Q.R.requestid);
jaddnum(item,"quoteid",sp->Q.R.quoteid);
jaddnum(item,"finished",sp->finished);
jaddnum(item,"expired",sp->expired);
jaddnum(item,"ind",sp->methodind);
//jaddstr(item,"line",line);
return(item);
}
char *LP_swapstatus_recv(cJSON *argjson)
{
struct LP_swapstats *sp; int32_t methodind;
//printf("swapstatus.(%s)\n",jprint(argjson,0));
if ( (sp= LP_swapstats_find(j64bits(argjson,"aliceid"))) != 0 )
{
sp->lasttime = (uint32_t)time(NULL);
if ( (methodind= jint(argjson,"ind")) > sp->methodind && methodind < sizeof(LP_stats_methods)/sizeof(*LP_stats_methods) )
{
if ( sp->finished == 0 && sp->expired == 0 )
printf("SWAPSTATUS updated %llu %s %u %u\n",(long long)sp->aliceid,LP_stats_methods[sp->methodind],juint(argjson,"finished"),juint(argjson,"expired"));
sp->methodind = methodind;
sp->finished = juint(argjson,"finished");
sp->expired = juint(argjson,"expired");
}
}
return(clonestr("{\"result\":\"success\"}"));
}
char *LP_gettradestatus(uint64_t aliceid)
{
struct LP_swapstats *sp; cJSON *reqjson; bits256 zero;
//printf("gettradestatus.(%llu)\n",(long long)aliceid);
if ( (sp= LP_swapstats_find(aliceid)) != 0 && time(NULL) > sp->lasttime+60 )
{
if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 )
if ( (reqjson= LP_swapstats_json(sp)) != 0 )
{
jaddstr(reqjson,"method","swapstatus");
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
}
}
return(clonestr("{\"error\":\"cant find aliceid\"}"));
}
int32_t LP_stats_dispiter(cJSON *array,struct LP_swapstats *sp,uint32_t starttime,uint32_t endtime,char *refbase,char *refrel,char *refgui,bits256 refpubkey)
{
int32_t dispflag,retval = 0;
if ( sp->finished == 0 && sp->expired == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 )
sp->expired = (uint32_t)time(NULL);
if ( sp->finished != 0 || sp->expired != 0 )
retval = 1;
dispflag = 0;
if ( starttime == 0 && endtime == 0 )
dispflag = 1;
@ -353,6 +414,10 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu
dispflag = 1;
else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime )
dispflag = 1;
if ( refbase != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 )
dispflag = 0;
if ( refrel != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 )
dispflag = 0;
if ( dispflag != 0 )
{
dispflag = 0;
@ -363,24 +428,61 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu
}
}
if ( dispflag != 0 )
jaddi(array,LP_swapstats_json(sp));
return(retval);
}
cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel)
{
static int32_t rval;
cJSON *retjson,*array,*item,*reqjson; struct LP_pubkey_info *pubp,*ptmp; bits256 zero; uint32_t now; struct LP_swapstats *sp,*tmp; int32_t i,n,numtrades[LP_MAXPRICEINFOS]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
if ( rval == 0 )
rval = (LP_rand() % 300) + 60;
if ( starttime > endtime )
starttime = endtime;
n = LP_statslog_parse();
memset(basevols,0,sizeof(basevols));
memset(relvols,0,sizeof(relvols));
memset(numtrades,0,sizeof(numtrades));
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"newlines",n);
array = cJSON_CreateArray();
LP_RTcount = LP_swapscount = 0;
now = (uint32_t)time(NULL);
HASH_ITER(hh,LP_RTstats,sp,tmp)
{
LP_swapstats_line(numtrades,basevols,relvols,line,sp);
item = cJSON_CreateObject();
jadd64bits(item,"aliceid",sp->aliceid);
jaddbits256(item,"src",sp->Q.srchash);
jaddstr(item,"base",sp->Q.srccoin);
jaddnum(item,"basevol",dstr(sp->Q.satoshis));
jaddbits256(item,"dest",sp->Q.desthash);
jaddstr(item,"rel",sp->Q.destcoin);
jaddnum(item,"relvol",dstr(sp->Q.destsatoshis));
jaddnum(item,"price",sp->qprice);
jaddnum(item,"requestid",sp->Q.R.requestid);
jaddnum(item,"quoteid",sp->Q.R.quoteid);
jaddstr(item,"line",line);
jaddi(array,item);
if ( LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey) > 0 )
{
HASH_DELETE(hh,LP_RTstats,sp);
HASH_ADD(hh,LP_swapstats,aliceid,sizeof(sp->aliceid),sp);
}
else
{
LP_RTcount++;
if ( now > sp->lasttime+rval )
{
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","gettradestatus");
jadd64bits(reqjson,"aliceid",sp->aliceid);
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
}
}
}
HASH_ITER(hh,LP_swapstats,sp,tmp)
{
LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey);
LP_swapscount++;
}
HASH_ITER(hh,LP_pubkeyinfos,pubp,ptmp)
{
pubp->dynamictrust = LP_dynamictrust(pubp->pubkey,0);
}
//printf("RT.%d completed.%d\n",LP_RTcount,LP_swapscount);
jadd(retjson,"swaps",array);
jaddnum(retjson,"RTcount",LP_RTcount);
jaddnum(retjson,"swapscount",LP_swapscount);
array = cJSON_CreateArray();
for (i=0; i<LP_MAXPRICEINFOS; i++)
{
@ -405,7 +507,99 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu
jaddnum(retjson,"uniques",LP_aliceids);
jaddnum(retjson,"tradestatus",LP_tradestatuses);
jaddnum(retjson,"unknown",LP_unknowns);
return(jprint(retjson,1));
return(retjson);
}
//tradesarray(base, rel, starttime=<now>-timescale*1024, endtime=<now>, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]
struct LP_ohlc
{
uint32_t timestamp,firsttime,lasttime,numtrades;
double high,low,open,close,relsum,basesum;
};
cJSON *LP_ohlc_json(struct LP_ohlc *bar)
{
cJSON *item;
if ( bar->numtrades != 0 && bar->relsum > SMALLVAL && bar->basesum > SMALLVAL )
{
item = cJSON_CreateArray();
jaddinum(item,bar->timestamp);
jaddinum(item,bar->high);
jaddinum(item,bar->low);
jaddinum(item,bar->open);
jaddinum(item,bar->close);
jaddinum(item,bar->relsum);
jaddinum(item,bar->basesum);
jaddinum(item,bar->relsum / bar->basesum);
jaddinum(item,bar->numtrades);
return(item);
}
return(0);
}
void LP_ohlc_update(struct LP_ohlc *bar,uint32_t timestamp,double basevol,double relvol)
{
double price;
if ( basevol > SMALLVAL && relvol > SMALLVAL )
{
price = relvol / basevol;
if ( bar->firsttime == 0 || timestamp < bar->firsttime )
{
bar->firsttime = timestamp;
bar->open = price;
}
if ( bar->lasttime == 0 || timestamp > bar->lasttime )
{
bar->lasttime = timestamp;
bar->close = price;
}
if ( bar->low == 0. || price < bar->low )
bar->low = price;
if ( bar->high == 0. || price > bar->high )
bar->high = price;
bar->basesum += basevol;
bar->relsum += relvol;
bar->numtrades++;
//printf("%d %.8f/%.8f -> %.8f\n",bar->numtrades,basevol,relvol,price);
}
}
cJSON *LP_tradesarray(char *base,char *rel,uint32_t starttime,uint32_t endtime,int32_t timescale)
{
struct LP_ohlc *bars; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; int32_t i,n,numbars,bari;
if ( timescale < 60 )
return(cJSON_Parse("{\"error\":\"one minute is shortest timescale\"}"));
memset(zero.bytes,0,sizeof(zero));
if ( endtime == 0 )
endtime = (((uint32_t)time(NULL) / timescale) * timescale);
if ( starttime == 0 || starttime >= endtime )
starttime = (endtime - LP_SCREENWIDTH*timescale);
numbars = ((endtime - starttime) / timescale) + 1;
bars = calloc(numbars,sizeof(*bars));
for (bari=0; bari<numbars; bari++)
bars[bari].timestamp = starttime + bari*timescale;
if ( (statsjson= LP_statslog_disp(starttime,endtime,"",zero,base,rel)) != 0 )
{
if ( (swaps= jarray(&n,statsjson,"swaps")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(swaps,i);
if ( (timestamp= juint(item,"timestamp")) != 0 && timestamp >= starttime && timestamp <= endtime )
{
bari = (timestamp - starttime) / timescale;
LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"basevol"),jdouble(item,"relvol"));
} else printf("skip.(%s)\n",jprint(item,0));
}
}
free_json(statsjson);
}
array = cJSON_CreateArray();
for (bari=0; bari<numbars; bari++)
if ( (item= LP_ohlc_json(&bars[bari])) != 0 )
jaddi(array,item);
free(bars);
return(array);
}

21
iguana/exchanges/LP_swap.c

@ -109,6 +109,13 @@
*/
uint32_t LP_atomic_locktime(char *base,char *rel)
{
if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 )
return(INSTANTDEX_LOCKTIME);
else return(INSTANTDEX_LOCKTIME * 10);
}
void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx)
{
if ( rawtx->vins != 0 )
@ -1041,7 +1048,7 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
} else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr);
}
struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp)
struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp,int32_t dynamictrust)
{
//FILE *fp; char fname[512];
uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *bobcoin,*alicecoin;
@ -1101,14 +1108,18 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
swap->I.iambob = 0;
swap->I.otherhash = swap->I.req.desthash;
swap->I.aliceistrusted = 1;
swap->I.otheristrusted = swap->I.bobistrusted = LP_pubkey_istrusted(swap->I.req.srchash);
if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.srchash) != 0 )
dynamictrust = 1;
swap->I.otheristrusted = swap->I.bobistrusted = dynamictrust;
}
else
{
swap->I.iambob = 1;
swap->I.otherhash = swap->I.req.srchash;
swap->I.bobistrusted = 1;
swap->I.otheristrusted = swap->I.aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.desthash) != 0 )
dynamictrust = 1;
swap->I.otheristrusted = swap->I.aliceistrusted = dynamictrust;
}
if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE )
{
@ -1198,7 +1209,7 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
return(swap);
}
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp)
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust)
{
struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33];
swap = calloc(1,sizeof(*swap));
@ -1217,7 +1228,7 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256
swap->persistent_privkey = privkey;
memcpy(swap->persistent_pubkey33,pubkey33,33);
calc_rmd160_sha256(swap->changermd160,pubkey33,33);
if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp) == 0 )
if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp,dynamictrust) == 0 )
{
printf("error doing swapinit\n");
free(swap);

2
iguana/exchanges/LP_tradebots.c

@ -195,7 +195,7 @@ cJSON *LP_tradebot_json(struct LP_tradebot *bot)
jadd(json,"trades",array);
if ( bot->basesum > SMALLVAL && bot->relsum > SMALLVAL && bot->completed > 0 )
{
jaddnum(json,"completed",bot->completed);
jadd(json,"complete",bot->completed!=0?jtrue():jfalse());
jaddnum(json,"percentage",100. * (bot->relsum / bot->totalrelvolume));
if ( bot->dispdir > 0 )
{

27
iguana/exchanges/LP_transaction.c

@ -420,7 +420,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,
//printf(" scriptlen.%d\n",scriptlen);
//printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen);
sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys,zcash);
printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen);
//printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen);
if ( bits256_nonz(sigtxid) != 0 )
{
vp = &V[vini];
@ -461,14 +461,14 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,
{
flag++;
numsigs++;
int32_t z; char tmpaddr[64];
/*int32_t z; char tmpaddr[64];
for (z=0; z<siglen-1; z++)
printf("%02x",sig[z]);
printf(" <- sig[%d]\n",j);
for (z=0; z<33; z++)
printf("%02x",vp->signers[j].pubkey[z]);
bitcoin_address(tmpaddr,0,0,vp->signers[j].pubkey,33);
printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr);
printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr);*/
}
}
if ( numsigs >= vp->M )
@ -731,7 +731,7 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt
jaddstr(retjson,"error","interpreter rejects tx");
else complete = 1;
jadd(retjson,"interpreter",log);
jaddnum(retjson,"complete",complete);
jadd(retjson,"complete",complete!=0?jtrue():jfalse());
free(serialized), free(serialized2);
if ( signedtx != 0 )
free(signedtx);
@ -980,8 +980,10 @@ cJSON *LP_inputjson(bits256 txid,int32_t vout,char *spendscriptstr)
uint64_t _komodo_interestnew(uint64_t nValue,uint32_t nLockTime,uint32_t tiptime)
{
int32_t minutes; uint64_t interest = 0;
if ( (minutes= (tiptime - nLockTime) / 60) >= 60 )
if ( tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= 60 )
{
//minutes.71582779 tiptime.1511292969 locktime.1511293505
printf("minutes.%d tiptime.%u locktime.%u\n",minutes,tiptime,nLockTime);
if ( minutes > 365 * 24 * 60 )
minutes = 365 * 24 * 60;
minutes -= 59;
@ -1124,20 +1126,21 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_
if ( LP_validSPV(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout) < 0 )
continue;
}
if ( LP_allocated(up->U.txid,up->U.vout) != 0 )
continue;
up->spendheight = 1;
total += up->U.value;
remains -= up->U.value;
interest = 0;
if ( up->U.height < 7777777 && strcmp(coin->symbol,"KMD") == 0 )
{
if ( 0 && (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 )
if ( (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 )
{
interestsum += interest;
char str[65]; printf("%s/%d %.8f interest %.8f -> sum %.8f\n",bits256_str(str,up->U.txid),up->U.vout,dstr(up->U.value),dstr(interest),dstr(interestsum));
}
}
//printf("numunspents.%d vini.%d value %.8f, total %.8f remains %.8f interest %.8f sum %.8f %s/v%d\n",numunspents,n,dstr(up->U.value),dstr(total),dstr(remains),dstr(interest),dstr(interestsum),bits256_str(str,up->U.txid),up->U.vout);
printf("numunspents.%d vini.%d value %.8f, total %.8f remains %.8f interest %.8f sum %.8f %s/v%d\n",numunspents,n,dstr(up->U.value),dstr(total),dstr(remains),dstr(interest),dstr(interestsum),bits256_str(str,up->U.txid),up->U.vout);
vp = &V[n++];
vp->N = vp->M = 1;
vp->signers[0].privkey = privkey;
@ -1146,7 +1149,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));
LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+600,G.LP_mypub25519);
LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+LP_RESERVETIME,G.LP_mypub25519);
if ( remains <= 0 && i >= numpre-1 )
break;
if ( numunspents < 0 )
@ -1264,6 +1267,12 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
if ( addrtype == coin->pubtype )
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
else spendlen = bitcoin_p2shspend(spendscript,0,rmd160);
if ( i == numvouts-1 && strcmp(coinaddr,coin->smartaddr) == 0 && change != 0 )
{
printf("combine last vout %.8f with change %.8f\n",dstr(value+adjust),dstr(change));
value += change;
change = 0;
}
txobj = bitcoin_txoutput(txobj,spendscript,spendlen,value + adjust);
}
else

24
iguana/exchanges/LP_utxo.c

@ -99,9 +99,10 @@ struct LP_inuse_info *_LP_inuse_add(uint32_t expiration,bits256 otherpub,bits256
{
if ( bits256_nonz(otherpub) != 0 )
lp->otherpub = otherpub;
if ( expiration > lp->expiration || expiration == 0 )
//if ( expiration > lp->expiration || expiration == 0 )
lp->expiration = expiration;
}
char str[65]; printf("set inuse until %u lag.%d for %s/v%d\n",expiration,(int32_t)(expiration-(uint32_t)time(NULL)),bits256_str(str,txid),vout);
return(lp);
} else printf("_LP_inuse_add [%d] overflow\n",LP_numinuse);
return(0);
@ -446,20 +447,7 @@ struct LP_address *LP_address_utxo_reset(struct iguana_info *coin)
{
//{"tx_hash":"38d1b7c73015e1b1d6cb7fc314cae402a635b7d7ea294970ab857df8777a66f4","tx_pos":0,"height":577975,"value":238700}
item = jitem(array,i);
if ( coin->electrum != 0 )
{
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
}
else
{
txid = jbits256(item,"txid");
vout = juint(item,"vout");
value = LP_value_extract(item,0);
height = LP_txheight(coin,txid);
}
value = LP_listunspent_parseitem(coin,&txid,&vout,&height,item);
LP_address_utxoadd(now,"withdraw",coin,coin->smartaddr,txid,vout,value,height,-1);
if ( (up= LP_address_utxofind(coin,coin->smartaddr,txid,vout)) == 0 )
printf("couldnt find just added %s/%d ht.%d %.8f\n",bits256_str(str,txid),vout,height,dstr(value));
@ -573,9 +561,9 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
}
else
{
if ( strcmp(coin->smartaddr,coinaddr) == 0 )
//if ( strcmp(coin->smartaddr,coinaddr) == 0 )
balance = LP_unspents_load(coin->symbol,coinaddr);
else
/*else
{
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
@ -589,7 +577,7 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
}
free_json(array);
}
}
}*/
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");

41
iguana/exchanges/LP_utxos.c

@ -559,6 +559,26 @@ int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targe
return(mini);
}
int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item)
{
int64_t satoshis = 0;
if ( coin->electrum == 0 )
{
*txidp = jbits256(item,"txid");
*voutp = juint(item,"vout");
satoshis = LP_value_extract(item,0);
*heightp = LP_txheight(coin,*txidp);
}
else
{
*txidp = jbits256(item,"tx_hash");
*voutp = juint(item,"tx_pos");
satoshis = j64bits(item,"value");
*heightp = jint(item,"height");
}
return(satoshis);
}
int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub)
{
int32_t enable_utxos = 0;
@ -572,8 +592,8 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri
return(0);
coin->privkeydepth++;
LP_address(coin,coin->smartaddr);
if ( coin->inactive == 0 )
LP_listunspent_issue(coin->symbol,coin->smartaddr,0);
//if ( coin->inactive == 0 )
// LP_listunspent_issue(coin->symbol,coin->smartaddr,0);
array = LP_listunspent(coin->symbol,coin->smartaddr);
if ( array != 0 )
{
@ -591,20 +611,7 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( coin->electrum == 0 )
{
txid = jbits256(item,"txid");
vout = juint(item,"vout");
value = LP_value_extract(item,0);
height = LP_txheight(coin,txid);//LP_getheight(coin) - jint(item,"confirmations") + 1;
}
else
{
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
}
value = LP_listunspent_parseitem(coin,&txid,&vout,&height,item);
satoshis = LP_txvalue(destaddr,coin->symbol,txid,vout);
if ( satoshis != 0 && satoshis != value )
printf("%s %s privkey_init value %.8f vs %.8f (%s) %.8f %.8f\n",coin->symbol,coin->smartaddr,dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest"));
@ -848,7 +855,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
else if ( IAMLP == 0 || coin->inactive == 0 )
{
//printf("from updates %s\n",coin->symbol);
if ( LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 )
if ( 0 && LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 )
{
//LP_postutxos(coin->symbol,coin->smartaddr);
}

278
iguana/exchanges/LP_zeroconf.c

@ -0,0 +1,278 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_zeroconf.c
// marketmaker
//
int32_t LP_deposit_addr(char *p2shaddr,uint8_t *script,uint8_t taddr,uint8_t p2shtype,uint32_t timestamp,uint8_t *pubsecp33)
{
uint8_t elsepub33[33],p2sh_rmd160[20]; int32_t n;
decode_hex(elsepub33,33,BOTS_BONDPUBKEY33);
n = bitcoin_performancebond(p2sh_rmd160,script,0,timestamp,pubsecp33,elsepub33);
bitcoin_address(p2shaddr,taddr,p2shtype,script,n);
return(n);
}
char *LP_zeroconf_deposit(struct iguana_info *coin,int32_t weeks,double amount,int32_t broadcast)
{
char p2shaddr[64],*retstr,*hexstr; uint8_t script[512]; int32_t weeki,scriptlen; cJSON *argjson,*retjson,*array,*item,*obj; uint32_t timestamp; bits256 txid,sendtxid; uint64_t amount64;
if ( strcmp(coin->symbol,"KMD") != 0 )
return(clonestr("{\"error\":\"zeroconf deposit must be in KMD\"}"));
if ( amount < 10.0 )
return(clonestr("{\"error\":\"minimum zeroconf deposit is 10 KMD\"}"));
if ( weeks < 0 || weeks > 52 )
return(clonestr("{\"error\":\"weeks must be between 0 and 52\"}"));
if ( weeks > 0 )
{
timestamp = (uint32_t)time(NULL);
timestamp /= LP_WEEKMULT;
timestamp += weeks+1;
timestamp *= LP_WEEKMULT;
weeki = (timestamp - LP_FIRSTWEEKTIME) / LP_WEEKMULT;
if ( weeks >= 10000 )
return(clonestr("{\"error\":\"numweeks must be less than 10000\"}"));
} else timestamp = (uint32_t)time(NULL) + 300, weeki = 0;
scriptlen = LP_deposit_addr(p2shaddr,script,coin->taddr,coin->p2shtype,timestamp,G.LP_pubsecp);
argjson = cJSON_CreateObject();
array = cJSON_CreateArray();
item = cJSON_CreateObject();
jaddnum(item,p2shaddr,amount);
jaddi(array,item);
item = cJSON_CreateObject();
amount64 = (amount * SATOSHIDEN) / 1000;
amount64 = (amount64 / 10000) * 10000 + weeki;
jaddnum(item,BOTS_BONDADDRESS,dstr(amount64));
jaddi(array,item);
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,0.0001);
jaddi(array,item);
jadd(argjson,"outputs",array);
//printf("deposit.(%s)\n",jprint(argjson,0));
if ( (retstr= LP_withdraw(coin,argjson)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jobj(retjson,"result") != 0 )
jdelete(retjson,"result");
jaddstr(retjson,"address",p2shaddr);
jaddnum(retjson,"expiration",timestamp);
jaddnum(retjson,"deposit",amount);
if ( (obj= jobj(retjson,"complete")) != 0 && is_cJSON_True(obj) != 0 && (hexstr= jstr(retjson,"hex")) != 0 )
{
txid = jbits256(retjson,"txid");
if ( broadcast != 0 )
{
if (bits256_nonz(txid) != 0 )
{
sendtxid = LP_broadcast("deposit","KMD",hexstr,txid);
if ( bits256_cmp(sendtxid,txid) != 0 )
{
jaddstr(retjson,"error","broadcast txid mismatch");
jaddbits256(retjson,"broadcast",sendtxid);
free(retstr);
return(jprint(retjson,1));
}
else
{
jaddstr(retjson,"result","success");
jaddbits256(retjson,"broadcast",sendtxid);
free(retstr);
return(jprint(retjson,1));
}
}
else
{
jaddstr(retjson,"error","couldnt broadcast since no txid created");
free(retstr);
return(jprint(retjson,1));
}
}
else
{
jaddstr(retjson,"result","success");
free(retstr);
return(jprint(retjson,1));
}
}
else
{
jaddstr(retjson,"error","couldnt create deposit txid");
free(retstr);
return(jprint(retjson,1));
}
free_json(retjson);
}
free(retstr);
}
return(clonestr("{\"error\":\"error with LP_withdraw for zeroconf deposit\"}"));
}
char *LP_zeroconf_claim(struct iguana_info *coin,char *depositaddr,uint32_t expiration)
{
static void *ctx;
uint8_t redeemscript[512],userdata[64]; char vinaddr[64],str[65],*signedtx=0; uint32_t timestamp,now,redeemlen,claimtime; int32_t i,n,height,utxovout,userdatalen; bits256 signedtxid,utxotxid,sendtxid; int64_t sum,destamount,satoshis; cJSON *array,*item,*txids,*retjson;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( strcmp(coin->symbol,"KMD") != 0 )
return(clonestr("{\"error\":\"zeroconf deposit must be in KMD\"}"));
now = (uint32_t)time(NULL);
sum = 0;
txids = cJSON_CreateArray();
timestamp = (now / LP_WEEKMULT) * LP_WEEKMULT + LP_WEEKMULT;
while ( timestamp > LP_FIRSTWEEKTIME )
{
if ( expiration != 0 )
timestamp = expiration;
else timestamp -= LP_WEEKMULT;
redeemlen = LP_deposit_addr(vinaddr,redeemscript,coin->taddr,coin->p2shtype,timestamp,G.LP_pubsecp);
if ( strcmp(depositaddr,vinaddr) == 0 )
{
claimtime = (uint32_t)time(NULL)-777/2;
if ( claimtime <= timestamp )
{
printf("claimtime.%u vs locktime.%u, need to wait %d seconds\n",claimtime,timestamp,(int32_t)timestamp-claimtime);
}
else
{
printf("found %s at timestamp.%u\n",vinaddr,timestamp);
if ( (array= LP_listunspent(coin->symbol,vinaddr)) != 0 )
{
userdata[0] = 0x51;
userdatalen = 1;
utxovout = 0;
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
satoshis = LP_listunspent_parseitem(coin,&utxotxid,&utxovout,&height,item);
if ( (signedtx= basilisk_swap_bobtxspend(&signedtxid,10000,"zeroconfclaim",coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,G.LP_privkey,0,redeemscript,redeemlen,userdata,userdatalen,utxotxid,utxovout,coin->smartaddr,G.LP_pubsecp,0,claimtime,&destamount,0,0,vinaddr,1,coin->zcash)) != 0 )
{
printf("signedtx.(%s)\n",signedtx);
sendtxid = LP_broadcast("claim","KMD",signedtx,signedtxid);
if ( bits256_cmp(sendtxid,signedtxid) == 0 )
{
jaddibits256(txids,sendtxid);
sum += (satoshis-coin->txfee);
}
else printf("error sending %s\n",bits256_str(str,signedtxid));
free(signedtx);
} else printf("error claiming zeroconf deposit %s/v%d %.8f\n",bits256_str(str,utxotxid),utxovout,dstr(satoshis));
}
}
free_json(array);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"claimed",dstr(sum));
jadd(retjson,"txids",txids);
return(jprint(retjson,1));
}
}
}
if ( expiration != 0 )
break;
}
return(clonestr("{\"error\":\"no zeroconf deposits to claim\"}"));
}
void LP_zeroconf_credit(char *coinaddr,uint64_t satoshis,int32_t weeki,char *p2shaddr)
{
uint32_t timestamp; struct LP_address *ap; struct iguana_info *coin = LP_coinfind("KMD");
if ( coin != 0 )
{
timestamp = LP_FIRSTWEEKTIME + weeki*LP_WEEKMULT;
if ( time(NULL) < timestamp-24*3600 && (ap= LP_address(coin,coinaddr)) != 0 )
{
ap->zeroconf_credits += satoshis;
printf("ZEROCONF credit.(%s) %.8f weeki.%d (%s) -> sum %.8f\n",coinaddr,dstr(satoshis),weeki,p2shaddr,dstr(ap->zeroconf_credits));
}
}
}
void LP_zeroconf_deposits(struct iguana_info *coin)
{
cJSON *array,*item,*txjson,*vouts,*v,*txobj; int32_t i,n,numvouts,height,vout,weeki; bits256 txid; char destaddr[64],p2shaddr[64]; struct LP_address *ap,*tmp; int64_t satoshis,amount64;
HASH_ITER(hh,coin->addresses,ap,tmp)
{
ap->zeroconf_credits = 0;
}
if ( (array= LP_listreceivedbyaddress("KMD",BOTS_BONDADDRESS)) != 0 )
{
//printf("ZEROCONF.(%s)\n",jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
if ( coin->electrum != 0 )
{
item = jitem(array,i);
LP_listunspent_parseitem(coin,&txid,&vout,&height,item);
} else txid = jbits256i(array,i);
if ( (txjson= LP_gettx(coin->symbol,txid)) != 0 )
{
// vout0 deposit, vout1 botsfee, vout2 smartaddress
if ( (vouts= jarray(&numvouts,txjson,"vout")) > 0 && numvouts >= 3 && LP_destaddr(destaddr,jitem(vouts,2)) == 0 )
{
amount64 = LP_value_extract(jitem(vouts,1),0);
weeki = (amount64 % 10000);
v = jitem(vouts,0);
satoshis = LP_value_extract(v,0);
//printf("%s funded %.8f weeki.%d\n",destaddr,dstr(satoshis),weeki);
if ( LP_destaddr(p2shaddr,v) == 0 )
{
if ( (txobj= LP_gettxout(coin->symbol,p2shaddr,txid,0)) != 0 )
{
free_json(txobj);
LP_zeroconf_credit(destaddr,satoshis,weeki,p2shaddr);
}
}
}
free_json(txjson);
}
}
}
free_json(array);
}
}
int64_t LP_dynamictrust(bits256 pubkey,int64_t kmdvalue)
{
struct LP_pubswap *ptr,*tmp; struct LP_swapstats *sp; struct LP_pubkey_info *pubp; struct LP_address *ap; char coinaddr[64]; struct iguana_info *coin; int64_t swaps_kmdvalue = 0;
if ( (coin= LP_coinfind("KMD")) != 0 && (pubp= LP_pubkeyfind(pubkey)) != 0 )
{
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->pubsecp,33);
if ((ap= LP_address(coin,coinaddr)) != 0 )//&& ap->zeroconf_credits >= kmdvalue )
{
DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && sp->finished == 0 && sp->expired == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis);
}
DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && sp->finished == 0 && sp->expired == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis);
}
//printf("%s zeroconf_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(ap->zeroconf_credits),dstr(swaps_kmdvalue),dstr(kmdvalue));
//if ( ap->zeroconf_credits > swaps_kmdvalue+kmdvalue )
return(ap->zeroconf_credits - (swaps_kmdvalue+kmdvalue));
}
}
return(0);
}

3
iguana/exchanges/claim

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"zeroconf_claim\",\"address\":\"$1\",\"expiration\":$2}"

3
iguana/exchanges/deposit

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"zeroconf_deposit\",\"weeks\":0,\"amount\":10.0,\"broadcast\":1}"

3
iguana/exchanges/deposit1

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"zeroconf_deposit\",\"weeks\":1,\"amount\":10.0,\"broadcast\":1}"

2
iguana/exchanges/install

@ -1,5 +1,5 @@
#!/bin/bash
cp invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts
cp tradesarray claim deposit invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts
cp coins.json ..
cd ../dexscripts
#cp ../exchanges/passphrase ../exchanges/userpass .

12
iguana/exchanges/mm.c

@ -881,6 +881,18 @@ int main(int argc, const char * argv[])
double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr;
cJSON *retjson,*loginjson; int32_t i;
OS_init();
if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 )
{
uint8_t addrtype,rmd160[20],rmd160b[20]; char coinaddr[64],coinaddr2[64];
bitcoin_addr2rmd160(0,&addrtype,rmd160,(char *)argv[1]);
bitcoin_address(coinaddr,0,60,rmd160,20);
bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr);
bitcoin_address(coinaddr2,0,0,rmd160b,20);
printf("(%s) -> %s -> %s\n",(char *)argv[1],coinaddr,coinaddr2);
if ( strcmp((char *)argv[1],coinaddr2) != 0 )
printf("ERROR\n");
exit(0);
}
sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname);

64
iguana/exchanges/stats.c

@ -33,7 +33,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char
char *stats_validmethods[] =
{
"psock", "getprices", "notify", "getpeers", // from issue_ "uitem", "listunspent",
"orderbook", "help", "getcoins", "pricearray", "balance", "tradestatus"
"orderbook", "help", "getcoins", "pricearray", "balance", "tradesarray"
};
int32_t LP_valid_remotemethod(cJSON *argjson)
@ -310,7 +310,7 @@ cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr)
jaddstr(json,key,value);
else jaddistr(array,key);
len += (n + 1);
if ( strcmp(key,"Content-Length") == 0 && (datalen= atoi(value)) > 0 )
if ( (strcmp(key,"Content-Length") == 0 || strcmp(key,"content-length") == 0) && (datalen= atoi(value)) > 0 )
{
data = &urlstr[totallen - datalen];
data[-1] = 0;
@ -329,8 +329,7 @@ extern void *bitcoin_ctx();
char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port)
{
static void *ctx;
cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0;
//printf("rpcparse.(%s)\n",urlstr);
cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr=0,*filestr,*token = 0; int32_t i,j,n,num=0;
if ( ctx == 0 )
ctx = bitcoin_ctx();
for (i=0; i<sizeof(urlmethod)-1&&urlstr[i]!=0&&urlstr[i]!=' '; i++)
@ -339,6 +338,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
n = i;
//printf("URLMETHOD.(%s)\n",urlmethod);
*postflagp = (strcmp(urlmethod,"POST") == 0);
//printf("POST.%d rpcparse.(%s)\n",*postflagp,urlstr);
for (i=0; i<sizeof(url)-1&&urlstr[n+i]!=0&&urlstr[n+i]!=' '; i++)
url[i] = urlstr[n+i];
url[i++] = 0;
@ -412,7 +412,13 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
{
jadd(json,"tokens",tokens);
jaddstr(json,"urlmethod",urlmethod);
if ( (data= jstr(json,"POST")) == 0 || (argjson= cJSON_Parse(data)) == 0 )
if ( (data= jstr(json,"POST")) != 0 )
{
free_json(argjson);
argjson = cJSON_Parse(data);
//printf("data.(%s)\n",data);
}
if ( argjson != 0 )
{
userpass = jstr(argjson,"userpass");
//printf("userpass.(%s)\n",userpass);
@ -499,7 +505,6 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
}
}
}
}
if ( is_cJSON_Array(argjson) != 0 && (n= cJSON_GetArraySize(argjson)) > 0 )
{
cJSON *retitem,*retarray = cJSON_CreateArray();
@ -555,6 +560,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
#endif
}
free_json(argjson);
}
free_json(json);
if ( tmpjson != 0 )
free(tmpjson);
@ -562,15 +568,17 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
}
free_json(argjson);
if ( tmpjson != 0 )
free(tmpjson);
free_json(tmpjson);
if ( tokens != 0 )
free_json(tokens);
*jsonflagp = 1;
return(clonestr("{\"error\":\"couldnt process packet\"}"));
}
int32_t iguana_getcontentlen(char *buf,int32_t recvlen)
{
char *str,*clenstr = "Content-Length: "; int32_t len = -1;
if ( (str= strstr(buf,clenstr)) != 0 )
char *str,*clenstr = "Content-Length: ",*clenstr2 = "content-length: "; int32_t len = -1;
if ( (str= strstr(buf,clenstr)) != 0 || (str= strstr(buf,clenstr2)) != 0 )
{
//printf("strstr.(%s)\n",str);
str += strlen(clenstr);
@ -597,15 +605,16 @@ void LP_rpc_processreq(void *_ptr)
static uint32_t spawned,maxspawned;
char filetype[128],content_type[128];
int32_t recvlen,flag,postflag=0,contentlen,remains,sock,numsent,jsonflag=0,hdrsize,len;
char helpname[512],remoteaddr[64],*buf,*retstr,*space,*jsonbuf; struct rpcrequest_info *req = _ptr;
char helpname[512],remoteaddr[64],*buf,*retstr,space[8192],space2[32786],*jsonbuf; struct rpcrequest_info *req = _ptr;
uint32_t ipbits,i,size = IGUANA_MAXPACKETSIZE + 512;
ipbits = req->ipbits;;
expand_ipbits(remoteaddr,ipbits);
sock = req->sock;
recvlen = flag = 0;
retstr = 0;
space = calloc(1,size);
//space = calloc(1,size);
jsonbuf = calloc(1,size);
//printf("alloc jsonbuf.%p\n",jsonbuf);
remains = size-1;
buf = jsonbuf;
spawned++;
@ -624,10 +633,12 @@ void LP_rpc_processreq(void *_ptr)
printf("EAGAIN for len %d, remains.%d\n",len,remains);
usleep(10000);
}
//printf("errno.%d len.%d remains.%d\n",errno,len,remains);
break;
}
else
{
//printf("received len.%d\n%s\n",len,buf);
if ( len > 0 )
{
buf[len] = 0;
@ -694,16 +705,23 @@ void LP_rpc_processreq(void *_ptr)
//printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag);
if ( jsonflag != 0 || postflag != 0 )
{
if ( retstr == 0 )
retstr = clonestr("{}");
if ( strlen(retstr)+1024+1+1 < sizeof(space2) )
response = space2;
else
{
response = malloc(strlen(retstr)+1024+1+1);
printf("alloc response.%p\n",response);
}
sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr));
response[0] = '\0';
strcat(response,hdrs);
strcat(response,retstr);
strcat(response,"\n");
if ( retstr != space )
{
//printf("free retstr0.%p\n",retstr);
free(retstr);
}
retstr = response;
//printf("RET.(%s)\n",retstr);
}
@ -727,16 +745,28 @@ void LP_rpc_processreq(void *_ptr)
printf("iguana sent.%d remains.%d of recvlen.%d (%s)\n",numsent,remains,recvlen,jsonbuf);
}
}
if ( retstr != space)
if ( retstr != space && retstr != space2 )
{
//printf("free retstr.%p\n",retstr);
free(retstr);
}
free(space);
}
//free(space);
//printf("free jsonbuf.%p\n",jsonbuf);
free(jsonbuf);
closesocket(sock);
if ( 1 )
{
portable_mutex_lock(&LP_gcmutex);
DL_APPEND(LP_garbage_collector,req);
spawned--;
portable_mutex_unlock(&LP_gcmutex);
}
else
{
//printf("free req.%p\n",req);
free(req);
}
spawned--;
}
extern int32_t IAMLP;
@ -787,10 +817,12 @@ void stats_rpcloop(void *args)
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
if ( port == RPC_port && ipbits != localhostbits )
{
//printf("port.%u RPC_port.%u ipbits %x != %x\n",port,RPC_port,ipbits,localhostbits);
closesocket(sock);
continue;
}
req = calloc(1,sizeof(*req));
//printf("alloc req.%p\n",req);
req->sock = sock;
req->ipbits = ipbits;
req->port = port;

3
iguana/exchanges/tradesarray

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"tradesarray\",\"base\":\"REVS\",\"rel\":\"KMD\",\"timescale\":3600}"

2
iguana/main.c

@ -793,7 +793,7 @@ void iguana_launchdaemons(struct supernet_info *myinfo)
if ( COMMANDLINE_ARGFILE == 0 )
iguana_launch(0,"rpcloop",iguana_rpcloop,myinfo,IGUANA_PERMTHREAD); // limit to oneprocess
printf("launch mainloop\n");
OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo);
// disable basilisk: OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo);
OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)jumblr_loop,(void *)myinfo);
OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_psockloop,(void *)myinfo);
mainloop(myinfo);

Loading…
Cancel
Save