Browse Source

Merge pull request #374 from jl777/spvdex

Spvdex
etomic
jl777 7 years ago
committed by GitHub
parent
commit
e0232f5839
  1. 1
      .gitignore
  2. 4
      basilisk/basilisk_bitcoin.c
  3. 2
      crypto777/OS_portable.h
  4. 7
      crypto777/bitcoind_RPC.c
  5. 4
      crypto777/iguana_OS.c
  6. 2
      crypto777/jpeg/unix/jmemname.c
  7. 3
      iguana/dPoW.h
  8. 7
      iguana/dpow/dpow_fsm.c
  9. 16
      iguana/dpow/dpow_rpc.c
  10. 52
      iguana/exchanges/LP_coins.c
  11. 231
      iguana/exchanges/LP_commands.c
  12. 27
      iguana/exchanges/LP_include.h
  13. 308
      iguana/exchanges/LP_nativeDEX.c
  14. 36
      iguana/exchanges/LP_network.c
  15. 430
      iguana/exchanges/LP_ordermatch.c
  16. 5
      iguana/exchanges/LP_peers.c
  17. 110
      iguana/exchanges/LP_portfolio.c
  18. 46
      iguana/exchanges/LP_prices.c
  19. 477
      iguana/exchanges/LP_remember.c
  20. 83
      iguana/exchanges/LP_rpc.c
  21. 11
      iguana/exchanges/LP_scan.c
  22. 45
      iguana/exchanges/LP_socket.c
  23. 58
      iguana/exchanges/LP_statemachine.c
  24. 127
      iguana/exchanges/LP_swap.c
  25. 385
      iguana/exchanges/LP_transaction.c
  26. 146
      iguana/exchanges/LP_utxo.c
  27. 48
      iguana/exchanges/LP_utxos.c
  28. 89
      iguana/exchanges/assetchains.old
  29. 10
      iguana/exchanges/autoprice
  30. 3
      iguana/exchanges/coins
  31. 3
      iguana/exchanges/coins.json
  32. 2
      iguana/exchanges/enable
  33. 3
      iguana/exchanges/install
  34. 2
      iguana/exchanges/listunspent
  35. 2
      iguana/exchanges/mm.c
  36. 2
      iguana/exchanges/orderbook
  37. 1
      iguana/exchanges/profile
  38. 2
      iguana/exchanges/recentswaps
  39. 3
      iguana/exchanges/register
  40. 3
      iguana/exchanges/sendrawtransaction
  41. 3
      iguana/exchanges/setconfirms
  42. 293
      iguana/exchanges/stats.c
  43. 3
      iguana/exchanges/stop
  44. 4
      iguana/exchanges/trust
  45. 3
      iguana/exchanges/trusted
  46. 3
      iguana/exchanges/withdraw
  47. 1
      iguana/help/InstantDEX_DEXratio.json
  48. 1
      iguana/help/InstantDEX_accept.json
  49. 1
      iguana/help/InstantDEX_allcoins.json
  50. 1
      iguana/help/InstantDEX_allexchanges.json
  51. 1
      iguana/help/InstantDEX_allpairs.json
  52. 1
      iguana/help/InstantDEX_apikeypair.json
  53. 1
      iguana/help/InstantDEX_automatched.json
  54. 1
      iguana/help/InstantDEX_available.json
  55. 1
      iguana/help/InstantDEX_balance.json
  56. 1
      iguana/help/InstantDEX_buy.json
  57. 1
      iguana/help/InstantDEX_cancelorder.json
  58. 1
      iguana/help/InstantDEX_getswaplist.json
  59. 1
      iguana/help/InstantDEX_incoming.json
  60. 1
      iguana/help/InstantDEX_init.json
  61. 1
      iguana/help/InstantDEX_openorders.json
  62. 1
      iguana/help/InstantDEX_orderbook.json
  63. 1
      iguana/help/InstantDEX_orderstatus.json
  64. 1
      iguana/help/InstantDEX_pollgap.json
  65. 1
      iguana/help/InstantDEX_request.json
  66. 1
      iguana/help/InstantDEX_sell.json
  67. 1
      iguana/help/InstantDEX_setuserid.json
  68. 1
      iguana/help/InstantDEX_smartaddress.json
  69. 1
      iguana/help/InstantDEX_smartaddresses.json
  70. 1
      iguana/help/InstantDEX_supports.json
  71. 1
      iguana/help/InstantDEX_tradehistory.json
  72. 1
      iguana/help/InstantDEX_withdraw.json
  73. 1
      iguana/help/SuperNET_activehandle.json
  74. 1
      iguana/help/SuperNET_addr2rmd160.json
  75. 1
      iguana/help/SuperNET_bitcoinrpc.json
  76. 1
      iguana/help/SuperNET_broadcastcipher.json
  77. 1
      iguana/help/SuperNET_broadcastdecipher.json
  78. 1
      iguana/help/SuperNET_cipher.json
  79. 1
      iguana/help/SuperNET_decipher.json
  80. 1
      iguana/help/SuperNET_decryptjson.json
  81. 1
      iguana/help/SuperNET_encryptjson.json
  82. 1
      iguana/help/SuperNET_getpeers.json
  83. 1
      iguana/help/SuperNET_help.json
  84. 1
      iguana/help/SuperNET_html.json
  85. 1
      iguana/help/SuperNET_keypair.json
  86. 1
      iguana/help/SuperNET_layer.json
  87. 1
      iguana/help/SuperNET_login.json
  88. 1
      iguana/help/SuperNET_logout.json
  89. 1
      iguana/help/SuperNET_multicastcipher.json
  90. 1
      iguana/help/SuperNET_multicastdecipher.json
  91. 1
      iguana/help/SuperNET_myipaddr.json
  92. 1
      iguana/help/SuperNET_mypeers.json
  93. 1
      iguana/help/SuperNET_priv2pub.json
  94. 1
      iguana/help/SuperNET_priv2wif.json
  95. 1
      iguana/help/SuperNET_rmd160conv.json
  96. 1
      iguana/help/SuperNET_rosetta.json
  97. 1
      iguana/help/SuperNET_saveconf.json
  98. 1
      iguana/help/SuperNET_setmyipaddr.json
  99. 1
      iguana/help/SuperNET_stop.json
  100. 1
      iguana/help/SuperNET_utc2utime.json

1
.gitignore

@ -170,7 +170,6 @@ iguana/help.json
iguana/index7778.html
*.json
iguana/DB/KMD/utxo.dat

4
basilisk/basilisk_bitcoin.c

@ -602,7 +602,7 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi
free_json(vins);
return(rawtx);
}
printf("splitfunds tx.(%s) vins.(%s)\n",rawtx,jprint(vins,0));
printf("%s splitfunds tx.(%s) vins.(%s)\n",coin->symbol,rawtx,jprint(vins,0));
if ( signedtxidp != 0 )
{
if ( (signedtx= iguana_signrawtx(myinfo,coin,0,signedtxidp,completedp,vins,rawtx,0,0)) != 0 )
@ -615,7 +615,7 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi
free(rawtx);
rawtx = signedtx, signedtx = 0;
}
} else printf("error signing raw utxoduplicates tx\n");
} else printf("error signing raw %s utxoduplicates tx\n",coin->symbol);
}
}
if ( vins != 0 )

2
crypto777/OS_portable.h

@ -40,7 +40,7 @@
#include <sys/types.h>
#include <time.h>
#ifdef WIN32
#ifdef _WIN32
#define sleep(x) Sleep(1000*(x))
#include "../OSlibs/win/mingw.h"
#include "../OSlibs/win/mman.h"

7
crypto777/bitcoind_RPC.c

@ -55,17 +55,18 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
long i,j,len;
char *retstr = 0;
cJSON *json,*result,*error;
usleep(2500);
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
{
if ( strcmp(command,"signrawtransaction") != 0 && strcmp(command,"getrawtransaction") != 0 )
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
printf("<<<<<<<<<<< A bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,params);
return(rpcstr);
}
json = cJSON_Parse(rpcstr);
if ( json == 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params);
printf("<<<<<<<<<<< B bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params);
free(rpcstr);
return(0);
}
@ -227,7 +228,7 @@ try_again:
{
count++;
elapsedsum += (OS_milliseconds() - starttime);
if ( (count % 10000) == 0)
if ( (count % 100000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
if ( retstrp != 0 )
{

4
crypto777/iguana_OS.c

@ -30,7 +30,7 @@
char *OS_mvstr()
{
#ifdef __WIN32
#ifdef _WIN32
return("rename");
#else
return("mv");
@ -659,7 +659,7 @@ int64_t OS_copyfile(char *src,char *dest,int32_t cmpflag)
{
if ( (destfp= fopen(OS_compatible_path(dest),"wb")) != 0 )
{
#ifdef WIN32
#ifdef _WIN32
allocsize = 1024 * 1024 * 8L;
#else
allocsize = 1024 * 1024 * 128L;

2
crypto777/jpeg/unix/jmemname.c

@ -11,7 +11,7 @@
* Also, the problem of determining the amount of memory available
* is shoved onto the user.
*/
#ifndef WIN32
#ifndef _WIN32
#include <unistd.h>
#endif

3
iguana/dPoW.h

@ -20,6 +20,7 @@
#define DPOW_CHECKPOINTFREQ 10
#define DPOW_MINSIGS 13
#define DPOW_MIN_ASSETCHAIN_SIGS 11
//#define DPOW_M(bp) ((bp)->minsigs) // (((bp)->numnotaries >> 1) + 1)
#define DPOW_MODIND(bp,offset) (((((bp)->height / DPOW_CHECKPOINTFREQ) % (bp)->numnotaries) + (offset)) % (bp)->numnotaries)
#define DPOW_VERSION 0x0781
@ -132,7 +133,7 @@ struct dpow_info
char symbol[16],dest[16]; uint8_t minerkey33[33],minerid; uint64_t lastrecvmask;
struct dpow_checkpoint checkpoint,last,destchaintip,srcfifo[DPOW_FIFOSIZE],destfifo[DPOW_FIFOSIZE];
struct dpow_hashheight approved[DPOW_FIFOSIZE],notarized[DPOW_FIFOSIZE];
bits256 srctx[DPOW_MAXTX],desttx[DPOW_MAXTX];
bits256 activehash,lastnotarized,srctx[DPOW_MAXTX],desttx[DPOW_MAXTX];
uint32_t SRCREALTIME,destupdated,srcconfirms,numdesttx,numsrctx,lastsplit,cancelratify;
int32_t lastheight,maxblocks,SRCHEIGHT,SHORTFLAG,ratifying;
struct pax_transaction *PAX;

7
iguana/dpow/dpow_fsm.c

@ -326,7 +326,7 @@ void dpow_statemachinestart(void *ptr)
return;
}
bp->myind = myind;
printf("[%d] statemachinestart %s->%s %s ht.%d minsigs.%d duration.%d start.%u\n",bp->myind,dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration,checkpoint.timestamp);
printf("[%d] notarize %s->%s %s ht.%d minsigs.%d duration.%d start.%u\n",bp->myind,dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration,checkpoint.timestamp);
if ( bp->isratify != 0 && memcmp(bp->notaries[0].pubkey,bp->ratified_pubkeys[0],33) != 0 )
{
for (i=0; i<33; i++)
@ -447,6 +447,11 @@ void dpow_statemachinestart(void *ptr)
dpow_send(myinfo,dp,bp,srchash,bp->hashmsg,0,bp->height,(void *)"ping",0);
dpow_nanomsg_update(myinfo);
}
else
{
dp->lastnotarized = bp->srctxid;
printf("notarized %s %s\n",dp->symbol,bits256_str(str,bp->srctxid));
}
if ( 0 && dp->cancelratify != 0 && bp->isratify != 0 )
{
printf("abort pending ratify\n");

16
iguana/dpow/dpow_rpc.c

@ -177,7 +177,7 @@ bits256 dpow_getbestblockhash(struct supernet_info *myinfo,struct iguana_info *c
memset(blockhash.bytes,0,sizeof(blockhash));
if ( coin->FULLNODE < 0 )
{
if ( coin->lastbesthashtime+20 > time(NULL) && bits256_nonz(coin->lastbesthash) != 0 )
if ( coin->lastbesthashtime+2 > time(NULL) && bits256_nonz(coin->lastbesthash) != 0 )
return(coin->lastbesthash);
if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getbestblockhash","")) != 0 )
{
@ -1154,10 +1154,11 @@ void dpow_issuer_voutupdate(struct dpow_info *dp,char *symbol,int32_t isspecial,
}
}
int32_t dpow_issuer_tx(struct dpow_info *dp,struct iguana_info *coin,int32_t height,int32_t txi,char *txidstr,uint32_t port)
int32_t dpow_issuer_tx(int32_t *isspecialp,struct dpow_info *dp,struct iguana_info *coin,int32_t height,int32_t txi,char *txidstr,uint32_t port)
{
char *retstr,params[256],*hexstr; uint8_t script[16384]; cJSON *json,*oldpub,*newpub,*result,*vouts,*item,*sobj; int32_t vout,n,len,isspecial,retval = -1; uint64_t value; bits256 txid;
char *retstr,params[256],*hexstr; uint8_t script[16384]; cJSON *json,*oldpub,*newpub,*result,*vouts,*item,*sobj; int32_t vout,n,len,retval = -1; uint64_t value; bits256 txid;
sprintf(params,"[\"%s\", 1]",txidstr);
*isspecialp = 0;
if ( (retstr= dpow_issuemethod(coin->chain->userpass,(char *)"getrawtransaction",params,port)) != 0 )
{
if ( (json= cJSON_Parse(retstr)) != 0 )
@ -1170,7 +1171,6 @@ int32_t dpow_issuer_tx(struct dpow_info *dp,struct iguana_info *coin,int32_t hei
retval = 0;
if ( oldpub == 0 && newpub == 0 && (vouts= jarray(&n,result,(char *)"vout")) != 0 )
{
isspecial = 0;
txid = jbits256(result,(char *)"txid");
for (vout=0; vout<n; vout++)
{
@ -1182,11 +1182,11 @@ int32_t dpow_issuer_tx(struct dpow_info *dp,struct iguana_info *coin,int32_t hei
{
len = (int32_t)strlen(hexstr) >> 1;
if ( vout == 0 && ((memcmp(&hexstr[2],CRYPTO777_PUBSECPSTR,66) == 0 && len == 35) || (memcmp(&hexstr[6],CRYPTO777_RMD160STR,40) == 0 && len == 25)) )
isspecial = 1;
*isspecialp = 1;
else if ( len <= sizeof(script) )
{
decode_hex(script,len,hexstr);
dpow_issuer_voutupdate(dp,coin->symbol,isspecial,height,txi,txid,vout,n,value,script,len);
dpow_issuer_voutupdate(dp,coin->symbol,*isspecialp,height,txi,txid,vout,n,value,script,len);
}
}
}
@ -1202,7 +1202,7 @@ int32_t dpow_issuer_tx(struct dpow_info *dp,struct iguana_info *coin,int32_t hei
int32_t dpow_issuer_block(struct dpow_info *dp,struct iguana_info *coin,int32_t height,uint16_t port)
{
char *retstr,*retstr2,params[128],*txidstr; int32_t i,n,retval = -1; cJSON *json,*tx=0,*result=0,*result2;
char *retstr,*retstr2,params[128],*txidstr; int32_t i,isspecial,n,retval = -1; cJSON *json,*tx=0,*result=0,*result2;
sprintf(params,"[%d]",height);
if ( (retstr= dpow_issuemethod(coin->chain->userpass,(char *)"getblockhash",params,port)) != 0 )
{
@ -1219,7 +1219,7 @@ int32_t dpow_issuer_block(struct dpow_info *dp,struct iguana_info *coin,int32_t
if ( (result2= jobj(json,(char *)"result")) != 0 && (tx= jarray(&n,result2,(char *)"tx")) != 0 )
{
for (i=0; i<n; i++)
if ( dpow_issuer_tx(dp,coin,height,i,jstri(tx,i),port) < 0 )
if ( dpow_issuer_tx(&isspecial,dp,coin,height,i,jstri(tx,i),port) < 0 )
break;
if ( i == n )
retval = 0;

52
iguana/exchanges/LP_coins.c

@ -54,9 +54,9 @@ char *parse_conf_line(char *line,char *field)
return(clonestr(line));
}
void LP_userpassfp(char *symbol,char *username,char *password,FILE *fp)
uint16_t LP_userpassfp(char *symbol,char *username,char *password,FILE *fp)
{
char *rpcuser,*rpcpassword,*str,line[8192];
char *rpcuser,*rpcpassword,*str,line[8192]; uint16_t port = 0;
rpcuser = rpcpassword = 0;
username[0] = password[0] = 0;
while ( fgets(line,sizeof(line),fp) != 0 )
@ -68,6 +68,16 @@ void LP_userpassfp(char *symbol,char *username,char *password,FILE *fp)
rpcuser = parse_conf_line(str,(char *)"rpcuser");
else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 )
rpcpassword = parse_conf_line(str,(char *)"rpcpassword");
else if ( (str= strstr(line,(char *)"rpcport")) != 0 )
{
str = parse_conf_line(str,(char *)"rpcport");
if ( str != 0 )
{
port = atoi(str);
//printf("RPCPORT.%u\n",port);
free(str);
}
}
}
if ( rpcuser != 0 && rpcpassword != 0 )
{
@ -79,6 +89,7 @@ void LP_userpassfp(char *symbol,char *username,char *password,FILE *fp)
free(rpcuser);
if ( rpcpassword != 0 )
free(rpcpassword);
return(port);
}
void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name,char *confpath)
@ -89,7 +100,7 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
return;
}
sprintf(fname,"%s",LP_getdatadir());
#ifdef WIN32
#ifdef _WIN32
strcat(fname,"\\");
#else
strcat(fname,"/");
@ -127,7 +138,7 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
#endif
if ( strcmp(symbol,"KMD") != 0 )
{
#ifdef WIN32
#ifdef _WIN32
strcat(fname,"\\");
#else
strcat(fname,"/");
@ -135,7 +146,7 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
strcat(fname,assetname);
}
}
#ifdef WIN32
#ifdef _WIN32
strcat(fname,"\\");
#else
strcat(fname,"/");
@ -143,9 +154,9 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
strcat(fname,str);
}
int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,char *name,char *confpath)
uint16_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,char *name,char *confpath,uint16_t origport)
{
FILE *fp; char fname[512],username[512],password[512],confname[512];
FILE *fp; char fname[512],username[512],password[512],confname[512]; uint16_t port = 0;
userpass[0] = 0;
sprintf(confname,"%s.conf",confroot);
if ( 0 )
@ -160,14 +171,15 @@ int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,c
LP_statefname(fname,symbol,assetname,confname,name,confpath);
if ( (fp= fopen(fname,"rb")) != 0 )
{
LP_userpassfp(symbol,username,password,fp);
if ( (port= LP_userpassfp(symbol,username,password,fp)) == 0 )
port = origport;
sprintf(userpass,"%s:%s",username,password);
fclose(fp);
if ( 0 )
printf("LP_statefname.(%s) <- %s %s %s (%s) (%s)\n",fname,name,symbol,assetname,userpass,confpath);
return((int32_t)strlen(userpass));
return(port);
} else printf("cant open.(%s)\n",fname);
return(-1);
return(0);
}
cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
@ -269,24 +281,29 @@ struct iguana_info *LP_coinadd(struct iguana_info *cdata)
return(coin);
}
int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath)
uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath)
{
char *name2;
memset(coin,0,sizeof(*coin));
safecopy(coin->symbol,symbol,sizeof(coin->symbol));
sprintf(coin->serverport,"127.0.0.1:%u",port);
coin->updaterate = (uint32_t)time(NULL);
coin->isPoS = isPoS;
coin->taddr = taddr;
coin->wiftaddr = wiftaddr;
coin->longestchain = longestchain;
coin->txfee = txfee;
if ( (coin->txfee= txfee) > 0 && txfee < LP_MIN_TXFEE )
coin->txfee = LP_MIN_TXFEE;
coin->pubtype = pubtype;
coin->p2shtype = p2shtype;
coin->wiftype = wiftype;
coin->inactive = (uint32_t)time(NULL);
coin->bussock = LP_coinbus(busport);
coin->ctx = bitcoin_ctx();
if ( assetname != 0 && strcmp(name,assetname) == 0 )
{
printf("%s is assetchain\n",symbol);
coin->isassetchain = 1;
}
if ( strcmp(symbol,"KMD") == 0 || (assetname != 0 && assetname[0] != 0) )
name2 = 0;
else name2 = name;
@ -295,7 +312,9 @@ int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asset
coin->noimportprivkey_flag = 1;
printf("truncate importprivkey for %s\n",symbol);
}
return(LP_userpass(coin->userpass,symbol,assetname,name,name2,confpath));
port = LP_userpass(coin->userpass,symbol,assetname,name,name2,confpath,port);
sprintf(coin->serverport,"127.0.0.1:%u",port);
return(port);
}
int32_t LP_isdisabled(char *base,char *rel)
@ -338,7 +357,10 @@ struct iguana_info *LP_coinfind(char *symbol)
else if ( strcmp(symbol,"KMD") == 0 )
name = "komodo";
else return(0);
isinactive = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0) < 0;
port = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0);
if ( port == 0 )
isinactive = 1;
else isinactive = 0;
if ( (coin= LP_coinadd(&cdata)) != 0 )
{
coin->inactive = isinactive * (uint32_t)time(NULL);

231
iguana/exchanges/LP_commands.c

@ -94,19 +94,24 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
// return(clonestr("{\"result\":\"success\"}"));
else if ( strcmp(method,"help") == 0 )
return(clonestr("{\"result\":\" \
available localhost RPC commands:\n \
available localhost RPC commands: * means it needs to be a signed request\n \
pricearray(base, rel, firsttime=0, lasttime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
setprice(base, rel, price)\n\
autoprice(base, rel, price, margin, type)\n\
goal(coin=*, val=<autocalc>)\n\
setprice(base, rel, price)*\n\
autoprice(base, rel, minprice, margin, refbase, refrel, factor, offset)*\n\
goal(coin=*, val=<autocalc>)*\n\
myprice(base, rel)\n\
enable(coin)\n\
disable(coin)\n\
enable(coin)*\n\
disable(coin)*\n\
inventory(coin)\n\
bestfit(rel, relvolume)\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600)\n\
swapstatus()\n\
swapstatus(requestid, quoteid)\n\
lastnonce()\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)*\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)*\n\
withdraw(coin, outputs[])*\n\
sendrawtransaction(coin, signedtx)\n\
swapstatus()*\n\
recentswaps(limit=3)\n\
swapstatus(requestid, quoteid)*\n\
public API:\n \
getcoins()\n\
getcoin(coin)\n\
@ -114,17 +119,20 @@ portfolio()\n\
getpeers()\n\
passphrase(passphrase, gui)\n\
listunspent(coin, address)\n\
setconfirms(coin, numconfirms, maxconfirms=6)*\n\
trust(pubkey, trust)*\n\
balance(coin, address)\n\
orderbook(base, rel, duration=3600)\n\
getprices(base, rel)\n\
sendmessage(base=coin, rel="", pubkey=zero, <argjson method2>)\n\
getmessages(firsti=0, num=100)\n\
clearmessages(firsti=0, num=100)\n\
secretaddresses(passphrase, num=10, pubtype=60, taddr=0)\n\
electrum(coin, ipaddr, port)\n\
deletemessages(firsti=0, num=100)\n\
secretaddresses(prefix='secretaddress', passphrase, num=10, pubtype=60, taddr=0)\n\
electrum(coin, ipaddr, port)*\n\
snapshot(coin, height)\n\
snapshot_balance(coin, height, addresses[])\n\
dividends(coin, height, <args>)\n\
stop()\n\
\"}"));
//sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\
@ -149,11 +157,19 @@ dividends(coin, height, <args>)\n\
{
if ( jobj(argjson,"method2") == 0 )
{
printf("broadcast message\n");
LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,jbits256(argjson,"pubkey"),jprint(argjson,0));
}
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"recentswaps") == 0 )
{
return(LP_recent_swaps(jint(argjson,"limit")));
}
else if ( strcmp(method,"stop") == 0 )
{
printf("DEBUG stop\n");
exit(0);
}
else if ( strcmp(method,"getmessages") == 0 )
{
if ( (retjson= LP_getmessages(jint(argjson,"firsti"),jint(argjson,"num"))) != 0 )
@ -186,7 +202,7 @@ dividends(coin, height, <args>)\n\
uint8_t taddr,pubtype;
pubtype = (jobj(argjson,"pubtype") == 0) ? 60 : juint(argjson,"pubtype");
taddr = (jobj(argjson,"taddr") == 0) ? 0 : juint(argjson,"taddr");
return(LP_secretaddresses(ctx,jstr(argjson,"passphrase"),juint(argjson,"num"),taddr,pubtype));
return(LP_secretaddresses(ctx,jstr(argjson,"prefix"),jstr(argjson,"passphrase"),juint(argjson,"num"),taddr,pubtype));
}
if ( base != 0 && rel != 0 )
{
@ -198,6 +214,7 @@ dividends(coin, height, <args>)\n\
{
if ( price > SMALLVAL )
{
//LP_signature_add(argjson,base,rel,(uint64_t)price * SATOSHIDEN);
if ( LP_mypriceset(&changed,base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
@ -207,7 +224,8 @@ dividends(coin, height, <args>)\n\
}
else if ( strcmp(method,"autoprice") == 0 )
{
if ( LP_autoprice(base,rel,price,jdouble(argjson,"margin"),jstr(argjson,"type")) < 0 )
//LP_signature_add(argjson,base,rel,(uint64_t)price * SATOSHIDEN);
if ( LP_autoprice(base,rel,argjson) < 0 )
return(clonestr("{\"error\":\"couldnt set autoprice\"}"));
else return(clonestr("{\"result\":\"success\"}"));
}
@ -229,16 +247,18 @@ dividends(coin, height, <args>)\n\
}
else if ( strcmp(method,"buy") == 0 )
{
//*
if ( price > SMALLVAL )
{
return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui")));
return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"sell") == 0 )
{
//*
if ( price > SMALLVAL )
{
return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui")));
return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
}
@ -253,28 +273,77 @@ dividends(coin, height, <args>)\n\
{
if ( strcmp(method,"enable") == 0 )
{
//*
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
if ( ptr->userpass[0] == 0 )
{
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","couldnt find coin locally installed");
jaddstr(retjson,"coin",coin);
return(jprint(retjson,1));
}
if ( LP_conflicts_find(ptr) == 0 )
{
ptr->inactive = 0;
else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}"));
}
return(jprint(LP_coinsjson(0),1));
cJSON *array = cJSON_CreateArray();
jaddi(array,LP_coinjson(ptr,0));
return(jprint(array,1));
} else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}"));
} else return(clonestr("{\"error\":\"couldnt find coin\"}"));
}
else if ( strcmp(method,"disable") == 0 )
{
//*
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
ptr->inactive = (uint32_t)time(NULL);
return(jprint(LP_coinsjson(0),1));
cJSON *array = cJSON_CreateArray();
jaddi(array,LP_coinjson(ptr,0));
return(jprint(array,1));
} else return(clonestr("{\"error\":\"couldnt find coin\"}"));
}
else if ( strcmp(method,"electrum") == 0 )
{
//*
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
ptr->inactive = 0;
return(jprint(LP_electrumserver(ptr,jstr(argjson,"ipaddr"),juint(argjson,"port")),1));
} else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"sendrawtransaction") == 0 )
{
return(LP_sendrawtransaction(coin,jstr(argjson,"signedtx")));
}
else if ( strcmp(method,"withdraw") == 0 )
{
///*
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
if ( jobj(argjson,"outputs") == 0 )
return(clonestr("{\"error\":\"withdraw needs to have outputs\"}"));
else return(LP_withdraw(ptr,argjson));
}
return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"setconfirms") == 0 )
{
int32_t n;
//*
n = jint(argjson,"numconfirms");
if ( n < 0 )
return(clonestr("{\"error\":\"illegal numconfirms\"}"));
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
ptr->userconfirms = n;
if ( (n= jint(argjson,"maxconfirms")) > 0 )
ptr->maxconfirms = n;
if ( ptr->maxconfirms > 0 && ptr->userconfirms > ptr->maxconfirms )
ptr->userconfirms = ptr->maxconfirms;
return(clonestr("{\"result\":\"success\"}"));
} else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"snapshot") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
@ -311,27 +380,47 @@ dividends(coin, height, <args>)\n\
jaddnum(retjson,"timestamp",time(NULL));
jadd(retjson,"alice",LP_inventory(coin));
//jadd(retjson,"bob",LP_inventory(coin,1));
LP_smartutxos_push(ptr);
return(jprint(retjson,1));
}
}
else if ( strcmp(method,"goal") == 0 )
{
//*
return(LP_portfolio_goal(coin,jdouble(argjson,"val")));
}
else if ( strcmp(method,"getcoin") == 0 )
return(LP_getcoin(coin));
}
else if ( strcmp(method,"goal") == 0 )
{
//*
return(LP_portfolio_goal("*",100.));
}
else if ( strcmp(method,"swapstatus") == 0 )
{
uint32_t requestid,quoteid;
//*
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
return(basilisk_swapentry(requestid,quoteid));
else return(basilisk_swaplist(0,0));
}
else if ( strcmp(method,"lastnonce") == 0 )
{
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"lastnonce",LP_lastnonce);
return(jprint(retjson,1));
}
else if ( strcmp(method,"myprices") == 0 )
return(LP_myprices());
else if ( strcmp(method,"trust") == 0 )
{
//*
return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust")));
}
else if ( strcmp(method,"trusted") == 0 )
return(LP_pubkey_trusted());
}
if ( IAMLP == 0 )
{
@ -372,8 +461,27 @@ dividends(coin, height, <args>)\n\
else if ( strcmp(method,"listunspent") == 0 )
{
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
return(jprint(LP_address_utxos(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
{
char *coinaddr;
if ( (coinaddr= jstr(argjson,"address")) != 0 )
{
if ( coinaddr[0] != 0 )
{
LP_address(ptr,coinaddr);
LP_listunspent_issue(coin,coinaddr,1);
if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_mypriv25519) != 0 )
{
LP_privkey_init(-1,ptr,G.LP_mypriv25519,G.LP_mypub25519);
//LP_smartutxos_push(ptr);
}
else
{
}
}
return(jprint(LP_address_utxos(ptr,coinaddr,1),1));
} else return(clonestr("{\"error\":\"no address specified\"}"));
} else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"balance") == 0 )
{
@ -381,56 +489,39 @@ dividends(coin, height, <args>)\n\
return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"result\":\"at least one of coins disabled\"}"));
else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 )
retstr = clonestr("{\"result\":\"coin is disabled\"}");
else if ( strcmp(method,"reserved") == 0 )
{
//printf("RESERVED.(%s)\n",jprint(argjson,0));
retstr = LP_quotereceived(argjson);
}
else if ( strcmp(method,"connected") == 0 )
{
//printf("CONNECTED.(%s)\n",jprint(argjson,0));
retstr = LP_connectedalice(argjson);
}
else if ( strcmp(method,"checktxid") == 0 )
retstr = LP_spentcheck(argjson);
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"numutxos") == 0 )
else if ( strcmp(method,"addr_unspents") == 0 )
{
printf("deprecated numutxos received\n");
retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
//return(LP_numutxos());
//printf("GOT ADDR_UNSPENTS %s %s\n",jstr(argjson,"coin"),jstr(argjson,"address"));
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
{
char *coinaddr; //cJSON *array,*item,*req; int32_t i,n,vout,height; bits256 zero,txid; uint64_t value;
if ( (coinaddr= jstr(argjson,"address")) != 0 )
{
if ( coinaddr[0] != 0 )
{
LP_address(ptr,coinaddr);
if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_mypriv25519) != 0 )
{
//printf("ADDR_UNSPENTS %s %s is my address being asked for!\n",ptr->symbol,coinaddr);
ptr->addr_listunspent_requested = (uint32_t)time(NULL);
}
}
}
}
retstr = clonestr("{\"result\":\"success\"}");
}
//else if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
// return(clonestr("{\"result\":\"at least one of coins disabled\"}"));
//else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 )
// retstr = clonestr("{\"result\":\"coin is disabled\"}");
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"encrypted") == 0 )
retstr = clonestr("{\"result\":\"success\"}");
else if ( strcmp(method,"registerall") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"forward") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"keepalive") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers());
else if ( strcmp(method,"getutxos") == 0 )
{
printf("deprecated getutxos received\n");
retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
//return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn")));
}
else if ( strcmp(method,"utxo") == 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("deprecated utxo received\n");
//if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 )
// retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}");
//else
retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
}
else
{
if ( base != 0 && rel != 0 && strcmp(method,"pricearray") == 0 )
@ -461,10 +552,6 @@ dividends(coin, height, <args>)\n\
}
if ( IAMLP != 0 )
{
if ( strcmp(method,"register") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"lookup") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
if ( strcmp(method,"broadcast") == 0 )
{
bits256 zero; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE];
@ -482,11 +569,9 @@ dividends(coin, height, <args>)\n\
}
else
{
char *msg;
memset(zero.bytes,0,sizeof(zero));
msg = jprint(reqjson,0);
//printf("broadcast.(%s)\n",msg);
LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,zero,msg);
//printf("broadcast.(%s)\n",Broadcaststr);
LP_reserved_msg(base!=0?base:jstr(argjson,"coin"),rel,zero,jprint(reqjson,0));
}
retstr = clonestr("{\"result\":\"success\"}");
} else retstr = clonestr("{\"error\":\"couldnt dereference sendmessage\"}");

27
iguana/exchanges/LP_include.h

@ -35,7 +35,7 @@
#define MIN_PSOCK_PORT 10000
#define LP_MEMPOOL_TIMEINCR 10
#define LP_GETINFO_INCR 30
#define LP_ORDERBOOK_DURATION 3600
#define LP_ORDERBOOK_DURATION 120
#define LP_HTTP_TIMEOUT 2 // 1 is too small due to edge cases of time(NULL)
#define LP_MAXPEER_ERRORS 3
@ -43,7 +43,7 @@
#define LP_PEERGOOD_ERRORDECAY 0.9
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 60
#define LP_AUTOTRADE_TIMEOUT 10
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 50
@ -71,7 +71,8 @@
#define LP_RESERVETIME 60
#define LP_AVETXSIZE 256
#define LP_CACHEDURATION 60
#define BASILISK_DEFAULT_NUMCONFIRMS 1
#define BASILISK_DEFAULT_NUMCONFIRMS 3
#define BASILISK_DEFAULT_MAXCONFIRMS 6
#define DEX_SLEEP 3
#define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2))
@ -151,7 +152,7 @@ struct basilisk_swapinfo
char bobstr[64],alicestr[64];
bits256 myhash,otherhash,orderhash;
uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration;
int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad;
int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad,aliceistrusted,bobistrusted,otheristrusted,otherstrust,alicemaxconfirms,bobmaxconfirms;
uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee;
bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn;
@ -183,8 +184,8 @@ struct iguana_info
portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses;
uint64_t txfee;
int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport;
uint32_t lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag;
uint32_t addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms;
char symbol[16],smartaddr[64],userpass[1024],serverport[128],lastunspent[64];
// portfolio
double price_kmd,force,perc,goal,goalperc,relvolume,rate;
@ -269,7 +270,7 @@ struct basilisk_swap
struct basilisk_swapmessage *messages; int32_t nummessages,sentflag;
char Bdeposit[64],Bpayment[64];
uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2];
uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[100000];
uint8_t persistent_pubkey33[33],persistent_other33[33],changermd160[20],pad[15],verifybuf[100000];
};
@ -288,6 +289,7 @@ int32_t LP_ismine(struct LP_utxoinfo *utxo);
int32_t LP_isavailable(struct LP_utxoinfo *utxo);
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);
void LP_availableset(struct LP_utxoinfo *utxo);
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);
@ -295,10 +297,13 @@ int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsoc
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
//void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
int32_t LP_coinbus(uint16_t coin_busport);
int32_t LP_nanomsg_recvs(void *ctx);
int32_t LP_reserved_msgs();
int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg);
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);
uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee);
uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen);
struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr);
struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr);
struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr);
@ -311,11 +316,13 @@ struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid)
cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj);
int32_t LP_mempoolscan(char *symbol,bits256 searchtxid);
int32_t LP_txheight(struct iguana_info *coin,bits256 txid);
int32_t LP_numpeers();
int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight);
void LP_smartutxos_push(struct iguana_info *coin);
cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret);
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 LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag);
uint16_t LP_randpeer(char *destip);
cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys);
//int32_t LP_butxo_findeither(bits256 txid,int32_t vout);
@ -325,5 +332,7 @@ 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);
void LP_listunspent_query(char *symbol,char *coinaddr);
int32_t bitcoin_priv2wif(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype);
#endif

308
iguana/exchanges/LP_nativeDEX.c

@ -13,27 +13,28 @@
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//alice only coins GAME UNO BTM ANC: GAME BTCD PPC RDD XZC POT EAC FTC BASH SPR WDC UNO XPM XCN BELA CHC DIME MEC NAUT MED AUR MAX DGC RIC EB3 DOT BTM GEO ANC CANN ICASH WBB SRC PTC ADZ TIPS EQT START EFL FST FJC NYC GCN
//
// LP_nativeDEX.c
// marketmaker
//
// SPV at tx level
// stats, fix pricearray
// sign packets
// dPoW security
// electrum peers
// withdraw
// verify portfolio
// bittrex balancing
// dPoW security -> 4: KMD notarized, 5: BTC notarized
// dICO allocation script
// sign critical api calls (pubkey reg, listunspent, orders?)
// process stats.log local file
// verify portfolio, pricearray, interest to KMD withdraw
// handles <-> pubkeys
// deal with offline pubkeys, reputations, etc.
// alice only coins GAME UNO BTM ANC: GAME BTCD PPC RDD XZC POT EAC FTC BASH SPR WDC UNO XPM XCN BELA CHC DIME MEC NAUT MED AUR MAX DGC RIC EB3 DOT BTM GEO ANC CANN ICASH WBB SRC PTC ADZ TIPS EQT START EFL FST FJC NYC GCN
#include <stdio.h>
#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;
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;
int32_t LP_canbind;
char *Broadcaststr;
char *Broadcaststr,*Reserved_msgs[1000];
int32_t num_Reserved_msgs,max_Reserved_msgs;
struct LP_peerinfo *LP_peerinfos,*LP_mypeer;
struct LP_forwardinfo *LP_forwardinfos;
struct iguana_info *LP_coins;
@ -48,6 +49,7 @@ char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.25
//uint32_t LP_deadman_switch;
uint16_t LP_fixed_pairport,LP_publicport;
uint32_t LP_lastnonce;
int32_t LP_mybussock = -1;
int32_t LP_mypubsock = -1;
int32_t LP_mypullsock = -1;
@ -161,7 +163,7 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,
if ( duplicate != 0 )
dup++;
else uniq++;
if ( (rand() % 1000) == 0 )
if ( (rand() % 10000) == 0 )
printf("%s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x\n",typestr,duplicate,dup,dup+uniq,(double)100*dup/(dup+uniq),encrypted,crc32,ptr[0],ptr[1],crc32&0xff,(crc32>>8)&0xff);
if ( duplicate == 0 )
{
@ -242,7 +244,19 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
break;
if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
//printf("RECV.(%s)\n",(char *)ptr);
if ( 0 )
{
cJSON *recvjson; char *mstr,*cstr;
if ( (recvjson= cJSON_Parse((char *)ptr)) != 0 )
{
if ( (mstr= jstr(recvjson,"method")) != 0 && strcmp(mstr,"uitem") == 0 &&
(cstr= jstr(recvjson,"coin")) != 0 && strcmp(cstr,"REVS") == 0 )
{
printf("%s RECV.(%s)\n",typestr,(char *)ptr);
}
free_json(recvjson);
}
}
nonz++;
if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 )
free(retstr);
@ -257,8 +271,10 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
printf("self.(%s)\n",str);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
{
portable_mutex_lock(&LP_commandmutex);
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 )
free(retstr);
portable_mutex_unlock(&LP_commandmutex);
}
free_json(argjson);
}
@ -270,55 +286,121 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
return(nonz);
}
int32_t LP_nanomsg_recvs(void *ctx)
{
static double lastmilli;
int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; double milli;
if ( (origipaddr= LP_myipaddr) == 0 )
origipaddr = "127.0.0.1";
milli = OS_milliseconds();
if ( lastmilli > 0. && milli > lastmilli+3000 )
fprintf(stderr,">>>>>>>>>>>>>>>>> BIG latency lag %.3f milliseconds\n",milli-lastmilli);
lastmilli = milli;
//portable_mutex_lock(&LP_nanorecvsmutex);
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( peer->errors >= LP_MAXPEER_ERRORS )
{
if ( (rand() % 10000) == 0 )
peer->errors--;
else
{
//printf("skip %s\n",peer->ipaddr);
continue;
}
}
//printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr);
}
/*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
if ( coin->inactive != 0 )
continue;
if ( coin->bussock >= 0 )
nonz += LP_sock_check(coin->symbol,ctx,origipaddr,-1,coin->bussock,LP_profitratio - 1.);
}*/
if ( LP_mypullsock >= 0 )
nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1");
//portable_mutex_unlock(&LP_nanorecvsmutex);
return(nonz);
}
void command_rpcloop(void *myipaddr)
{
int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; void *ctx;
int32_t nonz = 0; void *ctx;
ctx = bitcoin_ctx();
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
while ( 1 )
{
nonz = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
nonz = LP_nanomsg_recvs(ctx);
//if ( LP_mybussock >= 0 )
// nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock);
if ( nonz == 0 )
{
if ( IAMLP != 0 )
usleep(1000);
else usleep(10000);
}
else if ( IAMLP == 0 )
usleep(1000);
}
}
void LP_smartutxos_push(struct iguana_info *coin)
{
struct LP_peerinfo *peer,*tmp; uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; char *retstr; cJSON *array,*item,*req;
if ( coin->smartaddr[0] == 0 )
return;
if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
if ( peer->errors >= LP_MAXPEER_ERRORS )
//printf("PUSH %s %s\n",coin->symbol,coin->smartaddr);
for (i=0; i<n; i++)
{
if ( (rand() % 10000) == 0 )
peer->errors--;
else
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
vout = jint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
if ( (rand() % 100) == 0 && IAMLP == 0 )
{
//printf("skip %s\n",peer->ipaddr);
continue;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( (retstr= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,vout,height,value)) != 0 )
free(retstr);
}
}
req = cJSON_CreateObject();
jaddstr(req,"method","uitem");
jaddstr(req,"coin",coin->symbol);
jaddstr(req,"coinaddr",coin->smartaddr);
jaddbits256(req,"txid",txid);
jaddnum(req,"vout",vout);
jaddnum(req,"ht",height);
jadd64bits(req,"value",value);
//printf("ADDR_UNSPENTS[] <- %s\n",jprint(req,0));
LP_reserved_msg("","",zero,jprint(req,1));
}
//printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr);
}
/*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
if ( coin->inactive != 0 )
continue;
if ( coin->bussock >= 0 )
nonz += LP_sock_check(coin->symbol,ctx,origipaddr,-1,coin->bussock,LP_profitratio - 1.);
}*/
if ( LP_mypullsock >= 0 )
nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1");
//if ( LP_mybussock >= 0 )
// nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock);
if ( nonz == 0 )
usleep(10000);
free_json(array);
}
}
int32_t LP_utxos_sync(struct LP_peerinfo *peer)
{
int32_t i,j,n=0,m,v,posted=0; bits256 txid; cJSON *array,*item,*item2,*array2,*array3; uint64_t total,total2,metric; struct iguana_info *coin,*ctmp; struct LP_address *ap; char *retstr,*retstr2,*coinaddr;
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
return(0);
HASH_ITER(hh,LP_coins,coin,ctmp)
{
if ( coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) )
if ( IAMLP == 0 && coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) )
continue;
if ( coin->smartaddr[0] == 0 )
continue;
total = 0;
LP_listunspent_both(coin->symbol,coin->smartaddr);
if ( (j= LP_listunspent_both(coin->symbol,coin->smartaddr,0)) == 0 )
continue;
if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
@ -331,6 +413,7 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer)
}
if ( n > 0 && total > 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr)) != 0 )
{
//printf("UTXO sync.%d %s n.%d total %.8f -> %s (%s)\n",j,coin->symbol,n,dstr(total),peer->ipaddr,retstr);
total2 = 0;
if ( (array2= cJSON_Parse(retstr)) != 0 )
{
@ -356,7 +439,7 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer)
}
if ( j == m )
{
//printf("%s missing %s\n",peer->ipaddr,jprint(item,0));
//printf("%s missing %s %s\n",peer->ipaddr,coin->symbol,jprint(item,0));
if ( (retstr2= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 )
free(retstr2);
posted++;
@ -364,13 +447,26 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer)
}
if ( 0 && posted != 0 )
printf(">>>>>>>> %s compare %s %s (%.8f n%d) (%.8f m%d)\n",peer->ipaddr,coin->symbol,coin->smartaddr,dstr(total),n,dstr(total2),m);
} //else printf("%s matches\n",peer->ipaddr);
} //else printf("%s matches %s\n",peer->ipaddr,coin->symbol);
free_json(array2);
}
} else printf("parse error (%s)\n",retstr);
free(retstr);
}
else if ( n != 0 && total != 0 )
{
//printf("no response from %s for %s %s\n",peer->ipaddr,coin->symbol,coin->smartaddr);
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
if ( (retstr2= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 )
free(retstr2);
}
}
free_json(array);
}
if ( (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 )
if ( 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 )
{
if ( (array2= cJSON_Parse(retstr)) != 0 )
{
@ -381,7 +477,7 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer)
item = jitem(array2,j);
if ( (coinaddr= jfieldname(item)) != 0 )
{
metric = j64bits(item,"coinaddr");
metric = j64bits(item,coinaddr);
//printf("(%s) -> %.8f n.%d\n",coinaddr,dstr(metric>>16),(uint16_t)metric);
if ( (ap= LP_addressfind(coin,coinaddr)) == 0 || _LP_unspents_metric(ap->total,ap->n) != metric )
{
@ -414,7 +510,7 @@ int32_t LP_utxos_sync(struct LP_peerinfo *peer)
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,numpeers;
struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; bits256 zero; int32_t needpings,height,nonz = 0;
struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; bits256 zero; int32_t needpings,j,height,nonz = 0;
now = (uint32_t)time(NULL);
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
@ -435,23 +531,28 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
if ( IAMLP == 0 )
continue;
}
if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 1000) == 0) )
if ( now > peer->lastpeers+60 || (rand() % 10000) == 0 )
{
peer->lastpeers = now;
if ( strcmp(peer->ipaddr,myipaddr) != 0 )
{
nonz++;
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport);
peer->diduquery = 0;
LP_utxos_sync(peer);
}
peer->lastpeers = now;
}
if ( peer->diduquery == 0 )
{
nonz++;
needpings++;
LP_peer_pricesquery(peer);
LP_utxos_sync(peer);
peer->diduquery = now;
}
if ( peer->needping != 0 )
{
nonz++;
needpings++;
if ( (retstr= issue_LP_notify(peer->ipaddr,peer->port,"127.0.0.1",0,numpeers,G.LP_sessionid,G.LP_myrmd160str,G.LP_mypub25519)) != 0 )
free(retstr);
@ -460,16 +561,24 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
}
if ( needpings != 0 || (counter % 6000) == 5 )
{
nonz++;
//printf("needpings.%d send notify\n",needpings);
LP_notify_pubkeys(ctx,pubsock);
}
if ( (counter % 6000) == 10 )
{
nonz++;
LP_privkey_updates(ctx,pubsock,0);
}
HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
memset(&zero,0,sizeof(zero));
if ( coin->addr_listunspent_requested != 0 )
{
//printf("PUSH addr_listunspent_requested %u\n",coin->addr_listunspent_requested);
LP_smartutxos_push(coin);
coin->addr_listunspent_requested = 0;
}
if ( coin->inactive != 0 )
continue;
if ( coin->electrum != 0 )
@ -478,6 +587,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
// continue;
if ( time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR )
{
nonz++;
if ( (height= LP_getheight(coin)) > coin->longestchain )
{
coin->longestchain = height;
@ -507,13 +617,22 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
coin->lastscanht = coin->firstscanht;
continue;
}
printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
if ( (coin->lastscanht % 1000) == 0 )
printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
for (j=0; j<100; j++)
{
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
continue;
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
{
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
break;
}
coin->lastscanht++;
if ( coin->lastscanht == coin->longestchain+1 )
break;
}
coin->lastscanht++;
if ( j < 100 )
continue;
nonz++;
//LP_getestimatedrate(coin);
break;
}
@ -522,6 +641,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
{
//printf("SWAPS.(%s)\n",retstr);
nonz++;
free(retstr);
}
}
@ -591,9 +711,56 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint
}
}
int32_t LP_reserved_msgs()
{
bits256 zero; int32_t n = 0; //struct nn_pollfd pfd;
memset(zero.bytes,0,sizeof(zero));
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs > 0 )
{
/*memset(&pfd,0,sizeof(pfd));
pfd.fd = LP_mypubsock;
pfd.events = NN_POLLOUT;
if ( nn_poll(&pfd,1,1) != 1 )
break;*/
num_Reserved_msgs--;
#ifdef __APPLE__
// printf("%d BROADCASTING RESERVED.(%s)\n",num_Reserved_msgs,Reserved_msgs[num_Reserved_msgs]);
#endif
LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[num_Reserved_msgs]);
Reserved_msgs[num_Reserved_msgs] = 0;
n++;
#ifdef __APPLE__
usleep(5000);
#else
usleep(100);
#endif
}
portable_mutex_unlock(&LP_reservedmutex);
return(n);
}
int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg)
{
int32_t n = 0;
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs) )
{
Reserved_msgs[num_Reserved_msgs++] = msg;
n = num_Reserved_msgs;
} else LP_broadcast_message(LP_mypubsock,base,rel,pubkey,msg);
portable_mutex_unlock(&LP_reservedmutex);
if ( num_Reserved_msgs > max_Reserved_msgs )
{
max_Reserved_msgs = num_Reserved_msgs;
printf("New max_Reserved_msgs.%d\n",max_Reserved_msgs);
}
return(n);
}
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybusport,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson)
{
char *myipaddr=0; long filesize,n; int32_t timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128]; void *ctx = bitcoin_ctx();
char *myipaddr=0; long filesize,n; int32_t timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx();
LP_showwif = juint(argjson,"wif");
if ( passphrase == 0 || passphrase[0] == 0 )
{
@ -651,6 +818,9 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
portable_mutex_init(&LP_messagemutex);
portable_mutex_init(&LP_portfoliomutex);
portable_mutex_init(&LP_butxomutex);
portable_mutex_init(&LP_reservedmutex);
portable_mutex_init(&LP_nanorecvsmutex);
#ifndef _WIN32
if ( system("curl -s4 checkip.amazonaws.com > DB/myipaddr") == 0 )
{
char ipfname[64];
@ -663,6 +833,9 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
strcpy(LP_myipaddr,myipaddr);
} else printf("error getting myipaddr\n");
} else printf("error issuing curl\n");
#else
myipaddr = clonestr("127.0.0.1");
#endif
if ( IAMLP != 0 )
{
pubsock = -1;
@ -694,8 +867,23 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
LP_mybussock = LP_coinbus(mybusport);
//LP_deadman_switch = (uint32_t)time(NULL);
printf("canbind.%d my command address is (%s) pullsock.%d pullport.%u\n",LP_canbind,pushaddr,LP_mypullsock,mypullport);
printf("initcoins\n");
LP_initcoins(ctx,pubsock,jobj(argjson,"coins"));
if ( (coinsjson= jobj(argjson,"coins")) == 0 )
{
if ( (coins_str= OS_filestr(&filesize,"coins.json")) != 0 )
{
unstringify(coins_str);
printf("UNSTRINGIFIED.(%s)\n",coins_str);
coinsjson = cJSON_Parse(coins_str);
free(coins_str);
// yes I know this coinsjson is not freed, not sure about if it is referenced
}
}
if ( coinsjson == 0 )
{
printf("no coins object or coins file, must abort\n");
exit(-1);
}
LP_initcoins(ctx,pubsock,coinsjson);
G.waiting = 1;
LP_passphrase_init(passphrase,jstr(argjson,"gui"));
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 )
@ -739,8 +927,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport) != 0 )
nonz++;
if ( nonz == 0 )
usleep(50000);
else usleep(5000);
usleep(10000);
else if ( IAMLP != 0 )
usleep(1000);
else usleep(10000);
}
}

36
iguana/exchanges/LP_network.c

@ -87,7 +87,7 @@ void _LP_sendqueueadd(uint32_t crc32,int32_t sock,uint8_t *msg,int32_t msglen,in
int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32)
{
static uint32_t crcs[8192]; static unsigned long dup,total;
static uint32_t crcs[64]; static unsigned long dup,total;
int32_t i;
*duplicatep = 0;
if ( ind < 0 )
@ -144,6 +144,7 @@ void queue_loop(void *ignore)
struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0;
while ( 1 )
{
LP_reserved_msgs();
nonz = 0;
//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 = 0;
@ -157,7 +158,9 @@ void queue_loop(void *ignore)
{
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 printf("%d %p qsent %u msglen.%d peerind.%d (%s)\n",n,ptr,ptr->crc32,ptr->msglen,ptr->peerind,ptr->msg);
#ifdef __APPLE__
//else printf("%d %p qsent %u msglen.%d peerind.%d (%s)\n",n,ptr,ptr->crc32,ptr->msglen,ptr->peerind,ptr->msg);
#endif
ptr->sock = -1;
if ( ptr->peerind > 0 )
ptr->starttime = (uint32_t)time(NULL);
@ -170,11 +173,11 @@ void queue_loop(void *ignore)
if ( duplicate > 0 )
{
LP_Qfound++;
if ( (LP_Qfound % 10) == 0 )
if ( (LP_Qfound % 100) == 0 )
printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound);
flag = 1;
}
else
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++;
@ -199,22 +202,24 @@ void queue_loop(void *ignore)
//if ( n != 0 )
// printf("LP_Q.[%d]\n",n);
if ( nonz == 0 )
usleep(50000);
usleep(5000);
else if ( IAMLP == 0 )
usleep(1000);
}
}
void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32_t msglen,int32_t needack)
{
int32_t sentbytes,peerind = 0;
int32_t maxind,peerind = 0; //sentbytes,
if ( sock0 >= 0 || sock1 >= 0 )
{
if ( sock0 >= 0 && LP_sockcheck(sock0) > 0 )
/* if ( sock0 >= 0 && LP_sockcheck(sock0) > 0 )
{
if ( (sentbytes= nn_send(sock0,msg,msglen,0)) != msglen )
printf("_LP_queuesend0 sent %d instead of %d\n",sentbytes,msglen);
else
{
//printf("Q sent %u msglen.%d (%s)\n",crc32,msglen,msg);
printf("Q sent %u msglen.%d (%s)\n",crc32,msglen,msg);
sock0 = -1;
}
}
@ -222,14 +227,20 @@ void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32
{
if ( (sentbytes= nn_send(sock1,msg,msglen,0)) != msglen )
printf("_LP_queuesend1 sent %d instead of %d\n",sentbytes,msglen);
else sock1 = -1;
else
{
printf("Q sent1 %u msglen.%d (%s)\n",crc32,msglen,msg);
sock1 = -1;
}
}
if ( sock0 < 0 && sock1 < 0 )
return;
return;*/
}
else
{
peerind = 1;
if ( (maxind= LP_numpeers()) > 0 )
peerind = (rand() % maxind);
else peerind = 0;
sock0 = LP_peerindsock(&peerind);
}
if ( sock0 >= 0 )
@ -271,6 +282,9 @@ void LP_broadcast_finish(int32_t pubsock,char *base,char *rel,uint8_t *msg,cJSON
free(msg);
jdelete(argjson,"method");
jaddstr(argjson,"method","broadcast");
if ( jobj(argjson,"timestamp") == 0 )
jaddnum(argjson,"timestamp",(uint32_t)time(NULL));
// add signature here
msg = (void *)jprint(argjson,0);
msglen = (int32_t)strlen((char *)msg) + 1;
LP_queuesend(crc32,-1,base,rel,msg,msglen);

430
iguana/exchanges/LP_ordermatch.c

@ -19,18 +19,20 @@
// marketmaker
//
uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee)
uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen)
{
if ( coin != 0 )
{
if ( strcmp(coin->symbol,"BTC") == 0 )
{
if ( txlen == 0 )
txlen = LP_AVETXSIZE;
coin->rate = LP_getestimatedrate(coin);
if ( (txfee= SATOSHIDEN * coin->rate * LP_AVETXSIZE) <= LP_MIN_TXFEE )
if ( (txfee= SATOSHIDEN * coin->rate * txlen) <= LP_MIN_TXFEE )
{
coin->rate = -1.;
coin->rate = _LP_getestimatedrate(coin);
if ( (txfee= SATOSHIDEN * coin->rate * LP_AVETXSIZE) <= LP_MIN_TXFEE )
if ( (txfee= SATOSHIDEN * coin->rate * txlen) <= LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
}
} else txfee = coin->txfee;
@ -42,8 +44,8 @@ uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee)
void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel)
{
*txfeep = LP_txfeecalc(LP_coinfind(base),0);
*desttxfeep = LP_txfeecalc(LP_coinfind(rel),0);
*txfeep = LP_txfeecalc(LP_coinfind(base),0,0);
*desttxfeep = LP_txfeecalc(LP_coinfind(rel),0,0);
printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep));
}
@ -219,29 +221,37 @@ char *LP_quotereceived(cJSON *argjson)
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price)
{
bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject();
bits256 zero; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
jaddstr(reqjson,"base",base);
jaddstr(reqjson,"rel",rel);
jaddnum(reqjson,"price",price);
jaddstr(reqjson,"method","postprice");
msg = jprint(reqjson,1);
LP_broadcast_message(pubsock,base,rel,zero,msg);
LP_reserved_msg(base,rel,zero,jprint(reqjson,1));
return(clonestr("{\"result\":\"success\"}"));
}
void LP_notify_pubkeys(void *ctx,int32_t pubsock)
{
bits256 zero; char *msg,secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
bits256 zero; char secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","notify");
jaddstr(reqjson,"rmd160",G.LP_myrmd160str);
jaddbits256(reqjson,"pub",G.LP_mypub25519);
init_hexbytes_noT(secpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",secpstr);
msg = jprint(reqjson,1);
LP_broadcast_message(pubsock,"","",zero,msg);
LP_reserved_msg("","",zero,jprint(reqjson,1));
}
void LP_listunspent_query(char *symbol,char *coinaddr)
{
bits256 zero; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","addr_unspents");
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"address",coinaddr);
LP_reserved_msg("","",zero,jprint(reqjson,1));
}
char *LP_postedprice(cJSON *argjson)
@ -279,7 +289,7 @@ int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo,
double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp,int32_t iambob)
{
double qprice=0.; uint64_t txfee,desttxfee,srcvalue=0,srcvalue2=0,destvalue=0,destvalue2=0;
printf("quote %s %.8f -> %s %.8f\n",qp->srccoin,dstr(qp->satoshis),qp->destcoin,dstr(qp->destsatoshis));
printf(">>>>>>> quote satoshis.(%.8f %.8f) %s %.8f -> %s %.8f\n",dstr(qp->satoshis),dstr(qp->destsatoshis),qp->srccoin,dstr(qp->satoshis),qp->destcoin,dstr(qp->destsatoshis));
if ( butxo != 0 )
{
if (LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 )
@ -316,12 +326,12 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str
if ( strcmp(autxo->coinaddr,qp->destaddr) != 0 )
return(-10);
}
if ( autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis )
if ( autxo != 0 && destvalue < 2*qp->desttxfee+qp->destsatoshis )
{
printf("destvalue %.8f destsatoshis %.8f is too small txfee %.8f?\n",dstr(destvalue),dstr(qp->destsatoshis),dstr(qp->desttxfee));
return(-11);
}
if ( butxo != 0 && srcvalue < qp->txfee+qp->satoshis )
if ( butxo != 0 && srcvalue < 2*qp->txfee+qp->satoshis )
{
printf("srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f?\n",dstr(srcvalue),dstr(srcvalue) - dstr(qp->txfee+qp->satoshis),dstr(qp->satoshis),dstr(qp->txfee));
return(-33);
@ -338,10 +348,9 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str
return(-14);
if ( butxo != 0 )
{
//qprice 2259.01692494 <- 10.34279604/0.00457845 txfees.(0.00042631 0.00010000) vs (0.00042791 0.00010000)
if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT )
{
printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee));
printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f [%d %d]\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee),qp->satoshis < (srcvalue / LP_MINVOL),srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT);
return(-12);
}
}
@ -368,9 +377,9 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout)
return(-1);
}
double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp)
void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp)
{
cJSON *reqjson; bits256 zero; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo;
cJSON *reqjson; bits256 zero; char *msg; int32_t flag = 0; struct LP_utxoinfo *utxo;
if ( strcmp(method,"request") == 0 )
{
if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 )
@ -378,7 +387,7 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L
else
{
printf("couldnt find my txid to make request\n");
return(0.);
return;
}
}
reqjson = LP_quotejson(qp);
@ -389,24 +398,16 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L
msg = jprint(reqjson,1);
printf("QUERY.(%s)\n",msg);
memset(&zero,0,sizeof(zero));
if ( 1 && strcmp(method,"request") == 0 )
{
sleep(3);
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg);
} else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
for (i=0; i<20; i++)
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs) )
Reserved_msgs[num_Reserved_msgs++] = msg;
else
{
if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL )
{
if ( flag == 0 || bits256_nonz(qp->desthash) != 0 )
{
printf("break out of loop.%d price %.8f %s/%s\n",i,price,qp->srccoin,qp->destcoin);
break;
}
}
sleep(1);
//if ( 1 && strcmp(method,"request") == 0 )
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg);
//else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
}
return(price);
portable_mutex_unlock(&LP_reservedmutex);
}
int32_t LP_nanobind(void *ctx,char *pairstr)
@ -441,28 +442,58 @@ int32_t LP_nanobind(void *ctx,char *pairstr)
return(pairsock);
}
int32_t LP_nearest_utxovalue(int32_t noSPV,struct LP_address_utxo **utxos,int32_t n,uint64_t targetval)
int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_address_utxo **utxos,int32_t n,uint64_t targetval)
{
int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1LL << 60);
int32_t i,oldht,mini = -1; struct LP_address_utxo *up; struct electrum_info *backupep=0,*ep; char str[65]; int64_t dist; uint64_t mindist = (1LL << 60);
if ( (ep= coin->electrum) != 0 )
{
if ( (backupep= ep->prev) == 0 )
backupep = ep;
}
//printf("LP_nearest_utxovalue %s utxos[%d] target %.8f\n",coin->symbol,n,dstr(targetval));
for (i=0; i<n; i++)
{
if ( utxos[i] != 0 && (noSPV != 0 || (utxos[i]->spendheight == 0 && utxos[i]->SPV > 0)) )
if ( (up= utxos[i]) != 0 )
{
dist = (utxos[i]->U.value - targetval);
if ( dist >= 0 && dist < mindist )
dist = (up->U.value - targetval);
//printf("nearest i.%d target %.8f val %.8f dist %.8f mindist %.8f mini.%d spent.%d\n",i,dstr(targetval),dstr(up->U.value),dstr(dist),dstr(mindist),mini,up->spendheight);
if ( up->spendheight <= 0 )
{
printf("(%.8f %.8f %.8f).%d ",dstr(utxos[i]->U.value),dstr(dist),dstr(mindist),mini);
mini = i;
mindist = dist;
if ( coin->electrum != 0 )
{
if ( up->SPV == 0 || up->SPV == -1 )
up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height);
if ( up->SPV == 0 || up->SPV == -1 )
{
printf("SPV failure for %s %s\n",coin->symbol,bits256_str(str,up->U.txid));
if ( up->SPV == -1 )
{
oldht = up->U.height;
LP_txheight_check(coin,coinaddr,up);
if ( oldht != up->U.height )
up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height);
if ( up->SPV < 0 )
up->SPV = -2;
}
continue;
} //else printf("%s %s: SPV.%d\n",coin->symbol,bits256_str(str,up->U.txid),up->SPV);
}
if ( (coin->electrum == 0 || up->SPV > 0) && dist >= 0 && dist < mindist )
{
//printf("(%.8f %.8f %.8f).%d ",dstr(up->U.value),dstr(dist),dstr(mindist),mini);
mini = i;
mindist = dist;
}
}
}
}
//printf("return mini.%d\n",mini);
return(mini);
}
uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t desttxfee)
{
printf("basesatoshis %.8f (rel %.8f / price %.8f)\n",dstr(SATOSHIDEN * ((relvolume) / price) + 2*txfee),relvolume,price);
//printf("basesatoshis %.8f (rel %.8f / price %.8f)\n",dstr(SATOSHIDEN * ((relvolume) / price) + 2*txfee),relvolume,price);
if ( relvolume > dstr(desttxfee) && price > SMALLVAL )
return(SATOSHIDEN * (relvolume / price) + 2*txfee);
else return(0);
@ -473,10 +504,10 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **
struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; struct LP_utxoinfo *utxo = 0;
if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( (m= LP_address_utxo_ptrs(iambob,utxos,max,ap)) > 1 )
if ( (m= LP_address_utxo_ptrs(iambob,utxos,max,ap,coinaddr)) > 1 )
{
targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee);
if ( 1 )
if ( 0 )
{
int32_t i;
for (i=0; i<m; i++)
@ -484,26 +515,31 @@ struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **
printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s\n",dstr(targetval),relvolume,price,dstr(txfee),coinaddr);
}
mini = -1;
if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin->electrum == 0,utxos,m,targetval)) >= 0 && (double)utxos[mini]->U.value/targetval < LP_MINVOL-1 )
if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval)) >= 0 )
{
up = utxos[mini];
utxos[mini] = 0;
targetval2 = (targetval / 8) * 9 + 2*txfee;
if ( (mini= LP_nearest_utxovalue(coin->electrum == 0,utxos,m,targetval2 * 1.01)) >= 0 )
//printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval);
if ( (double)up->U.value/targetval < LP_MINVOL-1 )
{
if ( up != 0 && (up2= utxos[mini]) != 0 )
if ( (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval2 * 1.01)) >= 0 )
{
if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0)) != 0 )
if ( up != 0 && (up2= utxos[mini]) != 0 )
{
utxo->S.satoshis = targetval;
char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid));
return(utxo);
if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0)) != 0 )
{
utxo->S.satoshis = targetval;
char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid));
return(utxo);
}
}
}
} else printf("cant find targetval2 %.8f\n",dstr(targetval2));
} //else printf("cant find targetval2 %.8f\n",dstr(targetval2));
} else printf("failed ratio test %.8f\n",(double)up->U.value/targetval);
} else if ( targetval != 0 && mini >= 0 )
printf("targetval %.8f mini.%d ratio %.8f\n",dstr(targetval),mini,(double)utxos[mini]->U.value/targetval);
} else printf("no utxos pass LP_address_utxo_ptrs filter\n");
printf("targetval %.8f mini.%d\n",dstr(targetval),mini);
} else printf("no %s utxos pass LP_address_utxo_ptrs filter\n",coinaddr);
} else printf("couldnt find %s %s\n",coin->symbol,coinaddr);
return(0);
}
@ -544,7 +580,7 @@ void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP
int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *base,char *rel,double price,struct LP_quoteinfo *qp)
{
char pairstr[512],*msg; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin;
char pairstr[512]; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin;
printf("LP_connectstartbob.(%s) with.(%s) %s\n",LP_myipaddr,jprint(argjson,0),LP_myipaddr);
qp->quotetime = (uint32_t)time(NULL);
if ( (coin= LP_coinfind(utxo->coin)) == 0 )
@ -557,10 +593,8 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
{
if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 )
{
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
printf("call swapinit\n");
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-2*qp->txfee,rel,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
swap = LP_swapinit(1,0,privkey,&qp->R,qp);
printf("swapinit.%p\n",swap);
swap->N.pair = pair;
utxo->S.swap = swap;
swap->utxo = utxo;
@ -572,8 +606,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
jaddnum(retjson,"requestid",qp->R.requestid);
jaddnum(retjson,"quoteid",qp->R.quoteid);
char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,utxo->S.otherpubkey));
msg = jprint(retjson,1);
LP_broadcast_message(pubsock,base,rel,utxo->S.otherpubkey,msg);
LP_reserved_msg(base,rel,utxo->S.otherpubkey,jprint(retjson,1));
retval = 0;
} else printf("error launching swaploop\n");
} else printf("couldnt bind to any port %s\n",pairstr);
@ -657,7 +690,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
return(clonestr("{\"error\":\"cant get alicecoin\"}"));
}
Q.privkey = LP_privkey(Q.destaddr,coin->taddr);
if ( bits256_nonz(Q.privkey) != 0 && Q.quotetime >= Q.timestamp-3 )
if ( bits256_nonz(Q.privkey) != 0 )//&& Q.quotetime >= Q.timestamp-3 )
{
retjson = cJSON_CreateObject();
if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 )
@ -667,7 +700,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
//timeout = 1;
//nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
//nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
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_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q);
swap->N.pair = pairsock;
autxo->S.swap = swap;
@ -690,22 +723,22 @@ char *LP_connectedalice(cJSON *argjson) // alice
else
{
LP_availableset(autxo);
printf("no privkey found\n");
printf("no privkey found coin.%s %s taddr.%u\n",Q.destcoin,Q.destaddr,coin->taddr);
return(clonestr("{\"error\",\"no privkey\"}"));
}
}
int32_t LP_listunspent_both(char *symbol,char *coinaddr)
int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag)
{
int32_t i,v,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin != 0 && coin->inactive == 0 )
if ( coin != 0 )//&& (IAMLP != 0 || coin->inactive == 0) )
{
if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 )
{
//printf("issue path electrum.%p\n",coin->electrum);
//if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 )
// free_json(array);
n = LP_listunspent_issue(symbol,coinaddr);
n = LP_listunspent_issue(symbol,coinaddr,fullflag);
}
else
{
@ -732,19 +765,99 @@ int32_t LP_listunspent_both(char *symbol,char *coinaddr)
return(n);
}
char *LP_bestfit(char *rel,double relvolume)
{
struct LP_utxoinfo *autxo;
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(jprint(LP_utxojson(autxo),1));
}
struct LP_quoteinfo LP_Alicequery;
double LP_Alicemaxprice;
uint32_t Alice_expiration;
char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration)
{
struct LP_utxoinfo *aliceutxo; double price; //cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap;
if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 )
{
char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout);
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
}
price = 0.;
LP_query(ctx,myipaddr,mypubsock,"request",qp);
LP_Alicequery = *qp, LP_Alicemaxprice = maxprice, Alice_expiration = qp->timestamp + timeout;
return(clonestr("{\"result\":\"success\"}"));
}
int32_t LP_quotecmp(struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2)
{
if ( bits256_cmp(qp->srchash,qp2->srchash) == 0 && bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee )
return(0);
else return(-1);
}
void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp)
{
double price,maxprice = LP_Alicemaxprice;
if ( time(NULL) > Alice_expiration )
{
printf("time expired for Alice_request\n");
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
Alice_expiration = 0;
}
else if ( LP_quotecmp(qp,&LP_Alicequery) == 0 )
{
price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout);
if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice )
{
memset(&LP_Alicequery,0,sizeof(LP_Alicequery));
LP_Alicemaxprice = 0.;
LP_query(ctx,myipaddr,mypubsock,"connect",qp);
}
}
}
int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
{
char *method,*msg; uint64_t value,value2; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) )
char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t value,value2; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"reserved") == 0 ||strcmp(method,"connected") == 0 || strcmp(method,"request") == 0 || strcmp(method,"connect") == 0) )
{
printf("LP_tradecommand: check received %s\n",method);
LP_quoteparse(&Q,argjson);
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
LP_tradecommand_log(argjson);
printf("LP_tradecommand: check received method %s\n",method);
retval = 1;
if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 )
if ( strcmp(method,"reserved") == 0 )
{
if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 )
{
printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
if ( (retstr= LP_quotereceived(argjson)) != 0 )
free(retstr);
LP_reserved(ctx,myipaddr,pubsock,&Q);
}
return(retval);
}
else if ( strcmp(method,"connected") == 0 )
{
if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 )
{
printf("alice %s received CONNECTED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0));
if ( (retstr= LP_connectedalice(argjson)) != 0 )
free(retstr);
}
return(retval);
}
if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 )
{
if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL )
{
printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin);
return(-3);
return(retval);
}
price = ask;
autxo = &A;
@ -761,7 +874,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
if ( LP_allocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_allocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
{
printf("butxo.%p replace path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1));
LP_listunspent_both(Q.srccoin,Q.coinaddr);
LP_listunspent_both(Q.srccoin,Q.coinaddr,0);
if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 )
{
Q.txid = butxo->payment.txid;
@ -790,17 +903,17 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 )
{
char str[65],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis));
return(1);
return(retval);
}
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(-4);
return(-3);
}
if ( qprice < (price - 0.00000001) * 0.9999 )
{
printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin);
return(-5);
return(-4);
}
if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending )
butxo->T.swappending = 0;
@ -808,7 +921,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
{
if ( LP_isavailable(butxo) > 0 )
{
butxo->T.swappending = Q.timestamp + LP_RESERVETIME;
autxo->T.swappending = butxo->T.swappending = Q.timestamp + LP_RESERVETIME;
retjson = LP_quotejson(&Q);
butxo->S.otherpubkey = jbits256(argjson,"desthash");
LP_unavailableset(butxo,butxo->S.otherpubkey);
@ -819,17 +932,9 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
jaddstr(retjson,"method","reserved");
msg = jprint(retjson,1);
butxo->T.lasttime = (uint32_t)time(NULL);
printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg);
{
bits256 zero; char *msg2;
memset(&zero,0,sizeof(zero));
msg2 = clonestr(msg);
LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,zero,msg);
LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg2);
//LP_butxo_swapfields_set(butxo);
printf("return after RESERVED\n");
return(2);
}
printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg);
LP_reserved_msg(Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg);
return(retval);
} else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap);
}
else if ( strcmp(method,"connect") == 0 ) // bob
@ -840,7 +945,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
// validate SPV alice
LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q);
//LP_butxo_swapfields_set(butxo);
return(3);
return(retval);
}
else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0));
}
@ -850,76 +955,26 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
return(retval);
}
char *LP_bestfit(char *rel,double relvolume)
{
struct LP_utxoinfo *autxo;
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(jprint(LP_utxojson(autxo),1));
}
char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration)
struct LP_utxoinfo *LP_ordermatch_iter(struct LP_address_utxo **utxos,int32_t max,double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct iguana_info *basecoin,char *coinaddr,uint64_t asatoshis,double price,uint64_t txfee,uint64_t desttxfee,bits256 pubkey,char *gui)
{
struct LP_utxoinfo *aliceutxo; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap;
if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 )
{
char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout);
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
}
price = LP_query(ctx,myipaddr,mypubsock,"request",qp);
bestitem = LP_quotejson(qp);
if ( LP_pricevalid(price) > 0 )
{
if ( price <= maxprice )
{
price = LP_query(ctx,myipaddr,mypubsock,"connect",qp);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
expiration = (uint32_t)time(NULL) + timeout;
while ( time(NULL) < expiration )
{
if ( aliceutxo->S.swap != 0 )
break;
sleep(3);
}
jaddnum(bestitem,"quotedprice",price);
jaddnum(bestitem,"maxprice",maxprice);
if ( (swap= aliceutxo->S.swap) == 0 )
{
if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 )
pubp->numerrors++;
jaddstr(bestitem,"status","couldnt establish connection");
}
else
{
jaddstr(bestitem,"status","connected");
jaddnum(bestitem,"requestid",swap->I.req.requestid);
jaddnum(bestitem,"quoteid",swap->I.req.quoteid);
printf("Alice r.%u qp->%u\n",swap->I.req.requestid,swap->I.req.quoteid);
}
}
else
{
jaddnum(bestitem,"quotedprice",price);
jaddnum(bestitem,"maxprice",maxprice);
jaddstr(bestitem,"status","too expensive");
}
}
else
uint64_t basesatoshis; struct LP_utxoinfo *bestutxo;
basesatoshis = LP_basesatoshis(dstr(asatoshis),price,txfee,desttxfee);
if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 )
{
printf("invalid price %.8f\n",price);
jaddnum(bestitem,"maxprice",maxprice);
jaddstr(bestitem,"status","no response to request");
bestutxo->pubkey = pubkey;
safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui));
*bestsatoshisp = basesatoshis;
*ordermatchpricep = price;
*bestdestsatoshisp = asatoshis;
return(bestutxo);
}
if ( aliceutxo->S.swap == 0 )
LP_availableset(aliceutxo);
return(jprint(bestitem,0));
return(0);
}
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 pubkey; char *obookstr,coinaddr[64],str[65]; cJSON *orderbook,*asks,*item; int32_t i,j,n,numasks,max = 10000; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; struct iguana_info *basecoin; uint64_t basesatoshis; struct LP_utxoinfo *bestutxo = 0;
bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*item; int32_t maxiters,i,j,numasks,max = 10000; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0;
maxiters = 100;
*ordermatchpricep = 0.;
*bestsatoshisp = *bestdestsatoshisp = 0;
basecoin = LP_coinfind(base);
@ -941,7 +996,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
item = jitem(asks,i);
price = jdouble(item,"price");
pubkey = jbits256(item,"pubkey");
printf("[%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f\n",i,numasks,jprint(item,0),bits256_cmp(pubkey,G.LP_mypub25519),price,maxprice);
//printf("[%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f\n",i,numasks,jprint(item,0),bits256_cmp(pubkey,G.LP_mypub25519),price,maxprice);
if ( LP_pricevalid(price) > 0 && price <= maxprice )
{
for (j=0; j<numavoids; j++)
@ -952,22 +1007,20 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
if ( bits256_cmp(pubkey,G.LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160));
n = LP_listunspent_both(base,coinaddr);
//printf("unspent.(%s) n.%d\n",coinaddr,n);
if ( n > 1 )
LP_listunspent_query(base,coinaddr);
LP_listunspent_both(base,coinaddr,1);
asatoshis = autxo->S.satoshis;
for (j=0; j<maxiters; j++)
{
basesatoshis = LP_basesatoshis(dstr(autxo->S.satoshis),price,txfee,desttxfee);
if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 )
if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,price,txfee,desttxfee,pubp->pubkey,gui)) != 0 )
{
bestutxo->pubkey = pubp->pubkey;
safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui));
*bestsatoshisp = basesatoshis;
*ordermatchpricep = price;
*bestdestsatoshisp = autxo->S.satoshis;
printf("ordermatch %.8f %.8f %.8f txfees (%.8f %.8f)\n",price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee));
printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee));
break;
}
} else printf("no unspents %s %s %s\n",base,coinaddr,bits256_str(str,pubkey));
asatoshis = (asatoshis / 64) * 63;
}
if ( j < maxiters )
break;
} else printf("self trading or blacklisted peer\n");
}
else
@ -990,24 +1043,30 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
return(bestutxo);
}
char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui)
char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui,uint32_t nonce)
{
uint64_t desttxfee,txfee; int32_t numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100];
printf("LP_autobuy %s/%s price %.8f vol %.8f\n",base,rel,maxprice,relvolume);
uint64_t desttxfee,txfee; uint32_t lastnonce; int32_t i,maxiters,numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100];
printf("LP_autobuy %s/%s price %.8f vol %.8f nonce %u\n",base,rel,maxprice,relvolume,nonce);
if ( (lastnonce= LP_lastnonce) != 0 && nonce <= lastnonce )
{
printf("nonce.%u not bigger than lastnonce.%u\n",nonce,lastnonce);
return(clonestr("{\"error\":\"invalid nonce\"}"));
}
LP_lastnonce = nonce;
if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION;
if ( timeout <= 0 )
timeout = LP_AUTOTRADE_TIMEOUT;
if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 )
return(clonestr("{\"error\":\"invalid parameter\"}"));
if ( strcmp("BTC",rel) == 0 )
maxprice *= 1.01;
else maxprice *= 1.001;
//if ( strcmp("BTC",rel) == 0 )
// maxprice *= 1.01;
//else maxprice *= 1.001;
memset(pubkeys,0,sizeof(pubkeys));
LP_txfees(&txfee,&desttxfee,base,rel);
destsatoshis = SATOSHIDEN * relvolume + 2*desttxfee;
if ( (autxo= LP_utxo_bestfit(rel,destsatoshis)) == 0 )
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}"));
return(clonestr("{\"error\":\"cant find alice utxo that is big enough\"}"));
if ( destsatoshis < autxo->S.satoshis )
autxo->S.satoshis = destsatoshis;
while ( 1 )
@ -1015,16 +1074,33 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
{
printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis));
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
return(clonestr("{\"error\":\"cant find ordermatch utxo, need to change relvolume to be closer to available\"}"));
}
pubkeys[numpubs++] = bestutxo->pubkey;
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,G.LP_mypub25519,autxo->coinaddr) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
if ( (qprice= LP_quote_validate(autxo,0,&Q,0)) <= SMALLVAL )
maxiters = 200;
qprice = 1. / SMALLVAL;
for (i=0; i<maxiters; i++)
{
if ( (qprice= LP_quote_validate(autxo,0,&Q,0)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(clonestr("{\"error\":\"quote validate error\"}"));
}
if ( qprice/ordermatchprice < 1.+SMALLVAL )
{
printf("i.%d/%d qprice %.8f < ordermatchprice %.8f\n",i,maxiters,qprice,ordermatchprice);
if ( strcmp("BTC",Q.destcoin) == 0 || strcmp("BTC",Q.srccoin) == 0 )
Q.satoshis *= 0.999;
else Q.satoshis *= 0.9999;
} else break;
}
if ( i == maxiters || qprice > maxprice )
{
printf("continue searching, quote validate error %.0f\n",qprice);
printf("i.%d maxiters.%d qprice %.8f vs maxprice %.8f, no acceptable quote for this pubkey\n",i,maxiters,dstr(qprice),dstr(maxprice));
continue;
}
break;

5
iguana/exchanges/LP_peers.c

@ -128,11 +128,10 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
portable_mutex_unlock(&LP_peermutex);
if ( IAMLP != 0 && mypubsock >= 0 )
{
struct iguana_info *coin,*ctmp; bits256 zero; char *msg,busaddr[64];
msg = jprint(LP_peerjson(peer),1);
struct iguana_info *coin,*ctmp; bits256 zero; char busaddr[64];
memset(zero.bytes,0,sizeof(zero));
//LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1);
LP_broadcast_message(mypubsock,"","",zero,msg);
LP_reserved_msg("","",zero,jprint(LP_peerjson(peer),1));
if ( 0 )
{
HASH_ITER(hh,LP_coins,coin,ctmp)

110
iguana/exchanges/LP_portfolio.c

@ -198,7 +198,12 @@ char *LP_portfolio_goal(char *symbol,double goal)
} else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}"));
}
int32_t LP_autoprices;
int32_t LP_autoprices,num_LP_autorefs;
struct LP_autoprice_ref
{
char refbase[16],refrel[16],base[16],rel[16];
} LP_autorefs[100];
/*int32_t LP_autofill(char *base,char *rel,double maxprice,double totalrelvolume)
{
@ -213,38 +218,88 @@ int32_t LP_autoprices;
return(-1);
}*/
int32_t LP_autoprice(char *base,char *rel,double minprice,double margin,char *type)
int32_t LP_autoprice(char *base,char *rel,cJSON *argjson)
{
struct LP_priceinfo *basepp,*relpp;
//curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}"
struct LP_priceinfo *basepp,*relpp; int32_t i; char *refbase,*refrel; double minprice,margin,offset,factor;
//printf("autoprice.(%s %s) %s\n",base,rel,jprint(argjson,0));
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( jobj(argjson,"minprice") != 0 )
minprice = jdouble(argjson,"minprice");
else minprice = 0.;
margin = jdouble(argjson,"margin");
offset = jdouble(argjson,"offset");
factor = jdouble(argjson,"factor");
basepp->minprices[relpp->ind] = minprice;
basepp->margins[relpp->ind] = margin;
basepp->offsets[relpp->ind] = offset;
basepp->factors[relpp->ind] = factor;
if ( (refbase= jstr(argjson,"refbase")) != 0 && (refrel= jstr(argjson,"refrel")) != 0 )
{
for (i=0; i<num_LP_autorefs; i++)
{
if ( strcmp(base,LP_autorefs[i].base) == 0 && strcmp(rel,LP_autorefs[i].rel) == 0 )
{
safecopy(LP_autorefs[i].refbase,refbase,sizeof(LP_autorefs[i].refbase));
safecopy(LP_autorefs[i].refrel,refrel,sizeof(LP_autorefs[i].refrel));
printf("%d Update ref %s/%s for %s/%s factor %.8f offset %.8f\n",i,refbase,refrel,base,rel,factor,offset);
break;
}
}
if ( i == num_LP_autorefs && num_LP_autorefs < sizeof(LP_autorefs)/sizeof(*LP_autorefs) )
{
safecopy(LP_autorefs[num_LP_autorefs].refbase,refbase,sizeof(LP_autorefs[num_LP_autorefs].refbase));
safecopy(LP_autorefs[num_LP_autorefs].refrel,refrel,sizeof(LP_autorefs[num_LP_autorefs].refrel));
safecopy(LP_autorefs[num_LP_autorefs].base,base,sizeof(LP_autorefs[num_LP_autorefs].base));
safecopy(LP_autorefs[num_LP_autorefs].rel,rel,sizeof(LP_autorefs[num_LP_autorefs].rel));
printf("%d Using ref %s/%s for %s/%s factor %.8f, offset %.8f, margin %.8f\n",num_LP_autorefs,refbase,refrel,base,rel,factor,offset,margin);
num_LP_autorefs++;
}
}
LP_autoprices++;
return(0);
}
return(-1);
}
void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *relpp,struct LP_priceinfo *basepp,double price)
void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP_priceinfo *relpp,double price,char *refbase,char *refrel)
{
double margin,minprice,oppomargin; int32_t changed;
double margin,minprice,newprice,oppomargin,factor,offset; double bid,ask; int32_t changed;
margin = basepp->margins[relpp->ind];
oppomargin = relpp->margins[basepp->ind];
if ( margin != 0. || oppomargin != 0. )
{
if ( margin == 0. )
margin = oppomargin;
//printf("min %.8f %s/%s %.8f dir.%d margin %.8f (%.8f %.8f)\n",basepp->minprices[relpp->ind],relpp->symbol,basepp->symbol,price,dir,margin,1. / (price * (1. - margin)),(price * (1. + margin)));
if ( dir > 0 )
price = 1. / (price * (1. - margin));
else price = (price * (1. + margin));
if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice )
offset = basepp->offsets[relpp->ind];
factor = basepp->factors[relpp->ind];
if ( fabs(price) < SMALLVAL && refbase != 0 && refrel != 0 )
{
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,price);
//printf("changed.%d\n",changed);
if ( changed != 0 )
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,price);
price = LP_myprice(&bid,&ask,refbase,refrel);
//printf("%s/%s USE ref %s/%s %.8f factor %.8f offset %.8f margin %.8f\n",basepp->symbol,relpp->symbol,refbase,refrel,price,factor,offset,margin);
}
if ( LP_pricevalid(price) > 0 )
{
if ( factor > SMALLVAL )
{
//double tmp = (price * factor) + offset;
//printf("price %.8f -> %.8f factor %.8f offset %.8f margin %.8f [%.8f %.8f] [%.8f %.8f]\n",price,tmp,factor,offset,margin,(tmp * (1. + margin)),1./(tmp * (1. - margin)),(tmp * (1. - margin)),1./(tmp * (1. + margin)));
price = (price * factor) + offset;
}
if ( margin == 0. )
margin = oppomargin;
//printf("min %.8f %s/%s %.8f dir.%d margin %.8f (%.8f %.8f)\n",basepp->minprices[relpp->ind],relpp->symbol,basepp->symbol,price,dir,margin,1. / (price * (1. - margin)),(price * (1. + margin)));
if ( dir > 0 )
newprice = (1. / price) * (1. + margin);
else newprice = (price * (1. + margin));
//newprice = 1. / (price * (1. - margin));
if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice )
{
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,newprice);
//printf("changed.%d %s/%s <- %.8f\n",changed,basepp->symbol,relpp->symbol,price);
if ( changed != 0 )
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,newprice);
}
}
}
}
@ -325,8 +380,8 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf
//printf("have trex: iter.%d trexflag.%d %s %.8f %.8f\n",iter,trexflag,symbol,coinpp->bid[1],coinpp->ask[1]);
continue;
}
LP_autopriceset(ctx,1,refpp,coinpp,price);
LP_autopriceset(ctx,-1,coinpp,refpp,price);
LP_autopriceset(ctx,1,coinpp,refpp,price,0,0);
LP_autopriceset(ctx,-1,refpp,coinpp,price,0,0);
}
}
}
@ -358,7 +413,7 @@ static char *assetids[][3] =
void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
{
char *retstr; cJSON *retjson,*bid,*ask; uint64_t bidsatoshis,asksatoshis; int32_t i; double nxtkmd,price; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp;
char *retstr; cJSON *retjson,*bid,*ask; uint64_t bidsatoshis,asksatoshis; int32_t i; double nxtkmd,price; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp,*basepp,*relpp;
if ( (retstr= issue_curlt("https://bittrex.com/api/v1.1/public/getmarketsummaries",LP_HTTP_TIMEOUT*10)) == 0 )
{
printf("trex error getting marketsummaries\n");
@ -385,8 +440,8 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
{
//printf("(%s %.8f %.8f) ",CURRENCIES[i],jdouble(retjson,"price"),jdouble(retjson,"invprice"));
price = jdouble(retjson,"price");
LP_autopriceset(ctx,1,kmdpp,fiatpp,price);
LP_autopriceset(ctx,-1,fiatpp,kmdpp,price);
LP_autopriceset(ctx,1,fiatpp,kmdpp,price,0,0);
LP_autopriceset(ctx,-1,kmdpp,fiatpp,price,0,0);
free_json(retjson);
}
}
@ -409,14 +464,21 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
if ( bidsatoshis != 0 && asksatoshis != 0 )
price = 0.5 * dstr(bidsatoshis + asksatoshis) * nxtkmd;
}
LP_autopriceset(ctx,1,kmdpp,nxtpp,price);
LP_autopriceset(ctx,-1,nxtpp,kmdpp,price);
LP_autopriceset(ctx,1,nxtpp,kmdpp,price,0,0);
LP_autopriceset(ctx,-1,kmdpp,nxtpp,price,0,0);
//printf("%s %s -> (%s) nxtkmd %.8f %.8f %.8f\n",assetids[i][1],assetids[i][0],jprint(retjson,0),nxtkmd,0.5*dstr(bidsatoshis + asksatoshis),price);
free_json(retjson);
}
}
}
}
for (i=0; i<num_LP_autorefs; i++)
{
basepp = LP_priceinfofind(LP_autorefs[i].base);
relpp = LP_priceinfofind(LP_autorefs[i].rel);
if ( basepp != 0 && relpp != 0 )
LP_autopriceset(ctx,1,basepp,relpp,0,LP_autorefs[i].refbase,LP_autorefs[i].refrel);
}
}
int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel,char *gui)
@ -441,7 +503,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
break;
if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
{
if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui)) != 0 )
if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1)) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr2)) != 0 )
{

46
iguana/exchanges/LP_prices.c

@ -31,6 +31,8 @@ struct LP_priceinfo
double myprices[LP_MAXPRICEINFOS];
double minprices[LP_MAXPRICEINFOS]; // autoprice
double margins[LP_MAXPRICEINFOS];
double offsets[LP_MAXPRICEINFOS];
double factors[LP_MAXPRICEINFOS];
//double maxprices[LP_MAXPRICEINFOS]; // autofill of base/rel
//double relvols[LP_MAXPRICEINFOS];
FILE *fps[LP_MAXPRICEINFOS];
@ -221,10 +223,21 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval)
return(clonestr("{\"error\":\"pubkey not found\"}"));
}
char *LP_pubkey_trusted()
{
struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray();
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
if ( pubp->istrusted != 0 )
jaddibits256(array,pubp->pubkey);
}
return(jprint(array,1));
}
uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr)
{
cJSON *array,*item; int32_t i,n; uint64_t metric=0,total;
LP_listunspent_both(coin->symbol,coinaddr);
LP_listunspent_both(coin->symbol,coinaddr,0);
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
total = 0;
@ -360,6 +373,8 @@ void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj)
void LP_peer_pricesquery(struct LP_peerinfo *peer)
{
char *retstr; cJSON *array; int32_t i,n;
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
return;
peer->needping = (uint32_t)time(NULL);
if ( (retstr= issue_LP_getprices(peer->ipaddr,peer->port)) != 0 )
{
@ -481,6 +496,7 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
*changedp = 0;
if ( base != 0 && rel != 0 && LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( fabs(basepp->myprices[relpp->ind] - price) > SMALLVAL )
*changedp = 1;
basepp->myprices[relpp->ind] = price; // ask
@ -664,8 +680,8 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op)
jaddstr(item,"address",op->coinaddr);
jaddnum(item,"price",op->price);
jaddnum(item,"numutxos",op->numutxos);
jaddnum(item,"minvolume",dstr(op->minsatoshis));
jaddnum(item,"maxvolume",dstr(op->maxsatoshis));
jaddnum(item,"minvolume",dstr(op->minsatoshis)*0.8);
jaddnum(item,"maxvolume",dstr(op->maxsatoshis)*0.8);
jaddbits256(item,"pubkey",op->pubkey);
jaddnum(item,"age",time(NULL)-op->timestamp);
}
@ -706,6 +722,8 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
//printf("skip pubp since no rmd160\n");
continue;
}
if ( pubp->timestamp < oldest )
continue;
bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160));
minsatoshis = maxsatoshis = n = 0;
ap = 0;
@ -769,8 +787,15 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
for (i=n=0; i<numbids; i++)
{
jaddi(array,LP_orderbookjson(rel,bids[i]));
if ( bids[i]->numutxos == 0 )//|| relcoin->electrum == 0 )
LP_address(relcoin,bids[i]->coinaddr), n++;
if ( n < 10 && bids[i]->numutxos == 0 )//|| relcoin->electrum == 0 )
{
//printf("bid ping %s %s\n",rel,bids[i]->coinaddr);
LP_address(relcoin,bids[i]->coinaddr);
if ( relcoin->electrum == 0 )
LP_listunspent_issue(rel,bids[i]->coinaddr,0);
LP_listunspent_query(rel,bids[i]->coinaddr);
n++;
}
free(bids[i]);
bids[i] = 0;
}
@ -782,8 +807,15 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
for (i=n=0; i<numasks; i++)
{
jaddi(array,LP_orderbookjson(base,asks[i]));
if ( asks[i]->numutxos == 0 )//|| basecoin->electrum == 0 )
LP_address(basecoin,asks[i]->coinaddr), n++;
if ( n < 10 && asks[i]->numutxos == 0 )//|| basecoin->electrum == 0 )
{
//printf("ask ping %s %s\n",base,asks[i]->coinaddr);
LP_address(basecoin,asks[i]->coinaddr);
if ( basecoin->electrum == 0 )
LP_listunspent_issue(base,asks[i]->coinaddr,0);
LP_listunspent_query(base,asks[i]->coinaddr);
n++;
}
free(asks[i]);
asks[i] = 0;
}

477
iguana/exchanges/LP_remember.c

@ -152,7 +152,10 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
fprintf(fp,",\"otherfee\":\"%s\"",bits256_str(str,swap->otherfee.I.actualtxid));
if ( bits256_nonz(swap->myfee.I.actualtxid) != 0 )
fprintf(fp,",\"myfee\":\"%s\"",bits256_str(str,swap->myfee.I.actualtxid));
fprintf(fp,",\"dest33\":\"");
fprintf(fp,",\"other33\":\"");
for (i=0; i<33; i++)
fprintf(fp,"%02x",swap->persistent_other33[i]);
fprintf(fp,"\",\"dest33\":\"");
for (i=0; i<33; i++)
fprintf(fp,"%02x",swap->persistent_pubkey33[i]);
fprintf(fp,"\"}\n");
@ -244,7 +247,7 @@ bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 b
return(privBn);
}
bits256 basilisk_swap_spendupdate(char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr)
bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr,char *Adest,char *dest)
{
bits256 spendtxid,txid; char destaddr[64],str[65]; struct iguana_info *coin; cJSON *histobj;
if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 )
@ -264,30 +267,31 @@ bits256 basilisk_swap_spendupdate(char *symbol,char *spentaddr,int32_t *sentflag
if ( bits256_nonz(spendtxid) != 0 )
{
sentflags[utxoind] = 1;
if ( aliceaddr != 0 && strcmp(destaddr,aliceaddr) == 0 )
printf("utxoind.%d Alice.(%s %s) Bob.(%s %s) vs destaddr.(%s)\n",utxoind,aliceaddr,Adest,bobaddr,dest,destaddr);
if ( aliceaddr != 0 && (strcmp(destaddr,aliceaddr) == 0 || strcmp(Adest,destaddr) == 0) )
{
//printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
sentflags[alicespent] = 1;
sentflags[bobspent] = 0;
txids[alicespent] = spendtxid;
}
else if ( bobaddr != 0 && strcmp(destaddr,bobaddr) == 0 )
else if ( bobaddr != 0 && (strcmp(destaddr,bobaddr) == 0 || strcmp(dest,destaddr) == 0) )
{
//printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
sentflags[bobspent] = 1;
sentflags[alicespent] = 0;
txids[bobspent] = spendtxid;
}
else
{
//printf("OTHER dest spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
if ( aliceaddr != 0 )
printf("OTHER dest spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
if ( iambob == 0 )
{
sentflags[bobspent] = 1;
sentflags[alicespent] = 0;
txids[bobspent] = spendtxid;
}
else if ( bobaddr != 0 )
else
{
sentflags[alicespent] = 1;
sentflags[bobspent] = 0;
@ -334,7 +338,6 @@ int32_t basilisk_isbobcoin(int32_t iambob,int32_t ind)
}
}
// add blocktrail presence requirement for BTC
int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflags,bits256 paymentspent,bits256 Apaymentspent,bits256 depositspent)
{
int32_t i,n = 0;
@ -343,7 +346,7 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag
n++;
if ( n == 0 )
{
printf("if nothing sent, it is finished\n");
//printf("if nothing sent, it is finished\n");
return(1);
}
if ( iambob != 0 )
@ -355,7 +358,7 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag
if ( bits256_nonz(depositspent) != 0 )
return(1);
}
else if ( bits256_nonz(paymentspent) != 0 )
else if ( bits256_nonz(Apaymentspent) != 0 )
return(1);
}
else
@ -463,8 +466,8 @@ struct LP_swap_remember
uint64_t Atxfee,Btxfee,srcamount,destamount; int64_t values[sizeof(txnames)/sizeof(*txnames)];
uint32_t requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate;
int32_t iambob,finishedflag,origfinishedflag,Predeemlen,Dredeemlen,sentflags[sizeof(txnames)/sizeof(*txnames)];
uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],Predeemscript[1024],Dredeemscript[1024];
char src[64],dest[64],destaddr[64],Adestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)];
uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],Predeemscript[1024],Dredeemscript[1024],pubkey33[33],other33[33];
char src[64],dest[64],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)];
};
cJSON *LP_swap_json(struct LP_swap_remember *rswap)
@ -508,7 +511,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap)
int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t quoteid)
{
char fname[1024],*fstr,*secretstr,*srcstr,*deststr,*dest33,*txname; long fsize; cJSON *item,*txobj,*array; bits256 privkey; uint32_t r,q; int32_t i,j,n;
char fname[1024],*fstr,*secretstr,*srcstr,*deststr,*dest33,*txname; long fsize; cJSON *item,*txobj,*array; bits256 privkey; struct iguana_info *coin; uint32_t r,q; int32_t i,j,n; uint8_t other33[33];
memset(rswap,0,sizeof(*rswap));
rswap->requestid = requestid;
rswap->quoteid = quoteid;
@ -533,10 +536,28 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t
if ( (dest33= jstr(item,"dest33")) != 0 && strlen(dest33) == 66 )
{
decode_hex(rswap->pubkey33,33,dest33);
if ( rswap->iambob != 0 && (coin= LP_coinfind(rswap->src)) != 0 )
bitcoin_address(rswap->destaddr,coin->taddr,coin->pubtype,rswap->pubkey33,33);
else if ( rswap->iambob == 0 && (coin= LP_coinfind(rswap->dest)) != 0 )
bitcoin_address(rswap->Adestaddr,coin->taddr,coin->pubtype,rswap->pubkey33,33);
//for (i=0; i<33; i++)
// printf("%02x",pubkey33[i]);
//printf(" <- %s dest33\n",dest33);
}
if ( (dest33= jstr(item,"other33")) != 0 && strlen(dest33) == 66 )
{
decode_hex(other33,33,dest33);
for (i=0; i<33; i++)
if ( other33[i] != 0 )
break;
if ( i < 33 )
memcpy(rswap->other33,other33,33);
if ( rswap->iambob != 0 && (coin= LP_coinfind(rswap->dest)) != 0 )
bitcoin_address(rswap->Adestaddr,coin->taddr,coin->pubtype,rswap->other33,33);
else if ( rswap->iambob == 0 && (coin= LP_coinfind(rswap->src)) != 0 )
bitcoin_address(rswap->destaddr,coin->taddr,coin->pubtype,rswap->other33,33);
//printf("(%s, %s) <- %s other33\n",rswap->destaddr,rswap->Adestaddr,dest33);
}
if ( (rswap->plocktime= juint(item,"plocktime")) == 0 )
rswap->plocktime = LP_extract(requestid,quoteid,fname,"plocktime");
if ( (rswap->dlocktime= juint(item,"dlocktime")) == 0 )
@ -615,15 +636,52 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t
}
}
}
rswap->origfinishedflag = rswap->finishedflag = 1;
rswap->origfinishedflag = basilisk_swap_isfinished(rswap->iambob,rswap->txids,rswap->sentflags,rswap->paymentspent,rswap->Apaymentspent,rswap->depositspent);
rswap->finishedflag = rswap->origfinishedflag;
free(fstr);
}
return(rswap->iambob);
}
int32_t _LP_refht_update(struct iguana_info *coin,bits256 txid,int32_t refht)
{
refht -= 9;
if ( refht > 10 && (coin->firstrefht == 0 || refht < coin->firstrefht) )
{
char str[65]; printf(">>>>>>>>. 1st refht %s %s <- %d, scan %d %d\n",coin->symbol,bits256_str(str,txid),refht,coin->firstscanht,coin->lastscanht);
if ( coin->firstscanht == 0 || refht < coin->firstscanht )
coin->firstscanht = coin->lastscanht = refht;
coin->firstrefht = refht;
return(1);
}
return(0);
}
int32_t LP_refht_update(char *symbol,bits256 txid)
{
int32_t refht; struct iguana_info *coin;
if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 )
{
if ( (refht= LP_txheight(coin,txid)) > 0 && refht > 0 )
return(_LP_refht_update(coin,txid,refht));
}
return(0);
}
int32_t LP_swap_load(struct LP_swap_remember *rswap)
{
int32_t i,needflag,addflag; long fsize; char fname[1024],str[65],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj; bits256 txid,checktxid; uint64_t value;
int32_t i,needflag,addflag; long fsize; char fname[1024],str[65],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj,*fileobj; bits256 txid,checktxid; uint64_t value;
rswap->iambob = -1;
sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap->requestid,rswap->quoteid), OS_compatible_path(fname);
if ( (fstr= OS_filestr(&fsize,fname)) != 0 )
{
if ( (fileobj= cJSON_Parse(fstr)) != 0 )
{
rswap->origfinishedflag = rswap->finishedflag = 1;
free_json(fileobj);
}
free(fstr);
}
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
{
needflag = addflag = 0;
@ -636,7 +694,8 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
if ( (txobj= cJSON_Parse(fstr)) != 0 )
{
//printf("TXOBJ.(%s)\n",jprint(txobj,0));
rswap->iambob = jint(txobj,"iambob");
if ( jobj(txobj,"iambob") != 0 )
rswap->iambob = jint(txobj,"iambob");
txid = jbits256(txobj,"txid");
if ( bits256_nonz(txid) == 0 )
continue;
@ -663,6 +722,26 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
decode_hex(rswap->Dredeemscript,rswap->Dredeemlen,rstr);
}
rswap->values[i] = value = LP_value_extract(txobj,1);
if ( (symbol= jstr(txobj,"src")) != 0 )
{
safecopy(rswap->src,symbol,sizeof(rswap->src));
if ( rswap->iambob >= 0 )
{
if ( rswap->iambob > 0 )
safecopy(rswap->bobcoin,symbol,sizeof(rswap->bobcoin));
else safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin));
}
}
if ( (symbol= jstr(txobj,"dest")) != 0 )
{
safecopy(rswap->dest,symbol,sizeof(rswap->dest));
if ( rswap->iambob >= 0 )
{
if ( rswap->iambob == 0 )
safecopy(rswap->bobcoin,symbol,sizeof(rswap->bobcoin));
else safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin));
}
}
if ( (symbol= jstr(txobj,"coin")) != 0 )
{
if ( i == BASILISK_ALICESPEND || i == BASILISK_BOBPAYMENT || i == BASILISK_BOBDEPOSIT || i == BASILISK_BOBREFUND || i == BASILISK_BOBRECLAIM || i == BASILISK_ALICECLAIM )
@ -677,15 +756,10 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
}
else
{
struct iguana_info *coin; int32_t ht = -1;
checktxid = jbits256(sentobj,"txid");
if ( (coin= LP_coinfind(symbol)) != 0 && (ht= LP_txheight(coin,txid)) > 0 && ht > 0 )
{
if ( coin->firstrefht == 0 || ht < coin->firstrefht )
coin->firstrefht = ht;
}
if ( bits256_nonz(checktxid) == 0 )
checktxid = jbits256(sentobj,"hash");
LP_refht_update(symbol,txid);
if ( bits256_cmp(checktxid,txid) == 0 )
{
//printf(">>>>>> %s txid %s\n",jprint(sentobj,0),bits256_str(str,txid));
@ -693,8 +767,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
}
free_json(sentobj);
}
if ( rswap->finishedflag == 0 )
printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
}
}
} //else printf("no symbol\n");
@ -702,104 +775,150 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
} else if ( 0 && rswap->finishedflag == 0 )
printf("%s not finished\n",fname);
}
if ( rswap->bobcoin[0] == 0 )
strcpy(rswap->bobcoin,rswap->src);
if ( rswap->alicecoin[0] == 0 )
strcpy(rswap->alicecoin,rswap->dest);
if ( rswap->src[0] == 0 )
strcpy(rswap->src,rswap->bobcoin);
if ( rswap->dest[0] == 0 )
strcpy(rswap->dest,rswap->alicecoin);
return(rswap->finishedflag);
}
/*{
if ( txbytes[BASILISK_BOBREFUND] != 0 )
void LP_txbytes_update(char *name,char *symbol,char *txbytes,bits256 *txidp,bits256 *ptr,int32_t *flagp)
{
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
if ( txbytes != 0 )
{
txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND],zero);
if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested
*txidp = LP_broadcast(name,symbol,txbytes,zero);
if ( bits256_nonz(*txidp) != 0 )
{
sentflags[BASILISK_BOBREFUND] = 1;
depositspent = txids[BASILISK_BOBREFUND];
*flagp = 1;
if ( ptr != 0 )
*ptr = *txidp;
}
}
}*/
}
int32_t LP_rswap_checktx(struct LP_swap_remember *rswap,char *symbol,int32_t txi)
{
cJSON *sentobj; char str[65];
struct LP_transaction *tx; struct iguana_info *coin; char str[65];
if ( rswap->sentflags[txi] == 0 && bits256_nonz(rswap->txids[txi]) != 0 )
{
printf("[%s] txbytes.%p Apayment.%s\n",txnames[txi],rswap->txbytes[txi],bits256_str(str,rswap->txids[txi]));
if ( rswap->txbytes[txi] != 0 )
rswap->sentflags[txi] = 1;
else if ( (sentobj= LP_gettx(symbol,rswap->txids[txi])) != 0 )
coin = LP_coinfind(symbol);
printf("[%s] %s txbytes.%p %s\n",txnames[txi],txnames[txi],rswap->txbytes[txi],bits256_str(str,rswap->txids[txi]));
if ( coin != 0 && (tx= LP_transactionfind(coin,rswap->txids[txi])) != 0 && tx->height > 0 )
{
rswap->sentflags[txi] = 1;
free_json(sentobj);
return(1);
}
_LP_refht_update(coin,rswap->txids[txi],tx->height);
} else LP_refht_update(symbol,rswap->txids[txi]);
}
return(0);
}
int32_t LP_spends_set(struct LP_swap_remember *rswap)
{
int32_t numspent = 0;
if ( bits256_nonz(rswap->paymentspent) == 0 )
{
if ( bits256_nonz(rswap->txids[BASILISK_ALICESPEND]) != 0 )
rswap->paymentspent = rswap->txids[BASILISK_ALICESPEND];
else rswap->paymentspent = rswap->txids[BASILISK_BOBRECLAIM];
} else numspent++;
if ( bits256_nonz(rswap->depositspent) == 0 )
{
if ( bits256_nonz(rswap->txids[BASILISK_BOBREFUND]) != 0 )
rswap->depositspent = rswap->txids[BASILISK_BOBREFUND];
else rswap->depositspent = rswap->txids[BASILISK_ALICECLAIM];
} else numspent++;
if ( bits256_nonz(rswap->Apaymentspent) == 0 )
{
if ( bits256_nonz(rswap->txids[BASILISK_BOBSPEND]) != 0 )
rswap->Apaymentspent = rswap->txids[BASILISK_BOBSPEND];
else rswap->Apaymentspent = rswap->txids[BASILISK_ALICERECLAIM];
} else numspent++;
return(numspent);
}
cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid)
{
static void *ctx;
struct LP_swap_remember rswap; int32_t i,j,len,secretstart,redeemlen; char str[65],*Adest,*Bdest,*AAdest,*ABdest; cJSON *item; bits256 rev,signedtxid,zero; struct iguana_info *bob=0,*alice=0; uint8_t redeemscript[1024],userdata[1024];
struct LP_swap_remember rswap; int32_t i,j,numspent,len,secretstart,redeemlen; char str[65],*srcAdest,*srcBdest,*destAdest,*destBdest,otheraddr[64]; cJSON *item; bits256 rev,signedtxid,zero; struct iguana_info *bob=0,*alice=0; uint8_t redeemscript[1024],userdata[1024];
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( (rswap.iambob= LP_rswap_init(&rswap,requestid,quoteid)) < 0 )
return(0);
return(cJSON_Parse("{\"error\":\"couldnt initialize rswap, are all coins active?\"}"));
LP_swap_load(&rswap);
memset(zero.bytes,0,sizeof(zero));
Adest = Bdest = AAdest = ABdest = 0;
otheraddr[0] = 0;
srcAdest = srcBdest = destAdest = destBdest = 0;
if ( rswap.bobcoin[0] == 0 || rswap.alicecoin[0] == 0 || strcmp(rswap.bobcoin,rswap.src) != 0 || strcmp(rswap.alicecoin,rswap.dest) != 0 )
return(0);
{
printf("legacy DB SWAPS files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest);
return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}"));
}
alice = LP_coinfind(rswap.alicecoin);
bob = LP_coinfind(rswap.bobcoin);
rswap.Atxfee = LP_txfeecalc(alice,rswap.Atxfee);
rswap.Btxfee = LP_txfeecalc(bob,rswap.Btxfee);
//printf("%s %.8f txfee, %s %.8f txfee\n",alicecoin,dstr(Atxfee),bobcoin,dstr(Btxfee));
//printf("privAm.(%s) %p/%p\n",bits256_str(str,privAm),Adest,AAdest);
//printf("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest);
if ( rswap.finishedflag == 0 && rswap.bobcoin[0] != 0 && rswap.alicecoin[0] != 0 )
rswap.Atxfee = LP_txfeecalc(alice,rswap.Atxfee,0);
rswap.Btxfee = LP_txfeecalc(bob,rswap.Btxfee,0);
if ( rswap.iambob == 0 )
{
if ( rswap.iambob == 0 )
if ( alice != 0 )
{
if ( alice != 0 )
{
bitcoin_address(rswap.Adestaddr,alice->taddr,alice->pubtype,rswap.pubkey33,33);
AAdest = rswap.Adestaddr;
}
if ( (bob= LP_coinfind(rswap.bobcoin)) != 0 )
{
bitcoin_address(rswap.destaddr,bob->taddr,bob->pubtype,rswap.pubkey33,33);
Adest = rswap.destaddr;
}
bitcoin_address(otheraddr,alice->taddr,alice->pubtype,rswap.other33,33);
destBdest = otheraddr;
destAdest = rswap.Adestaddr;
}
else
if ( (bob= LP_coinfind(rswap.bobcoin)) != 0 )
{
if ( bob != 0 )
{
bitcoin_address(rswap.destaddr,bob->taddr,bob->pubtype,rswap.pubkey33,33);
Bdest = rswap.destaddr;
}
if ( (alice= LP_coinfind(rswap.alicecoin)) != 0 )
{
bitcoin_address(rswap.Adestaddr,alice->taddr,alice->pubtype,rswap.pubkey33,33);
ABdest = rswap.Adestaddr;
}
bitcoin_address(rswap.Sdestaddr,bob->taddr,bob->pubtype,rswap.pubkey33,33);
srcAdest = rswap.Sdestaddr;
}
srcBdest = rswap.destaddr;
}
else
{
if ( bob != 0 )
{
bitcoin_address(otheraddr,bob->taddr,bob->pubtype,rswap.other33,33);
srcAdest = otheraddr;
srcBdest = rswap.destaddr;
}
if ( bob == 0 || alice == 0 )
if ( (alice= LP_coinfind(rswap.alicecoin)) != 0 )
{
printf("Bob.%p is null or Alice.%p is null\n",bob,alice);
return(0);
bitcoin_address(rswap.Sdestaddr,alice->taddr,alice->pubtype,rswap.pubkey33,33);
destBdest = rswap.Sdestaddr;
}
destAdest = rswap.Adestaddr;
}
if ( bob == 0 || alice == 0 )
{
printf("Bob.%p is null or Alice.%p is null\n",bob,alice);
return(cJSON_Parse("{\"error\":\"null bob or alice coin\"}"));
}
//printf("src.(Adest %s, Bdest %s), dest.(Adest %s, Bdest %s)\n",srcAdest,srcBdest,destAdest,destBdest);
//printf("iambob.%d finishedflag.%d %s %.8f txfee, %s %.8f txfee\n",rswap.iambob,rswap.finishedflag,rswap.alicecoin,dstr(rswap.Atxfee),rswap.bobcoin,dstr(rswap.Btxfee));
//printf("privAm.(%s) %p/%p\n",bits256_str(str,rswap.privAm),Adest,AAdest);
//printf("privBn.(%s) %p/%p\n",bits256_str(str,rswap.privBn),Bdest,ABdest);
if ( rswap.finishedflag == 0 && rswap.bobcoin[0] != 0 && rswap.alicecoin[0] != 0 )
{
//printf("ALICE.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.Adestaddr,alice->symbol,alice->firstrefht,alice->firstscanht,alice->lastscanht);
//printf("BOB.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.destaddr,bob->symbol,bob->firstrefht,bob->firstscanht,bob->lastscanht);
if ( alice->inactive != 0 || bob->inactive != 0 )
{
printf("Alice.%s inactive.%u or Bob.%s inactive.%u\n",rswap.alicecoin,alice->inactive,rswap.bobcoin,bob->inactive);
return(0);
return(cJSON_Parse("{\"error\":\"inactive bob or alice coin\"}"));
}
LP_rswap_checktx(&rswap,rswap.alicecoin,BASILISK_ALICEPAYMENT);
LP_rswap_checktx(&rswap,rswap.bobcoin,BASILISK_BOBPAYMENT);
LP_rswap_checktx(&rswap,rswap.bobcoin,BASILISK_BOBDEPOSIT);
rswap.paymentspent = basilisk_swap_spendupdate(rswap.bobcoin,rswap.bobpaymentaddr,rswap.sentflags,rswap.txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest);
rswap.Apaymentspent = basilisk_swap_spendupdate(rswap.alicecoin,rswap.alicepaymentaddr,rswap.sentflags,rswap.txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest);
rswap.depositspent = basilisk_swap_spendupdate(rswap.bobcoin,rswap.bobdepositaddr,rswap.sentflags,rswap.txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest);
rswap.paymentspent = basilisk_swap_spendupdate(rswap.iambob,rswap.bobcoin,rswap.bobpaymentaddr,rswap.sentflags,rswap.txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,srcAdest,srcBdest,rswap.Adestaddr,rswap.destaddr);
rswap.Apaymentspent = basilisk_swap_spendupdate(rswap.iambob,rswap.alicecoin,rswap.alicepaymentaddr,rswap.sentflags,rswap.txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,destAdest,destBdest,rswap.Adestaddr,rswap.destaddr);
rswap.depositspent = basilisk_swap_spendupdate(rswap.iambob,rswap.bobcoin,rswap.bobdepositaddr,rswap.sentflags,rswap.txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,srcAdest,srcBdest,rswap.Adestaddr,rswap.destaddr);
rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent);
LP_spends_set(&rswap);
if ( rswap.iambob == 0 )
{
if ( rswap.sentflags[BASILISK_ALICESPEND] == 0 )
@ -832,15 +951,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
printf("alicespend.(%s)\n",rswap.txbytes[BASILISK_ALICESPEND]);
}
}
if ( rswap.txbytes[BASILISK_ALICESPEND] != 0 )
{
rswap.txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",rswap.bobcoin,rswap.txbytes[BASILISK_ALICESPEND],zero);
if ( bits256_nonz(rswap.txids[BASILISK_ALICESPEND]) != 0 ) // tested
{
rswap.sentflags[BASILISK_ALICESPEND] = 1;
rswap.paymentspent = rswap.txids[BASILISK_ALICESPEND];
}
}
LP_txbytes_update("alicespend",rswap.bobcoin,rswap.txbytes[BASILISK_ALICESPEND],&rswap.txids[BASILISK_ALICESPEND],&rswap.paymentspent,&rswap.sentflags[BASILISK_ALICESPEND]);
}
}
if ( rswap.sentflags[BASILISK_ALICECLAIM] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 )
@ -864,15 +975,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
}
}
if ( rswap.txbytes[BASILISK_ALICECLAIM] != 0 )
{
rswap.txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",rswap.bobcoin,rswap.txbytes[BASILISK_ALICECLAIM],zero);
if ( bits256_nonz(rswap.txids[BASILISK_ALICECLAIM]) != 0 ) // tested
{
rswap.sentflags[BASILISK_ALICECLAIM] = 1;
rswap.depositspent = rswap.txids[BASILISK_ALICECLAIM];
}
}
LP_txbytes_update("aliceclaim",rswap.bobcoin,rswap.txbytes[BASILISK_ALICECLAIM],&rswap.txids[BASILISK_ALICECLAIM],&rswap.depositspent,&rswap.sentflags[BASILISK_ALICECLAIM]);
} else printf("now %u before expiration %u\n",(uint32_t)time(NULL),rswap.expiration);
}
if ( rswap.sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(rswap.Apaymentspent) == 0 && rswap.sentflags[BASILISK_ALICECLAIM] == 0 )
@ -886,15 +989,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICERECLAIM]);
}
}
if ( rswap.txbytes[BASILISK_ALICERECLAIM] != 0 )
{
rswap.txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",rswap.alicecoin,rswap.txbytes[BASILISK_ALICERECLAIM],zero);
if ( bits256_nonz(rswap.txids[BASILISK_ALICERECLAIM]) != 0 ) // tested
{
rswap.sentflags[BASILISK_ALICERECLAIM] = 1;
rswap.Apaymentspent = rswap.txids[BASILISK_ALICERECLAIM];
}
}
LP_txbytes_update("alicereclaim",rswap.alicecoin,rswap.txbytes[BASILISK_ALICERECLAIM],&rswap.txids[BASILISK_ALICERECLAIM],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_ALICERECLAIM]);
}
}
else if ( rswap.iambob == 1 )
@ -909,6 +1004,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( bits256_nonz(rswap.privAm) == 0 )
{
rswap.privAm = basilisk_swap_privbob_extract(rswap.bobcoin,rswap.txids[BASILISK_ALICESPEND],0,1);
printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm));
}
if ( bits256_nonz(rswap.privAm) != 0 && bits256_nonz(rswap.privBn) != 0 )
{
@ -916,15 +1012,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
printf("bobspend.(%s)\n",rswap.txbytes[BASILISK_BOBSPEND]);
}
}
if ( rswap.txbytes[BASILISK_BOBSPEND] != 0 )
{
rswap.txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",rswap.alicecoin,rswap.txbytes[BASILISK_BOBSPEND],zero);
if ( bits256_nonz(rswap.txids[BASILISK_BOBSPEND]) != 0 ) // tested
{
rswap.sentflags[BASILISK_BOBSPEND] = 1;
rswap.Apaymentspent = rswap.txids[BASILISK_BOBSPEND];
}
}
LP_txbytes_update("bobspend",rswap.alicecoin,rswap.txbytes[BASILISK_BOBSPEND],&rswap.txids[BASILISK_BOBSPEND],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_BOBSPEND]);
}
}
if ( rswap.sentflags[BASILISK_BOBRECLAIM] == 0 && rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 && time(NULL) > rswap.expiration && bits256_nonz(rswap.paymentspent) == 0 )
@ -945,21 +1033,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
}
}
if ( rswap.txbytes[BASILISK_BOBRECLAIM] != 0 )
{
rswap.txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",rswap.bobcoin,rswap.txbytes[BASILISK_BOBRECLAIM],zero);
if ( bits256_nonz(rswap.txids[BASILISK_BOBRECLAIM]) != 0 ) // tested
{
rswap.sentflags[BASILISK_BOBRECLAIM] = 1;
rswap.paymentspent = rswap.txids[BASILISK_BOBRECLAIM];
}
}
LP_txbytes_update("bobreclaim",rswap.bobcoin,rswap.txbytes[BASILISK_BOBRECLAIM],&rswap.txids[BASILISK_BOBRECLAIM],&rswap.paymentspent,&rswap.sentflags[BASILISK_BOBRECLAIM]);
}
if ( rswap.sentflags[BASILISK_BOBREFUND] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 )
{
if ( bits256_nonz(rswap.paymentspent) != 0 || time(NULL) > rswap.expiration )
if ( bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration )
{
printf("do the refund!\n");
printf("do the refund! paymentspent.%s now.%u vs expiration.%u\n",bits256_str(str,rswap.paymentspent),(uint32_t)time(NULL),rswap.expiration);
//if ( txbytes[BASILISK_BOBREFUND] == 0 )
{
revcalc_rmd160_sha256(rswap.secretBn,rswap.privBn);
@ -969,15 +1049,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( (rswap.txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_BOBREFUND],0,0,rswap.bobdepositaddr,1)) != 0 )
printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,rswap.pubB1),rswap.txbytes[BASILISK_BOBREFUND]);
}
if ( rswap.txbytes[BASILISK_BOBREFUND] != 0 )
{
rswap.txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],zero);
if ( bits256_nonz(rswap.txids[BASILISK_BOBREFUND]) != 0 ) // tested
{
rswap.sentflags[BASILISK_BOBREFUND] = 1;
rswap.depositspent = rswap.txids[BASILISK_BOBREFUND];
}
}
LP_txbytes_update("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],&rswap.txids[BASILISK_BOBREFUND],&rswap.depositspent,&rswap.sentflags[BASILISK_BOBREFUND]);
} else printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),rswap.expiration);
}
}
@ -999,30 +1071,14 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
printf("depositspent.(%s) alice.%d bob.%d %s %.8f\n",bits256_str(str,rswap.depositspent),rswap.sentflags[BASILISK_ALICECLAIM],rswap.sentflags[BASILISK_BOBREFUND],rswap.bobcoin,dstr(rswap.values[BASILISK_BOBDEPOSIT]));
}
LP_totals_update(rswap.iambob,rswap.alicecoin,rswap.bobcoin,KMDtotals,BTCtotals,rswap.sentflags,rswap.values);
if ( bits256_nonz(rswap.paymentspent) == 0 )
{
if ( bits256_nonz(rswap.txids[BASILISK_ALICESPEND]) != 0 )
rswap.paymentspent = rswap.txids[BASILISK_ALICESPEND];
else rswap.paymentspent = rswap.txids[BASILISK_BOBRECLAIM];
}
if ( bits256_nonz(rswap.depositspent) == 0 )
{
if ( bits256_nonz(rswap.txids[BASILISK_BOBREFUND]) != 0 )
rswap.depositspent = rswap.txids[BASILISK_BOBREFUND];
else rswap.depositspent = rswap.txids[BASILISK_ALICECLAIM];
}
if ( bits256_nonz(rswap.Apaymentspent) == 0 )
{
if ( bits256_nonz(rswap.txids[BASILISK_BOBSPEND]) != 0 )
rswap.Apaymentspent = rswap.txids[BASILISK_BOBSPEND];
else rswap.Apaymentspent = rswap.txids[BASILISK_ALICERECLAIM];
}
rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent);
if ( (numspent= LP_spends_set(&rswap)) == 3 )
rswap.finishedflag = 1;
else rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent);
item = LP_swap_json(&rswap);
if ( rswap.origfinishedflag == 0 && rswap.finishedflag != 0 )
{
char fname[1024],*itemstr; FILE *fp;
//printf("SWAP %u-%u finished!\n",requestid,quoteid);
printf("SWAP %u-%u finished!\n",requestid,quoteid);
sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap.requestid,rswap.quoteid), OS_compatible_path(fname);
if ( (fp= fopen(fname,"wb")) != 0 )
{
@ -1044,21 +1100,28 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
//,statebits; int32_t optionduration; struct basilisk_request R; bits256 privkey;
retjson = cJSON_CreateObject();
array = cJSON_CreateArray();
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb")) != 0 )
if ( origrequestid != 0 && origquoteid != 0 )
{
//struct basilisk_swap *swap;
int32_t flag = 0;
while ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread(&quoteid,1,sizeof(quoteid),fp) == sizeof(quoteid) )
//printf("orig req.%u q.%u\n",origrequestid,origquoteid);
if ( (item= basilisk_remember(KMDtotals,BTCtotals,origrequestid,origquoteid)) != 0 )
jaddi(array,item);
//printf("got.(%s)\n",jprint(item,0));
}
else
{
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb")) != 0 )
{
flag = 0;
for (i=0; i<G.LP_numskips; i++)
//struct basilisk_swap *swap;
int32_t flag = 0;
while ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread(&quoteid,1,sizeof(quoteid),fp) == sizeof(quoteid) )
{
r = (uint32_t)(G.LP_skipstatus[i] >> 32);
q = (uint32_t)G.LP_skipstatus[i];
if ( r == requestid && q == quoteid )
flag = 0;
for (i=0; i<G.LP_numskips; i++)
{
if ( r != origrequestid || q != origquoteid )
r = (uint32_t)(G.LP_skipstatus[i] >> 32);
q = (uint32_t)G.LP_skipstatus[i];
if ( r == requestid && q == quoteid )
{
item = cJSON_CreateObject();
jaddstr(item,"status","realtime");
@ -1066,21 +1129,17 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
jaddnum(item,"quoteid",q);
jaddi(array,item);
flag = 1;
break;
}
break;
}
}
if ( flag == 0 )
{
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
if ( flag == 0 )
{
jaddi(array,item);
//if ( (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 )
// break;
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
jaddi(array,item);
}
}
fclose(fp);
}
fclose(fp);
}
jaddstr(retjson,"result","success");
jadd(retjson,"swaps",array);
@ -1119,6 +1178,7 @@ char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid)
char *liststr,*retstr = 0; cJSON *retjson,*array,*item; int32_t i,n;
if ( (liststr= basilisk_swaplist(requestid,quoteid)) != 0 )
{
//printf("swapentry.(%s)\n",liststr);
if ( (retjson= cJSON_Parse(liststr)) != 0 )
{
if ( (array= jarray(&n,retjson,"swaps")) != 0 )
@ -1141,5 +1201,70 @@ char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid)
return(retstr);
}
void LP_tradecommand_log(cJSON *argjson)
{
static FILE *logfp; char *jsonstr;
if ( logfp == 0 )
{
if ( (logfp= fopen("stats.log","rb+")) != 0 )
fseek(logfp,0,SEEK_END);
else logfp = fopen("stats.log","wb");
}
if ( logfp != 0 )
{
jsonstr = jprint(argjson,0);
fprintf(logfp,"%s\n",jsonstr);
free(jsonstr);
fflush(logfp);
}
}
extern struct LP_quoteinfo LP_Alicequery;
extern uint32_t Alice_expiration;
char *LP_recent_swaps(int32_t limit)
{
char fname[512]; long fsize,offset; FILE *fp; int32_t i=0; uint32_t requestid,quoteid; cJSON *array,*item,*retjson;
if ( limit <= 0 )
limit = 3;
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
array = cJSON_CreateArray();
if ( (fp= fopen(fname,"rb")) != 0 )
{
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
offset = (sizeof(requestid) + sizeof(quoteid));
while ( offset <= fsize && i < limit )
{
i++;
offset = i * (sizeof(requestid) + sizeof(quoteid));
fseek(fp,fsize-offset,SEEK_SET);
if ( ftell(fp) == fsize-offset )
{
if ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread(&quoteid,1,sizeof(quoteid),fp) == sizeof(quoteid) )
{
item = cJSON_CreateArray();
jaddinum(item,requestid);
jaddinum(item,quoteid);
jaddi(array,item);
} else break;
} else break;
}
fclose(fp);
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jadd(retjson,"swaps",array);
if ( time(NULL) < Alice_expiration )
{
item = cJSON_CreateObject();
jaddnum(item,"expiration",Alice_expiration);
jaddnum(item,"timeleft",Alice_expiration-time(NULL));
jaddstr(item,"base",LP_Alicequery.srccoin);
jaddnum(item,"basevalue",dstr(LP_Alicequery.satoshis));
jaddstr(item,"rel",LP_Alicequery.destcoin);
jaddnum(item,"relvalue",dstr(LP_Alicequery.destsatoshis));
jadd(retjson,"pending",item);
} else Alice_expiration = 0;
return(jprint(retjson,1));
}

83
iguana/exchanges/LP_rpc.c

@ -94,10 +94,11 @@ char *issue_LP_getprices(char *destip,uint16_t destport)
char *issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr)
{
char url[512];
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/listunspent?coin=%s&address=%s",destip,destport,symbol,coinaddr);
//printf("listunspent.(%s)\n",url);
return(LP_issue_curl("listunspent",destip,destport,url));
retstr = LP_issue_curl("listunspent",destip,destport,url);
//printf("listunspent.(%s) -> (%s)\n",url,retstr);
return(retstr);
}
char *LP_apicall(struct iguana_info *coin,char *method,char *params)
@ -131,9 +132,10 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
if ( coin->electrum == 0 )
{
retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,params);
if ( 0 && strcmp("KMD",coin->symbol) == 0 )
printf("%s.(%s %s): %s.%s -> (%s)\n",coin->symbol,coin->serverport,coin->userpass,method,params,retstr);
if ( retstr != 0 && retstr[0] != 0 )
{
//printf("%s: %s.%s -> (%s)\n",coin->symbol,method,params,retstr);
retjson = cJSON_Parse(retstr);
free(retstr);
}
@ -254,7 +256,8 @@ cJSON *LP_gettx(char *symbol,bits256 txid)
if ( coin->electrum == 0 )
{
sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid));
return(bitcoin_json(coin,"getrawtransaction",buf));
retjson = bitcoin_json(coin,"getrawtransaction",buf);
return(retjson);
}
else
{
@ -265,6 +268,17 @@ cJSON *LP_gettx(char *symbol,bits256 txid)
}
}
uint32_t LP_locktime(char *symbol,bits256 txid)
{
cJSON *txobj; uint32_t locktime = 0;
if ( (txobj= LP_gettx(symbol,txid)) != 0 )
{
locktime = juint(txobj,"locktime");
free_json(txobj);
}
return(locktime);
}
cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,uint64_t value)
{
cJSON *retjson,*addresses,*sobj;
@ -280,7 +294,7 @@ cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,
jaddstr(sobj,"type","pubkey");
jadd(sobj,"addresses",addresses);
jadd(retjson,"scriptPubKey",sobj);
printf("GETTXOUT.(%s)\n",jprint(retjson,0));
//printf("GETTXOUT.(%s)\n",jprint(retjson,0));
return(retjson);
}
@ -323,7 +337,7 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
return(0);
return(LP_gettxout_json(txid,vout,up->U.height,coinaddr,up->U.value));
}
if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr)) != 0 )
if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr,1)) != 0 )
{
//printf("array.(%s)\n",jprint(array,0));
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
@ -416,6 +430,24 @@ int32_t LP_address_ismine(char *symbol,char *address)
return(doneflag);
}
int32_t LP_address_isvalid(char *symbol,char *address)
{
int32_t isvalid = 0; cJSON *retjson;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"isvalid") != 0 && is_cJSON_True(jobj(retjson,"isvalid")) != 0 )
{
isvalid = 1;
//printf("%s ismine (%s)\n",address,jprint(retjson,0));
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
}
return(isvalid);
}
cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
char buf[128]; cJSON *retjson; struct iguana_info *coin;
@ -423,7 +455,7 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr)
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
if ( coin == 0 || coin->inactive != 0 )
if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum == 0 )
{
@ -432,10 +464,10 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr)
sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr);
return(bitcoin_json(coin,"listunspent",buf));
} else return(LP_address_utxos(coin,coinaddr,0));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1));
}
int32_t LP_listunspent_issue(char *symbol,char *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,destip[64]; uint16_t destport;
if ( symbol == 0 || symbol[0] == 0 )
@ -444,7 +476,7 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr)
{
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr)) != 0 )
if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)) != 0 )
{
n = cJSON_GetArraySize(retjson);
//printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0));
@ -457,15 +489,24 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr)
retjson = LP_listunspent(symbol,coinaddr);
//printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr);
}
else if ( (destport= LP_randpeer(destip)) > 0 )
else if ( IAMLP == 0 )
{
retstr = issue_LP_listunspent(destip,destport,symbol,coinaddr);
retjson = cJSON_Parse(retstr);
} else printf("LP_listunspent_issue couldnt get a random peer?\n");
printf("LP_listunspent_query.(%s %s)\n",symbol,coinaddr);
LP_listunspent_query(coin->symbol,coin->smartaddr);
if ( fullflag != 0 )
{
if ( (destport= LP_randpeer(destip)) > 0 )
{
retstr = issue_LP_listunspent(destip,destport,symbol,coinaddr);
//printf("issue %s %s %s -> (%s)\n",coin->symbol,coinaddr,destip,retstr);
retjson = cJSON_Parse(retstr);
} else printf("LP_listunspent_issue couldnt get a random peer?\n");
}
}
if ( retjson != 0 )
{
n = cJSON_GetArraySize(retjson);
if ( electrum_process_array(coin,0,coinaddr,retjson) != 0 )
if ( electrum_process_array(coin,0,coinaddr,retjson,1) != 0 )
{
//LP_postutxos(symbol,coinaddr); // might be good to not saturate
}
@ -601,18 +642,24 @@ double LP_getestimatedrate(struct iguana_info *coin)
char *LP_sendrawtransaction(char *symbol,char *signedtx)
{
cJSON *array,*errobj; char *paramstr,*tmpstr,*retstr=0; int32_t n,alreadyflag = 0; cJSON *retjson; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
if ( symbol == 0 || symbol[0] == 0 || signedtx == 0 || signedtx[0] == 0 )
{
printf("LP_sendrawtransaction null symbol %p or signedtx.%p\n",symbol,signedtx);
return(0);
}
coin = LP_coinfind(symbol);
if ( coin == 0 )
{
printf("LP_sendrawtransaction null coin\n");
return(0);
}
if ( coin->electrum == 0 )
{
array = cJSON_CreateArray();
jaddistr(array,signedtx);
paramstr = jprint(array,1);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr);
//printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr);
printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr);
free(paramstr);
}
else

11
iguana/exchanges/LP_scan.c

@ -391,7 +391,7 @@ char *LP_dividends(struct iguana_info *coin,int32_t height,cJSON *argjson)
return(clonestr("{\"error\":\"symbol not found\"}"));
}
int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 searchtxid,int32_t searchvout)
int32_t LP_spendsearch(char *coinaddr,bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 searchtxid,int32_t searchvout)
{
struct LP_transaction *tx; struct iguana_info *coin;
*indp = -1;
@ -404,6 +404,7 @@ int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 se
{
*spendtxidp = tx->outpoints[searchvout].spendtxid;
*indp = tx->outpoints[searchvout].spendvini;
LP_swap_getcoinaddr(symbol,coinaddr,*spendtxidp,*indp);
return(tx->outpoints[searchvout].spendheight);
}
}
@ -481,7 +482,7 @@ int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int
}
free(array);
}
LP_listunspent_issue(coin->symbol,coinaddr);
LP_listunspent_issue(coin->symbol,coinaddr,1);
struct LP_address_utxo *up;
if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 )
{
@ -504,7 +505,7 @@ int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int
int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,char *coinaddr,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2)
{
struct iguana_info *coin; int32_t selector; cJSON *array;
struct iguana_info *coin; int32_t selector; cJSON *array; char addr[64];
if ( symbol == 0 || symbol[0] == 0 || bits256_nonz(searchtxid) == 0 || bits256_nonz(searchtxid2) == 0 )
return(-1);
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 )
@ -517,9 +518,9 @@ int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,c
coin->lastmempool = (uint32_t)time(NULL);
}
}
if ( (selector= LP_spendsearch(spendtxidp,spendvinp,symbol,searchtxid,searchvout)) >= 0 )
if ( (selector= LP_spendsearch(addr,spendtxidp,spendvinp,symbol,searchtxid,searchvout)) >= 0 )
return(selector);
else if ( (selector= LP_spendsearch(spendtxidp,spendvinp,symbol,searchtxid2,searchvout2)) >= 0 )
else if ( (selector= LP_spendsearch(addr,spendtxidp,spendvinp,symbol,searchtxid2,searchvout2)) >= 0 )
return(selector);
return(-1);
}

45
iguana/exchanges/LP_socket.c

@ -26,7 +26,7 @@
//#include <WinSock2.h>
//#endif
#define ELECTRUM_TIMEOUT 5
#define ELECTRUM_TIMEOUT 10
int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
{
@ -86,7 +86,7 @@ int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
#endif
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
//#ifdef WIN32
//#ifdef _WIN32
// saddr.sin_addr.s_addr = (uint32_t)calc_ipbits("127.0.0.1");
//#else
@ -111,7 +111,7 @@ int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
opt = 1;
slen = sizeof(opt);
//printf("set keepalive.%d\n",setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(void *)&opt,slen));
#ifndef WIN32
#ifndef _WIN32
if ( 1 )//&& bindflag != 0 )
{
opt = 0;
@ -295,7 +295,7 @@ struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep)
return(ep);
}
int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array)
int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array,int32_t electrumflag)
{
int32_t i,v,n,ht,flag = 0; char str[65]; uint64_t value; bits256 txid; cJSON *item,*retjson,*txobj; struct LP_transaction *tx;
if ( array != 0 && coin != 0 && (n= cJSON_GetArraySize(array)) > 0 )
@ -304,7 +304,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( coin->electrum == 0 )
if ( electrumflag == 0 )
{
txid = jbits256(item,"txid");
v = jint(item,"vout");
@ -350,7 +350,10 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
}
}
if ( value != 0 || tx->height > 0 )
{
//printf("from electrum_process_array\n");
flag += LP_address_utxoadd(coin,coinaddr,txid,v,value,tx->height,-1);
}
//printf("v.%d numvouts.%d %.8f (%s)\n",v,tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0));
} //else printf("cant find tx\n");
}
@ -457,7 +460,7 @@ cJSON *electrum_address_subscribe(char *symbol,struct electrum_info *ep,cJSON **
cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr)
{
struct LP_transaction *tx; cJSON *retjson,*txobj,*item; int32_t i,n,height; bits256 txid; struct iguana_info *coin = LP_coinfind(symbol);
char str[65]; struct LP_transaction *tx; cJSON *retjson,*txobj,*item; int32_t i,n,height; bits256 txid; struct iguana_info *coin = LP_coinfind(symbol);
retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_history",addr,ELECTRUM_TIMEOUT);
//printf("history.(%s)\n",jprint(retjson,0));
if ( retjson != 0 && (n= cJSON_GetArraySize(retjson)) > 0 )
@ -478,7 +481,10 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON *
{
if ( (tx= LP_transactionfind(coin,txid)) != 0 )
{
if ( tx->height > 0 && tx->height != height )
printf("update %s height.%d <- %d\n",bits256_str(str,txid),tx->height,height);
tx->height = height;
//printf("from history\n");
LP_address_utxoadd(coin,addr,txid,0,0,height,-1);
}
}
@ -488,25 +494,36 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON *
return(retjson);
}
int32_t LP_txheight_check(struct iguana_info *coin,char *coinaddr,struct LP_address_utxo *up)
{
cJSON *retjson;
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_gethistory(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 )
free_json(retjson);
}
return(0);
}
cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr)
{
cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol);
retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_mempool",addr,ELECTRUM_TIMEOUT);
//printf("MEMPOOL.(%s)\n",jprint(retjson,0));
electrum_process_array(coin,ep,addr,retjson);
electrum_process_array(coin,ep,addr,retjson,1);
return(retjson);
}
cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr)
cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,int32_t electrumflag)
{
cJSON *retjson=0; struct iguana_info *coin = LP_coinfind(symbol);
//printf("electrum.%s/%s listunspent last.(%s lag %d)\n",ep->symbol,coin->symbol,coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime));
if ( 1 || strcmp(coin->lastunspent,addr) != 0 || time(NULL) > coin->unspenttime+30 )
if ( strcmp(coin->lastunspent,addr) != 0 || time(NULL) > coin->unspenttime+30 )
{
if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.listunspent",addr,ELECTRUM_TIMEOUT)) != 0 )
{
//printf("LISTUNSPENT.(%s)\n",jprint(retjson,0));
if ( electrum_process_array(coin,ep,addr,retjson) != 0 )
if ( electrum_process_array(coin,ep,addr,retjson,electrumflag) != 0 )
LP_postutxos(coin->symbol,addr);
safecopy(coin->lastunspent,addr,sizeof(coin->lastunspent));
coin->unspenttime = (uint32_t)time(NULL);
@ -530,9 +547,9 @@ cJSON *electrum_getchunk(char *symbol,struct electrum_info *ep,cJSON **retjsonp,
cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len)
{
uint8_t *extraspace; cJSON *txobj; char str[65],str2[65]; struct iguana_msgtx msgtx; bits256 checktxid;
extraspace = calloc(1,1000000);
extraspace = calloc(1,4000000);
memset(&msgtx,0,sizeof(msgtx));
txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,1000000,serialized,len,0,0);
txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,4000000,serialized,len,0,0);
//printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid));
free(extraspace);
if ( bits256_cmp(txid,checktxid) != 0 )
@ -654,7 +671,7 @@ void electrum_test()
printf("electrum_address_getmempool %s\n",jprint(retjson,1));
if ( (retjson= electrum_address_getbalance(symbol,ep,0,addr)) != 0 )
printf("electrum_address_getbalance %s\n",jprint(retjson,1));
if ( (retjson= electrum_address_listunspent(symbol,ep,0,addr)) != 0 )
if ( (retjson= electrum_address_listunspent(symbol,ep,0,addr,1)) != 0 )
printf("electrum_address_listunspent %s\n",jprint(retjson,1));
if ( (retjson= electrum_addpeer(symbol,ep,0,"electrum.be:50001")) != 0 )
printf("electrum_addpeer %s\n",jprint(retjson,1));
@ -909,7 +926,7 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
}
else
{
printf("launched.(%s:%u)\n",ep->ipaddr,ep->port);
printf("launched electrum.(%s:%u)\n",ep->ipaddr,ep->port);
jaddstr(retjson,"result","success");
ep->prev = coin->electrum;
coin->electrum = ep;

58
iguana/exchanges/LP_statemachine.c

@ -1871,6 +1871,64 @@ int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pu
} //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
return(n);
}
bestitem = LP_quotejson(qp);
if ( LP_pricevalid(price) > 0 )
{
if ( price <= maxprice )
{
LP_query(ctx,myipaddr,mypubsock,"connect",qp);
//price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-2*qp->txfee,qp->destcoin,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
while ( time(NULL) < expiration )
{
if ( aliceutxo->S.swap != 0 )
break;
sleep(3);
}
jaddnum(bestitem,"quotedprice",price);
jaddnum(bestitem,"maxprice",maxprice);
if ( (swap= aliceutxo->S.swap) == 0 )
{
if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 )
pubp->numerrors++;
jaddstr(bestitem,"status","couldnt establish connection");
}
else
{
jaddstr(bestitem,"status","connected");
jaddnum(bestitem,"requestid",swap->I.req.requestid);
jaddnum(bestitem,"quoteid",swap->I.req.quoteid);
printf("Alice r.%u qp->%u\n",swap->I.req.requestid,swap->I.req.quoteid);
}
}
else
{
jaddnum(bestitem,"quotedprice",price);
jaddnum(bestitem,"maxprice",maxprice);
jaddstr(bestitem,"status","too expensive");
}
}
else
{
printf("invalid price %.8f\n",price);
jaddnum(bestitem,"maxprice",maxprice);
jaddstr(bestitem,"status","no response to request");
}
/*while ( time(NULL) < expiration )
{
if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL )
{
printf("break out of price %.8f %s/%s\n",price,qp->srccoin,qp->destcoin);
break;
}
sleep(1);
}*/
if ( aliceutxo->S.swap == 0 )
LP_availableset(aliceutxo);
return(jprint(bestitem,0));
}
/*if ( time(NULL) > coin->lastmonitor+60 )
{
//portable_mutex_lock(&coin->addrmutex);

127
iguana/exchanges/LP_swap.c

@ -177,6 +177,13 @@ uint32_t basilisk_requestid(struct basilisk_request *rp)
int32_t LP_pubkeys_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
int32_t i,datalen = 0;
data[datalen++] = swap->I.aliceconfirms;
data[datalen++] = swap->I.bobconfirms;
data[datalen++] = swap->I.alicemaxconfirms;
data[datalen++] = swap->I.bobmaxconfirms;
data[datalen++] = swap->I.otheristrusted;
for (i=0; i<33; i++)
data[datalen++] = swap->persistent_pubkey33[i];
for (i=0; i<sizeof(swap->deck)/sizeof(swap->deck[0][0]); i++)
datalen += iguana_rwnum(1,&data[datalen],sizeof(swap->deck[i>>1][i&1]),&swap->deck[i>>1][i&1]);
return(datalen);
@ -184,14 +191,49 @@ int32_t LP_pubkeys_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
int32_t i,len = 0;
if ( datalen == sizeof(swap->otherdeck) )
int32_t i,nonz=0,alicemaxconfirms,bobmaxconfirms,aliceconfirms,bobconfirms,len = 0; uint8_t other33[33];
if ( datalen == sizeof(swap->otherdeck)+38 )
{
aliceconfirms = data[len++];
bobconfirms = data[len++];
alicemaxconfirms = data[len++];
bobmaxconfirms = data[len++];
if ( aliceconfirms != swap->I.aliceconfirms || bobconfirms != swap->I.bobconfirms )
{
printf("MISMATCHED required confirms me.(%d %d) vs (%d %d) max.(%d %d) othermax.(%d %d)\n",swap->I.aliceconfirms,swap->I.bobconfirms,aliceconfirms,bobconfirms,swap->I.alicemaxconfirms,swap->I.bobmaxconfirms,alicemaxconfirms,bobmaxconfirms);
if ( alicemaxconfirms > swap->I.alicemaxconfirms )
alicemaxconfirms = swap->I.alicemaxconfirms;
if ( bobmaxconfirms > swap->I.bobmaxconfirms )
bobmaxconfirms = swap->I.bobmaxconfirms;
if ( swap->I.aliceconfirms < aliceconfirms )
swap->I.aliceconfirms = aliceconfirms;
if ( swap->I.bobconfirms < bobconfirms )
swap->I.bobconfirms = bobconfirms;
if ( swap->I.aliceconfirms > swap->I.alicemaxconfirms || swap->I.bobconfirms > swap->I.bobmaxconfirms )
{
printf("numconfirms (%d %d) exceeds max (%d %d)\n",swap->I.aliceconfirms,swap->I.bobconfirms,swap->I.alicemaxconfirms,swap->I.bobmaxconfirms);
return(-1);
}
}
if ( (swap->I.otherstrust= data[len++]) != 0 )
{
if ( swap->I.otheristrusted != 0 )
{
swap->I.aliceconfirms = swap->I.bobconfirms = 0;
printf("Otherside trusts us, adjust required confirms to: alice.%d bob.%d\n",swap->I.aliceconfirms,swap->I.bobconfirms);
}
}
printf("NUMCONFIRMS for SWAP alice.%d bob.%d, otheristrusted.%d othertrusts.%d\n",swap->I.aliceconfirms,swap->I.bobconfirms,swap->I.otheristrusted,swap->I.otherstrust);
for (i=0; i<33; i++)
if ( (other33[i]= data[len++]) != 0 )
nonz++;
if ( nonz > 8 )
memcpy(swap->persistent_other33,other33,33);
for (i=0; i<sizeof(swap->otherdeck)/sizeof(swap->otherdeck[0][0]); i++)
len += iguana_rwnum(0,&data[len],sizeof(swap->otherdeck[i>>1][i&1]),&swap->otherdeck[i>>1][i&1]);
return(0);
}
printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)sizeof(swap->otherdeck));
printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)sizeof(swap->otherdeck)+36);
return(-1);
}
@ -412,10 +454,10 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i
pfd.events = NN_POLLIN;
if ( nn_poll(&pfd,1,1) > 0 )
{
printf("start wait\n");
//printf("start wait\n");
if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 )
{
printf("wait for got.%d\n",datalen);
//printf("wait for got.%d\n",datalen);
retval = (*verify)(swap,data,datalen);
nn_freemsg(data);
//printf("retval.%d\n",retval);
@ -600,7 +642,7 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba
printf("got %s txid.%s (%s) -> %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0),rawtx->p2shaddr);
} else bitcoin_address(rawtx->p2shaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen);
}
} else printf("%s ERROR.(%s) txfees.[%.8f %.8f: %.8f] amount.%.8f -> %.8f\n",rawtx->name,jprint(txobj,0),dstr(swap->I.Atxfee),dstr(swap->I.Btxfee),dstr(txfee),dstr(rawtx->I.amount),dstr(rawtx->I.amount)-dstr(txfee));
} else printf("%s satoshis %.8f ERROR.(%s) txfees.[%.8f %.8f: %.8f] amount.%.8f -> %.8f\n",rawtx->name,dstr(j64bits(vout,"satoshis")),jprint(txobj,0),dstr(swap->I.Atxfee),dstr(swap->I.Btxfee),dstr(txfee),dstr(rawtx->I.amount),dstr(rawtx->I.amount)-dstr(txfee));
}
free_json(txobj);
}
@ -664,11 +706,11 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime)
{
char *retstr; cJSON *retjson=0; uint32_t divisor=8,expiration = (uint32_t)(time(NULL) + duration);
char *retstr; cJSON *retjson=0; uint32_t expiration = (uint32_t)(time(NULL) + duration);
printf("wait %d:%d for SWAP.(r%u/q%u) to complete\n",duration,sleeptime,requestid,quoteid);
sleep(10);
if ( sleeptime < divisor*60 )
sleeptime = divisor * 60;
//if ( sleeptime < divisor*60 )
// sleeptime = divisor * 60;
while ( time(NULL) < expiration )
{
if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 )
@ -683,9 +725,10 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t
}
free(retstr);
}
sleep(sleeptime/divisor);
if ( divisor > 1 )
divisor--;
sleep(sleeptime);
//sleep(sleeptime/divisor);
//if ( divisor > 1 )
// divisor--;
}
if ( retjson != 0 )
{
@ -738,21 +781,23 @@ void LP_bobloop(void *_swap)
{
if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
m = 0;
else m = 1;
else m = swap->I.aliceconfirms;
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice
{
char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(3);
}
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 )
printf("error sending bobpayment\n");
//if ( LP_waitfor(swap->N.pair,swap,10,LP_verify_alicespend) < 0 )
// printf("error waiting for alicespend\n");
swap->sentflag = 1;
swap->bobreclaim.utxovout = 0;
swap->bobreclaim.utxotxid = swap->bobpayment.I.signedtxid;
basilisk_bobpayment_reclaim(swap,swap->I.callduration);
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300);
LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,30);
}
}
}
@ -791,10 +836,10 @@ void LP_aliceloop(void *_swap)
{
if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
m = 0;
else m = 1;
else m = swap->I.aliceconfirms;
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m )
{
char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(10);
}
swap->sentflag = 1;
@ -807,16 +852,16 @@ void LP_aliceloop(void *_swap)
char str[65];printf("%d waiting for bobpayment %s to be confirmed.%d %s %s\n",n,swap->bobpayment.I.destaddr,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT);
}
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 )
/*if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 )
printf("error sending alicespend\n");
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,0,1)) < swap->I.aliceconfirms )
{
char str[65];printf("%d waiting for alicespend %s to be confirmed.%d %s %s\n",n,swap->alicespend.I.destaddr,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT);
}
}*/
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300);
LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,30);
}
}
}
@ -947,7 +992,7 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
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)
{
//FILE *fp; char fname[512];
uint8_t *alicepub33=0,*bobpub33=0; int32_t bobistrusted,aliceistrusted,jumblrflag=-2,x = -1; struct iguana_info *coin;
uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *coin;
swap->I.Atxfee = qp->desttxfee;
swap->I.Btxfee = qp->txfee;
swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME;
@ -975,15 +1020,15 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
{
swap->I.iambob = 0;
swap->I.otherhash = swap->I.req.desthash;
aliceistrusted = 1;
bobistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
swap->I.aliceistrusted = 1;
swap->I.otheristrusted = swap->I.bobistrusted = LP_pubkey_istrusted(swap->I.req.srchash);
}
else
{
swap->I.iambob = 1;
swap->I.otherhash = swap->I.req.srchash;
bobistrusted = 1;
aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
swap->I.bobistrusted = 1;
swap->I.otheristrusted = swap->I.aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
}
if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE )
{
@ -1009,31 +1054,47 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
if ( strcmp("BTC",swap->bobcoin.symbol) == 0 )
{
swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1));
swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms);
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 )
{
swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1));
swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.aliceconfirms);
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
else
{
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
swap->I.bobconfirms *= !bobistrusted;
swap->I.aliceconfirms *= !aliceistrusted;
if ( swap->bobcoin.isassetchain != 0 )
swap->I.bobconfirms = 1;
if ( swap->alicecoin.isassetchain != 0 )
swap->I.aliceconfirms = 1;
if ( swap->bobcoin.userconfirms > 0 )
swap->I.bobconfirms = swap->bobcoin.userconfirms;
if ( swap->alicecoin.userconfirms > 0 )
swap->I.aliceconfirms = swap->alicecoin.userconfirms;
if ( (swap->I.bobmaxconfirms= swap->bobcoin.maxconfirms) == 0 )
swap->I.bobmaxconfirms = BASILISK_DEFAULT_MAXCONFIRMS;
if ( (swap->I.alicemaxconfirms= swap->alicecoin.maxconfirms) == 0 )
swap->I.alicemaxconfirms = BASILISK_DEFAULT_MAXCONFIRMS;
if ( swap->I.bobconfirms > swap->I.bobmaxconfirms )
swap->I.bobconfirms = swap->I.bobmaxconfirms;
if ( swap->I.aliceconfirms > swap->I.alicemaxconfirms )
swap->I.aliceconfirms = swap->I.alicemaxconfirms;
swap->I.bobconfirms *= !swap->I.bobistrusted;
swap->I.aliceconfirms *= !swap->I.aliceistrusted;
printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d taddr.%d %d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms,swap->bobcoin.taddr,swap->alicecoin.taddr);
if ( swap->I.iambob != 0 )
{
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis),0,0,jumblrflag);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + swap->bobcoin.txfee,0,0,jumblrflag);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + swap->alicecoin.txfee,0,0,jumblrflag);
bobpub33 = pubkey33;
}
else
{
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis),0,0,jumblrflag);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + swap->bobcoin.txfee,0,0,jumblrflag);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + swap->alicecoin.txfee,0,0,jumblrflag);
alicepub33 = pubkey33;
}
basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,&swap->bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + swap->bobcoin.txfee,4,0,jumblrflag);

385
iguana/exchanges/LP_transaction.c

@ -37,10 +37,21 @@ int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid)
bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxid)
{
char *retstr; bits256 txid; cJSON *retjson,*errorobj; int32_t i,sentflag = 0;
char *retstr; bits256 txid; uint8_t *ptr; cJSON *retjson,*errorobj; int32_t i,len,sentflag = 0;
memset(&txid,0,sizeof(txid));
if ( txbytes == 0 || txbytes[0] == 0 )
return(txid);
if ( bits256_nonz(expectedtxid) == 0 )
{
len = (int32_t)strlen(txbytes) >> 1;
ptr = malloc(len);
decode_hex(ptr,len,txbytes);
expectedtxid = bits256_doublesha256(0,ptr,len);
free(ptr);
}
for (i=0; i<2; i++)
{
//char str[65]; printf("LP_broadcast.%d (%s) %s i.%d sentflag.%d\n",i,symbol,bits256_str(str,expectedtxid),i,sentflag);
if ( sentflag == 0 && LP_gettx_presence(symbol,expectedtxid) != 0 )
sentflag = 1;
if ( sentflag == 0 && (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 )
@ -63,10 +74,11 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxi
txid = expectedtxid;
sentflag = 1;
}
else printf("broadcast error.(%s)\n",retstr);
}
free_json(retjson);
}
char str[65]; printf("sentflag.%d [%s] %s RETSTR.(%s) %s.%s\n",sentflag,txname,txbytes,retstr,symbol,bits256_str(str,txid));
//char str[65]; printf("sentflag.%d [%s] %s RETSTR.(%s) %s.%s\n",sentflag,txname,txbytes,retstr,symbol,bits256_str(str,txid));
free(retstr);
}
if ( sentflag != 0 )
@ -432,14 +444,14 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_
extraspace = malloc(extralen);
memset(msgtx,0,sizeof(*msgtx));
decode_hex(serialized,len,rawtx);
// printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0));
if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys)) != 0 )
{
//printf("back from bitcoin_hex2json (%s)\n",jprint(vins,0));
} else fprintf(stderr,"no txobj from bitcoin_hex2json\n");
//printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0));
if ( (numinputs= cJSON_GetArraySize(vins)) > 0 )
{
//printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in);
//printf("numinputs.%d (%s) msgtx.%d\n",numinputs,jprint(vins,0),msgtx->tx_in);
memset(msgtx,0,sizeof(*msgtx));
if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,extralen,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in )
{
@ -548,9 +560,11 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_
return(complete);
}
char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys)
char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t utxovout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys)
{
char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*obj,*vouts,*item,*privkeys; int32_t completed,spendlen,n,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin;
if ( txfee > 0 && txfee < 10000 )
txfee = 10000;
*destamountp = 0;
memset(signedtxidp,0,sizeof(*signedtxidp));
if ( finalseqid == 0 )
@ -564,19 +578,19 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
{
if ( (txobj= LP_gettx(symbol,utxotxid)) != 0 )
{
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && utxovout < n )
{
obj = jitem(vouts,vout);
obj = jitem(vouts,utxovout);
value = LP_value_extract(obj,1);
//printf("value in vout.%d %.8f (%s)\n",vout,dstr(value),jprint(txobj,0));
}
free_json(txobj);
//if ( value != 0 )
// gettxout
}
} else printf("cant gettx\n");
if ( value == 0 )
{
printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid));
printf("basilisk_swap_bobtxspend.%s %s utxo.(%s).v%d already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid),utxovout);
return(0);
}
}
@ -646,7 +660,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
jaddstr(item,"userdata",hexstr);
}
jaddbits256(item,"txid",utxotxid);
jaddnum(item,"vout",vout);
jaddnum(item,"vout",utxovout);
bitcoin_address(tmpaddr,taddr,pubtype,pubkey33,33);
bitcoin_addr2rmd160(taddr,&addrtype,rmd160,tmpaddr);
if ( redeemlen != 0 )
@ -710,9 +724,321 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
return(signedtx);
}
int32_t LP_vin_select(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct LP_address_utxo **utxos,int32_t numunspents,uint64_t value,int32_t maxmode)
{
int32_t i,abovei,belowi; int64_t above,below,gap,atx_value;
abovei = belowi = -1;
for (above=below=i=0; i<numunspents; i++)
{
if ( utxos[i] == 0 )
continue;
if ( (atx_value= utxos[i]->U.value) <= 0 )
{
//printf("illegal value.%d\n",i);
continue;
}
if ( atx_value == value )
{
*aboveip = *belowip = i;
*abovep = *belowp = 0;
return(i);
}
else if ( atx_value > value )
{
gap = (atx_value - value);
if ( above == 0 || gap < above )
{
above = gap;
abovei = i;
}
} else gap = (value - atx_value);
if ( below == 0 || gap < below )
{
below = gap;
belowi = i;
}
}
*aboveip = abovei;
*abovep = above;
*belowip = belowi;
*belowp = below;
//printf("above.%d below.%d\n",abovei,belowi);
return(abovei >= 0 && above < (below>>1) ? abovei : belowi);
}
cJSON *LP_inputjson(bits256 txid,int32_t vout,char *spendscriptstr)
{
cJSON *sobj,*item = cJSON_CreateObject();
jaddbits256(item,"txid",txid);
jaddnum(item,"vout",vout);
sobj = cJSON_CreateObject();
jaddstr(sobj,"hex",spendscriptstr);
jadd(item,"scriptPubKey",sobj);
//printf("vin.%s\n",jprint(item,0));
return(item);
}
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 ( minutes > 365 * 24 * 60 )
minutes = 365 * 24 * 60;
minutes -= 59;
interest = ((nValue / 10512000) * minutes);
}
return(interest);
}
int64_t LP_komodo_interest(bits256 txid,int64_t value)
{
uint32_t nLockTime; uint32_t tiptime; int64_t interest = 0;
if ( value >= 10*SATOSHIDEN )
{
if ( (nLockTime= LP_locktime("KMD",txid)) >= 500000000 )
{
tiptime = (uint32_t)time(NULL) - 777;
interest = _komodo_interestnew(value,nLockTime,tiptime);
}
}
return(interest);
}
int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_t amount,struct vin_info *V,struct LP_address_utxo **utxos,int32_t numunspents,int32_t suppress_pubkeys,int32_t ignore_cltverr,bits256 privkey,cJSON *privkeys,cJSON *vins,uint8_t *script,int32_t scriptlen)
{
char wifstr[128],spendscriptstr[128]; int32_t i,n,ind,abovei,belowi,maxmode=0; struct vin_info *vp; struct LP_address_utxo *up; int64_t interest,interestsum,above,below,remains = amount,total = 0;
*totalp = 0;
interestsum = 0;
init_hexbytes_noT(spendscriptstr,script,scriptlen);
bitcoin_priv2wif(coin->wiftaddr,wifstr,privkey,coin->wiftype);
for (i=n=0; i<numunspents; i++)
{
//printf("vinselect.%d of %d: remain %.8f amount %.8f\n",i,numunspents,dstr(remains),dstr(amount));
below = above = 0;
abovei = belowi = -1;
if ( LP_vin_select(&abovei,&above,&belowi,&below,utxos,numunspents,remains,maxmode) < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,numunspents,dstr(remains),dstr(amount));
return(0);
}
if ( belowi < 0 || abovei >= 0 )
ind = abovei;
else ind = belowi;
if ( ind < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,numunspents,dstr(remains),dstr(amount),abovei,belowi,ind);
return(0);
}
up = utxos[ind];
utxos[ind] = utxos[--numunspents];
utxos[numunspents] = 0;
total += up->U.value;
remains -= up->U.value;
//if ( coin->electrum == 0 && strcmp(coin->symbol,"KMD") == 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));
}
}
vp = &V[n++];
vp->N = vp->M = 1;
vp->signers[0].privkey = privkey;
jaddistr(privkeys,wifstr);
bitcoin_pubkey33(ctx,vp->signers[0].pubkey,privkey);
vp->suppress_pubkeys = suppress_pubkeys;
vp->ignore_cltverr = ignore_cltverr;
jaddi(vins,LP_inputjson(up->U.txid,up->U.vout,spendscriptstr));
//printf("wif.%s i.%d privkeys.%s vins.%s %p %p\n",wifstr,i,jprint(privkeys,0),jprint(vins,0),privkeys,vins);
//printf("%s value %.8f -> remains %.8f\n",coinaddr,dstr(value),dstr(remains));
if ( remains <= 0 )
break;
if ( numunspents == 0 )
{
printf("total %.8f not enough for amount %.8f\n",dstr(total),dstr(amount));
return(0);
}
}
*totalp = total + interestsum;
return(n);
}
char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_info *coin,struct vin_info *V,int32_t max,bits256 privkey,cJSON *outputs,cJSON *vins,cJSON *privkeys,int64_t txfee)
{
static void *ctx;
cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[64]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp,locktime; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[256]; struct LP_address *ap;
if ( ctx == 0 )
ctx = bitcoin_ctx();
*numvinsp = 0;
*txobjp = 0;
if ( sizeof(utxos)/sizeof(*utxos) != max )
{
printf("LP_createrawtransaction: internal error %ld != max.%d\n",sizeof(utxos)/sizeof(*utxos),max);
return(0);
}
if ( coin == 0 || outputs == 0 || (numvouts= cJSON_GetArraySize(outputs)) <= 0 )
{
printf("LP_createrawtransaction: illegal coin.%p outputs.%p or arraysize.%d, error\n",coin,outputs,numvouts);
return(0);
}
amount = txfee;
for (i=0; i<numvouts; i++)
{
item = jitem(outputs,i);
if ( (coinaddr= jfieldname(item)) != 0 )
{
if ( LP_address_isvalid(coin->symbol,coinaddr) <= 0 )
{
printf("LP_createrawtransaction %s i.%d of %d is invalid\n",coinaddr,i,numvouts);
return(0);
}
if ( (value= SATOSHIDEN * jdouble(item,coinaddr)) <= 0 )
{
printf("cant get value %s i.%d of %d %s\n",coinaddr,i,numvouts,jprint(outputs,0));
return(0);
}
amount += value;
}
else
{
printf("cant get fieldname.%d of %d %s\n",i,numvouts,jprint(outputs,0));
return(0);
}
}
LP_listunspent_issue(coin->symbol,coin->smartaddr,1);
if ( (ap= LP_addressfind(coin,coin->smartaddr)) == 0 )
{
printf("LP_createrawtransaction: cant find address data\n");
return(0);
}
memset(utxos,0,sizeof(utxos));
if ( (numutxos= LP_address_utxo_ptrs(0,utxos,max,ap,coin->smartaddr)) <= 0 )
{
printf("LP_createrawtransaction: address_utxo_ptrs %d, error\n",numutxos);
return(0);
}
ignore_cltverr = 0;
suppress_pubkeys = 1;
scriptlen = bitcoin_standardspend(script,0,G.LP_myrmd160);
numvins = LP_vins_select(ctx,coin,&total,amount,V,utxos,numutxos,suppress_pubkeys,ignore_cltverr,privkey,privkeys,vins,script,scriptlen);
change = (total - amount);
timestamp = (uint32_t)time(NULL);
if ( strcmp("KMD",coin->symbol) == 0 )
locktime = timestamp - 777;
else locktime = 0;
txobj = bitcoin_txcreate(coin->symbol,coin->isPoS,locktime,1,timestamp);
jdelete(txobj,"vin");
jadd(txobj,"vin",jduplicate(vins));
if ( change < 6000 )
{
adjust = change / numvouts;
change = 0;
}
for (i=0; i<numvouts; i++)
{
item = jitem(outputs,i);
if ( (coinaddr= jfieldname(item)) != 0 )
{
if ( (value= SATOSHIDEN * jdouble(item,coinaddr)) <= 0 )
{
printf("cant get value i.%d of %d %s\n",i,numvouts,jprint(outputs,0));
return(0);
}
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr);
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
txobj = bitcoin_txoutput(txobj,spendscript,spendlen,value + adjust);
}
else
{
printf("cant get fieldname.%d of %d %s\n",i,numvouts,jprint(outputs,0));
return(0);
}
}
if ( change != 0 )
txobj = bitcoin_txoutput(txobj,script,scriptlen,change);
if ( (rawtxbytes= bitcoin_json2hex(coin->isPoS,&txid,txobj,V)) != 0 )
{
} else printf("error making rawtx suppress.%d\n",suppress_pubkeys);
*txobjp = txobj;
return(rawtxbytes);
}
char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
{
static void *ctx;
int32_t iter,completed=0,maxV,numvins,numvouts,datalen,suppress_pubkeys; bits256 privkey; char changeaddr[64],vinaddr[64],str[65],*signedtx=0,*rawtx=0; struct vin_info *V; cJSON *retjson,*outputs,*vins=0,*txobj=0,*privkeys=0; struct iguana_msgtx msgtx; bits256 signedtxid; uint64_t txfee,newtxfee=10000;
if ( (outputs= jarray(&numvouts,argjson,"outputs")) == 0 )
{
printf("no outputs in argjson (%s)\n",jprint(argjson,0));
return(clonestr("{\"error\":\"no outputs specified\"}"));
}
txfee = coin->txfee;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( txfee > 0 && txfee < 10000 )
txfee = 10000;
suppress_pubkeys = 0;
memset(signedtxid.bytes,0,sizeof(signedtxid));
safecopy(changeaddr,coin->smartaddr,sizeof(changeaddr));
safecopy(vinaddr,coin->smartaddr,sizeof(vinaddr));
privkey = LP_privkey(vinaddr,coin->taddr);
maxV = 256;
V = malloc(maxV * sizeof(*V));
for (iter=0; iter<2; iter++)
{
privkeys = cJSON_CreateArray();
vins = cJSON_CreateArray();
memset(V,0,sizeof(*V) * maxV);
if ( (rawtx= LP_createrawtransaction(&txobj,&numvins,coin,V,maxV,privkey,outputs,vins,privkeys,iter == 0 ? txfee : newtxfee)) != 0 )
{
completed = 0;
memset(&msgtx,0,sizeof(msgtx));
memset(signedtxid.bytes,0,sizeof(signedtxid));
if ( (completed= iguana_signrawtransaction(ctx,coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&msgtx,&signedtx,&signedtxid,V,numvins,rawtx,vins,privkeys)) < 0 )
printf("couldnt sign withdraw %s\n",bits256_str(str,signedtxid));
else if ( completed == 0 )
{
printf("incomplete signing withdraw (%s)\n",jprint(vins,0));
if ( signedtx != 0 )
free(signedtx), signedtx = 0;
} else printf("LP_withdraw %s -> %s\n",jprint(argjson,0),bits256_str(str,signedtxid));
if ( signedtx == 0 )
break;
datalen = (int32_t)strlen(signedtx) / 2;
if ( strcmp(coin->symbol,"BTC") == 0 )
{
newtxfee = LP_txfeecalc(coin,0,datalen);
printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee));
} else break;
} else break;
free_json(vins), vins = 0;
free_json(txobj), txobj = 0;
free_json(privkeys), privkeys = 0;
if ( rawtx != 0 )
free(rawtx), rawtx = 0;
}
free(V);
if ( vins != 0 )
free_json(vins);
if ( privkeys != 0 )
free_json(privkeys);
retjson = cJSON_CreateObject();
if ( rawtx != 0 )
jaddstr(retjson,"rawtx",rawtx);
if ( signedtx != 0 )
jaddstr(retjson,"hex",signedtx);
if ( txobj != 0 )
jadd(retjson,"tx",txobj);
jaddbits256(retjson,"txid",signedtxid);
jadd(retjson,"complete",completed!=0?jtrue():jfalse());
return(jprint(retjson,1));
}
int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr)
{
int32_t retval=-1,len,iter; char *signedtx,*changeaddr = 0,_changeaddr[64]; struct iguana_info *coin; int64_t newtxfee=0,destamount;
int32_t retval=-1,iter; char *signedtx,*changeaddr = 0,_changeaddr[64]; struct iguana_info *coin; int64_t newtxfee=0,destamount;
char str2[65]; printf("%s rawtxgen.(%s/v%d)\n",rawtx->name,bits256_str(str2,rawtx->utxotxid),rawtx->utxovout);
if ( (coin= rawtx->coin) == 0 )
return(-1);
@ -739,8 +1065,7 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub
free(signedtx);
if ( strcmp(coin->symbol,"BTC") != 0 )
return(retval);
len = rawtx->I.datalen;
newtxfee = LP_txfeecalc(coin,0);
newtxfee = LP_txfeecalc(coin,0,rawtx->I.datalen);
printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee));
} else break;
if ( strcmp(str,"myfee") == 0 )
@ -921,13 +1246,21 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut
bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout)
{
bits256 spendtxid; int32_t spendvin; char coinaddr[64],str[65];
bits256 spendtxid; int32_t spendvin; char coinaddr[64],str[65]; cJSON *retjson; struct iguana_info *coin;
// listtransactions or listspents
destaddr[0] = 0;
coinaddr[0] = 0;
memset(&spendtxid,0,sizeof(spendtxid));
if ( LP_spendsearch(&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 )
if ( LP_spendsearch(destaddr,&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 )
printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout);
else if ( 0 && (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 )
{
if ( (retjson= LP_gettxout(symbol,coinaddr,utxotxid,vout)) == 0 )
{
decode_hex(spendtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
printf("couldnt find spend of %s/v%d, but no gettxout\n",bits256_str(str,utxotxid),vout);
} else free_json(retjson);
}
return(spendtxid);
//char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid));
}
@ -1055,16 +1388,16 @@ int32_t basilisk_swapuserdata(uint8_t *userdata,bits256 privkey,int32_t ifpath,b
int32_t basilisk_bobpayment_reclaim(struct basilisk_swap *swap,int32_t delay)
{
uint8_t userdata[512]; int32_t retval,len = 0; static bits256 zero;
uint8_t userdata[512]; int32_t retval,i,len = 0; static bits256 zero;
//printf("basilisk_bobpayment_reclaim\n");
len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
memcpy(swap->I.userdata_bobreclaim,userdata,len);
swap->I.userdata_bobreclaimlen = len;
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.wiftaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr)) == 0 )
{
//for (i=0; i<swap->bobreclaim.I.datalen; i++)
// printf("%02x",swap->bobreclaim.txbytes[i]);
//printf(" <- bobreclaim\n");
for (i=0; i<swap->bobreclaim.I.datalen; i++)
printf("%02x",swap->bobreclaim.txbytes[i]);
printf(" <- bobreclaim\n");
//basilisk_txlog(swap,&swap->bobreclaim,delay);
return(retval);
}
@ -1307,6 +1640,20 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data
return(-1);
}
int32_t LP_verify_alicespend(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->alicespend,0,data,datalen,0) == 0 )
{
printf("alicespend amount %.8f -> %s vs %s\n",dstr(swap->alicespend.I.amount),swap->alicespend.p2shaddr,swap->alicespend.I.destaddr);
if ( strcmp(swap->alicespend.I.destaddr,swap->alicespend.p2shaddr) == 0 )
{
printf("alicespend verified\n");
return(0);
}
}
return(-1);
}
/* Bob deposit:
OP_IF
<now + INSTANTDEX_LOCKTIME*2> OP_CLTV OP_DROP <alice_pubA0> OP_CHECKSIG

146
iguana/exchanges/LP_utxo.c

@ -151,12 +151,16 @@ struct LP_utxoinfo *LP_allocated(bits256 txid,int32_t vout)
return(0);
}
int32_t LP_address_utxo_ptrs(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap)
int32_t LP_address_utxo_ptrs(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap,char *coinaddr)
{
struct LP_address_utxo *up,*tmp; int32_t n = 0;
//printf("LP_address_utxo_ptrs for (%s).(%s)\n",ap->coinaddr,coinaddr);
if ( strcmp(ap->coinaddr,coinaddr) != 0 )
printf("UNEXPECTED coinaddr mismatch (%s) != (%s)\n",ap->coinaddr,coinaddr);
portable_mutex_lock(&LP_utxomutex);
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
//char str[65]; printf("LP_address_utxo_ptrs %s n.%d %.8f %s v%d spendheight.%d allocated.%p\n",ap->coinaddr,n,dstr(up->U.value),bits256_str(str,up->U.txid),up->U.vout,up->spendheight,LP_allocated(up->U.txid,up->U.vout));
if ( up->spendheight <= 0 )
{
if ( LP_allocated(up->U.txid,up->U.vout) == 0 )
@ -168,13 +172,14 @@ int32_t LP_address_utxo_ptrs(int32_t iambob,struct LP_address_utxo **utxos,int32
}
}
portable_mutex_unlock(&LP_utxomutex);
//printf("return n.%d\n",n);
return(n);
}
struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout)
{
struct LP_address *ap; struct LP_address_utxo *up,*tmp;
//printf("%s add addr.%s ht.%d\n",coin->symbol,coinaddr,height);
//printf("LP_address_utxofind %s add addr.%s\n",coin->symbol,coinaddr);
if ( (ap= _LP_address(coin,coinaddr)) != 0 )
{
DL_FOREACH_SAFE(ap->utxos,up,tmp)
@ -188,13 +193,13 @@ struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coina
int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight)
{
struct LP_address *ap; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; char str[65];
//printf("%s add addr.%s ht.%d\n",coin->symbol,coinaddr,height);
struct LP_address *ap; cJSON *txobj; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; char str[65];
if ( coin == 0 )
return(0);
if ( spendheight > 0 ) // dont autocreate entries for spends we dont care about
ap = LP_addressfind(coin,coinaddr);
else ap = LP_address(coin,coinaddr);
//printf("%s add addr.%s ht.%d ap.%p\n",coin->symbol,coinaddr,height,ap);
if ( ap != 0 )
{
flag = 0;
@ -203,18 +208,30 @@ int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,
if ( vout == up->U.vout && bits256_cmp(up->U.txid,txid) == 0 )
{
flag = 1;
if ( up->U.height <= 0 && height > 0 && up->U.height != height )
if ( height > 0 && up->U.height != height && up->SPV <= 0 )
{
if ( up->U.height > 0 )
printf("%s SPV.%d update %s/v%d up->U.height %d <- %d\n",coin->symbol,up->SPV,bits256_str(str,up->U.txid),up->U.vout,up->U.height,height);
up->U.height = height, flag |= 2;
}
if ( spendheight > 0 && up->spendheight != spendheight )
up->spendheight = spendheight, flag |= 4;
if ( up->U.value == 0 && up->U.value != value )
up->U.value = value, flag |= 8;
//printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
//printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
break;
}
}
if ( flag == 0 )
{
if ( coin->electrum == 0 )
{
if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) == 0 )
{
//printf("prevent utxoadd since gettxout %s %s %s/v%d missing\n",coin->symbol,coinaddr,bits256_str(str,txid),vout);
return(0);
} else free_json(txobj);
}
up = calloc(1,sizeof(*up));
up->U.txid = txid;
up->U.vout = vout;
@ -225,8 +242,8 @@ int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,
DL_APPEND(ap->utxos,up);
portable_mutex_unlock(&coin->addrmutex);
retval = 1;
if ( 0 && height > 0 )
printf("ADDRESS_UTXO >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
if ( 0 && height > 0 && strcmp("REVS",coin->symbol) == 0 )
printf("ADD UTXO >> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
}
} // else printf("cant get ap %s %s\n",coin->symbol,coinaddr);
//printf("done %s add addr.%s ht.%d\n",coin->symbol,coinaddr,height);
@ -240,7 +257,7 @@ cJSON *LP_address_item(struct iguana_info *coin,struct LP_address_utxo *up,int32
{
jaddbits256(item,"txid",up->U.txid);
jaddnum(item,"vout",up->U.vout);
jaddnum(item,"confirmations",LP_getheight(coin) - up->U.height);
jaddnum(item,"confirmations",LP_getheight(coin) - up->U.height + 1);
jaddnum(item,"amount",dstr(up->U.value));
jaddstr(item,"scriptPubKey","");
}
@ -302,9 +319,42 @@ bits256 validate_merkle(int32_t pos,bits256 txid,cJSON *proofarray,int32_t proof
return(hash);
}
int32_t LP_merkleproof(struct iguana_info *coin,struct electrum_info *ep,bits256 txid,int32_t height)
{
cJSON *merkobj,*merkles,*hdrobj; bits256 roothash,merkleroot; int32_t m,SPV = 0;
if ( (merkobj= electrum_getmerkle(coin->symbol,ep,&merkobj,txid,height)) != 0 )
{
char str[65],str2[65],str3[65];
SPV = -1;
memset(roothash.bytes,0,sizeof(roothash));
if ( (merkles= jarray(&m,merkobj,"merkle")) != 0 )
{
roothash = validate_merkle(jint(merkobj,"pos"),txid,merkles,m);
if ( (hdrobj= electrum_getheader(coin->symbol,ep,&hdrobj,height)) != 0 )
{
if ( jobj(hdrobj,"merkle_root") != 0 )
{
merkleroot = jbits256(hdrobj,"merkle_root");
if ( bits256_cmp(merkleroot,roothash) == 0 )
{
SPV = height;
//printf("validated MERK %s ht.%d -> %s root.(%s)\n",bits256_str(str,up->U.txid),up->U.height,jprint(merkobj,0),bits256_str(str2,roothash));
}
else printf("ERROR MERK %s ht.%d -> %s root.(%s) vs %s (%s)\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash),bits256_str(str3,merkleroot),jprint(hdrobj,0));
} else SPV = 0;
free_json(hdrobj);
} else printf("couldnt get header for ht.%d\n",height);
}
if ( SPV < 0 )
printf("MERKLE DIDNT VERIFY.(%s)\n",jprint(merkobj,0));
free_json(merkobj);
}
return(SPV);
}
cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret)
{
cJSON *array,*item,*merkobj,*merkles,*hdrobj; int32_t n,m; uint64_t total; struct LP_address *ap=0,*atmp; struct LP_address_utxo *up,*tmp; bits256 merkleroot,roothash; struct electrum_info *ep,*backupep=0;
cJSON *array,*item; int32_t n; uint64_t total; struct LP_address *ap=0,*atmp; struct LP_address_utxo *up,*tmp; cJSON *txobj; struct electrum_info *ep,*backupep=0;
array = cJSON_CreateArray();
if ( coinaddr != 0 && coinaddr[0] != 0 )
{
@ -321,33 +371,21 @@ cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrum
{
if ( up->spendheight <= 0 && up->U.height > 0 )
{
if ( ep != 0 && up->SPV == 0 && up->U.height > 0 )
if ( coin->electrum == 0 )
{
if ( (txobj= LP_gettxout(coin->symbol,coinaddr,up->U.txid,up->U.vout)) == 0 )
up->spendheight = 1;
else free_json(txobj);
}
if ( up->spendheight <= 0 )
{
if ( (merkobj= electrum_getmerkle(coin->symbol,backupep,&merkobj,up->U.txid,up->U.height)) != 0 )
if ( up->SPV >= 0 )
{
char str[65],str2[65],str3[65];
memset(roothash.bytes,0,sizeof(roothash));
if ( (merkles= jarray(&m,merkobj,"merkle")) != 0 )
{
roothash = validate_merkle(jint(merkobj,"pos"),up->U.txid,merkles,m);
if ( (hdrobj= electrum_getheader(coin->symbol,backupep,&hdrobj,up->U.height)) != 0 )
{
merkleroot = jbits256(hdrobj,"merkle_root");
if ( bits256_cmp(merkleroot,roothash) == 0 )
{
up->SPV = up->U.height;
//printf("validated MERK %s ht.%d -> %s root.(%s)\n",bits256_str(str,up->U.txid),up->U.height,jprint(merkobj,0),bits256_str(str2,roothash));
}
else printf("ERROR MERK %s ht.%d -> %s root.(%s) vs %s\n",bits256_str(str,up->U.txid),up->U.height,jprint(merkobj,0),bits256_str(str2,roothash),bits256_str(str3,merkleroot));
free_json(hdrobj);
}
}
free_json(merkobj);
jaddi(array,LP_address_item(coin,up,electrumret));
n++;
total += up->U.value;
}
}
jaddi(array,LP_address_item(coin,up,electrumret));
n++;
total += up->U.value;
//printf("new array %s\n",jprint(array,0));
}
}
@ -393,7 +431,7 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
void LP_postutxos(char *symbol,char *coinaddr)
{
bits256 zero; char *msg; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
bits256 zero; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
if ( (coin= LP_coinfind(symbol)) != 0 && (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
//printf("LP_postutxos pubsock.%d %s %s\n",pubsock,symbol,coin->smartaddr);
@ -406,9 +444,8 @@ void LP_postutxos(char *symbol,char *coinaddr)
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"coinaddr",coinaddr);
jadd(reqjson,"utxos",array);
msg = jprint(reqjson,1);
//printf("post (%s) -> %d\n",msg,LP_mypubsock);
LP_broadcast_message(LP_mypubsock,symbol,symbol,zero,msg);
LP_reserved_msg(symbol,symbol,zero,jprint(reqjson,1));
}
}
}
@ -427,8 +464,6 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
v = jint(item,"tx_pos");
height = jint(item,"height");
val = j64bits(item,"value");
//if ( strcmp(coin->symbol,"LBC") == 0 )
// printf("(%s)\n",jprint(item,0));
if ( coin->electrum == 0 && (txobj= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 )
{
value = LP_value_extract(txobj,0);
@ -437,9 +472,10 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
char str[65]; printf("REJECT %s %s/v%d value.%llu vs %llu (%s)\n",coin->symbol,bits256_str(str,txid),v,(long long)value,(long long)val,jprint(txobj,0));
errs++;
}
if ( coin->height != 0 )
ht = LP_getheight(coin) - jint(txobj,"confirmations");
else ht = 0;
ht = LP_txheight(coin,txid);
//if ( coin->height != 0 )
// ht = LP_getheight(coin) - jint(txobj,"confirmations") + 1;
//else ht = 0;
/*if ( ht != 0 && ht < height-2 )
{
printf("REJECT %s %s/v%d ht.%d vs %d confs.%d (%s)\n",symbol,bits256_str(str,txid),v,ht,height,jint(txobj,"confirmations"),jprint(item,0));
@ -449,6 +485,7 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
}
if ( errs == 0 )
{
//printf("from LP_unspents_array\n");
LP_address_utxoadd(coin,coinaddr,txid,v,val,height,-1);
count++;
}
@ -467,7 +504,7 @@ char *LP_postedutxos(cJSON *argjson)
if ( (array= jarray(&n,argjson,"utxos")) != 0 )
LP_unspents_array(coin,coinaddr,array);
}
else if ( (array= electrum_address_listunspent(symbol,coin->electrum,&array,coinaddr)) != 0 )
else if ( (array= electrum_address_listunspent(symbol,coin->electrum,&array,coinaddr,1)) != 0 )
free_json(array);
}
return(clonestr("{\"result\":\"success\"}"));
@ -596,6 +633,8 @@ uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_inf
cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj)
{
struct LP_transaction *tx; int32_t i,height,numvouts,numvins,spentvout; cJSON *vins,*vouts,*vout,*vin; bits256 spenttxid; char str[65];
if ( coin->inactive != 0 )
return(0);
if ( txobj != 0 || (txobj= LP_gettx(coin->symbol,txid)) != 0 )
{
if ( coin->electrum == 0 )
@ -613,7 +652,8 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS
tx->outpoints[i].value = LP_value_extract(vout,0);
tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest");
LP_destaddr(tx->outpoints[i].coinaddr,vout);
LP_address_utxoadd(coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1);
//printf("from transaction init\n");
//LP_address_utxoadd(coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1);
}
//printf("numvouts.%d\n",numvouts);
}
@ -665,9 +705,11 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid)
if ( bits256_nonz(blockhash) != 0 && (blockobj= LP_getblock(coin->symbol,blockhash)) != 0 )
{
height = jint(blockobj,"height");
//printf("%s LP_txheight.%d\n",coin->symbol,height);
//char str[65];
//if ( strcmp(coin->symbol,"CHIPS") != 0 && strcmp(coin->symbol,"BTC") != 0 )
// printf("%s %s LP_txheight.%d\n",coin->symbol,bits256_str(str,txid),height);
free_json(blockobj);
} //else printf("%s LP_txheight error (%s)\n",coin->symbol,jprint(txobj,0));
} // else printf("%s LP_txheight error (%s)\n",coin->symbol,jprint(txobj,0)); likely just unconfirmed
free_json(txobj);
}
}
@ -698,7 +740,7 @@ int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int
}
else
{
LP_listunspent_issue(symbol,coinaddr);
LP_listunspent_issue(symbol,coinaddr,1);
if ( (ht= LP_txheight(coin,txid)) > 0 && ht <= coin->height )
numconfirms = (LP_getheight(coin) - ht + 1);
else if ( mempool != 0 )
@ -784,7 +826,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2)
{
//struct LP_utxoinfo *utxo;
struct LP_address_utxo *up; uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol);
struct LP_address_utxo *up; uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64],str[65]; struct iguana_info *coin = LP_coinfind(symbol);
if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 )
{
printf("null txid not eligible\n");
@ -797,10 +839,16 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
val = satoshis;
else val = LP_txvalue(destaddr,symbol,txid,vout);
if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 )
{
//printf("%s/v%d spent %d\n",bits256_str(str,txid),vout,up->spendheight);
return(-2);
}
if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 )
{
//printf("%s/v%d spent %d\n",bits256_str(str,txid2),vout2,up->spendheight);
return(-3);
txfee = LP_txfeecalc(LP_coinfind(symbol),0);
}
txfee = LP_txfeecalc(LP_coinfind(symbol),0,0);
if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee )
{
threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : (LP_DEXFEE(satoshis) + txfee);
@ -821,7 +869,7 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
}
} // else printf("no val2\n");
}
char str[65],str2[65];
char str2[65];
if ( val != 0 && val2 != 0 )
printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee));
if ( val == 0 )

48
iguana/exchanges/LP_utxos.c

@ -36,6 +36,20 @@ int32_t LP_isavailable(struct LP_utxoinfo *utxo)
int32_t LP_isunspent(struct LP_utxoinfo *utxo)
{
struct LP_address_utxo *up; struct _LP_utxoinfo u; struct iguana_info *coin;
if ( (coin= LP_coinfind(utxo->coin)) == 0 )
return(0);
if ( (up= LP_address_utxofind(coin,utxo->coinaddr,utxo->payment.txid,utxo->payment.vout)) != 0 && up->spendheight > 0 )
{
utxo->T.spentflag = up->spendheight;
return(0);
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( (up= LP_address_utxofind(coin,utxo->coinaddr,u.txid,u.vout)) != 0 && up->spendheight > 0 )
{
utxo->T.spentflag = up->spendheight;
return(0);
}
if ( utxo != 0 && utxo->T.spentflag == 0 && LP_isavailable(utxo) > 0 )
return(1);
else return(0);
@ -298,7 +312,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
//printf("LP_utxoadd reject inactive %s\n",symbol);
return(0);
}
txfee = LP_txfeecalc(coin,0);
txfee = LP_txfeecalc(coin,0,0);
if ( iambob != 0 && value2 < 9 * (value >> 3) + 2*txfee ) // big txfee padding
{
if ( value2 > 2*txfee )
@ -331,7 +345,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t
}
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,vout2,0)) <= 0 )
{
printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms);
printf("LP_utxoadd reject2 numconfirms.%d %s %s/v%d\n",numconfirms,symbol,bits256_str(str,txid2),vout2);
return(0);
}
}
@ -436,7 +450,10 @@ cJSON *LP_inventory(char *symbol)
myipaddr = LP_mypeer->ipaddr;
else myipaddr = "127.0.0.1";
if ( (coin= LP_coinfind(symbol)) != 0 )
LP_listunspent_both(symbol,coin->smartaddr);
{
coin->unspenttime = (uint32_t)time(NULL) - 777;
LP_listunspent_both(symbol,coin->smartaddr,0);
}
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
char str[65];
@ -455,7 +472,7 @@ cJSON *LP_inventory(char *symbol)
// LP_utxo_clientpublish(utxo);
jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo));
}
else if ( LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 )
else if ( 0 && LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 )
printf("skip %s %s %d %d %d %d\n",utxo->coin,bits256_str(str,utxo->payment.txid),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0);
}
return(array);
@ -495,17 +512,18 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri
{
int32_t enable_utxos = 0;
char *script,destaddr[64]; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,value,total = 0; int64_t targetval;
if ( coin == 0 || coin->inactive != 0 )
if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) )
{
printf("coin not active\n");
//printf("coin not active\n");
return(0);
}
//printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr);
if ( coin->inactive == 0 )
LP_listunspent_issue(coin->symbol,coin->smartaddr);
LP_listunspent_issue(coin->symbol,coin->smartaddr,0);
LP_address(coin,coin->smartaddr);
if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 )
{
txfee = LP_txfeecalc(coin,0);
txfee = LP_txfeecalc(coin,0,0);
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
//printf("LP_privkey_init %s %s\n",coin->symbol,jprint(array,0));
@ -523,7 +541,7 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri
txid = jbits256(item,"txid");
vout = juint(item,"vout");
value = LP_value_extract(item,0);
height = LP_getheight(coin) - jint(item,"confirmations");
height = LP_txheight(coin,txid);//LP_getheight(coin) - jint(item,"confirmations") + 1;
}
else
{
@ -637,10 +655,12 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri
return(flag);
}
char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype)
char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype)
{
int32_t i; uint8_t tmptype,pubkey33[33],rmd160[20]; char output[777*45],str[65],str2[65],buf[8192],wifstr[128],coinaddr[64]; bits256 checkprivkey,privkey,pubkey; cJSON *retjson;
retjson = cJSON_CreateObject();
if ( prefix == 0 || prefix[0] == 0 )
prefix = "secretaddress";
if ( passphrase == 0 || passphrase[0] == 0 )
passphrase = "password";
if ( n <= 0 )
@ -653,7 +673,7 @@ char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint
sprintf(output,"\"addresses\":[");
for (i=0; i<n; i++)
{
sprintf(buf,"secretaddress %s %03d",passphrase,i);
sprintf(buf,"%s %s %03d",prefix,passphrase,i);
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)buf,(int32_t)strlen(buf));
bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype);
bitcoin_priv2wif(0,wifstr,privkey,188);
@ -725,9 +745,9 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
userpub = curve25519(userpass,curve25519_basepoint9());
printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub));
}
if ( coin->electrum == 0 )
if ( coin->electrum == 0 && coin->userpass[0] != 0 )
{
LP_listunspent_issue(coin->symbol,coin->smartaddr);
LP_listunspent_issue(coin->symbol,coin->smartaddr,0);
if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 )
{
if ( jobj(retjson,"error") != 0 )
@ -761,7 +781,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
}
//printf("i.%d of %d\n",i,LP_numcoins);
else if ( coin->inactive == 0 )
else if ( IAMLP == 0 || coin->inactive == 0 )
{
if ( LP_privkey_init(pubsock,coin,G.LP_mypriv25519,G.LP_mypub25519) == 0 && (rand() % 10) == 0 )
LP_postutxos(coin->symbol,coin->smartaddr);

89
iguana/exchanges/assetchains.old

@ -0,0 +1,89 @@
#!/bin/bash
set -x
delay=60
source pubkey.txt
echo $pubkey
./komodod -pubkey=$pubkey -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=SUPERNET -ac_supply=816061 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=DEX -ac_supply=999999 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=PANGEA -ac_supply=999999 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=JUMBLR -ac_supply=999999 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=BET -ac_supply=999999 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=CRYPTO -ac_supply=999999 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=HODL -ac_supply=9999999 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=SHARK -ac_supply=1401 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=MGW -ac_supply=999999 -addnode=78.47.196.146 $1 &
#./komodod -pubkey=$pubkey -ac_name=MVP -ac_supply=1000000 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=COQUI -ac_supply=72000000 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=WLC -ac_supply=210000000 -addnode=148.251.190.89 $1 &
./komodod -pubkey=$pubkey -ac_name=KV -ac_supply=1000000 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=CEAL -ac_supply=366666666 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=MESH -ac_supply=1000007 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=MNZ -ac_supply=257142858 -addnode=51.15.138.138 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=USD -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=EUR -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=JPY -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=GBP -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=AUD -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=CAD -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=CHF -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=NZD -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=CNY -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=RUB -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=MXN -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=BRL -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=INR -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=HKD -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=TRY -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=ZAR -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=PLN -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=NOK -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=SEK -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=DKK -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=CZK -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=HUF -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=ILS -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=KRW -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=MYR -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=PHP -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=RON -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=SGD -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=THB -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=BGN -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=IDR -addnode=78.47.196.146 $1 &
sleep $delay
./komodod -pubkey=$pubkey -ac_name=HRK -addnode=78.47.196.146 $1 &

10
iguana/exchanges/autoprice

@ -1,10 +1,12 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.0001}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"margin\":0.0001}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.03}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"margin\":0.03}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"HUSH\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"HUSH\",\"rel\":\"KMD\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"USD\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"USD\",\"rel\":\"KMD\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"JUMBLR\",\"margin\":0.01}"
#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"USD\",\"rel\":\"KMD\",\"margin\":0.01}"
#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"JUMBLR\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"JUMBLR\",\"rel\":\"KMD\",\"margin\":0.01}"
#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.0,\"refbase\":\"BTC\",\"refrel\":\"KMD\",\"factor\":0.00006667,\"margin\":-0.2}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"MNZ\",\"offset\":0.0,\"refbase\":\"KMD\",\"refrel\":\"BTC\",\"factor\":15000,\"margin\":-0.2}"

3
iguana/exchanges/coins

File diff suppressed because one or more lines are too long

3
iguana/exchanges/coins.json

File diff suppressed because one or more lines are too long

2
iguana/exchanges/enable

@ -1,3 +1,5 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"REVS\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"CHIPS\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MNZ\"}"

3
iguana/exchanges/install

@ -1,5 +1,6 @@
#!/bin/bash
cp balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug register registerall buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv setprice status utxos ../dexscripts
cp 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 .
#echo you will need to have a passphrase file with your passphrase and userpass file with userpass value in dexscripts dir

2
iguana/exchanges/listunspent

@ -1,3 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"listunspent\",\"coin\":\"BTC\",\"address\":\"1DPDsPCNNCF5SHhPPrddXcJe78rM6CBcH3\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"listunspent\",\"coin\":\"CHIPS\",\"address\":\"RMfQwu5ey23eWJ4as2ckd8dqsQJwo836ny\"}"

2
iguana/exchanges/mm.c

@ -880,7 +880,7 @@ int main(int argc, const char * argv[])
{
printf("error launching LP_main (%s)\n",jprint(retjson,0));
exit(-1);
} else printf("(%s) launched.(%s)\n",argv[1],passphrase);
} //else printf("(%s) launched.(%s)\n",argv[1],passphrase);
incr = 100.;
while ( (1) )
sleep(1);

2
iguana/exchanges/orderbook

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

1
iguana/exchanges/profile

@ -0,0 +1 @@
gprof -b ../marketmaker ../gmon.out

2
iguana/exchanges/utxos → iguana/exchanges/recentswaps

@ -1,3 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"recentswaps\",\"limit\":1}"

3
iguana/exchanges/register

@ -1,3 +0,0 @@
#!/bin/bash
source userpass
curl --url "http://5.9.253.195:7783" --data "{\"userpass\":\"9bb4846d24136fc7c33515e45bccbab5c8fb7b57b411aa20057b371da9358255\",\"agent\":\"stats\",\"method\":\"register\",\"client\":\"6d3332be4904feafd326609bd76b66528dc7b2e2d75a7bd110c6bf8d19c4cf58\",\"pushaddr\":\"5.9.253.195\",\"pushport\":\"10000\"}"

3
iguana/exchanges/sendrawtransaction

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sendrawtransaction\",\"coin\":\"KMD\",\"signedtx\":\"$1\"}"

3
iguana/exchanges/setconfirms

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setconfirms\",\"coin\":\"REVS\",\"numconfirms\":1}"

293
iguana/exchanges/stats.c

@ -28,7 +28,7 @@
#include "DEXstats.h"
char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char *remoteaddr,uint16_t port);
#ifndef WIN32
#ifndef _WIN32
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0x4000 // Do not generate SIGPIPE
#endif
@ -115,7 +115,7 @@ int32_t iguana_socket(int32_t bindflag,char *hostname,uint16_t port)
#endif
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
//#ifdef WIN32
//#ifdef _WIN32
// saddr.sin_addr.s_addr = (uint32_t)calc_ipbits("127.0.0.1");
//#else
@ -140,7 +140,7 @@ int32_t iguana_socket(int32_t bindflag,char *hostname,uint16_t port)
opt = 1;
slen = sizeof(opt);
//printf("set keepalive.%d\n",setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(void *)&opt,slen));
#ifndef WIN32
#ifndef _WIN32
if ( 1 )//&& bindflag != 0 )
{
opt = 0;
@ -337,7 +337,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
return(clonestr("{\"error\":\"cant find index7779\"}"));
else return(filestr);
}
else if ( (filestr= OS_filestr(&filesize,furl)) != 0 )
/*else if ( (filestr= OS_filestr(&filesize,furl)) != 0 ) allows arbitrary file access!
{
*jsonflagp = 1;
for (i=(int32_t)strlen(url)-1; i>0; i--)
@ -347,7 +347,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
strcpy(filetype,url+i+1);
//printf("return filetype.(%s) size.%ld\n",filetype,filesize);
return(filestr);
}
}*/
if ( strncmp(&url[i],"/api",strlen("/api")) == 0 )
{
*jsonflagp = 1;
@ -553,163 +553,194 @@ int32_t iguana_getheadersize(char *buf,int32_t recvlen)
return(recvlen);
}
void stats_rpcloop(void *args)
uint16_t RPC_port;
extern portable_mutex_t LP_commandmutex;
void LP_rpc_processreq(void *_ptr)
{
static char *jsonbuf;
uint16_t port; char filetype[128],content_type[128];
int32_t recvlen,flag,bindsock,postflag=0,contentlen,sock,remains,numsent,jsonflag=0,hdrsize,len;
socklen_t clilen; char helpname[512],remoteaddr[64],*buf,*retstr,*space;
struct sockaddr_in cli_addr; uint32_t ipbits,i,size = 32*IGUANA_MAXPACKETSIZE + 512;
if ( (port= *(uint16_t *)args) == 0 )
port = 7779;
if ( jsonbuf == 0 )
jsonbuf = calloc(1,IGUANA_MAXPACKETSIZE);
while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 )
{
//if ( coin->MAXPEERS == 1 )
// break;
//exit(-1);
sleep(3);
}
printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock);
uint64_t arg64 = *(uint64_t *)_ptr;
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;
uint32_t ipbits,i,size = 32*IGUANA_MAXPACKETSIZE + 512;
ipbits = (arg64 >> 32);
expand_ipbits(remoteaddr,ipbits);
sock = (arg64 & 0xffffffff);
recvlen = flag = 0;
retstr = 0;
space = calloc(1,size);
while ( bindsock >= 0 )
jsonbuf = calloc(1,size);
remains = size-1;
buf = jsonbuf;
while ( remains > 0 )
{
clilen = sizeof(cli_addr);
sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen);
if ( sock < 0 )
{
//printf("iguana_rpcloop ERROR on accept usock.%d errno %d %s\n",sock,errno,strerror(errno));
continue;
}
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
expand_ipbits(remoteaddr,ipbits);
//printf("remote RPC request from (%s) %x\n",remoteaddr,ipbits);
memset(jsonbuf,0,IGUANA_MAXPACKETSIZE);
remains = (int32_t)(IGUANA_MAXPACKETSIZE - 1);
buf = jsonbuf;
recvlen = flag = 0;
retstr = 0;
while ( remains > 0 )
//printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen);
if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 )
{
//printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen);
if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 )
if ( errno == EAGAIN )
{
if ( errno == EAGAIN )
{
printf("EAGAIN for len %d, remains.%d\n",len,remains);
usleep(10000);
}
break;
printf("EAGAIN for len %d, remains.%d\n",len,remains);
usleep(10000);
}
else
break;
}
else
{
if ( len > 0 )
{
if ( len > 0 )
buf[len] = 0;
if ( recvlen == 0 )
{
buf[len] = 0;
if ( recvlen == 0 )
if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 )
{
if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 )
hdrsize = iguana_getheadersize(buf,recvlen);
if ( hdrsize > 0 )
{
hdrsize = iguana_getheadersize(buf,recvlen);
if ( hdrsize > 0 )
if ( len < (hdrsize + contentlen) )
{
if ( len < (hdrsize + contentlen) )
{
remains = (hdrsize + contentlen) - len;
buf = &buf[len];
flag = 1;
//printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len);
continue;
}
remains = (hdrsize + contentlen) - len;
buf = &buf[len];
flag = 1;
//printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len);
continue;
}
}
}
recvlen += len;
remains -= len;
buf = &buf[len];
if ( flag == 0 || remains <= 0 )
break;
}
else
{
usleep(10000);
//printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len);
//retstr = iguana_rpcparse(space,size,&postflag,jsonbuf);
if ( flag == 0 )
break;
}
recvlen += len;
remains -= len;
buf = &buf[len];
if ( flag == 0 || remains <= 0 )
break;
}
}
content_type[0] = 0;
if ( recvlen > 0 )
{
retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,port);
if ( filetype[0] != 0 )
else
{
static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize;
sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR);
if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 )
{
mimejson = cJSON_Parse(tmp);
free(tmp);
}
if ( mimejson != 0 )
{
if ( (typestr= jstr(mimejson,filetype)) != 0 )
sprintf(content_type,"Content-Type: %s\r\n",typestr);
} else printf("parse error.(%s)\n",tmp);
//printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type);
usleep(10000);
//printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len);
//retstr = iguana_rpcparse(space,size,&postflag,jsonbuf);
if ( flag == 0 )
break;
}
}
if ( retstr != 0 )
}
content_type[0] = 0;
if ( recvlen > 0 )
{
jsonflag = postflag = 0;
portable_mutex_lock(&LP_commandmutex);
retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,RPC_port);
//if ( strcmp("5.9.253.195",remoteaddr) == 0 )
// printf("RPC.(%s)%s\n",jsonbuf,retstr);
portable_mutex_unlock(&LP_commandmutex);
if ( filetype[0] != 0 )
{
char *response,hdrs[1024];
//printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag);
if ( jsonflag != 0 || postflag != 0 )
static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize;
sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR);
if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 )
{
if ( retstr == 0 )
retstr = clonestr("{}");
response = malloc(strlen(retstr)+1024+1+1);
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 )
free(retstr);
retstr = response;
//printf("RET.(%s)\n",retstr);
mimejson = cJSON_Parse(tmp);
free(tmp);
}
remains = (int32_t)strlen(retstr);
i = 0;
while ( remains > 0 )
if ( mimejson != 0 )
{
if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 )
{
if ( errno != EAGAIN && errno != EWOULDBLOCK )
{
//printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock);
break;
}
}
else if ( remains > 0 )
if ( (typestr= jstr(mimejson,filetype)) != 0 )
sprintf(content_type,"Content-Type: %s\r\n",typestr);
} else printf("parse error.(%s)\n",tmp);
//printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type);
}
}
if ( retstr != 0 )
{
char *response,hdrs[1024];
//printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag);
if ( jsonflag != 0 || postflag != 0 )
{
if ( retstr == 0 )
retstr = clonestr("{}");
response = malloc(strlen(retstr)+1024+1+1);
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 )
free(retstr);
retstr = response;
//printf("RET.(%s)\n",retstr);
}
remains = (int32_t)strlen(retstr);
i = 0;
while ( remains > 0 )
{
if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 )
{
if ( errno != EAGAIN && errno != EWOULDBLOCK )
{
remains -= numsent;
i += numsent;
if ( remains > 0 )
printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen);
//printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock);
break;
}
}
if ( retstr != space)
free(retstr);
else if ( remains > 0 )
{
remains -= numsent;
i += numsent;
if ( remains > 0 )
printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen);
}
}
closesocket(sock);
if ( retstr != space)
free(retstr);
}
free(space);
free(jsonbuf);
closesocket(sock);
}
void stats_rpcloop(void *args)
{
uint16_t port; int32_t sock,bindsock; socklen_t clilen; struct sockaddr_in cli_addr; uint32_t ipbits; uint64_t arg64; void *arg64ptr;
if ( (port= *(uint16_t *)args) == 0 )
port = 7779;
RPC_port = port;
while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 )
{
//if ( coin->MAXPEERS == 1 )
// break;
//exit(-1);
sleep(3);
}
printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock);
while ( bindsock >= 0 )
{
clilen = sizeof(cli_addr);
sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen);
if ( sock < 0 )
{
//printf("iguana_rpcloop ERROR on accept usock.%d errno %d %s\n",sock,errno,strerror(errno));
continue;
}
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
//printf("remote RPC request from (%s) %x\n",remoteaddr,ipbits);
arg64 = ((uint64_t)ipbits << 32) | (sock & 0xffffffff);
arg64ptr = malloc(sizeof(arg64));
memcpy(arg64ptr,&arg64,sizeof(arg64));
if ( 1 )
{
LP_rpc_processreq((void *)&arg64);
free(arg64ptr);
}
else if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_rpc_processreq,arg64ptr) != 0 )
{
printf("error launching rpc handler on port %d\n",port);
}
// yes, small leak per command
}
}
#ifndef FROM_MARKETMAKER
portable_mutex_t LP_commandmutex;
void stats_kvjson(FILE *logfp,int32_t height,int32_t savedheight,uint32_t timestamp,char *key,cJSON *kvjson,bits256 pubkey,bits256 sigprev)
{
struct tai T; int32_t seconds,datenum,n;

3
iguana/exchanges/registerall → iguana/exchanges/stop

@ -1,4 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"registerall\",\"numnodes\":10}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"stop\"}"

4
iguana/exchanges/trust

@ -0,0 +1,4 @@
#!/bin/bash
echo "usage: ./trust <pubkey>"
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"$1\",\"method\":\"trust\",\"trust\":1}"

3
iguana/exchanges/trusted

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

3
iguana/exchanges/withdraw

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"withdraw\",\"coin\":\"KMD\",\"outputs\":[{\"RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf\":0.001}, {\"RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf\":0.002}]}"

1
iguana/help/InstantDEX_DEXratio.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"DEXratio","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_DEXratio_test.py"}]}

1
iguana/help/InstantDEX_accept.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"accept","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_accept_test.py"}]}

1
iguana/help/InstantDEX_allcoins.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"allcoins","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_allcoins_test.py"}]}

1
iguana/help/InstantDEX_allexchanges.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"allexchanges","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_allexchanges_test.py"}]}

1
iguana/help/InstantDEX_allpairs.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"allpairs","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_allpairs_test.py"}]}

1
iguana/help/InstantDEX_apikeypair.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"apikeypair","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_apikeypair_test.py"}]}

1
iguana/help/InstantDEX_automatched.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"automatched","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_automatched_test.py"}]}

1
iguana/help/InstantDEX_available.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"available","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_available_test.py"}]}

1
iguana/help/InstantDEX_balance.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"balance","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_balance_test.py"}]}

1
iguana/help/InstantDEX_buy.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"buy","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_buy_test.py"}]}

1
iguana/help/InstantDEX_cancelorder.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"cancelorder","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_cancelorder_test.py"}]}

1
iguana/help/InstantDEX_getswaplist.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"getswaplist","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_getswaplist_test.py"}]}

1
iguana/help/InstantDEX_incoming.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"incoming","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_incoming_test.py"}]}

1
iguana/help/InstantDEX_init.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"init","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_init_test.py"}]}

1
iguana/help/InstantDEX_openorders.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"openorders","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_openorders_test.py"}]}

1
iguana/help/InstantDEX_orderbook.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"orderbook","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_orderbook_test.py"}]}

1
iguana/help/InstantDEX_orderstatus.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"orderstatus","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_orderstatus_test.py"}]}

1
iguana/help/InstantDEX_pollgap.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"pollgap","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_pollgap_test.py"}]}

1
iguana/help/InstantDEX_request.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"request","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_request_test.py"}]}

1
iguana/help/InstantDEX_sell.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"sell","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_sell_test.py"}]}

1
iguana/help/InstantDEX_setuserid.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"setuserid","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_setuserid_test.py"}]}

1
iguana/help/InstantDEX_smartaddress.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"smartaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_smartaddress_test.py"}]}

1
iguana/help/InstantDEX_smartaddresses.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"smartaddresses","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_smartaddresses_test.py"}]}

1
iguana/help/InstantDEX_supports.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"supports","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_supports_test.py"}]}

1
iguana/help/InstantDEX_tradehistory.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"tradehistory","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_tradehistory_test.py"}]}

1
iguana/help/InstantDEX_withdraw.json

@ -0,0 +1 @@
{"agent":"InstantDEX","method":"withdraw","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_withdraw_test.py"}]}

1
iguana/help/SuperNET_activehandle.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"activehandle","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_activehandle_test.py"}]}

1
iguana/help/SuperNET_addr2rmd160.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"addr2rmd160","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_addr2rmd160_test.py"}]}

1
iguana/help/SuperNET_bitcoinrpc.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"bitcoinrpc","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_bitcoinrpc_test.py"}]}

1
iguana/help/SuperNET_broadcastcipher.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"broadcastcipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_broadcastcipher_test.py"}]}

1
iguana/help/SuperNET_broadcastdecipher.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"broadcastdecipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_broadcastdecipher_test.py"}]}

1
iguana/help/SuperNET_cipher.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"cipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_cipher_test.py"}]}

1
iguana/help/SuperNET_decipher.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"decipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_decipher_test.py"}]}

1
iguana/help/SuperNET_decryptjson.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"decryptjson","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_decryptjson_test.py"}]}

1
iguana/help/SuperNET_encryptjson.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"encryptjson","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_encryptjson_test.py"}]}

1
iguana/help/SuperNET_getpeers.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"getpeers","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_getpeers_test.py"}]}

1
iguana/help/SuperNET_help.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"help","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_help_test.py"}]}

1
iguana/help/SuperNET_html.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"html","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_html_test.py"}]}

1
iguana/help/SuperNET_keypair.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"keypair","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_keypair_test.py"}]}

1
iguana/help/SuperNET_layer.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"layer","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_layer_test.py"}]}

1
iguana/help/SuperNET_login.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"login","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_login_test.py"}]}

1
iguana/help/SuperNET_logout.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"logout","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_logout_test.py"}]}

1
iguana/help/SuperNET_multicastcipher.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"multicastcipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_multicastcipher_test.py"}]}

1
iguana/help/SuperNET_multicastdecipher.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"multicastdecipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_multicastdecipher_test.py"}]}

1
iguana/help/SuperNET_myipaddr.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"myipaddr","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_myipaddr_test.py"}]}

1
iguana/help/SuperNET_mypeers.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"mypeers","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_mypeers_test.py"}]}

1
iguana/help/SuperNET_priv2pub.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"priv2pub","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_priv2pub_test.py"}]}

1
iguana/help/SuperNET_priv2wif.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"priv2wif","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_priv2wif_test.py"}]}

1
iguana/help/SuperNET_rmd160conv.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"rmd160conv","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_rmd160conv_test.py"}]}

1
iguana/help/SuperNET_rosetta.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"rosetta","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_rosetta_test.py"}]}

1
iguana/help/SuperNET_saveconf.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"saveconf","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_saveconf_test.py"}]}

1
iguana/help/SuperNET_setmyipaddr.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"setmyipaddr","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_setmyipaddr_test.py"}]}

1
iguana/help/SuperNET_stop.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"stop","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_stop_test.py"}]}

1
iguana/help/SuperNET_utc2utime.json

@ -0,0 +1 @@
{"agent":"SuperNET","method":"utc2utime","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_utc2utime_test.py"}]}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save